diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-01-09 11:59:14 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-07-20 16:34:24 -0400 |
commit | 4bff1c34db3c37c4875454b3c647eaa933fee9c9 (patch) | |
tree | f51234a184dc23e74b6749351b8d3414f1fbe248 | |
parent | 6d702f0efb494d46be36c4b1855dc3bfe559bee5 (diff) |
-rw-r--r-- | setproject.c | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/setproject.c b/setproject.c index b1c0c2a..5f6e4bf 100644 --- a/setproject.c +++ b/setproject.c @@ -30,6 +30,10 @@ struct fsxattr { }; #endif +#ifndef BCHFS_IOC_REINHERIT_ATTRS +#define BCHFS_IOC_REINHERIT_ATTRS _IOR(0xbc, 64, const char *) +#endif + #include "pot.h" #include "common.h" @@ -92,23 +96,8 @@ success: return id; } -static void setproject_recurse(const char *path, unsigned id) +static void do_setproject(int fd, unsigned id) { - struct stat st; - if (stat(path, &st)) { - errstr(_("error statting %s: %m"), path); - return; - } - - if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) - return; - - int fd = open(path, O_RDONLY|O_NOATIME); - if (fd < 0) { - errstr(_("error opening %s: %m"), path); - return; - } - struct fsxattr fa; if (ioctl(fd, FS_IOC_FSGETXATTR, &fa)) @@ -118,26 +107,68 @@ static void setproject_recurse(const char *path, unsigned id) if (ioctl(fd, FS_IOC_FSSETXATTR, &fa)) die(1, _("FS_IOC_FSSETXATTR error\n")); +} - if (S_ISDIR(st.st_mode)) { - DIR *dir = fdopendir(fd); - struct dirent *d; +static void setproject_recurse(int dirfd, unsigned id, unsigned dev) +{ + DIR *dir = fdopendir(dirfd); + struct dirent *d; - while ((errno = 0), (d = readdir(dir))) { - if (!strcmp(d->d_name, ".") || - !strcmp(d->d_name, "..")) - continue; + while ((errno = 0), (d = readdir(dir))) { + if (!strcmp(d->d_name, ".") || + !strcmp(d->d_name, "..")) + continue; - char *child = malloc(strlen(path) + strlen(d->d_name) + 2); - if (!child) - die(1, _("malloc error\n")); + struct stat st; + if (fstatat(dirfd, d->d_name, &st, AT_SYMLINK_NOFOLLOW)) { + errstr(_("error statting %s: %m"), d->d_name); + errno = 0; + continue; + } + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + continue; - sprintf(child, "%s/%s", path, d->d_name); - setproject_recurse(child, id); - free(child); + int fd = openat(dirfd, d->d_name, AT_SYMLINK_NOFOLLOW); + if (fd < 0) { + errstr(_("error opening %s: %m"), d->d_name); + errno = 0; + continue; } + + if (st.st_dev != dev || + ioctl(dirfd, BCHFS_IOC_REINHERIT_ATTRS, d->d_name) < 0) + do_setproject(fd, id); + + if (S_ISDIR(st.st_mode)) + setproject_recurse(fd, id, st.st_dev); + + close(fd); + } +} + +static void setproject(const char *path, unsigned id) +{ + int fd = open(path, O_RDONLY|O_NOATIME); + if (fd < 0) { + errstr(_("error opening %s: %m"), path); + return; + } + + struct stat st; + if (fstat(fd, &st)) { + errstr(_("error statting %s: %m"), path); + return; } + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return; + + do_setproject(fd, id); + + if (S_ISDIR(st.st_mode)) + setproject_recurse(fd, id, st.st_dev); + close(fd); } @@ -192,7 +223,7 @@ int main(int argc, char *argv[]) unsigned i, project_id = project_name_to_id(project_name, create); for (i = 0; i < argc; i++) - setproject_recurse(argv[i], project_id); + setproject(argv[i], project_id); return 0; } |