Moves some logic from the recursive directory traversal into a helper function to make it easier to add support for regular files. Does not change functionality. Signed-off-by: Arvind Raghavan <raghavan.arvind@xxxxxxxxx> Signed-off-by: Jayashree Mohan <jaya@xxxxxxxxxxxxx> Signed-off-by: Vijay Chidambaram <vijay@xxxxxxxxxxxxx> --- Includes change to fstatat instead of fchdir and lstat. src/fssum.c | 265 ++++++++++++++++++++++++++++------------------------ 1 file changed, 141 insertions(+), 124 deletions(-) diff --git a/src/fssum.c b/src/fssum.c index 30f456c2..81e5cf5d 100644 --- a/src/fssum.c +++ b/src/fssum.c @@ -503,6 +503,10 @@ malformed: excess_file(fn); } +void +sum_one(int dirfd, int level, sum_t *dircs, char *path_prefix, + char *path_in, char *name); + void sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in) { @@ -513,8 +517,6 @@ sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in) int entries = 0; int i; int ret; - int fd; - int excl; struct stat64 dir_st; if (fstat64(dirfd, &dir_st)) { @@ -549,152 +551,167 @@ sum(int dirfd, int level, sum_t *dircs, char *path_prefix, char *path_in) qsort(namelist, entries, sizeof(*namelist), namecmp); for (i = 0; i < entries; ++i) { struct stat64 st; - sum_t cs; - sum_t meta; - char *path; - - sum_init(&cs); - sum_init(&meta); - path = alloc(strlen(path_in) + strlen(namelist[i]) + 3); - sprintf(path, "%s/%s", path_in, namelist[i]); - for (excl = 0; excl < n_excludes; ++excl) { - if (strncmp(excludes[excl].path, path, - excludes[excl].len) == 0) - goto next; - } - ret = fchdir(dirfd); - if (ret == -1) { - perror("fchdir"); - exit(-1); - } - ret = lstat64(namelist[i], &st); + ret = fstatat64(dirfd, namelist[i], &st, AT_SYMLINK_NOFOLLOW); if (ret) { - fprintf(stderr, "stat failed for %s/%s: %s\n", - path_prefix, path, strerror(errno)); + fprintf(stderr, "stat failed for %s/%s/%s: %s\n", + path_prefix, path_in, namelist[i], + strerror(errno)); exit(-1); } /* We are crossing into a different subvol, skip this subtree. */ if (st.st_dev != dir_st.st_dev) - goto next; - - sum_add_u64(&meta, level); - sum_add(&meta, namelist[i], strlen(namelist[i])); - if (!S_ISDIR(st.st_mode)) - sum_add_u64(&meta, st.st_nlink); - if (flags[FLAG_UID]) - sum_add_u64(&meta, st.st_uid); - if (flags[FLAG_GID]) - sum_add_u64(&meta, st.st_gid); - if (flags[FLAG_MODE]) - sum_add_u64(&meta, st.st_mode); - if (flags[FLAG_ATIME]) - sum_add_time(&meta, st.st_atime); - if (flags[FLAG_MTIME]) - sum_add_time(&meta, st.st_mtime); - if (flags[FLAG_CTIME]) - sum_add_time(&meta, st.st_ctime); - if (flags[FLAG_XATTRS] && - (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))) { - fd = openat(dirfd, namelist[i], 0); - if (fd == -1 && flags[FLAG_OPEN_ERROR]) { - sum_add_u64(&meta, errno); - } else if (fd == -1) { - fprintf(stderr, "open failed for %s/%s: %s\n", - path_prefix, path, strerror(errno)); + continue; + + sum_one(dirfd, level, dircs, path_prefix, path_in, namelist[i]); + } +} + +void +sum_one(int dirfd, int level, sum_t *dircs, char *path_prefix, + char *path_in, char *name) { + sum_t cs; + sum_t meta; + int fd; + int ret; + int excl; + char* path; + struct stat64 st; + + sum_init(&cs); + sum_init(&meta); + path = alloc(strlen(path_in) + strlen(name) + 3); + sprintf(path, "%s/%s", path_in, name); + for (excl = 0; excl < n_excludes; ++excl) { + if (strncmp(excludes[excl].path, path, + excludes[excl].len) == 0) + goto out; + } + + ret = fstatat64(dirfd, name, &st, AT_SYMLINK_NOFOLLOW); + if (ret) { + fprintf(stderr, "stat failed for %s/%s: %s\n", + path_prefix, path, strerror(errno)); + exit(-1); + } + + sum_add_u64(&meta, level); + sum_add(&meta, name, strlen(name)); + if (!S_ISDIR(st.st_mode)) + sum_add_u64(&meta, st.st_nlink); + if (flags[FLAG_UID]) + sum_add_u64(&meta, st.st_uid); + if (flags[FLAG_GID]) + sum_add_u64(&meta, st.st_gid); + if (flags[FLAG_MODE]) + sum_add_u64(&meta, st.st_mode); + if (flags[FLAG_ATIME]) + sum_add_time(&meta, st.st_atime); + if (flags[FLAG_MTIME]) + sum_add_time(&meta, st.st_mtime); + if (flags[FLAG_CTIME]) + sum_add_time(&meta, st.st_ctime); + if (flags[FLAG_XATTRS] && + (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))) { + fd = openat(dirfd, name, 0); + if (fd == -1 && flags[FLAG_OPEN_ERROR]) { + sum_add_u64(&meta, errno); + } else if (fd == -1) { + fprintf(stderr, "open failed for %s/%s: %s\n", + path_prefix, path, strerror(errno)); + exit(-1); + } else { + ret = sum_xattrs(fd, &meta); + close(fd); + if (ret < 0) { + fprintf(stderr, + "failed to read xattrs from " + "%s/%s: %s\n", + path_prefix, path, + strerror(-ret)); exit(-1); - } else { - ret = sum_xattrs(fd, &meta); - close(fd); - if (ret < 0) { - fprintf(stderr, - "failed to read xattrs from " - "%s/%s: %s\n", - path_prefix, path, - strerror(-ret)); - exit(-1); - } } } - if (S_ISDIR(st.st_mode)) { - fd = openat(dirfd, namelist[i], 0); + } + if (S_ISDIR(st.st_mode)) { + fd = openat(dirfd, name, 0); + if (fd == -1 && flags[FLAG_OPEN_ERROR]) { + sum_add_u64(&meta, errno); + } else if (fd == -1) { + fprintf(stderr, "open failed for %s/%s: %s\n", + path_prefix, path, strerror(errno)); + exit(-1); + } else { + sum(fd, level + 1, &cs, path_prefix, path); + close(fd); + } + } else if (S_ISREG(st.st_mode)) { + sum_add_u64(&meta, st.st_size); + if (flags[FLAG_DATA]) { + if (verbose) + fprintf(stderr, "file %s\n", + name); + fd = openat(dirfd, name, 0); if (fd == -1 && flags[FLAG_OPEN_ERROR]) { sum_add_u64(&meta, errno); } else if (fd == -1) { - fprintf(stderr, "open failed for %s/%s: %s\n", - path_prefix, path, strerror(errno)); + fprintf(stderr, + "open failed for %s/%s: %s\n", + path_prefix, path, + strerror(errno)); exit(-1); - } else { - sum(fd, level + 1, &cs, path_prefix, path); - close(fd); } - } else if (S_ISREG(st.st_mode)) { - sum_add_u64(&meta, st.st_size); - if (flags[FLAG_DATA]) { - if (verbose) - fprintf(stderr, "file %s\n", - namelist[i]); - fd = openat(dirfd, namelist[i], 0); - if (fd == -1 && flags[FLAG_OPEN_ERROR]) { - sum_add_u64(&meta, errno); - } else if (fd == -1) { + if (fd != -1) { + ret = sum_file_data(fd, &cs); + if (ret < 0) { fprintf(stderr, - "open failed for %s/%s: %s\n", + "read failed for " + "%s/%s: %s\n", path_prefix, path, strerror(errno)); exit(-1); } - if (fd != -1) { - ret = sum_file_data(fd, &cs); - if (ret < 0) { - fprintf(stderr, - "read failed for " - "%s/%s: %s\n", - path_prefix, path, - strerror(errno)); - exit(-1); - } - close(fd); - } - } - } else if (S_ISLNK(st.st_mode)) { - ret = readlink(namelist[i], buf, sizeof(buf)); - if (ret == -1) { - perror("readlink"); - exit(-1); + close(fd); } - sum_add(&cs, buf, ret); - } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { - sum_add_u64(&cs, major(st.st_rdev)); - sum_add_u64(&cs, minor(st.st_rdev)); } - sum_fini(&cs); - sum_fini(&meta); - if (gen_manifest || in_manifest) { - char *fn; - char *m; - char *c; - - if (S_ISDIR(st.st_mode)) - strcat(path, "/"); - fn = escape(path); - m = sum_to_string(&meta); - c = sum_to_string(&cs); - - if (gen_manifest) - fprintf(out_fp, "%s %s %s\n", fn, m, c); - if (in_manifest) - check_manifest(fn, m, c, 0); - free(c); - free(m); - free(fn); + } else if (S_ISLNK(st.st_mode)) { + ret = readlink(name, buf, sizeof(buf)); + if (ret == -1) { + perror("readlink"); + exit(-1); } - sum_add_sum(dircs, &cs); - sum_add_sum(dircs, &meta); -next: - free(path); + sum_add(&cs, buf, ret); + } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { + sum_add_u64(&cs, major(st.st_rdev)); + sum_add_u64(&cs, minor(st.st_rdev)); } + sum_fini(&cs); + sum_fini(&meta); + if (gen_manifest || in_manifest) { + char *fn; + char *m; + char *c; + + if (S_ISDIR(st.st_mode)) + strcat(path, "/"); + fn = escape(path); + m = sum_to_string(&meta); + c = sum_to_string(&cs); + + if (gen_manifest) + fprintf(out_fp, "%s %s %s\n", fn, m, c); + if (in_manifest) + check_manifest(fn, m, c, 0); + free(c); + free(m); + free(fn); + } + sum_add_sum(dircs, &cs); + sum_add_sum(dircs, &meta); + +out: + free(path); } int -- 2.20.1