From 1b85dcd9cabd478859e46bcfc9f7847acec98db6 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 20 Sep 2010 13:10:36 +0200 Subject: [PATCH] mount: rewrite is_readonly() This new implementation is more optimistic and always calls access(2). The fallback solution (modify atime by futimens(2)) should be used very rarely. Signed-off-by: Karel Zak --- mount/mount.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/mount/mount.c b/mount/mount.c index 84986e36..22828b4e 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -1308,38 +1308,46 @@ cdrom_setspeed(const char *spec) { } /* - * Check if @node is read-only filesystem by access() or futimens(). - * - * Note that access(2) uses real-UID (= useless for suid programs) - * and euidaccess(2) does not check for read-only FS. + * Check if @path is on read-only filesystem independently on file permissions. */ static int -is_readonly(const char *node) +is_readonly(const char *path) { - int res = 0; + int fd; + + if (access(path, W_OK) == 0) + return 0; + if (errno == EROFS) + return 1; + if (errno != EACCES) + return 0; - if (getuid() == geteuid()) { - if (access(node, W_OK) == -1 && errno == EROFS) - res = 1; - } #ifdef HAVE_FUTIMENS - else { + /* + * access(2) returns EACCES on read-only FS: + * + * - for set-uid application if one component of the path is not + * accessible for the current rUID. (Note that euidaccess(2) does not + * check for EROFS at all). + * + * - for read-write filesystem with read-only VFS node (aka -o remount,ro,bind) + */ + fd = open(path, O_RDONLY); + if (fd >= 0) { struct timespec times[2]; - int fd = open(node, O_RDONLY); - - if (fd < 0) - goto done; + int errsv = 0; times[0].tv_nsec = UTIME_NOW; /* atime */ times[1].tv_nsec = UTIME_OMIT; /* mtime */ - if (futimens(fd, times) == -1 && errno == EROFS) - res = 1; + if (futimens(fd, times) == -1) + errsv = errno; close(fd); + + return errsv == EROFS; } -done: #endif - return res; + return 0; } /* -- 2.39.5