diff options
author | Michael Olbrich <m.olbrich@pengutronix.de> | 2014-08-17 09:45:00 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-08-18 18:25:30 +0200 |
commit | 1924a97db5d55b6537a6c6ef84944caab93cd19c (patch) | |
tree | f4c5580566022758bfeb0d6a8e14b40fb4a6318a /src/tmpfiles | |
parent | 630a4d9ea7298fb4a494662cbb4871069143ff56 (diff) |
tmpfiles: only execute chmod()/chown() when needed
This avoids errors like this, when the paths are already there with the
correct permissions and owner:
chmod(/var/spool) failed: Read-only file system
Diffstat (limited to 'src/tmpfiles')
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 79fd0b72e7..3bab7ac137 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -453,35 +453,39 @@ finish: } static int item_set_perms(Item *i, const char *path) { + struct stat st; + bool st_valid; + assert(i); assert(path); + st_valid = stat(path, &st) == 0; + /* not using i->path directly because it may be a glob */ if (i->mode_set) { mode_t m = i->mode; - if (i->mask_perms) { - struct stat st; - - if (stat(path, &st) >= 0) { - if (!(st.st_mode & 0111)) - m &= ~0111; - if (!(st.st_mode & 0222)) - m &= ~0222; - if (!(st.st_mode & 0444)) - m &= ~0444; - if (!S_ISDIR(st.st_mode)) - m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */ - } + if (i->mask_perms && st_valid) { + if (!(st.st_mode & 0111)) + m &= ~0111; + if (!(st.st_mode & 0222)) + m &= ~0222; + if (!(st.st_mode & 0444)) + m &= ~0444; + if (!S_ISDIR(st.st_mode)) + m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */ } - if (chmod(path, m) < 0) { - log_error("chmod(%s) failed: %m", path); - return -errno; + if (!st_valid || m != (st.st_mode & 07777)) { + if (chmod(path, m) < 0) { + log_error("chmod(%s) failed: %m", path); + return -errno; + } } } - if (i->uid_set || i->gid_set) + if ((!st_valid || (i->uid != st.st_uid || i->gid != st.st_gid)) && + (i->uid_set || i->gid_set)) if (chown(path, i->uid_set ? i->uid : (uid_t) -1, i->gid_set ? i->gid : (gid_t) -1) < 0) { |