From d115ee9bd183412c41f2a8cc7b3485c1e286e34f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 12 Jan 2010 13:43:07 +0100 Subject: libmount: add mnt_entry Signed-off-by: Karel Zak --- shlibs/mount/src/fs.c | 545 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 545 insertions(+) create mode 100644 shlibs/mount/src/fs.c (limited to 'shlibs/mount/src/fs.c') diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c new file mode 100644 index 000000000..0e12052d5 --- /dev/null +++ b/shlibs/mount/src/fs.c @@ -0,0 +1,545 @@ +/* + * Copyright (C) 2008-2009 Karel Zak + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * + * The mnt_fs is representation of one line in a fstab / mtab / mountinfo. + */ + +#include +#include +#include +#include +#include + +#include "nls.h" +#include "mountP.h" + +/** + * mnt_new_fs: + * + * Returns newly allocated mnt_file fs. + */ +mnt_fs *mnt_new_fs(void) +{ + mnt_fs *fs = calloc(1, sizeof(struct _mnt_fs)); + if (!fs) + return NULL; + + INIT_LIST_HEAD(&fs->ents); + return fs; +} + +/** + * mnt_free_fs: + * @fs: fs pointer + * + * Deallocates the fs. + */ +void mnt_free_fs(mnt_fs *fs) +{ + if (!fs) + return; + list_del(&fs->ents); + + free(fs->source); + free(fs->tagname); + free(fs->tagval); + free(fs->mntroot); + free(fs->target); + free(fs->fstype); + free(fs->optstr); + free(fs->vfs_optstr); + free(fs->fs_optstr); + + free(fs); +} + +/** + * mnt_fs_get_srcpath: + * @fs: mnt_file (fstab/mtab/mountinfo) fs + * + * The mount "source path" is: + * - a directory for 'bind' mounts (in fstab or mtab only) + * - a device name for standard mounts + * - NULL when path is not set (for example when TAG + * (LABEL/UUID) is defined) + * + * See also mnt_fs_get_tag() and mnt_fs_get_source(). + * + * Returns mount "source" path or NULL in case of error or when the path + * is not defined. + * + */ +const char *mnt_fs_get_srcpath(mnt_fs *fs) +{ + assert(fs); + if (!fs) + return NULL; + + /* fstab-like fs */ + if (fs->tagname) + return NULL; /* the source contains a "NAME=value" */ + return fs->source; +} + +/** + * @fs: mnt_file (fstab/mtab/mountinfo) fs + * + * Returns mount "source". Note that the source could be unparsed TAG + * (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag(). + */ +const char *mnt_fs_get_source(mnt_fs *fs) +{ + return fs ? fs->source : NULL; +} + +/* Used by parser mnt_file ONLY (@source has to be allocated) */ +int __mnt_fs_set_source(mnt_fs *fs, char *source) +{ + assert(fs); + + if (!source) + return -1; + + if (strchr(source, '=')) { + char *name, *val; + + if (blkid_parse_tag_string(source, &name, &val) != 0) + return -1; + + fs->tagval = val; + fs->tagname = name; + } + + fs->source = source; + return 0; +} + +/** + * mnt_fs_set_source: + * @fs: fstab/mtab/mountinfo entry + * @source: new source + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_set_source(mnt_fs *fs, const char *source) +{ + char *p; + + if (!fs && !source) + return -1; + + p = strdup(source); + if (!p) + return -1; + + free(fs->tagval); + free(fs->tagname); + free(fs->source); + fs->tagval = fs->tagname = fs->source = NULL; + + return __mnt_fs_set_source(fs, p); +} + +/** + * mnt_fs_get_tag: + * @fs: fs + * @name: returns pointer to NAME string + * @value: returns pointer to VALUE string + * + * "TAG" is NAME=VALUE (e.g. LABEL=foo) + * + * The TAG is the first column in the fstab file. The TAG + * or "srcpath" has to be always set for all entries. + * + * See also mnt_fs_get_source(). + * + * Example: + * char *src; + * mnt_fs *fs = mnt_file_find_target(mf, "/home"); + * + * if (!fs) + * goto err; + * + * src = mnt_fs_get_srcpath(fs); + * if (!src) { + * char *tag, *val; + * if (mnt_fs_get_tag(fs, &tag, &val) == 0) + * printf("%s: %s\n", tag, val); // LABEL or UUID + * } else + * printf("device: %s\n", src); // device or bind path + * + * Returns 0 on success or -1 in case that a TAG is not defined. + */ +int mnt_fs_get_tag(mnt_fs *fs, const char **name, const char **value) +{ + if (fs == NULL || !fs->tagname) + return -1; + if (name) + *name = fs->tagname; + if (value) + *value = fs->tagval; + return 0; +} + +/** + * mnt_fs_get_target: + * @fs: fstab/mtab/mountinfo entry pointer + * + * Returns pointer to mountpoint path or NULL + */ +const char *mnt_fs_get_target(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->target : NULL; +} + +/** + * mnt_fs_set_target: + * @fs: fstab/mtab/mountinfo entry + * @target: mountpoint + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_set_target(mnt_fs *fs, const char *target) +{ + char *p; + + assert(fs); + + if (!fs || !target) + return -1; + + p = strdup(target); + if (!p) + return -1; + free(fs->target); + fs->target = p; + + return 0; +} + +/** + * mnt_fs_get_fstype: + * @fs: fstab/mtab/mountinfo entry pointer + * + * Returns pointer to filesystem type. + */ +const char *mnt_fs_get_fstype(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->fstype : NULL; +} + +/* Used by mnt_file parser only */ +int __mnt_fs_set_fstype(mnt_fs *fs, char *fstype) +{ + assert(fs); + + if (!fstype) + return -1; + + fs->fstype = fstype; + fs->flags &= ~MNT_FS_PSEUDO; + fs->flags &= ~MNT_FS_NET; + + /* save info about pseudo filesystems */ + if (mnt_fstype_is_pseudofs(fs->fstype)) + fs->flags |= MNT_FS_PSEUDO; + else if (mnt_fstype_is_netfs(fs->fstype)) + fs->flags |= MNT_FS_NET; + + return 0; +} + +/** + * mnt_fs_set_fstype: + * @fs: fstab/mtab/mountinfo entry + * @fstype: filesystem type + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_set_fstype(mnt_fs *fs, const char *fstype) +{ + char *p; + + if (!fs || !fstype) + return -1; + + p = strdup(fstype); + if (!p) + return -1; + free(fs->fstype); + + return __mnt_fs_set_fstype(fs, p); +} + +/** + * mnt_fs_get_optstr: + * @fs: fstab/mtab/mountinfo entry pointer + * + * Returns pointer to mount option string with all options (FS and VFS) + */ +const char *mnt_fs_get_optstr(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->optstr : NULL; +} + +/** + * mnt_fs_set_optstr: + * @fs: fstab/mtab/mountinfo entry + * @optstr: options string + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_set_optstr(mnt_fs *fs, const char *optstr) +{ + assert(fs); + + if (!fs || !optstr) + return -1; + free(fs->optstr); + free(fs->fs_optstr); + free(fs->vfs_optstr); + fs->fs_optstr = fs->vfs_optstr = NULL; + + fs->optstr = strdup(optstr); + + return fs->optstr ? 0 : -1; +} + +/** + * mnt_fs_get_fs_optstr: + * @fs: fstab/mtab/mountinfo entry pointer + * + * This function works for "mountinfo" files only. + * + * Returns pointer to superblock (fs-depend) mount option string or NULL. + */ +const char *mnt_fs_get_fs_optstr(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->fs_optstr : NULL; +} + +/** + * mnt_fs_get_vfs_optstr: + * @fs: fstab/mtab/mountinfo entry pointer + * + * This function works for "mountinfo" files only. + * + * Returns pointer to fs-independent (VFS) mount option string or NULL. + */ +const char *mnt_fs_get_vfs_optstr(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->vfs_optstr : NULL; +} + + +/** + * mnt_fs_get_freq: + * @fs: fstab/mtab/mountinfo entry pointer + * + * Returns "dump frequency in days". + */ +int mnt_fs_get_freq(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->freq : 0; +} + +/** + * mnt_fs_set_freq: + * @fs: fstab/mtab/mountinfo entry pointer + * @freq: dump frequency in days + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_set_freq(mnt_fs *fs, int freq) +{ + assert(fs); + + if (!fs) + return -1; + fs->freq = freq; + return 0; +} + +/** + * mnt_fs_get_passno: + * @fs: fstab/mtab/mountinfo entry pointer + * + * Returns "pass number on parallel fsck". + */ +int mnt_fs_get_passno(mnt_fs *fs) +{ + assert(fs); + return fs ? fs->passno: 0; +} + +/** + * mnt_fs_set_passno: + * @fs: fstab/mtab/mountinfo entry pointer + * @passno: pass number + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_set_passno(mnt_fs *fs, int passno) +{ + assert(fs); + + if (!fs) + return -1; + fs->passno = passno; + return 0; +} + +/** + * mnt_fs_get_option: + * @fs: fstab/mtab/mountinfo entry pointer + * @name: option name + * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL + * @valsz: returns size of options value or 0 + * + * Returns 0 on success, 1 when not found the @name or -1 in case of error. + */ +int mnt_fs_get_option(mnt_fs *fs, const char *name, + char **value, size_t *valsz) +{ + char *optstr = (char *) mnt_fs_get_optstr(fs); + return optstr ? mnt_optstr_get_option(optstr, name, value, valsz) : 1; +} + + +/* Unfortunately the classical Unix /etc/mtab and /etc/fstab + do not handle directory names containing spaces. + Here we mangle them, replacing a space by \040. + What do other Unices do? */ + +static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; + +static char *mangle(const char *s) +{ + char *ss, *sp; + int n; + + n = strlen(s); + ss = sp = malloc(4*n+1); + if (!sp) + return NULL; + while(1) { + for (n = 0; n < sizeof(need_escaping); n++) { + if (*s == need_escaping[n]) { + *sp++ = '\\'; + *sp++ = '0' + ((*s & 0300) >> 6); + *sp++ = '0' + ((*s & 070) >> 3); + *sp++ = '0' + (*s & 07); + goto next; + } + } + *sp++ = *s; + if (*s == 0) + break; + next: + s++; + } + return ss; +} + +/** + * mnt_fprintf_line: + * @f: FILE + * @fmt: printf-like format string (see MNT_MFILE_PRINTFMT) + * @source: (spec) device name or tag=value + * @target: mountpoint + * @fstype: filesystem type + * @options: mount options + * @freq: dump frequency in days + * @passno: pass number on parallel fsck + * + * Returns return value from fprintf(). + */ +int mnt_fprintf_line( FILE *f, + const char *fmt, + const char *source, + const char *target, + const char *fstype, + const char *options, + int freq, + int passno) +{ + char *m1 = NULL, *m2 = NULL, *m3 = NULL, *m4 = NULL; + int rc = -1; + + if (!f || !fmt || !source || !target || !fstype || !options) + return -1; + + m1 = mangle(source); + m2 = mangle(target); + m3 = mangle(fstype); + m4 = mangle(options); + + if (!m1 || !m2 || !m3 || !m4) + goto done; + + rc = fprintf(f, fmt, m1, m2, m3, m4, freq, passno); +done: + free(m1); + free(m2); + free(m3); + free(m4); + + return rc; +} + +/** + * mnt_fs_fprintf: + * @fs: fstab/mtab/mountinfo entry + * @f: FILE + * @fmt: printf-like format string (see MNT_MFILE_PRINTFMT) + * + * Returns return value from fprintf(). + */ +int mnt_fs_fprintf(mnt_fs *fs, FILE *f, const char *fmt) +{ + assert(fs); + assert(f); + assert(fmt); + + if (!fs || !f) + return -1; + + return mnt_fprintf_line(f, fmt, + mnt_fs_get_source(fs), + mnt_fs_get_target(fs), + mnt_fs_get_fstype(fs), + mnt_fs_get_optstr(fs), + mnt_fs_get_freq(fs), + mnt_fs_get_passno(fs)); +} + +/** + * mnt_fs_print_debug + * @fs: fstab/mtab/mountinfo entry + * @file: output + * + * Returns 0 on success or -1 in case of error. + */ +int mnt_fs_print_debug(mnt_fs *fs, FILE *file) +{ + if (!fs) + return -1; + fprintf(file, "------ fs: %p\n", fs); + fprintf(file, "source: %s\n", mnt_fs_get_source(fs)); + fprintf(file, "target: %s\n", mnt_fs_get_target(fs)); + fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs)); + fprintf(file, "optstr: %s\n", mnt_fs_get_optstr(fs)); + fprintf(file, "freq: %d\n", mnt_fs_get_freq(fs)); + fprintf(file, "pass: %d\n", mnt_fs_get_passno(fs)); + + return 0; +} -- cgit v1.2.3-55-g7522