summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2019-05-11 14:04:43 +0000
committerGitHub <noreply@github.com>2019-05-11 14:04:43 +0000
commitea09cdfb2c912f9fa00ab39b1618cc4ad71ea366 (patch)
tree8d39cfc9c66485f6cd757822c9097c12648f0ed9
parente685816116362afa64b15e510cc4a2d04a63243c (diff)
parent34aa92e4faf52c1a14c7c772c5b980e4bdc40b48 (diff)
downloadgenimage-ea09cdfb2c912f9fa00ab39b1618cc4ad71ea366.tar.gz
genimage-ea09cdfb2c912f9fa00ab39b1618cc4ad71ea366.tar.xz
Merge pull request #60 from michaelolbrich/percent
allow percentages for image sizes
-rw-r--r--.travis.yml2
-rw-r--r--Makefile.am2
-rw-r--r--README.rst6
-rw-r--r--config.c17
-rw-r--r--genimage.c16
-rw-r--r--genimage.h8
-rwxr-xr-xtest/basic-images.test5
-rw-r--r--test/ext2percent.config7
-rw-r--r--test/ext2test-percent.dump40
-rw-r--r--util.c64
10 files changed, 156 insertions, 11 deletions
diff --git a/.travis.yml b/.travis.yml
index 395937e..187a7f5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,4 +23,4 @@ script:
- ./configure
- make distcheck
after_failure:
- - cat genimage-*/_build/test-suite.log
+ - find -name test-suite.log -print0 | xargs -0 cat
diff --git a/Makefile.am b/Makefile.am
index 3c96229..d283212 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,6 +51,8 @@ EXTRA_DIST += \
test/cramfs.config \
test/ext2.config \
test/ext2test.dump \
+ test/ext2percent.config \
+ test/ext2test-percent.dump \
test/ext3.config \
test/ext3test.dump \
test/ext4.config \
diff --git a/README.rst b/README.rst
index 92ae9e8..e7c14e4 100644
--- a/README.rst
+++ b/README.rst
@@ -68,7 +68,11 @@ Here are all options for images:
:name: The name of this image. This is used for some image types
to set the name of the image.
-:size: Size of this image in bytes
+:size: Size of this image in bytes. 'k', 'M' or 'G' can be used as suffix to
+ specify the size in multiple of 1024 etc. If the image if filled from
+ a mountpoint then '%' as suffix indicates a percentage. '200%' means
+ the resulting filesystem should be about 50% filled. Note that is is
+ only a rough estimate based on the original size of the content.
:mountpoint: mountpoint if image refers to a filesystem image. The
default is "/". The content of "${rootpath}${mountpoint}"
will be used used fill the filesystem.
diff --git a/config.c b/config.c
index 3e5ab80..b0dd721 100644
--- a/config.c
+++ b/config.c
@@ -152,7 +152,22 @@ unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name)
unsigned long long val = 0;
if (str)
- val = strtoul_suffix(str, NULL, 0);
+ val = strtoul_suffix(str, NULL, NULL);
+
+ return val;
+}
+
+/*
+ * Like cfg_getint_suffix() but allow '%' as suffix as well
+ */
+unsigned long long cfg_getint_suffix_percent(cfg_t *sec, const char *name,
+ cfg_bool_t *percent)
+{
+ const char *str = cfg_getstr(sec, name);
+ unsigned long long val = 0;
+
+ if (str)
+ val = strtoul_suffix(str, NULL, percent);
return val;
}
diff --git a/genimage.c b/genimage.c
index 64a7b2e..ca2c6d6 100644
--- a/genimage.c
+++ b/genimage.c
@@ -157,6 +157,11 @@ static int image_setup(struct image *image)
image->seen = -1;
+ if (image->size_is_percent) {
+ image->size = image_dir_size(image) * image->size / 100;
+ image->size_is_percent = cfg_false;
+ }
+
list_for_each_entry(part, &image->partitions, list) {
struct image *child;
if (!part->image)
@@ -664,7 +669,8 @@ int main(int argc, char *argv[])
list_add_tail(&image->list, &images);
image->file = cfg_title(imagesec);
image->name = cfg_getstr(imagesec, "name");
- image->size = cfg_getint_suffix(imagesec, "size");
+ image->size = cfg_getint_suffix_percent(imagesec, "size",
+ &image->size_is_percent);
image->mountpoint = cfg_getstr(imagesec, "mountpoint");
image->exec_pre = cfg_getstr(imagesec, "exec-pre");
image->exec_post = cfg_getstr(imagesec, "exec-post");
@@ -717,6 +723,10 @@ int main(int argc, char *argv[])
if (ret)
goto cleanup;
+ ret = collect_mountpoints();
+ if (ret)
+ goto cleanup;
+
list_for_each_entry(image, &images, list) {
ret = image_setup(image);
if (ret)
@@ -731,10 +741,6 @@ int main(int argc, char *argv[])
if (ret)
goto cleanup;
- ret = collect_mountpoints();
- if (ret)
- goto cleanup;
-
list_for_each_entry(image, &images, list) {
ret = setenv_image(image);
if (ret)
diff --git a/genimage.h b/genimage.h
index e339d1d..1ebe1cd 100644
--- a/genimage.h
+++ b/genimage.h
@@ -51,6 +51,7 @@ struct image {
const char *name;
const char *file;
unsigned long long size;
+ cfg_bool_t size_is_percent;
const char *mountpoint;
const char *exec_pre;
const char *exec_post;
@@ -124,7 +125,8 @@ extern struct image_handler fit_handler;
(type *)( (char *)__mptr - offsetof(type,member) );})
void *xzalloc(size_t n);
-unsigned long long strtoul_suffix(const char *str, char **endp, int base);
+unsigned long long strtoul_suffix(const char *str, char **endp,
+ cfg_bool_t *percent);
int init_config(void);
cfg_opt_t *get_confuse_opts(void);
@@ -144,6 +146,8 @@ int insert_data(struct image *image, const char *data, const char *outfile,
int reload_partitions(struct image *image);
unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name);
+unsigned long long cfg_getint_suffix_percent(cfg_t *sec, const char *name,
+ cfg_bool_t *percent);
static inline const char *imageoutfile(const struct image *image)
{
@@ -154,6 +158,8 @@ int uuid_validate(const char *str);
void uuid_parse(const char *str, unsigned char *uuid);
char *uuid_random(void);
+unsigned long long image_dir_size(struct image *image);
+
uint32_t crc32(const void *data, size_t len);
#endif /* __PTX_IMAGE_H */
diff --git a/test/basic-images.test b/test/basic-images.test
index 9b53b45..cf6d68b 100755
--- a/test/basic-images.test
+++ b/test/basic-images.test
@@ -157,6 +157,11 @@ test_expect_success genext2fs,e2fsck "ext2" "
check_ext images/test.ext2 ext2test 4194304
"
+test_expect_success genext2fs,e2fsck "ext2percent" "
+ run_genimage ext2percent.config test.ext2 &&
+ check_ext images/test.ext2 ext2test-percent 69632
+"
+
test_expect_success genext2fs,e2fsck "ext3" "
run_genimage ext3.config test.ext3 &&
check_ext images/test.ext3 ext3test 4194304
diff --git a/test/ext2percent.config b/test/ext2percent.config
new file mode 100644
index 0000000..f9cd848
--- /dev/null
+++ b/test/ext2percent.config
@@ -0,0 +1,7 @@
+image test.ext2 {
+ ext2 {
+ label = "ext2test"
+ fs-timestamp = "20000101000000"
+ }
+ size = 100%
+}
diff --git a/test/ext2test-percent.dump b/test/ext2test-percent.dump
new file mode 100644
index 0000000..f771eb4
--- /dev/null
+++ b/test/ext2test-percent.dump
@@ -0,0 +1,40 @@
+Filesystem volume name: ext2test
+Last mounted on: <not available>
+Filesystem magic number: 0xEF53
+Filesystem revision #: 0 (original)
+Filesystem features: (none)
+Default mount options: (none)
+Filesystem state: clean
+Errors behavior: Unknown (continue)
+Filesystem OS type: Linux
+Inode count: 56
+Block count: 68
+Reserved block count: 3
+Free blocks: 36
+Free inodes: 5
+First block: 1
+Block size: 1024
+Fragment size: 1024
+Blocks per group: 72
+Fragments per group: 72
+Inodes per group: 56
+Inode blocks per group: 7
+Filesystem created: Sat Jan 1 00:00:00 2000
+Last mount time: n/a
+Last write time: Sat Jan 1 00:00:00 2000
+Mount count: 0
+Maximum mount count: 20
+Last checked: Sat Jan 1 00:00:00 2000
+Check interval: 0 (<none>)
+Reserved blocks uid: 0 (user root)
+Reserved blocks gid: 0 (group root)
+
+
+Group 0: (Blocks 1-67)
+ Primary superblock at 1, Group descriptors at 2-2
+ Block bitmap at 3 (+2)
+ Inode bitmap at 4 (+3)
+ Inode table at 5-11 (+4)
+ 36 free blocks, 5 free inodes, 18 directories
+ Free blocks: 32-67
+ Free inodes: 52-56
diff --git a/util.c b/util.c
index 2b91a94..71104a1 100644
--- a/util.c
+++ b/util.c
@@ -28,6 +28,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
+#include <dirent.h>
#include "genimage.h"
@@ -251,12 +252,16 @@ void *xzalloc(size_t n)
* Like simple_strtoul() but handles an optional G, M, K or k
* suffix for Gigabyte, Megabyte or Kilobyte
*/
-unsigned long long strtoul_suffix(const char *str, char **endp, int base)
+unsigned long long strtoul_suffix(const char *str, char **endp,
+ cfg_bool_t *percent)
{
unsigned long long val;
char *end;
- val = strtoull(str, &end, base);
+ val = strtoull(str, &end, 0);
+
+ if (percent)
+ *percent = cfg_false;
switch (*end) {
case 'G':
@@ -271,6 +276,12 @@ unsigned long long strtoul_suffix(const char *str, char **endp, int base)
end++;
case '\0':
break;
+ case '%':
+ if (percent) {
+ *percent = cfg_true;
+ break;
+ }
+ /* fall-through */
default:
error("Invalid size suffix '%s' in '%s'\n", end, str);
exit(1);
@@ -556,3 +567,52 @@ int reload_partitions(struct image *image)
close(fd);
return 0;
}
+
+#define ROUND_UP(num,align) ((((num) + ((align) - 1)) & ~((align) - 1)))
+
+static unsigned long long dir_size(struct image *image, int dirfd,
+ const char *subdir, size_t blocksize)
+{
+ struct dirent *d;
+ DIR *dir;
+ int fd;
+ unsigned long long size = 0;
+ struct stat st;
+
+ fd = openat(dirfd, subdir, O_RDONLY);
+ if (fd < 0) {
+ image_error(image, "failed to open '%s': %s", subdir,
+ strerror(errno));
+ return 0;
+ }
+
+ dir = fdopendir(dup(fd));
+ if (dir == NULL) {
+ image_error(image, "failed to opendir '%s': %s", subdir,
+ strerror(errno));
+ return 0;
+ }
+ while ((d = readdir(dir)) != NULL) {
+ if (d->d_type == DT_DIR) {
+ if (d->d_name[0] == '.' && (d->d_name[1] == '\0' ||
+ (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+ continue;
+ size += dir_size(image, fd, d->d_name, blocksize);
+ continue;
+ }
+ if (d->d_type != DT_REG)
+ continue;
+ if (fstatat(fd, d->d_name, &st, AT_NO_AUTOMOUNT) < 0) {
+ image_error(image, "failed to stat '%s': %s",
+ d->d_name, strerror(errno));
+ continue;
+ }
+ size += ROUND_UP(st.st_size, blocksize);
+ }
+ return size + blocksize;
+}
+
+unsigned long long image_dir_size(struct image *image)
+{
+ return dir_size(image, AT_FDCWD, mountpath(image), 4096);
+}