From c3dd820adff53837967e62497fa903bc9ff6b167 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 19 Feb 2016 10:51:37 +0100 Subject: When creating file bind mount destinations, check if they already exist If they already exist as a regular file then we don't need to create it, which is good because doing so would break if the filesystem is readonly. I.e. that returns EROFS instead of EEXISTS in that case. --- bubblewrap.c | 4 ++-- utils.c | 20 ++++++++++++++++++++ utils.h | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/bubblewrap.c b/bubblewrap.c index c016992..cbfe70d 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -550,7 +550,7 @@ setup_newroot (bool unshare_pid, } else { - if (create_file (dest, 0666, NULL) != 0 && errno != EEXIST) + if (ensure_file (dest, 0666) != 0) die_with_error ("Can't create file at %s", op->dest); } @@ -617,7 +617,7 @@ setup_newroot (bool unshare_pid, } else { - if (create_file (dst_path, 0666, NULL) != 0) + if (ensure_file (dst_path, 0666) != 0) die_with_error ("Can't create file at %s", dst_path); } diff --git a/utils.c b/utils.c index 55fd700..b459c63 100644 --- a/utils.c +++ b/utils.c @@ -330,6 +330,26 @@ create_file (const char *path, return res; } +int +ensure_file (const char *path, + mode_t mode) +{ + struct stat buf; + + /* We check this ahead of time, otherwise + the create file will fail in the read-only + case with EROFD instead of EEXIST */ + if (stat (path, &buf) == 0 && + S_ISREG (buf.st_mode)) + return 0; + + if (create_file (path, mode, NULL) != 0 && errno != EEXIST) + return -1; + + return 0; +} + + #define BUFSIZE 8192 /* Sets errno on error (!= 0), ENOSPC on short write */ int diff --git a/utils.h b/utils.h index 915bed3..1cfe93a 100644 --- a/utils.h +++ b/utils.h @@ -89,6 +89,8 @@ int copy_file (const char *src_path, int create_file (const char *path, mode_t mode, const char *content); +int ensure_file (const char *path, + mode_t mode); int get_file_mode (const char *pathname); int mkdir_with_parents (const char *pathname, int mode, -- cgit v1.2.1