/* * Parses one line from utab file */ static int mnt_parse_utab_line(struct libmnt_fs *fs, const char *s) { const char *p = s; assert(fs); assert(s); assert(!fs->source); assert(!fs->target); while (p && *p) { char *end = NULL; while (*p == ' ') p++; if (!*p) break; if (!fs->source && !strncmp(p, "SRC=", 4)) { char *v = unmangle(p + 4, &end); if (!v) goto enomem; __mnt_fs_set_source_ptr(fs, v); } else if (!fs->target && !strncmp(p, "TARGET=", 7)) { fs->target = unmangle(p + 7, &end); if (!fs->target) goto enomem; } else if (!fs->root && !strncmp(p, "ROOT=", 5)) { fs->root = unmangle(p + 5, &end); if (!fs->root) goto enomem; } else if (!fs->bindsrc && !strncmp(p, "BINDSRC=", 8)) { fs->bindsrc = unmangle(p + 8, &end); if (!fs->bindsrc) goto enomem; } else if (!fs->user_optstr && !strncmp(p, "OPTS=", 5)) { fs->user_optstr = unmangle(p + 5, &end); if (!fs->user_optstr) goto enomem; } else if (!fs->attrs && !strncmp(p, "ATTRS=", 6)) { fs->attrs = unmangle(p + 6, &end); if (!fs->attrs) goto enomem; } else { /* unknown variable */ while (*p && *p != ' ') p++; } if (end) p = end; } return 0; enomem: DBG(TAB, mnt_debug("utab parse error: ENOMEM")); return -ENOMEM; }
/* * Parses one line from {fs,m}tab */ static int mnt_parse_table_line(struct libmnt_fs *fs, char *s) { int rc, n = 0; char *src, *fstype, *optstr; rc = sscanf(s, UL_SCNsA" " /* (1) source */ UL_SCNsA" " /* (2) target */ UL_SCNsA" " /* (3) FS type */ UL_SCNsA" " /* (4) options */ "%n", /* byte count */ &src, &fs->target, &fstype, &optstr, &n); if (rc == 4) { unmangle_string(src); unmangle_string(fs->target); unmangle_string(fstype); unmangle_string(optstr); rc = __mnt_fs_set_source_ptr(fs, src); if (!rc) rc = __mnt_fs_set_fstype_ptr(fs, fstype); if (!rc) rc = mnt_fs_set_options(fs, optstr); free(optstr); } else { DBG(TAB, mnt_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s)); rc = -EINVAL; } if (rc) return rc; /* error */ fs->passno = fs->freq = 0; s = skip_spaces(s + n); if (*s) { if (next_number(&s, &fs->freq) != 0) { if (*s) { DBG(TAB, mnt_debug("tab parse error: [freq]")); rc = -EINVAL; } } else if (next_number(&s, &fs->passno) != 0 && *s) { DBG(TAB, mnt_debug("tab parse error: [passno]")); rc = -EINVAL; } } return rc; }
static int kernel_fs_postparse(struct libmnt_table *tb, struct libmnt_fs *fs, pid_t *tid, const char *filename) { int rc = 0; const char *src = mnt_fs_get_srcpath(fs); /* This is a filesystem description from /proc, so we're in some process * namespace. Let's remember the process PID. */ if (filename && *tid == -1) *tid = path_to_tid(filename); fs->tid = *tid; /* * Convert obscure /dev/root to something more usable */ if (src && strcmp(src, "/dev/root") == 0) { char *real = NULL; rc = mnt_guess_system_root(fs->devno, tb->cache, &real); if (rc < 0) return rc; if (rc == 0 && real) { DBG(TAB, ul_debugobj(tb, "canonical root FS: %s", real)); rc = __mnt_fs_set_source_ptr(fs, real); } else if (rc == 1) { /* mnt_guess_system_root() returns 1 if not able to conver to * the real devname; ignore this problem */ rc = 0; } } return rc; }
/* * Parses one line from {fs,m}tab */ static int mnt_parse_table_line(struct libmnt_fs *fs, char *s) { int rc, n = 0, xrc; char *src = NULL, *fstype = NULL, *optstr = NULL; rc = sscanf(s, UL_SCNsA" " /* (1) source */ UL_SCNsA" " /* (2) target */ UL_SCNsA" " /* (3) FS type */ UL_SCNsA" " /* (4) options */ "%n", /* byte count */ &src, &fs->target, &fstype, &optstr, &n); xrc = rc; if (rc == 3 || rc == 4) { /* options are optional */ unmangle_string(src); unmangle_string(fs->target); unmangle_string(fstype); if (optstr && *optstr) unmangle_string(optstr); /* note that __foo functions does not reallocate the string */ rc = __mnt_fs_set_source_ptr(fs, src); if (!rc) { src = NULL; rc = __mnt_fs_set_fstype_ptr(fs, fstype); if (!rc) fstype = NULL; } if (!rc && optstr) rc = mnt_fs_set_options(fs, optstr); free(optstr); optstr = NULL; } else { DBG(TAB, mnt_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s)); rc = -EINVAL; } if (rc) { free(src); free(fstype); free(optstr); DBG(TAB, mnt_debug("tab parse error: [set vars, rc=%d]\n", rc)); return rc; /* error */ } fs->passno = fs->freq = 0; if (xrc == 4 && n) s = skip_spaces(s + n); if (xrc == 4 && *s) { if (next_number(&s, &fs->freq) != 0) { if (*s) { DBG(TAB, mnt_debug("tab parse error: [freq]")); rc = -EINVAL; } } else if (next_number(&s, &fs->passno) != 0 && *s) { DBG(TAB, mnt_debug("tab parse error: [passno]")); rc = -EINVAL; } } return rc; }
/* * Parses one line from mountinfo file */ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, char *s) { int rc, end = 0; unsigned int maj, min; char *fstype = NULL, *src = NULL, *p; rc = sscanf(s, "%u " /* (1) id */ "%u " /* (2) parent */ "%u:%u " /* (3) maj:min */ UL_SCNsA" " /* (4) mountroot */ UL_SCNsA" " /* (5) target */ UL_SCNsA /* (6) vfs options (fs-independent) */ "%n", /* number of read bytes */ &fs->id, &fs->parent, &maj, &min, &fs->root, &fs->target, &fs->vfs_optstr, &end); if (rc >= 7 && end > 0) s += end; /* (7) optional fields, terminated by " - " */ p = strstr(s, " - "); if (!p) { DBG(TAB, mnt_debug("mountinfo parse error: not found separator")); return -EINVAL; } s = p + 3; rc += sscanf(s, UL_SCNsA" " /* (8) FS type */ UL_SCNsA" " /* (9) source */ UL_SCNsA, /* (10) fs options (fs specific) */ &fstype, &src, &fs->fs_optstr); if (rc >= 10) { fs->flags |= MNT_FS_KERNEL; fs->devno = makedev(maj, min); unmangle_string(fs->root); unmangle_string(fs->target); unmangle_string(fs->vfs_optstr); unmangle_string(fstype); unmangle_string(src); unmangle_string(fs->fs_optstr); rc = __mnt_fs_set_fstype_ptr(fs, fstype); if (!rc) { fstype = NULL; rc = __mnt_fs_set_source_ptr(fs, src); if (!rc) src = NULL; } /* merge VFS and FS options to the one string */ fs->optstr = mnt_fs_strdup_options(fs); if (!fs->optstr) rc = -ENOMEM; } else { free(fstype); free(src); DBG(TAB, mnt_debug( "mountinfo parse error [sscanf rc=%d]: '%s'", rc, s)); rc = -EINVAL; } return rc; }
/* * Parses one line from a mountinfo file */ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, char *s) { int rc, end = 0; unsigned int maj, min; char *fstype = NULL, *src = NULL, *p; #ifndef HAVE_SCANF_MS_MODIFIER size_t len = strlen(s) + 1; fs->root = malloc(len); fs->target = malloc(len); fs->vfs_optstr = malloc(len); fs->fs_optstr = malloc(len); fstype = malloc(len); src = malloc(len); #endif rc = sscanf(s, "%d " /* (1) id */ "%d " /* (2) parent */ "%u:%u " /* (3) maj:min */ UL_SCNsA" " /* (4) mountroot */ UL_SCNsA" " /* (5) target */ UL_SCNsA /* (6) vfs options (fs-independent) */ "%n", /* number of read bytes */ &fs->id, &fs->parent, &maj, &min, #ifdef HAVE_SCANF_MS_MODIFIER &fs->root, &fs->target, &fs->vfs_optstr, #else fs->root, fs->target, fs->vfs_optstr, #endif &end); if (rc >= 7 && end > 0) s += end; /* (7) optional fields, terminated by " - " */ p = strstr(s, " - "); if (!p) { DBG(TAB, ul_debug("mountinfo parse error: separator not found")); return -EINVAL; } if (p > s + 1) fs->opt_fields = strndup(s + 1, p - s - 1); s = p + 3; rc += sscanf(s, UL_SCNsA" " /* (8) FS type */ UL_SCNsA" " /* (9) source */ UL_SCNsA, /* (10) fs options (fs specific) */ #ifdef HAVE_SCANF_MS_MODIFIER &fstype, &src, &fs->fs_optstr); #else fstype, src, fs->fs_optstr); #endif if (rc >= 10) { size_t sz; fs->flags |= MNT_FS_KERNEL; fs->devno = makedev(maj, min); /* remove "(deleted)" suffix */ sz = strlen(fs->target); if (sz > PATH_DELETED_SUFFIX_SZ) { char *p = fs->target + (sz - PATH_DELETED_SUFFIX_SZ); if (strcmp(p, PATH_DELETED_SUFFIX) == 0) *p = '\0'; } unmangle_string(fs->root); unmangle_string(fs->target); unmangle_string(fs->vfs_optstr); unmangle_string(fstype); unmangle_string(src); unmangle_string(fs->fs_optstr); rc = __mnt_fs_set_fstype_ptr(fs, fstype); if (!rc) { fstype = NULL; rc = __mnt_fs_set_source_ptr(fs, src); if (!rc) src = NULL; } /* merge VFS and FS options to one string */ fs->optstr = mnt_fs_strdup_options(fs); if (!fs->optstr) rc = -ENOMEM; } else { free(fstype); free(src); DBG(TAB, ul_debug( "mountinfo parse error [sscanf rc=%d]: '%s'", rc, s)); rc = -EINVAL; } return rc; }