The branch, v3-0-test has been updated
       via  f94e4619d1b2985881ec7ed76587057f00fbf1f7 (commit)
       via  e8f569735e2c0523efa175ca44dd919f838ae49e (commit)
      from  76dcbbd1213ebf0212997d9a0599c894076d77bb (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-0-test


- Log -----------------------------------------------------------------
commit f94e4619d1b2985881ec7ed76587057f00fbf1f7
Merge: e8f569735e2c0523efa175ca44dd919f838ae49e 
76dcbbd1213ebf0212997d9a0599c894076d77bb
Author: Simo Sorce <[EMAIL PROTECTED]>
Date:   Mon Dec 17 09:40:10 2007 -0500

    Resolve conflict of merging in J.Layton patch
    
    Merge branch 'v3-0-test' of ssh://git.samba.org/data/git/samba into 
v3-0-simo
    
    Conflicts:
    
        source/client/mount.cifs.c

commit e8f569735e2c0523efa175ca44dd919f838ae49e
Author: Jeff Layton <[EMAIL PROTECTED]>
Date:   Tue Nov 13 09:04:33 2007 -0500

    mount.cifs: fix several problems when mounting subdirectories of shares
    
    This is essentially the same patch as I posted yesterday. The only
    difference is that I added the replace_char helper function and now
    have the code call it instead of doing the conversion internally.
    
    Thoughts?
    
    -------[snip]-------
    
    CIFS has a few problems when mounting subdirectories of shares:
    
    a) mount.cifs assumes that the prefixpath will always begin with a
    forward slash. If it begins with a backslash, then it fails to parse out
    the prefixpath and leaves it appended to the sharename. This causes the
    mount to fail.
    
    b) if the prefixpath uses '/' as a delimiter, it doesn't convert that to
    a "native" prefixpath ('\\' delimiter). The kernel will blindly stuff
    this prefix into the beginning of a path when it builds one from a dentry,
    and this confuses windows servers (samba doesn't seem to care).
    
    c) When you mount a subdir of a share, mount.cifs munges the device string
    so that you can't tell what the prefixpath is. So if I mount:
    
    //server/share/p1/p2/p3
    
    ..then /proc/mounts and mtab will show only:
    
    //server/share
    
    d) If the client has to retry the mount with an uppercase sharename, it
    doesn't also uppercase the prefixpath (not sure if that's a real issue,
    but it seems inconsistent).
    
    The following patch fixes all of these problems. It separates the
    "share_name" from the "device_name", and passes the share_name as the
    unc= string, and the device_name as the first arg to mount(), and to
    setmntent().
    
    It also changes mount.cifs to use '\\' exclusively as a delimiter for
    the unc= and prefixpath= options, and to use '/' exclusively as a
    delimiter in the device string (seemingly necessary since the kernel
    doesn't deal well with backslashes in the device string).
    
    Signed-off-by: Jeff Layton <[EMAIL PROTECTED]>

-----------------------------------------------------------------------

Summary of changes:
 source/client/mount.cifs.c |   94 +++++++++++++++++++++++++++++++-------------
 1 files changed, 66 insertions(+), 28 deletions(-)
 mode change 100755 => 100644 source/client/mount.cifs.c


Changeset truncated at 500 lines:

diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
old mode 100755
new mode 100644
index 33da1a2..3761adb
--- a/source/client/mount.cifs.c
+++ b/source/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;
@@ -829,17 +830,27 @@ 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)
+{
+       while (string) {
+               string = strchr(string, from);
+               if (string)
+                       *string = to;
+       }
+}
+
 /* 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;
        }
@@ -858,7 +869,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 
@@ -866,9 +876,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;
@@ -879,18 +889,21 @@ static char * parse_server(char ** punc_name)
                        }
                } else {
 continue_unc_parsing:
-                       unc_name[0] = '/';
-                       unc_name[1] = '/';
+                       unc_name[0] = '\\';
+                       unc_name[1] = '\\';
                        unc_name += 2;
-                       if ((share = strchr(unc_name, '/')) || 
-                               (share = strchr(unc_name,'\\'))) {
+
+                       /* convert any '/' in unc to '\\' */
+                       replace_char(unc_name, '/', '\\');
+
+                       if ((share = strchr(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 */
+                               if ((prefixpath = strchr(share, '\\'))) {
                                        *prefixpath = 0;  /* permanently 
terminate the string */
                                        if (!strlen(++prefixpath))
                                                prefixpath = NULL; /* this 
needs to be done explicitly */
@@ -955,6 +968,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;
@@ -967,6 +999,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;
@@ -1003,8 +1036,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 */
@@ -1144,7 +1185,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);
        }
@@ -1302,10 +1343,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 '/' so that /proc/mounts looks pretty */
+       replace_char(dev_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");
@@ -1316,12 +1359,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;
                                }
@@ -1335,9 +1375,9 @@ mount_retry:
        } else {
                pmntfile = setmntent(MOUNTED, "a+");
                if(pmntfile) {
-                       mountent.mnt_fsname = share_name;
-                       mountent.mnt_dir = mountpoint;
-                       mountent.mnt_type = CONST_DISCARD(char *,"cifs");
+                       mountent.mnt_fsname = dev_name;
+                       mountent.mnt_dir = mountpoint; 
+                       mountent.mnt_type = CONST_DISCARD(char *,"cifs"); 
                        mountent.mnt_opts = (char *)malloc(220);
                        if(mountent.mnt_opts) {
                                char * mount_user = getusername();
@@ -1395,8 +1435,6 @@ mount_exit:
                free(resolved_path);
        }
 
-       if(free_share_name) {
-               free(share_name);
-               }
+       free(share_name);
        return rc;
 }


-- 
Samba Shared Repository

Reply via email to