summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/client/mount.cifs.c90
1 files changed, 66 insertions, 24 deletions
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index e73d90859c..fdee87ae27 100644
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -63,6 +63,8 @@
#define MS_BIND 4096
#endif
+#define MAX_UNC_LEN 1024
+
#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
const char *thisprogram;
@@ -74,7 +76,6 @@ static int got_ip = 0;
static int got_unc = 0;
static int got_uid = 0;
static int got_gid = 0;
-static int free_share_name = 0;
static char * user_name = NULL;
static char * mountpassword = NULL;
char * domain_name = NULL;
@@ -837,17 +838,31 @@ static char * check_for_domain(char **ppuser)
return domainnm;
}
+/* replace all occurances of "from" in a string with "to" */
+static void replace_char(char *string, char from, char to, int maxlen)
+{
+ char *lastchar = string + maxlen;
+ while (string) {
+ string = strchr(string, from);
+ if (string) {
+ *string = to;
+ if (string >= lastchar)
+ return;
+ }
+ }
+}
+
/* Note that caller frees the returned buffer if necessary */
static char * parse_server(char ** punc_name)
{
char * unc_name = *punc_name;
- int length = strnlen(unc_name,1024);
+ int length = strnlen(unc_name, MAX_UNC_LEN);
char * share;
char * ipaddress_string = NULL;
struct hostent * host_entry = NULL;
struct in_addr server_ipaddr;
- if(length > 1023) {
+ if(length > (MAX_UNC_LEN - 1)) {
printf("mount error: UNC name too long");
return NULL;
}
@@ -866,7 +881,6 @@ static char * parse_server(char ** punc_name)
/* check for nfs syntax ie server:share */
share = strchr(unc_name,':');
if(share) {
- free_share_name = 1;
*punc_name = (char *)malloc(length+3);
if(*punc_name == NULL) {
/* put the original string back if
@@ -874,9 +888,9 @@ static char * parse_server(char ** punc_name)
*punc_name = unc_name;
return NULL;
}
-
*share = '/';
strncpy((*punc_name)+2,unc_name,length);
+ free(unc_name);
unc_name = *punc_name;
unc_name[length+2] = 0;
goto continue_unc_parsing;
@@ -890,15 +904,18 @@ continue_unc_parsing:
unc_name[0] = '/';
unc_name[1] = '/';
unc_name += 2;
- if ((share = strchr(unc_name, '/')) ||
- (share = strchr(unc_name,'\\'))) {
+
+ /* allow for either delimiter between host and sharename */
+ if ((share = strpbrk(unc_name, "/\\"))) {
*share = 0; /* temporarily terminate the string */
share += 1;
if(got_ip == 0) {
host_entry = gethostbyname(unc_name);
}
- *(share - 1) = '/'; /* put the slash back */
- if ((prefixpath = strchr(share, '/'))) {
+ *(share - 1) = '/'; /* put delimiter back */
+
+ /* we don't convert the prefixpath delimiters since '\\' is a valid char in posix paths */
+ if ((prefixpath = strpbrk(share, "/\\"))) {
*prefixpath = 0; /* permanently terminate the string */
if (!strlen(++prefixpath))
prefixpath = NULL; /* this needs to be done explicitly */
@@ -963,6 +980,25 @@ static struct option longopts[] = {
{ NULL, 0, NULL, 0 }
};
+/* convert a string to uppercase. return false if the string
+ * wasn't ASCII or was a NULL ptr */
+static int
+uppercase_string(char *string)
+{
+ if (!string)
+ return 0;
+
+ while (*string) {
+ /* check for unicode */
+ if ((unsigned char) string[0] & 0x80)
+ return 0;
+ *string = toupper((unsigned char) *string);
+ string++;
+ }
+
+ return 1;
+}
+
int main(int argc, char ** argv)
{
int c;
@@ -975,6 +1011,7 @@ int main(int argc, char ** argv)
char * options = NULL;
char * resolved_path = NULL;
char * temp;
+ char * dev_name;
int rc;
int rsize = 0;
int wsize = 0;
@@ -1011,8 +1048,16 @@ int main(int argc, char ** argv)
printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
#endif */
if(argc > 2) {
- share_name = argv[1];
+ dev_name = argv[1];
+ share_name = strndup(argv[1], MAX_UNC_LEN);
+ if (share_name == NULL) {
+ fprintf(stderr, "%s: %s", argv[0], strerror(ENOMEM));
+ exit(1);
+ }
mountpoint = argv[2];
+ } else {
+ mount_cifs_usage();
+ exit(1);
}
/* add sharename in opts string as unc= parm */
@@ -1152,7 +1197,7 @@ int main(int argc, char ** argv)
}
}
- if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
+ if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) {
mount_cifs_usage();
exit(1);
}
@@ -1310,10 +1355,12 @@ mount_retry:
}
if(verboseflag)
printf("\nmount.cifs kernel mount options %s \n",options);
- if(mount(share_name, mountpoint, "cifs", flags, options)) {
- /* remember to kill daemon on error */
- char * tmp;
+ /* convert all '\\' to '/' in share portion so that /proc/mounts looks pretty */
+ replace_char(dev_name, '\\', '/', strlen(share_name));
+
+ if(mount(dev_name, mountpoint, "cifs", flags, options)) {
+ /* remember to kill daemon on error */
switch (errno) {
case 0:
printf("mount failed but no error number set\n");
@@ -1324,12 +1371,9 @@ mount_retry:
case ENXIO:
if(retry == 0) {
retry = 1;
- tmp = share_name;
- while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
- *tmp = toupper((unsigned char)*tmp);
- tmp++;
- }
- if(!*tmp) {
+ if (uppercase_string(dev_name) &&
+ uppercase_string(share_name) &&
+ uppercase_string(prefixpath)) {
printf("retrying with upper case share name\n");
goto mount_retry;
}
@@ -1343,7 +1387,7 @@ mount_retry:
} else {
pmntfile = setmntent(MOUNTED, "a+");
if(pmntfile) {
- mountent.mnt_fsname = share_name;
+ mountent.mnt_fsname = dev_name;
mountent.mnt_dir = mountpoint;
mountent.mnt_type = CONST_DISCARD(char *,"cifs");
mountent.mnt_opts = (char *)malloc(220);
@@ -1403,8 +1447,6 @@ mount_exit:
free(resolved_path);
}
- if(free_share_name) {
- free(share_name);
- }
+ free(share_name);
return rc;
}