diff options
author | Alexander Larsson <alexl@redhat.com> | 2018-03-14 15:22:12 +0100 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-03-16 22:07:13 +0000 |
commit | 1e90a18a085e324b821a8bd0dc28a27082e43634 (patch) | |
tree | 563dbd09053d11ca8689dba24bfa61266f32fc3c /utils.c | |
parent | 3c488585bd9897c842c1708ddb413adee5a9b43a (diff) | |
download | bubblewrap-1e90a18a085e324b821a8bd0dc28a27082e43634.tar.gz |
Don't rely on mkdir returning EEXISTS (fixing NFS)
For NFS mounts if we call mkdir() on a read-only mount (such as when
we've created a read-only bind mount) the kernel will nor return EEXIST
even when the directory exists, instead returning EROFS.
So, we add (and use) an ensure_dir() helper that stats before calling
mkdir.
Closes: #258
Approved by: giuseppe
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 43 |
1 files changed, 31 insertions, 12 deletions
@@ -434,7 +434,7 @@ ensure_file (const char *path, /* We check this ahead of time, otherwise the create file will fail in the read-only - case with EROFD instead of EEXIST */ + case with EROFS instead of EEXIST */ if (stat (path, &buf) == 0 && S_ISREG (buf.st_mode)) return 0; @@ -593,6 +593,34 @@ get_file_mode (const char *pathname) return buf.st_mode & S_IFMT; } +int +ensure_dir (const char *path, + mode_t mode) +{ + struct stat buf; + + /* We check this ahead of time, otherwise + the mkdir call can fail in the read-only + case with EROFS instead of EEXIST on some + filesystems (such as NFS) */ + if (stat (path, &buf) == 0) + { + if (!S_ISDIR (buf.st_mode)) + { + errno = ENOTDIR; + return -1; + } + + return 0; + } + + if (mkdir (path, mode) == -1 && errno != EEXIST) + return -1; + + return 0; +} + + /* Sets errno on error (!= 0) */ int mkdir_with_parents (const char *pathname, @@ -601,7 +629,6 @@ mkdir_with_parents (const char *pathname, { cleanup_free char *fn = NULL; char *p; - struct stat buf; if (pathname == NULL || *pathname == '\0') { @@ -628,16 +655,8 @@ mkdir_with_parents (const char *pathname, if (!create_last && p == NULL) break; - if (stat (fn, &buf) != 0) - { - if (mkdir (fn, mode) == -1 && errno != EEXIST) - return -1; - } - else if (!S_ISDIR (buf.st_mode)) - { - errno = ENOTDIR; - return -1; - } + if (ensure_dir (fn, mode) != 0) + return -1; if (p) { |