libmount: don't use /{proc,ext}/filesystems when more fs types specified

# mkfs.ext4 /dev/sda1
 # mount -t foo,bar /dev/sda1 /mnt

successfully mount the device, this is unexpected as extN is no
between wanted (by -t specified) filesystems.

Summary about -t:

 * "mount -t foo"        mount(2) with "foo" type

 * "mount -t foo,bar"    try mount(2) with "foo" or "bar"

 * "mount -t foo,auto"   try mount(2) with "foo" or ask libblkid for
                         the type

 * "mount -t nofoo,bar"  try types from /{etc,proc}/filesystems, but
                         exclude "foo" and "bar"

Note that more filesystems may be specified in fstab (as comma
delimited list). The stuff from fstab is always interpreted as list
and never as a pattern ("no" prefix makes no sense in fstab).

Reported-by: Benno Schulenberg <bensberg@justemail.net>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2014-07-25 12:28:34 +02:00
parent 5cbbdfbfe8
commit 64a7e20980
2 changed files with 62 additions and 47 deletions

View File

@ -758,6 +758,52 @@ static int do_mount(struct libmnt_context *cxt, const char *try_type)
return rc;
}
/* try mount(2) for all items in comma separated list of the filesystem @types */
static int do_mount_by_types(struct libmnt_context *cxt, const char *types)
{
int rc = -EINVAL;
char *p, *p0;
assert(cxt);
assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
DBG(CXT, ul_debugobj(cxt, "trying to mount by FS list '%s'", types));
p0 = p = strdup(types);
if (!p)
return -ENOMEM;
do {
char *autotype = NULL;
char *end = strchr(p, ',');
if (end)
*end = '\0';
DBG(CXT, ul_debugobj(cxt, "-->trying '%s'", p));
/* Let's support things like "udf,iso9660,auto" */
if (strcmp(p, "auto") == 0) {
rc = mnt_context_guess_srcpath_fstype(cxt, &autotype);
if (rc) {
DBG(CXT, ul_debugobj(cxt, "failed to guess FS type"));
free(p0);
return rc;
}
p = autotype;
DBG(CXT, ul_debugobj(cxt, " --> '%s'", p));
}
if (p)
rc = do_mount(cxt, p);
p = end ? end + 1 : NULL;
free(autotype);
} while (!mnt_context_get_status(cxt) && p);
free(p0);
return rc;
}
static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern)
{
int neg = pattern && strncmp(pattern, "no", 2) == 0;
@ -767,54 +813,20 @@ static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern)
assert(cxt);
assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
if (!neg && pattern) {
/*
* try all types from the list
*/
char *p, *p0;
DBG(CXT, ul_debugobj(cxt, "trying to mount by FS pattern list '%s'", pattern));
p0 = p = strdup(pattern);
if (!p)
return -ENOMEM;
do {
char *autotype = NULL;
char *end = strchr(p, ',');
if (end)
*end = '\0';
DBG(CXT, ul_debugobj(cxt, "-->trying '%s'", p));
/* Let's support things like "udf,iso9660,auto" */
if (strcmp(p, "auto") == 0) {
rc = mnt_context_guess_srcpath_fstype(cxt, &autotype);
if (rc) {
DBG(CXT, ul_debugobj(cxt, "failed to guess FS type"));
free(p0);
return rc;
}
p = autotype;
DBG(CXT, ul_debugobj(cxt, " --> '%s'", p));
}
if (p)
rc = do_mount(cxt, p);
p = end ? end + 1 : NULL;
free(autotype);
} while (!mnt_context_get_status(cxt) && p);
free(p0);
if (mnt_context_get_status(cxt))
return rc;
}
/*
* try /etc/filesystems and /proc/filesystems
* Use the pattern as list of the filesystems
*/
if (!neg && pattern) {
DBG(CXT, ul_debugobj(cxt, "use FS pattern as FS list"));
return do_mount_by_types(cxt, pattern);
}
DBG(CXT, ul_debugobj(cxt, "trying to mount by FS pattern '%s'", pattern));
/*
* Apply pattern to /etc/filesystems and /proc/filesystems
*/
DBG(CXT, ul_debugobj(cxt, "trying to mount by filesystems lists"));
rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL);
if (rc)
@ -930,7 +942,7 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
if (type) {
if (strchr(type, ','))
/* this only happens if fstab contains a list of filesystems */
res = do_mount_by_pattern(cxt, type);
res = do_mount_by_types(cxt, type);
else
res = do_mount(cxt, NULL);
} else

View File

@ -572,7 +572,10 @@ try_readonly:
break;
case ENODEV:
warnx(_("unknown filesystem type '%s'"), mnt_context_get_fstype(cxt));
if (mnt_context_get_fstype(cxt))
warnx(_("unknown filesystem type '%s'"), mnt_context_get_fstype(cxt));
else
warnx(_("unknown filesystem type"));
break;
case ENOTBLK: