summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2014-08-17 09:45:00 +0200
committerLennart Poettering <lennart@poettering.net>2014-08-18 18:25:30 +0200
commit1924a97db5d55b6537a6c6ef84944caab93cd19c (patch)
treef4c5580566022758bfeb0d6a8e14b40fb4a6318a
parent630a4d9ea7298fb4a494662cbb4871069143ff56 (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
-rw-r--r--src/tmpfiles/tmpfiles.c38
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) {