summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2019-05-06 08:50:05 +0200
committerMichael Olbrich <m.olbrich@pengutronix.de>2019-05-06 08:59:08 +0200
commit393897209665117e32360d5346bc1d3960f40a41 (patch)
tree26f40ab91b9763f6915a4b542f6163193e7f660e
parente2f88d5af04413b61be4fce9176627ef71171677 (diff)
downloadgenimage-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.h2
-rw-r--r--util.c50
2 files changed, 52 insertions, 0 deletions
diff --git a/genimage.h b/genimage.h
index 1e87602..2559511 100644
--- a/genimage.h
+++ b/genimage.h
@@ -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 */
diff --git a/util.c b/util.c
index 3202b26..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"
@@ -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);
+}