* mount planned read-write, but loopdev is read-only,
* let's fix mount options...
*/
- cxt->mountflags |= MS_RDONLY;
-
+ mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY);
/* we have to keep the device open until mount(1),
* otherwise it will auto-cleared by kernel
rc = mnt_fs_set_fstype(fs, try_type);
}
- /* TODO: check if the result is really read-only/read-write
- * and if necessary update cxt->mountflags
- */
-
return rc;
}
int mnt_context_do_mount(struct libmnt_context *cxt)
{
const char *type;
+ int res;
assert(cxt);
assert(cxt->fs);
type = mnt_fs_get_fstype(cxt->fs);
if (type)
- return do_mount(cxt, NULL);
+ res = do_mount(cxt, NULL);
+ else
+ res = do_mount_by_pattern(cxt, cxt->fstype_pattern);
+
+ if (mnt_context_get_status(cxt)
+ && !(cxt->flags & MNT_FL_FAKE)
+ && !cxt->helper) {
+ /*
+ * Mounted by mount(2), do some post-mount checks
+ *
+ * Kernel allows to use MS_RDONLY for bind mounts, but the
+ * read-only request could be silently ignored. Check it to
+ * avoid 'ro' in mtab and 'rw' in /proc/mounts.
+ */
+ if ((cxt->mountflags & MS_BIND)
+ && (cxt->mountflags & MS_RDONLY)
+ && !mnt_is_readonly(mnt_context_get_target(cxt)))
+
+ mnt_context_set_mflags(cxt,
+ cxt->mountflags & ~MS_RDONLY);
+
+
+ /* Kernel can silently add MS_RDONLY flag when mounting file
+ * system that does not have write support. Check this to avoid
+ * 'ro' in /proc/mounts and 'rw' in mtab.
+ */
+ if (!(cxt->mountflags & (MS_RDONLY | MS_PROPAGATION | MS_MOVE))
+ && mnt_is_readonly(mnt_context_get_target(cxt)))
+
+ mnt_context_set_mflags(cxt,
+ cxt->mountflags | MS_RDONLY);
+ }
- return do_mount_by_pattern(cxt, cxt->fstype_pattern);
+ return res;
}
/**
extern int endswith(const char *s, const char *sx);
extern int startswith(const char *s, const char *sx);
+extern int mnt_is_readonly(const char *path);
+
extern int mnt_parse_offset(const char *str, size_t len, uintmax_t *res);
extern int mnt_chdir_to_parent(const char *target, char **filename);
return rc;
}
+/*
+ * Check if @path is on read-only filesystem independently on file permissions.
+ */
+int mnt_is_readonly(const char *path)
+{
+ if (access(path, W_OK) == 0)
+ return 0;
+ if (errno == EROFS)
+ return 1;
+ if (errno != EACCES)
+ return 0;
+
+#ifdef HAVE_FUTIMENS
+ /*
+ * 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)
+ */
+ {
+ struct timespec times[2];
+
+ times[0].tv_nsec = UTIME_NOW; /* atime */
+ times[1].tv_nsec = UTIME_OMIT; /* mtime */
+
+ if (utimensat(AT_FDCWD, path, times, 0) == -1)
+ return errno == EROFS;
+ }
+#endif
+ return 0;
+}
+
/**
* mnt_mangle:
* @str: string