Skip to content

Commit

Permalink
Merge pull request #60 from michaelolbrich/percent
Browse files Browse the repository at this point in the history
allow percentages for image sizes
  • Loading branch information
michaelolbrich authored May 11, 2019
2 parents e685816 + 34aa92e commit ea09cdf
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
6 changes: 5 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
17 changes: 16 additions & 1 deletion config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
16 changes: 11 additions & 5 deletions genimage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion genimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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)
{
Expand All @@ -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 */
5 changes: 5 additions & 0 deletions test/basic-images.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions test/ext2percent.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
image test.ext2 {
ext2 {
label = "ext2test"
fs-timestamp = "20000101000000"
}
size = 100%
}
40 changes: 40 additions & 0 deletions test/ext2test-percent.dump
Original file line number Diff line number Diff line change
@@ -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
64 changes: 62 additions & 2 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <dirent.h>

#include "genimage.h"

Expand Down Expand Up @@ -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':
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

0 comments on commit ea09cdf

Please sign in to comment.