summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2015-04-30 20:50:38 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2015-05-06 00:10:40 -0400
commitf44b28fda0a9ac88b0b20c475fc1d2f2036e7f71 (patch)
tree0bda1fdfee07ce2c190d2a45a179617190c24762
parent3e7f33ada92ccc9da96b2b1c9af1f123d09ad954 (diff)
tmpfiles: try to handle read-only file systems gracefully
On read-only filesystems trying to create the target will not fail with EEXIST but with EROFS. Handle EROFS by checking if the target already exists, and if empty when truncating. This avoids reporting errors if tmpfiles doesn't actually needs to do anything. [zj: revert condition to whitelist rather then blacklisting, and add goto to avoid stat'ting twice.]
-rw-r--r--src/tmpfiles/tmpfiles.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index d574254e0..640ad4788 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -984,8 +984,12 @@ static int write_one_file(Item *i, const char *path) {
return 0;
}
- log_error_errno(errno, "Failed to create file %s: %m", path);
- return -errno;
+ r = -errno;
+ if (!i->argument && errno == EROFS && stat(path, &st) == 0 &&
+ (i->type == CREATE_FILE || st.st_size == 0))
+ goto check_mode;
+
+ return log_error_errno(r, "Failed to create file %s: %m", path);
}
if (i->argument) {
@@ -1012,6 +1016,7 @@ static int write_one_file(Item *i, const char *path) {
if (stat(path, &st) < 0)
return log_error_errno(errno, "stat(%s) failed: %m", path);
+ check_mode:
if (!S_ISREG(st.st_mode)) {
log_error("%s is not a file.", path);
return -EEXIST;
@@ -1154,6 +1159,10 @@ static int create_item(Item *i) {
log_debug("Copying tree \"%s\" to \"%s\".", resolved, i->path);
r = copy_tree(resolved, i->path, false);
+
+ if (r == -EROFS && stat(i->path, &st) == 0)
+ r = -EEXIST;
+
if (r < 0) {
struct stat a, b;