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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
| cifs_parse_mount_options(const char *mountdata, const char *devname, | ||||
| 			 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->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) { | ||||
| 		substring_t args[MAX_OPT_ARGS]; | ||||
| 		unsigned long option; | ||||
|  | @ -1566,18 +1622,31 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 			got_ip = true; | ||||
| 			break; | ||||
| 		case Opt_unc: | ||||
| 			kfree(vol->UNC); | ||||
| 			string = vol->UNC; | ||||
| 			vol->UNC = match_strdup(args); | ||||
| 			if (vol->UNC == NULL) | ||||
| 			if (vol->UNC == NULL) { | ||||
| 				kfree(string); | ||||
| 				goto out_nomem; | ||||
| 			} | ||||
| 
 | ||||
| 			convert_delimiter(vol->UNC, '\\'); | ||||
| 			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"); | ||||
| 				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; | ||||
| 		case Opt_domain: | ||||
| 			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 == '\\') | ||||
| 				args[0].from++; | ||||
| 
 | ||||
| 			kfree(vol->prepath); | ||||
| 			string = vol->prepath; | ||||
| 			vol->prepath = match_strdup(args); | ||||
| 			if (vol->prepath == NULL) | ||||
| 			if (vol->prepath == NULL) { | ||||
| 				kfree(string); | ||||
| 				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; | ||||
| 		case Opt_iocharset: | ||||
| 			string = match_strdup(args); | ||||
|  | @ -1777,8 +1858,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 	} | ||||
| #endif | ||||
| 	if (!vol->UNC) { | ||||
| 		cERROR(1, "CIFS mount error: No UNC path (e.g. -o " | ||||
| 			"unc=\\\\192.168.1.100\\public) specified"); | ||||
| 		cERROR(1, "CIFS mount error: No usable UNC path provided in " | ||||
| 			  "device string or in unc= option!"); | ||||
| 		goto cifs_parse_mount_err; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeff Layton
				Jeff Layton