mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
cifs: parse the device name into UNC and prepath
This should fix a regression that was introduced when the new mount option parser went in. Also, when the unc= and prefixpath= options are provided, check their values against the ones we parsed from the device string. If they differ, then throw a warning that tells the user that we're using the values from the unc= option for now, but that that will change in 3.10. Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
839db3d10a
commit
d387a5c50b
1 changed files with 88 additions and 7 deletions
|
@ -1096,6 +1096,52 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a devname into substrings and populate the vol->UNC and vol->prepath
|
||||||
|
* fields with the result. Returns 0 on success and an error otherwise.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cifs_parse_devname(const char *devname, struct smb_vol *vol)
|
||||||
|
{
|
||||||
|
char *pos;
|
||||||
|
const char *delims = "/\\";
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* make sure we have a valid UNC double delimiter prefix */
|
||||||
|
len = strspn(devname, delims);
|
||||||
|
if (len != 2)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* find delimiter between host and sharename */
|
||||||
|
pos = strpbrk(devname + 2, delims);
|
||||||
|
if (!pos)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* skip past delimiter */
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
/* now go until next delimiter or end of string */
|
||||||
|
len = strcspn(pos, delims);
|
||||||
|
|
||||||
|
/* move "pos" up to delimiter or NULL */
|
||||||
|
pos += len;
|
||||||
|
vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
|
||||||
|
if (!vol->UNC)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
convert_delimiter(vol->UNC, '\\');
|
||||||
|
|
||||||
|
/* If pos is NULL, or is a bogus trailing delimiter then no prepath */
|
||||||
|
if (!*pos++ || !*pos)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vol->prepath = kstrdup(pos, GFP_KERNEL);
|
||||||
|
if (!vol->prepath)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_parse_mount_options(const char *mountdata, const char *devname,
|
cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||||
struct smb_vol *vol)
|
struct smb_vol *vol)
|
||||||
|
@ -1181,6 +1227,16 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||||
vol->backupuid_specified = false; /* no backup intent for a user */
|
vol->backupuid_specified = false; /* no backup intent for a user */
|
||||||
vol->backupgid_specified = false; /* no backup intent for a group */
|
vol->backupgid_specified = false; /* no backup intent for a group */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now, we ignore -EINVAL errors under the assumption that the
|
||||||
|
* unc= and prefixpath= options will be usable.
|
||||||
|
*/
|
||||||
|
if (cifs_parse_devname(devname, vol) == -ENOMEM) {
|
||||||
|
printk(KERN_ERR "CIFS: Unable to allocate memory to parse "
|
||||||
|
"device string.\n");
|
||||||
|
goto out_nomem;
|
||||||
|
}
|
||||||
|
|
||||||
while ((data = strsep(&options, separator)) != NULL) {
|
while ((data = strsep(&options, separator)) != NULL) {
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
unsigned long option;
|
unsigned long option;
|
||||||
|
@ -1566,18 +1622,31 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||||
got_ip = true;
|
got_ip = true;
|
||||||
break;
|
break;
|
||||||
case Opt_unc:
|
case Opt_unc:
|
||||||
kfree(vol->UNC);
|
string = vol->UNC;
|
||||||
vol->UNC = match_strdup(args);
|
vol->UNC = match_strdup(args);
|
||||||
if (vol->UNC == NULL)
|
if (vol->UNC == NULL) {
|
||||||
|
kfree(string);
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
|
}
|
||||||
|
|
||||||
convert_delimiter(vol->UNC, '\\');
|
convert_delimiter(vol->UNC, '\\');
|
||||||
if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') {
|
if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') {
|
||||||
printk(KERN_WARNING "CIFS: UNC Path does not "
|
kfree(string);
|
||||||
|
printk(KERN_ERR "CIFS: UNC Path does not "
|
||||||
"begin with // or \\\\\n");
|
"begin with // or \\\\\n");
|
||||||
goto cifs_parse_mount_err;
|
goto cifs_parse_mount_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compare old unc= option to new one */
|
||||||
|
if (!string || strcmp(string, vol->UNC))
|
||||||
|
printk(KERN_WARNING "CIFS: the value of the "
|
||||||
|
"unc= mount option does not match the "
|
||||||
|
"device string. Using the unc= option "
|
||||||
|
"for now. In 3.10, that option will "
|
||||||
|
"be ignored and the contents of the "
|
||||||
|
"device string will be used "
|
||||||
|
"instead. (%s != %s)\n", string,
|
||||||
|
vol->UNC);
|
||||||
break;
|
break;
|
||||||
case Opt_domain:
|
case Opt_domain:
|
||||||
string = match_strdup(args);
|
string = match_strdup(args);
|
||||||
|
@ -1616,10 +1685,22 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||||
if (*args[0].from == '/' || *args[0].from == '\\')
|
if (*args[0].from == '/' || *args[0].from == '\\')
|
||||||
args[0].from++;
|
args[0].from++;
|
||||||
|
|
||||||
kfree(vol->prepath);
|
string = vol->prepath;
|
||||||
vol->prepath = match_strdup(args);
|
vol->prepath = match_strdup(args);
|
||||||
if (vol->prepath == NULL)
|
if (vol->prepath == NULL) {
|
||||||
|
kfree(string);
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
|
}
|
||||||
|
/* Compare old prefixpath= option to new one */
|
||||||
|
if (!string || strcmp(string, vol->prepath))
|
||||||
|
printk(KERN_WARNING "CIFS: the value of the "
|
||||||
|
"prefixpath= mount option does not "
|
||||||
|
"match the device string. Using the "
|
||||||
|
"prefixpath= option for now. In 3.10, "
|
||||||
|
"that option will be ignored and the "
|
||||||
|
"contents of the device string will be "
|
||||||
|
"used instead.(%s != %s)\n", string,
|
||||||
|
vol->prepath);
|
||||||
break;
|
break;
|
||||||
case Opt_iocharset:
|
case Opt_iocharset:
|
||||||
string = match_strdup(args);
|
string = match_strdup(args);
|
||||||
|
@ -1777,8 +1858,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!vol->UNC) {
|
if (!vol->UNC) {
|
||||||
cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
|
cERROR(1, "CIFS mount error: No usable UNC path provided in "
|
||||||
"unc=\\\\192.168.1.100\\public) specified");
|
"device string or in unc= option!");
|
||||||
goto cifs_parse_mount_err;
|
goto cifs_parse_mount_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue