diff options
Diffstat (limited to 'libmount')
-rw-r--r-- | libmount/docs/libmount-sections.txt | 14 | ||||
-rw-r--r-- | libmount/src/context.c | 144 | ||||
-rw-r--r-- | libmount/src/context_mount.c | 358 | ||||
-rw-r--r-- | libmount/src/context_umount.c | 80 | ||||
-rw-r--r-- | libmount/src/libmount.h.in | 78 | ||||
-rw-r--r-- | libmount/src/libmount.sym | 7 | ||||
-rw-r--r-- | libmount/src/mountP.h | 20 |
7 files changed, 698 insertions, 3 deletions
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 78d89cae7..9c6ff2463 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -35,9 +35,12 @@ mnt_context_enable_fork mnt_context_enable_lazy mnt_context_enable_loopdel mnt_context_enable_rdonly_umount +mnt_context_enable_rwonly_mount mnt_context_enable_sloppy mnt_context_enable_verbose +mnt_context_forced_rdonly mnt_context_get_cache +mnt_context_get_excode mnt_context_get_fs mnt_context_get_fstab mnt_context_get_fstab_userdata @@ -72,6 +75,7 @@ mnt_context_is_nomtab mnt_context_is_parent mnt_context_is_rdonly_umount mnt_context_is_restricted +mnt_context_is_rwonly_mount mnt_context_is_sloppy mnt_context_is_swapmatch mnt_context_is_verbose @@ -105,6 +109,15 @@ MNT_ERR_NOFSTAB MNT_ERR_NOFSTYPE MNT_ERR_NOSOURCE MNT_ERR_LOOPOVERLAP +<SUBSECTION> +MNT_EX_SUCCESS +MNT_EX_USAGE +MNT_EX_SYSERR +MNT_EX_SOFTWARE +MNT_EX_USER +MNT_EX_FILEIO +MNT_EX_FAIL +MNT_EX_SOMEOK </SECTION> <SECTION> @@ -130,6 +143,7 @@ MNT_MS_UHELPER MNT_MS_USER MNT_MS_USERS MNT_MS_XCOMMENT +MNT_MS_XFSTABCOMM <SUBSECTION> MS_BIND MS_DIRSYNC diff --git a/libmount/src/context.c b/libmount/src/context.c index e731749b4..38e036330 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -172,8 +172,10 @@ int mnt_reset_context(struct libmnt_context *cxt) cxt->flags |= (fl & MNT_FL_FORCE); cxt->flags |= (fl & MNT_FL_NOCANONICALIZE); cxt->flags |= (fl & MNT_FL_RDONLY_UMOUNT); + cxt->flags |= (fl & MNT_FL_RWONLY_MOUNT); cxt->flags |= (fl & MNT_FL_NOSWAPMATCH); cxt->flags |= (fl & MNT_FL_TABPATHS_CHECKED); + return 0; } @@ -478,6 +480,48 @@ int mnt_context_is_rdonly_umount(struct libmnt_context *cxt) } /** + * mnt_context_enable_rwonly_mount: + * @cxt: mount context + * @enable: TRUE or FALSE + * + * Force read-write mount; if enabled libmount will never try MS_RDONLY + * after failed mount(2) EROFS. (See mount(8) man page, option -w). + * + * Returns: 0 on success, negative number in case of error. + */ +int mnt_context_enable_rwonly_mount(struct libmnt_context *cxt, int enable) +{ + return set_flag(cxt, MNT_FL_RWONLY_MOUNT, enable); +} + +/** + * mnt_context_is_rwonly_mount + * @cxt: mount context + * + * See also mnt_context_enable_rwonly_mount() and mount(8) man page, + * option -w. + * + * Returns: 1 if only read-write mount is allowed. + */ +int mnt_context_is_rwonly_mount(struct libmnt_context *cxt) +{ + return cxt->flags & MNT_FL_RWONLY_MOUNT ? 1 : 0; +} + +/** + * mnt_context_forced_rdonly: + * @cxt: mount context + * + * See also mnt_context_enable_rwonly_mount(). + * + * Returns: 1 if mounted read-only on write-protected device. + */ +int mnt_context_forced_rdonly(struct libmnt_context *cxt) +{ + return cxt->flags & MNT_FL_FORCED_RDONLY ? 1 : 0; +} + +/** * mnt_context_disable_helpers: * @cxt: mount context * @disable: TRUE or FALSE @@ -2002,8 +2046,10 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt) if (!cxt || !cxt->fs) return -EINVAL; - if (mnt_context_tab_applied(cxt)) /* already applied */ + if (mnt_context_tab_applied(cxt)) { /* already applied */ + DBG(CXT, ul_debugobj(cxt, "fstab already applied -- skip")); return 0; + } if (mnt_context_is_restricted(cxt)) { DBG(CXT, ul_debugobj(cxt, "force fstab usage for non-root users!")); @@ -2216,7 +2262,7 @@ int mnt_context_set_syscall_status(struct libmnt_context *cxt, int status) * @buf: buffer * @bufsiz: size of the buffer * - * Not implemented yet. + * Not implemented, deprecated in favor or mnt_context_get_excode(). * * Returns: 0 or negative number in case of error. */ @@ -2228,6 +2274,100 @@ int mnt_context_strerror(struct libmnt_context *cxt __attribute__((__unused__)), return 0; } + +int mnt_context_get_generic_excode(int rc, char *buf, size_t bufsz, char *fmt, ...) +{ + va_list va; + + if (rc == 0) + return MNT_EX_SUCCESS; + + va_start(va, fmt); + + /* we need to support "%m" */ + errno = rc < 0 ? -rc : rc; + + if (buf) + vsnprintf(buf, bufsz, fmt, va); + + switch (errno) { + case EINVAL: + case EPERM: + rc = MNT_EX_USAGE; + break; + case ENOMEM: + rc = MNT_EX_SYSERR; + break; + default: + rc = MNT_EX_FAIL; + break; + } + va_end(va); + return rc; +} + +/** + * mnt_context_get_excode: + * @cxt: context + * @rc: return code of the previous operation + * @buf: buffer to print error message (optional) + * @bufsz: size of the buffer + * + * This function analyzes context, [u]mount syscall and external helper status + * and @mntrc and generates unified return code (see MNT_EX_*) as expected + * from mount(8) or umount(8). + * + * If the external helper (e.g. /sbin/mount.type) has been executed than it + * returns status from wait() of the helper. It's not libmount fail if helper + * returns some crazy undocumented codes... See mnt_context_helper_executed() + * and mnt_context_get_helper_status(). Note that mount(8) and umount(8) utils + * always return code from helper without extra care about it. + * + * If the argument @buf is not NULL then error message is generated (if + * anything failed). + * + * The @mntrc is usually return code from mnt_context_mount(), + * mnt_context_umount(), or 'mntrc' as returned by mnt_context_next_mount(). + * + * Returns: MNT_EX_* codes. + */ +int mnt_context_get_excode( + struct libmnt_context *cxt, + int rc, + char *buf, + size_t bufsz) +{ + if (buf) { + *buf = '\0'; /* for sure */ + + if (!cxt->enabled_textdomain) { + bindtextdomain(LIBMOUNT_TEXTDOMAIN, LOCALEDIR); + cxt->enabled_textdomain = 1; + } + } + + switch (cxt->action) { + case MNT_ACT_MOUNT: + rc = mnt_context_get_mount_excode(cxt, rc, buf, bufsz); + break; + case MNT_ACT_UMOUNT: + rc = mnt_context_get_umount_excode(cxt, rc, buf, bufsz); + break; + default: + if (rc) + rc = mnt_context_get_generic_excode(rc, buf, bufsz, + _("operation failed: %m")); + else + rc = MNT_EX_SUCCESS; + break; + } + + DBG(CXT, ul_debugobj(cxt, "excode: rc=%d message=\"%s\"", rc, + buf ? buf : "<no-message>")); + return rc; +} + + /** * mnt_context_init_helper * @cxt: mount context diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 6368e9ba8..9caee70e5 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -1083,6 +1083,7 @@ int mnt_context_mount(struct libmnt_context *cxt) assert(cxt->helper_exec_status == 1); assert(cxt->syscall_status == 1); +again: rc = mnt_context_prepare_mount(cxt); if (!rc) rc = mnt_context_prepare_update(cxt); @@ -1090,6 +1091,32 @@ int mnt_context_mount(struct libmnt_context *cxt) rc = mnt_context_do_mount(cxt); if (!rc) rc = mnt_context_update_tabs(cxt); + + /* + * Read-only device; try mount filesystem read-only + */ + if ((rc == -EROFS && !mnt_context_syscall_called(cxt)) /* before syscall; rdonly loopdev */ + || mnt_context_get_syscall_errno(cxt) == EROFS /* syscall failed with EROFS */ + || mnt_context_get_syscall_errno(cxt) == EACCES) /* syscall failed with EACCES */ + { + unsigned long mflags = 0; + + mnt_context_get_mflags(cxt, &mflags); + + if (!(mflags & MS_RDONLY) /* not yet RDONLY */ + && !(mflags & MS_REMOUNT) /* not remount */ + && !(mflags & MS_BIND) /* not bin mount */ + && !mnt_context_is_rwonly_mount(cxt)) { /* no explicit read-write */ + + assert(!(cxt->flags & MNT_FL_FORCED_RDONLY)); + DBG(CXT, ul_debugobj(cxt, "write-protected source, trying RDONLY.")); + + mnt_context_reset_status(cxt); + mnt_context_set_mflags(cxt, mflags | MS_RDONLY); + cxt->flags |= MNT_FL_FORCED_RDONLY; + goto again; + } + } return rc; } @@ -1222,3 +1249,334 @@ int mnt_context_next_mount(struct libmnt_context *cxt, return 0; } +/* + * Returns 1 if @dir parent is shared + */ +static int is_shared_tree(struct libmnt_context *cxt, const char *dir) +{ + struct libmnt_table *tb = NULL; + struct libmnt_fs *fs; + unsigned long mflags = 0; + char *mnt = NULL, *p; + int rc = 0; + + if (!dir) + return 0; + if (mnt_context_get_mtab(cxt, &tb) || !tb) + goto done; + + mnt = strdup(dir); + if (!mnt) + goto done; + p = strrchr(mnt, '/'); + if (!p) + goto done; + if (p > mnt) + *p = '\0'; + fs = mnt_table_find_mountpoint(tb, mnt, MNT_ITER_BACKWARD); + + rc = fs && mnt_fs_is_kernel(fs) + && mnt_fs_get_propagation(fs, &mflags) == 0 + && (mflags & MS_SHARED); +done: + free(mnt); + return rc; +} + +int mnt_context_get_mount_excode( + struct libmnt_context *cxt, + int rc, + char *buf, + size_t bufsz) +{ + int syserr; + struct stat st; + unsigned long uflags = 0, mflags = 0; + + int restricted = mnt_context_is_restricted(cxt); + const char *tgt = mnt_context_get_target(cxt); + const char *src = mnt_context_get_source(cxt); + + if (mnt_context_helper_executed(cxt)) { + /* + * /sbin/mount.<type> called, return status + */ + if (rc == -MNT_ERR_APPLYFLAGS && buf) + snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags")); + + return mnt_context_get_helper_status(cxt); + } + + if (rc == 0 && mnt_context_get_status(cxt) == 1) { + /* + * Libmount success && syscall success. + */ + if (buf && mnt_context_forced_rdonly(cxt)) + snprintf(buf, bufsz, _("WARNING: device write-protected, mounted read-only")); + return MNT_EX_SUCCESS; + } + + mnt_context_get_mflags(cxt, &mflags); /* mount(2) flags */ + mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */ + + if (!mnt_context_syscall_called(cxt)) { + /* + * libmount errors (extra library checks) + */ + switch (rc) { + case -EPERM: + if (buf) + snprintf(buf, bufsz, _("operation permitted for root only")); + return MNT_EX_USAGE; + case -EBUSY: + if (buf) + snprintf(buf, bufsz, _("%s is already mounted"), src); + return MNT_EX_USAGE; + case -MNT_ERR_NOFSTAB: + if (!buf) + return MNT_EX_USAGE; + if (mnt_context_is_swapmatch(cxt)) + snprintf(buf, bufsz, _("can't find in %s"), + mnt_get_fstab_path()); + else if (tgt) + snprintf(buf, bufsz, _("can't find mount point in %s"), + mnt_get_fstab_path()); + else if (src) + snprintf(buf, bufsz, _("can't find mount source %s in %s"), + src, mnt_get_fstab_path()); + return MNT_EX_USAGE; + case -MNT_ERR_AMBIFS: + if (buf) + snprintf(buf, bufsz, _("more filesystems detected on %s; use -t <type> or wipefs(8)"), src); + return MNT_EX_USAGE; + case -MNT_ERR_NOFSTYPE: + if (buf) + snprintf(buf, bufsz, restricted ? + _("failed to determine filesystem type") : + _("no filesystem type specified")); + return MNT_EX_USAGE; + case -MNT_ERR_NOSOURCE: + if (uflags & MNT_MS_NOFAIL) + return MNT_EX_SUCCESS; + if (buf) { + if (src) + snprintf(buf, bufsz, _("can't find %s"), src); + else + snprintf(buf, bufsz, _("no mount source specified")); + } + return MNT_EX_USAGE; + case -MNT_ERR_MOUNTOPT: + if (buf) + snprintf(buf, bufsz, errno ? + _("failed to parse mount options: %m") : + _("failed to parse mount options")); + return MNT_EX_USAGE; + case -MNT_ERR_LOOPDEV: + if (buf) + snprintf(buf, bufsz, _("failed to setup loop device for %s"), src); + return MNT_EX_FAIL; + case -MNT_ERR_LOOPOVERLAP: + if (buf) + snprintf(buf, bufsz, _("overlapping loop device exists for %s"), src); + return MNT_EX_FAIL; + default: + return mnt_context_get_generic_excode(rc, buf, bufsz, _("mount failed: %m")); + } + + } else if (mnt_context_get_syscall_errno(cxt) == 0) { + /* + * mount(2) syscall success, but something else failed + * (probably error in mtab processing). + */ + if (rc < 0) + return mnt_context_get_generic_excode(rc, buf, bufsz, + _("filesystem was mounted, but any subsequent operation failed: %m")); + + return MNT_EX_SOFTWARE; /* internal error */ + + } + + /* + * mount(2) errors + */ + syserr = mnt_context_get_syscall_errno(cxt); + + + switch(syserr) { + case EPERM: + if (!buf) + break; + if (geteuid() == 0) { + if (stat(tgt, &st) || !S_ISDIR(st.st_mode)) + snprintf(buf, bufsz, _("mount point is not a directory")); + else + snprintf(buf, bufsz, _("permission denied")); + } else + snprintf(buf, bufsz, _("must be superuser to use mount")); + break; + + case EBUSY: + { + struct libmnt_table *tb; + + if (!buf) + break; + if (mflags & MS_REMOUNT) { + snprintf(buf, bufsz, _("mount point is busy")); + break; + } + if (src && mnt_context_get_mtab(cxt, &tb) == 0) { + struct libmnt_iter itr; + struct libmnt_fs *fs; + + mnt_reset_iter(&itr, MNT_ITER_FORWARD); + while (mnt_table_next_fs(tb, &itr, &fs) == 0) { + const char *s = mnt_fs_get_srcpath(fs), + *t = mnt_fs_get_target(fs); + + if (t && s && mnt_fs_streq_srcpath(fs, src)) { + snprintf(buf, bufsz, _("%s already mounted on %s"), s, t); + break; + } + } + } + if (!*buf) + snprintf(buf, bufsz, _("%s already mounted or mount point busy"), src); + break; + } + case ENOENT: + if (tgt && lstat(tgt, &st)) { + if (buf) + snprintf(buf, bufsz, _("mount point does not exist")); + } else if (tgt && stat(tgt, &st)) { + if (buf) + snprintf(buf, bufsz, _("mount point is a symbolic link to nowhere")); + } else if (src && stat(src, &st)) { + if (uflags & MNT_MS_NOFAIL) + return MNT_EX_SUCCESS; + if (buf) + snprintf(buf, bufsz, _("special device %s does not exist"), src); + } else if (buf) { + errno = syserr; + snprintf(buf, bufsz, _("mount(2) system call failed: %m")); + } + break; + + case ENOTDIR: + if (stat(tgt, &st) || ! S_ISDIR(st.st_mode)) { + if (buf) + snprintf(buf, bufsz, _("mount point is not a directory")); + } else if (src && stat(src, &st) && errno == ENOTDIR) { + if (uflags & MNT_MS_NOFAIL) + return MNT_EX_SUCCESS; + if (buf) + snprintf(buf, bufsz, _("special device %s does not exist " + "(a path prefix is not a directory)"), src); + } else if (buf) { + errno = syserr; + snprintf(buf, bufsz, _("mount(2) system call failed: %m")); + } + break; + + case EINVAL: + if (!buf) + break; + if (mflags & MS_REMOUNT) + snprintf(buf, bufsz, _("mount point not mounted or bad option")); + else if (rc == -MNT_ERR_APPLYFLAGS) + snprintf(buf, bufsz, _("not mount point or bad option")); + else if ((mflags & MS_MOVE) && is_shared_tree(cxt, src)) + snprintf(buf, bufsz, + _("bad option; moving a mount " + "residing under a shared mount is unsupported")); + else if (mnt_fs_is_netfs(mnt_context_get_fs(cxt))) + snprintf(buf, bufsz, + _("bad option; for several filesystems (e.g. nfs, cifs) " + "you might need a /sbin/mount.<type> helper program")); + else + snprintf(buf, bufsz, + _("wrong fs type, bad option, bad superblock on %s, " + "missing codepage or helper program, or other error"), + src); + break; + + case EMFILE: + if (buf) + snprintf(buf, bufsz, _("mount table full")); + break; + + case EIO: + if (buf) + snprintf(buf, bufsz, _("can't read superblock on %s"), src); + break; + + case ENODEV: + if (!buf) + break; + if (mnt_context_get_fstype(cxt)) + snprintf(buf, bufsz, _("unknown filesystem type '%s'"), + mnt_context_get_fstype(cxt)); + else + snprintf(buf, bufsz, _("unknown filesystem type")); + break; + + case ENOTBLK: + if (uflags & MNT_MS_NOFAIL) + return MNT_EX_SUCCESS; + if (!buf) + break; + if (stat(src, &st)) + snprintf(buf, bufsz, _("%s is not a block device, and stat(2) fails?"), src); + else if (S_ISBLK(st.st_mode)) + snprintf(buf, bufsz, + _("the kernel does not recognize %s as a block device; " + "maybe \"modprobe driver\" is necessary"), src); + else if (S_ISREG(st.st_mode)) + snprintf(buf, bufsz, _("%s is not a block device; try \"-o loop\""), src); + else + snprintf(buf, bufsz, _("%s is not a block device"), src); + break; + + case ENXIO: + if (uflags & MNT_MS_NOFAIL) + return MNT_EX_SUCCESS; + if (buf) + snprintf(buf, bufsz, _("%s is not a valid block device"), src); + break; + + case EACCES: + case EROFS: + if (!buf) + break; + if (mflags & MS_RDONLY) + snprintf(buf, bufsz, _("cannot mount %s read-only"), src); + else if (mnt_context_is_rwonly_mount(cxt)) + snprintf(buf, bufsz, _("%s is write-protected but explicit read-write mode requested"), src); + else if (mflags & MS_REMOUNT) + snprintf(buf, bufsz, _("cannot remount %s read-write, is write-protected"), src); + else if (mflags & MS_BIND) + snprintf(buf, bufsz, _("bind %s failed"), src); + else { + errno = syserr; + snprintf(buf, bufsz, _("mount(2) system call failed: %m")); + } + break; + + case ENOMEDIUM: + if (uflags & MNT_MS_NOFAIL) + return MNT_EX_SUCCESS; + if (buf) + snprintf(buf, bufsz, _("no medium found on %s"), src); + break; + + default: + if (buf) { + errno = syserr; + snprintf(buf, bufsz, _("mount(2) system call failed: %m")); + } + break; + } + + return MNT_EX_FAIL; +} + diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c index 28787dab1..a2bba8060 100644 --- a/libmount/src/context_umount.c +++ b/libmount/src/context_umount.c @@ -1016,3 +1016,83 @@ int mnt_context_next_umount(struct libmnt_context *cxt, *mntrc = rc; return 0; } + + +int mnt_context_get_umount_excode( + struct libmnt_context *cxt, + int rc, + char *buf, + size_t bufsz) +{ + if (mnt_context_helper_executed(cxt)) + /* + * /sbin/umount.<type> called, return status + */ + return mnt_context_get_helper_status(cxt); + + if (rc == 0 && mnt_context_get_status(cxt) == 1) + /* + * Libmount success && syscall success. + */ + return MNT_EX_SUCCESS; + + if (!mnt_context_syscall_called(cxt)) { + /* + * libmount errors (extra library checks) + */ + if (rc == -EPERM && !mnt_context_tab_applied(cxt)) { + /* failed to evaluate permissions because not found + * relevant entry in mtab */ + if (buf) + snprintf(buf, bufsz, _("not mounted")); + return MNT_EX_USAGE; + } + return mnt_context_get_generic_excode(rc, buf, bufsz, + _("umount failed: %m")); + + } else if (mnt_context_get_syscall_errno(cxt) == 0) { + /* + * umount(2) syscall success, but something else failed + * (probably error in mtab processing). + */ + if (rc < 0) + return mnt_context_get_generic_excode(rc, buf, bufsz, + _("filesystem was unmounted, but any subsequent operation failed: %m")); + + return MNT_EX_SOFTWARE; /* internal error */ + } + + /* + * umount(2) errors + */ + if (buf) { + int syserr = mnt_context_get_syscall_errno(cxt); + + switch (syserr) { + case ENXIO: + snprintf(buf, bufsz, _("invalid block device")); /* ??? */ + break; + case EINVAL: + snprintf(buf, bufsz, _("not mounted")); + break; + case EIO: + snprintf(buf, bufsz, _("can't write superblock")); + break; + case EBUSY: + snprintf(buf, bufsz, _("target is busy")); + break; + case ENOENT: + snprintf(buf, bufsz, _("no mount point specified")); + break; + case EPERM: + snprintf(buf, bufsz, _("must be superuser to unmount")); + break; + case EACCES: + snprintf(buf, bufsz, _("block devices are not permitted on filesystem")); + break; + default: + return mnt_context_get_generic_excode(syserr, buf, bufsz,_("umount(2) system call failed: %m")); + } + } + return MNT_EX_FAIL; +} diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index f191a52fe..123145fc4 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -185,6 +185,72 @@ enum { */ #define MNT_ERR_LOOPOVERLAP 5007 + +/* + * Overall return codes -- based on mount(8) and umount(8) return codes. + * See mnt_context_get_excode() for more details. + */ + +/** + * MNT_EX_SUCCESS: + * + * [u]mount(8) exit code: no errors + */ +#define MNT_EX_SUCCESS 0 + +/** + * MNT_EX_USAGE: + * + * [u]mount(8) exit code: incorrect invocation or permission + */ +#define MNT_EX_USAGE 1 + +/** + * MNT_EX_SYSERR: + * + * [u]mount(8) exit code: out of memory, cannot fork, ... + */ + +#define MNT_EX_SYSERR 2 + +/** + * MNT_EX_SOFTWARE: + * + * [u]mount(8) exit code: internal mount bug or wrong version + */ +#define MNT_EX_SOFTWARE 4 + +/** + * MNT_EX_USER: + * + * [u]mount(8) exit code: user interrupt + */ +#define MNT_EX_USER 8 + +/** + * MNT_EX_FILEIO: + * + * [u]mount(8) exit code: problems writing, locking, ... mtab/fstab + */ +#define MNT_EX_FILEIO 16 + +/** + * MNT_EX_FAIL: + * + * [u]mount(8) exit code: mount failure + */ +#define MNT_EX_FAIL 32 + +/** + * MNT_EX_SOMEOK: + * + * [u]mount(8) exit code: some mount succeeded; usually when executed with + * --all options. Never returned by libmount. + */ +#define MNT_EX_SOMEOK 64 + + + #ifndef __GNUC_PREREQ # if defined __GNUC__ && defined __GNUC_MINOR__ # define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) @@ -610,6 +676,7 @@ extern int mnt_context_set_optsmode(struct libmnt_context *cxt, int mode); extern int mnt_context_disable_canonicalize(struct libmnt_context *cxt, int disable); extern int mnt_context_enable_lazy(struct libmnt_context *cxt, int enable); extern int mnt_context_enable_rdonly_umount(struct libmnt_context *cxt, int enable); +extern int mnt_context_enable_rwonly_mount(struct libmnt_context *cxt, int enable); extern int mnt_context_disable_helpers(struct libmnt_context *cxt, int disable); extern int mnt_context_enable_sloppy(struct libmnt_context *cxt, int enable); extern int mnt_context_enable_fake(struct libmnt_context *cxt, int enable); @@ -626,6 +693,8 @@ extern int mnt_context_is_lazy(struct libmnt_context *cxt) __ul_attribute__((nonnull)); extern int mnt_context_is_rdonly_umount(struct libmnt_context *cxt) __ul_attribute__((nonnull)); +extern int mnt_context_is_rwonly_mount(struct libmnt_context *cxt) + __ul_attribute__((nonnull)); extern int mnt_context_is_sloppy(struct libmnt_context *cxt) __ul_attribute__((nonnull)); extern int mnt_context_is_fake(struct libmnt_context *cxt) @@ -644,6 +713,8 @@ extern int mnt_context_is_nocanonicalize(struct libmnt_context *cxt) __ul_attribute__((nonnull)); extern int mnt_context_is_swapmatch(struct libmnt_context *cxt) __ul_attribute__((nonnull)); +extern int mnt_context_forced_rdonly(struct libmnt_context *cxt) + __ul_attribute__((nonnull)); extern int mnt_context_is_fork(struct libmnt_context *cxt) __ul_attribute__((nonnull)); @@ -724,7 +795,12 @@ extern int mnt_context_syscall_called(struct libmnt_context *cxt); extern int mnt_context_get_syscall_errno(struct libmnt_context *cxt); extern int mnt_context_strerror(struct libmnt_context *cxt, char *buf, - size_t bufsiz); + size_t bufsiz) + __ul_attribute__((deprecated)); + +extern int mnt_context_get_excode(struct libmnt_context *cxt, + int rc, char *buf, size_t bufsz); + /* context_mount.c */ extern int mnt_context_mount(struct libmnt_context *cxt); diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index f0210c240..ca16cafa1 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -315,3 +315,10 @@ MOUNT_2.28 { mnt_table_find_target_with_option; mnt_fs_set_priority; } MOUNT_2.26; + +MOUNT_2.30 { + mnt_context_is_rwonly_mount; + mnt_context_forced_rdonly; + mnt_context_enable_rwonly_mount; + mnt_context_get_excode; +} MOUNT_2.28; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 2baab55de..e01de337d 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -50,6 +50,18 @@ UL_DEBUG_DECLARE_MASK(libmount); #define ON_DBG(m, x) __UL_DBG_CALL(libmount, MNT_DEBUG_, m, x) #define DBG_FLUSH __UL_DBG_FLUSH(libmount, MNT_DEBUG_) +/* + * NLS -- the library has to be independent on main program, so define + * UL_TEXTDOMAIN_EXPLICIT before you include nls.h. + * + * Now we use util-linux.po (=PACKAGE), rather than maintain the texts + * in the separate libmount.po file. + */ +#define LIBMOUNT_TEXTDOMAIN PACKAGE +#define UL_TEXTDOMAIN_EXPLICIT LIBMOUNT_TEXTDOMAIN +#include "nls.h" + + /* extension for files in the directory */ #define MNT_MNTTABDIR_EXT ".fstab" @@ -313,6 +325,8 @@ struct libmnt_context int syscall_status; /* 1: not called yet, 0: success, <0: -errno */ + + unsigned int enabled_textdomain : 1; /* bindtextdomain() called */ }; /* flags */ @@ -328,6 +342,7 @@ struct libmnt_context #define MNT_FL_RDONLY_UMOUNT (1 << 11) /* remount,ro after EBUSY umount(2) */ #define MNT_FL_FORK (1 << 12) #define MNT_FL_NOSWAPMATCH (1 << 13) +#define MNT_FL_RWONLY_MOUNT (1 << 14) /* explicit mount -w; never try read-only */ #define MNT_FL_MOUNTDATA (1 << 20) #define MNT_FL_TAB_APPLIED (1 << 21) /* mtab/fstab merged to cxt->fs */ @@ -338,6 +353,7 @@ struct libmnt_context #define MNT_FL_LOOPDEV_READY (1 << 26) /* /dev/loop<N> initialized by the library */ #define MNT_FL_MOUNTOPTS_FIXED (1 << 27) #define MNT_FL_TABPATHS_CHECKED (1 << 28) +#define MNT_FL_FORCED_RDONLY (1 << 29) /* mounted read-only on write-protected device */ /* default flags */ #define MNT_FL_DEFAULT 0 @@ -408,6 +424,10 @@ extern int mnt_context_set_tabfilter(struct libmnt_context *cxt, int (*fltr)(struct libmnt_fs *, void *), void *data); +extern int mnt_context_get_generic_excode(int rc, char *buf, size_t bufsz, char *fmt, ...); +extern int mnt_context_get_mount_excode(struct libmnt_context *cxt, int mntrc, char *buf, size_t bufsz); +extern int mnt_context_get_umount_excode(struct libmnt_context *cxt, int mntrc, char *buf, size_t bufsz); + /* tab_update.c */ extern int mnt_update_set_filename(struct libmnt_update *upd, const char *filename, int userspace_only); |