Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow percentages for image sizes #60

Merged
merged 4 commits into from
May 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}