aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-12-10 06:10:46 -0500
committerSteve French <smfrench@gmail.com>2012-12-11 12:48:50 -0500
commitd387a5c50bca619d56f276a69627c2e1c6e5c548 (patch)
tree86bc043af2734f67fabc1a3a1031a69e8ac31eaa /fs/cifs
parent839db3d10a5ba792d6533b8bb3380f52ac877344 (diff)
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/connect.c95
1 files changed, 88 insertions, 7 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 94c4484c9ea3..7635b5db26a7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1096,6 +1096,52 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
1096 return 0; 1096 return 0;
1097} 1097}
1098 1098
1099/*
1100 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1101 * fields with the result. Returns 0 on success and an error otherwise.
1102 */
1103static int
1104cifs_parse_devname(const char *devname, struct smb_vol *vol)
1105{
1106 char *pos;
1107 const char *delims = "/\\";
1108 size_t len;
1109
1110 /* make sure we have a valid UNC double delimiter prefix */
1111 len = strspn(devname, delims);
1112 if (len != 2)
1113 return -EINVAL;
1114
1115 /* find delimiter between host and sharename */
1116 pos = strpbrk(devname + 2, delims);
1117 if (!pos)
1118 return -EINVAL;
1119
1120 /* skip past delimiter */
1121 ++pos;
1122
1123 /* now go until next delimiter or end of string */
1124 len = strcspn(pos, delims);
1125
1126 /* move "pos" up to delimiter or NULL */
1127 pos += len;
1128 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1129 if (!vol->UNC)
1130 return -ENOMEM;
1131
1132 convert_delimiter(vol->UNC, '\\');
1133
1134 /* If pos is NULL, or is a bogus trailing delimiter then no prepath */
1135 if (!*pos++ || !*pos)
1136 return 0;
1137
1138 vol->prepath = kstrdup(pos, GFP_KERNEL);
1139 if (!vol->prepath)
1140 return -ENOMEM;
1141
1142 return 0;
1143}
1144
1099static int 1145static int
1100cifs_parse_mount_options(const char *mountdata, const char *devname, 1146cifs_parse_mount_options(const char *mountdata, const char *devname,
1101 struct smb_vol *vol) 1147 struct smb_vol *vol)
@@ -1181,6 +1227,16 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1181 vol->backupuid_specified = false; /* no backup intent for a user */ 1227 vol->backupuid_specified = false; /* no backup intent for a user */
1182 vol->backupgid_specified = false; /* no backup intent for a group */ 1228 vol->backupgid_specified = false; /* no backup intent for a group */
1183 1229
1230 /*
1231 * For now, we ignore -EINVAL errors under the assumption that the
1232 * unc= and prefixpath= options will be usable.
1233 */
1234 if (cifs_parse_devname(devname, vol) == -ENOMEM) {
1235 printk(KERN_ERR "CIFS: Unable to allocate memory to parse "
1236 "device string.\n");
1237 goto out_nomem;
1238 }
1239
1184 while ((data = strsep(&options, separator)) != NULL) { 1240 while ((data = strsep(&options, separator)) != NULL) {
1185 substring_t args[MAX_OPT_ARGS]; 1241 substring_t args[MAX_OPT_ARGS];
1186 unsigned long option; 1242 unsigned long option;
@@ -1566,18 +1622,31 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1566 got_ip = true; 1622 got_ip = true;
1567 break; 1623 break;
1568 case Opt_unc: 1624 case Opt_unc:
1569 kfree(vol->UNC); 1625 string = vol->UNC;
1570 vol->UNC = match_strdup(args); 1626 vol->UNC = match_strdup(args);
1571 if (vol->UNC == NULL) 1627 if (vol->UNC == NULL) {
1628 kfree(string);
1572 goto out_nomem; 1629 goto out_nomem;
1630 }
1573 1631
1574 convert_delimiter(vol->UNC, '\\'); 1632 convert_delimiter(vol->UNC, '\\');
1575 if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') { 1633 if (vol->UNC[0] != '\\' || vol->UNC[1] != '\\') {
1576 printk(KERN_WARNING "CIFS: UNC Path does not " 1634 kfree(string);
1635 printk(KERN_ERR "CIFS: UNC Path does not "
1577 "begin with // or \\\\\n"); 1636 "begin with // or \\\\\n");
1578 goto cifs_parse_mount_err; 1637 goto cifs_parse_mount_err;
1579 } 1638 }
1580 1639
1640 /* Compare old unc= option to new one */
1641 if (!string || strcmp(string, vol->UNC))
1642 printk(KERN_WARNING "CIFS: the value of the "
1643 "unc= mount option does not match the "
1644 "device string. Using the unc= option "
1645 "for now. In 3.10, that option will "
1646 "be ignored and the contents of the "
1647 "device string will be used "
1648 "instead. (%s != %s)\n", string,
1649 vol->UNC);
1581 break; 1650 break;
1582 case Opt_domain: 1651 case Opt_domain:
1583 string = match_strdup(args); 1652 string = match_strdup(args);
@@ -1616,10 +1685,22 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1616 if (*args[0].from == '/' || *args[0].from == '\\') 1685 if (*args[0].from == '/' || *args[0].from == '\\')
1617 args[0].from++; 1686 args[0].from++;
1618 1687
1619 kfree(vol->prepath); 1688 string = vol->prepath;
1620 vol->prepath = match_strdup(args); 1689 vol->prepath = match_strdup(args);
1621 if (vol->prepath == NULL) 1690 if (vol->prepath == NULL) {
1691 kfree(string);
1622 goto out_nomem; 1692 goto out_nomem;
1693 }
1694 /* Compare old prefixpath= option to new one */
1695 if (!string || strcmp(string, vol->prepath))
1696 printk(KERN_WARNING "CIFS: the value of the "
1697 "prefixpath= mount option does not "
1698 "match the device string. Using the "
1699 "prefixpath= option for now. In 3.10, "
1700 "that option will be ignored and the "
1701 "contents of the device string will be "
1702 "used instead.(%s != %s)\n", string,
1703 vol->prepath);
1623 break; 1704 break;
1624 case Opt_iocharset: 1705 case Opt_iocharset:
1625 string = match_strdup(args); 1706 string = match_strdup(args);
@@ -1777,8 +1858,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1777 } 1858 }
1778#endif 1859#endif
1779 if (!vol->UNC) { 1860 if (!vol->UNC) {
1780 cERROR(1, "CIFS mount error: No UNC path (e.g. -o " 1861 cERROR(1, "CIFS mount error: No usable UNC path provided in "
1781 "unc=\\\\192.168.1.100\\public) specified"); 1862 "device string or in unc= option!");
1782 goto cifs_parse_mount_err; 1863 goto cifs_parse_mount_err;
1783 } 1864 }
1784 1865