summaryrefslogtreecommitdiffstats
path: root/libmount/src/tab_parse.c
diff options
context:
space:
mode:
authorKarel Zak2019-04-08 13:33:04 +0200
committerKarel Zak2019-04-08 13:34:47 +0200
commit36fcefa651621fdea19ca0cedf4d64a78c0a8446 (patch)
tree764762aee50209fa43ad61e4b6b148b2442feb38 /libmount/src/tab_parse.c
parentMerge branch 'spelling' of https://github.com/jwilk-forks/util-linux (diff)
downloadkernel-qcow2-util-linux-36fcefa651621fdea19ca0cedf4d64a78c0a8446.tar.gz
kernel-qcow2-util-linux-36fcefa651621fdea19ca0cedf4d64a78c0a8446.tar.xz
kernel-qcow2-util-linux-36fcefa651621fdea19ca0cedf4d64a78c0a8446.zip
libmount: don't use sscanf() for fstab parsing
Addresses: https://github.com/karelzak/util-linux/issues/780 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount/src/tab_parse.c')
-rw-r--r--libmount/src/tab_parse.c135
1 files changed, 68 insertions, 67 deletions
diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c
index 45ca45966..6eec8ba35 100644
--- a/libmount/src/tab_parse.c
+++ b/libmount/src/tab_parse.c
@@ -43,110 +43,111 @@ static void parser_cleanup(struct libmnt_parser *pa)
memset(pa, 0, sizeof(*pa));
}
-static const char *next_number(const char *s, int *num, int *ok)
+static const char *next_number(const char *s, int *num, int *rc)
{
char *end = NULL;
assert(num);
assert(s);
- assert(ok);
-
- *ok = 0;
- s = skip_blank(s);
- if (!s || !*s)
- return s;
+ assert(rc);
+ *rc = -EINVAL;
*num = strtol(s, &end, 10);
if (end == NULL || s == end)
return s;
/* valid end of number is a space or a terminator */
if (*end == ' ' || *end == '\t' || *end == '\0')
- *ok = 1;
+ *rc = 0;
return end;
}
+static inline const char *skip_separator(const char *p)
+{
+ while (p && (*p == ' ' || *p == '\t'))
+ ++p;
+ return p;
+}
+
/*
* Parses one line from {fs,m}tab
*/
static int mnt_parse_table_line(struct libmnt_fs *fs, const char *s)
{
- int rc, n = 0, xrc;
- char *src = NULL, *fstype = NULL, *optstr = NULL;
+ int rc = 0;
+ char *p;
- rc = sscanf(s, UL_SCNsA" " /* (1) source */
- UL_SCNsA" " /* (2) target */
- UL_SCNsA" " /* (3) FS type */
- UL_SCNsA" " /* (4) options */
- "%n", /* byte count */
+ fs->passno = fs->freq = 0;
- &src,
- &fs->target,
- &fstype,
- &optstr,
- &n);
- xrc = rc;
+ /* (1) source */
+ p = unmangle(s, &s);
+ if (!p || (rc = __mnt_fs_set_source_ptr(fs, p))) {
+ DBG(TAB, ul_debug("tab parse error: [source]"));
+ goto fail;
+ }
- if (rc == 3 || rc == 4) { /* options are optional */
- unmangle_string(src);
- unmangle_string(fs->target);
- unmangle_string(fstype);
+ s = skip_separator(s);
- if (optstr && *optstr)
- unmangle_string(optstr);
+ /* (2) target */
+ fs->target = unmangle(s, &s);
+ if (!fs->target) {
+ DBG(TAB, ul_debug("tab parse error: [target]"));
+ goto fail;
+ }
- /* note that __foo functions do 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, ul_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s));
- rc = -EINVAL;
+ s = skip_separator(s);
+
+ /* (3) FS type */
+ p = unmangle(s, &s);
+ if (!p || (rc = __mnt_fs_set_fstype_ptr(fs, p))) {
+ DBG(TAB, ul_debug("tab parse error: [fstype]"));
+ goto fail;
}
- if (rc) {
- free(src);
- free(fstype);
- free(optstr);
- DBG(TAB, ul_debug("tab parse error: [set vars, rc=%d]\n", rc));
- return rc; /* error */
+ s = skip_separator(s);
+
+ /* (4) options (optional) */
+ p = unmangle(s, &s);
+ if (p && (rc = mnt_fs_set_options(fs, p))) {
+ DBG(TAB, ul_debug("tab parse error: [options]"));
+ goto fail;
}
- fs->passno = fs->freq = 0;
+ if (!p)
+ goto done;
+ s = skip_separator(s);
+ if (!s || !*s)
+ goto done;
- if (xrc == 4 && n)
- s = skip_blank(s + n);
- if (xrc == 4 && *s) {
- int ok = 0;
+ /* (5) freq (optional) */
+ s = next_number(s, &fs->freq, &rc);
+ if (s && *s && rc) {
+ DBG(TAB, ul_debug("tab parse error: [freq]"));
+ goto fail;
+ }
- s = next_number(s, &fs->freq, &ok);
- if (!ok) {
- if (s && *s) {
- DBG(TAB, ul_debug("tab parse error: [freq]"));
- rc = -EINVAL;
- }
- } else {
- s = next_number(s, &fs->passno, &ok);
- if (!ok && s && *s) {
- DBG(TAB, ul_debug("tab parse error: [passno]"));
- rc = -EINVAL;
- }
- }
+ s = skip_separator(s);
+ if (!s || !*s)
+ goto done;
+
+ /* (6) freq (optional) */
+ s = next_number(s, &fs->passno, &rc);
+ if (s && *s && rc) {
+ DBG(TAB, ul_debug("tab parse error: [passno]"));
+ goto fail;
}
+done:
+ return 0;
+fail:
+ if (rc == 0)
+ rc = -EINVAL;
+ DBG(TAB, ul_debug("tab parse error on: '%s' [rc=%d]", s, rc));
return rc;
}
+
/*
* Parses one line from a mountinfo file
*/