diff options
author | Michael Olbrich <m.olbrich@pengutronix.de> | 2019-05-06 08:50:05 +0200 |
---|---|---|
committer | Michael Olbrich <m.olbrich@pengutronix.de> | 2019-05-06 08:59:08 +0200 |
commit | 393897209665117e32360d5346bc1d3960f40a41 (patch) | |
tree | 26f40ab91b9763f6915a4b542f6163193e7f660e | |
parent | e2f88d5af04413b61be4fce9176627ef71171677 (diff) | |
download | genimage-393897209665117e32360d5346bc1d3960f40a41.tar.gz genimage-393897209665117e32360d5346bc1d3960f40a41.tar.xz |
util: add helper to calculate directory size
Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
-rw-r--r-- | genimage.h | 2 | ||||
-rw-r--r-- | util.c | 50 |
2 files changed, 52 insertions, 0 deletions
@@ -157,6 +157,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 */ @@ -28,6 +28,7 @@ #include <unistd.h> #include <fcntl.h> #include <ctype.h> +#include <dirent.h> #include "genimage.h" @@ -566,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); +} |