[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / client / mount.cifs.c
index b984aaaee857cc7b3053fe440a2b1742ad98578e..eb45ae5b4a038ed2ff76a4bce6fd09971e50c1b6 100755 (executable)
@@ -4,7 +4,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
@@ -24,6 +23,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <grp.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <sys/mount.h>
 #include <fcntl.h>
 
 #define MOUNT_CIFS_VERSION_MAJOR "1"
-#define MOUNT_CIFS_VERSION_MINOR "7"
+#define MOUNT_CIFS_VERSION_MINOR "10"
 
 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
-#define MOUNT_CIFS_VENDOR_SUFFIX ""
-#endif
+ #ifdef _SAMBA_BUILD_
+  #include "include/version.h"
+  #ifdef SAMBA_VERSION_VENDOR_SUFFIX
+   #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
+  #else
+   #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
+  #endif /* SAMBA_VERSION_OFFICIAL_STRING and SAMBA_VERSION_VENDOR_SUFFIX */
+ #else
+   #define MOUNT_CIFS_VENDOR_SUFFIX ""
+ #endif /* _SAMBA_BUILD_ */
+#endif /* MOUNT_CIFS_VENDOR_SUFFIX */
 
 #ifndef MS_MOVE 
 #define MS_MOVE 8192 
 #endif 
 
-char * thisprogram;
+#ifndef MS_BIND
+#define MS_BIND 4096
+#endif
+
+#define CONST_DISCARD(type, ptr)      ((type) ((void *) (ptr)))
+
+const char *thisprogram;
 int verboseflag = 0;
 static int got_password = 0;
 static int got_user = 0;
@@ -62,6 +77,7 @@ static int free_share_name = 0;
 static char * user_name = NULL;
 static char * mountpassword = NULL;
 char * domain_name = NULL;
+char * prefixpath = NULL;
 
 
 /* BB finish BB
@@ -83,11 +99,16 @@ static void mount_cifs_usage(void)
        printf(" to a local directory.\n\nOptions:\n");
        printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
        printf("\nLess commonly used options:");
-       printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,\n\trw,ro,sep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,directio");
-       printf("\n\nOptions not needed for servers supporting CIFS Unix extensions (e.g. most Samba versions):");
-       printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>");
+       printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
+       printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
+       printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
+       printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
+       printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
+       printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
        printf("\n\nRarely used options:");
-       printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,dev,nodev");
+       printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
+       printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
+       printf("\n\tnointr,ignorecase,noposixpaths,noacl");
        printf("\n\nOptions are described in more detail in the manual page");
        printf("\n\tman 8 mount.cifs\n");
        printf("\nTo display the version number of the mount helper:");
@@ -126,9 +147,11 @@ static int open_cred_file(char * file_name)
        fs = fopen(file_name,"r");
        if(fs == NULL)
                return errno;
-       line_buf = malloc(4096);
-       if(line_buf == NULL)
+       line_buf = (char *)malloc(4096);
+       if(line_buf == NULL) {
+               fclose(fs);
                return -ENOMEM;
+       }
 
        while(fgets(line_buf,4096,fs)) {
                /* parse line from credential file */
@@ -157,7 +180,7 @@ static int open_cred_file(char * file_name)
                                        exit(1);
                                } else {
                                        got_user = 1;
-                                       user_name = calloc(1 + length,1);
+                                       user_name = (char *)calloc(1 + length,1);
                                        /* BB adding free of user_name string before exit,
                                                not really necessary but would be cleaner */
                                        strncpy(user_name,temp_val, length);
@@ -181,17 +204,45 @@ static int open_cred_file(char * file_name)
                                        exit(1);
                                } else {
                                        if(mountpassword == NULL) {
-                                               mountpassword = calloc(65,1);
+                                               mountpassword = (char *)calloc(65,1);
                                        } else
                                                memset(mountpassword,0,64);
                                        if(mountpassword) {
-                                               /* BB add handling for commas in password here */
                                                strncpy(mountpassword,temp_val,length);
                                                got_password = 1;
                                        }
                                }
                        }
-               }
+                } else if (strncasecmp("domain",line_buf+i,6) == 0) {
+                        temp_val = strchr(line_buf+i,'=');
+                        if(temp_val) {
+                                /* go past equals sign */
+                                temp_val++;
+                               if(verboseflag)
+                                       printf("\nDomain %s\n",temp_val);
+                                for(length = 0;length<65;length++) {
+                                        if(temp_val[length] == '\n')
+                                                break;
+                                }
+                                if(length > 64) {
+                                        printf("mount.cifs failed: domain in credentials file too long\n");
+                                        if(mountpassword) {
+                                                memset(mountpassword,0,64);
+                                        }
+                                        exit(1);
+                                } else {
+                                        if(domain_name == NULL) {
+                                                domain_name = (char *)calloc(65,1);
+                                        } else
+                                                memset(domain_name,0,64);
+                                        if(domain_name) {
+                                                strncpy(domain_name,temp_val,length);
+                                                got_domain = 1;
+                                        }
+                                }
+                        }
+                }
+
        }
        fclose(fs);
        if(line_buf) {
@@ -208,10 +259,15 @@ static int get_password_from_file(int file_descript, char * filename)
        char c;
 
        if(mountpassword == NULL)
-               mountpassword = calloc(65,1);
+               mountpassword = (char *)calloc(65,1);
        else 
                memset(mountpassword, 0, 64);
 
+       if (mountpassword == NULL) {
+               printf("malloc failed\n");
+               exit(1);
+       }
+
        if(filename != NULL) {
                file_descript = open(filename, O_RDONLY);
                if(file_descript < 0) {
@@ -254,21 +310,23 @@ static int get_password_from_file(int file_descript, char * filename)
        return rc;
 }
 
-static int parse_options(char * options, int * filesys_flags)
+static int parse_options(char ** optionsp, int * filesys_flags)
 {
-       char * data;
+       const char * data;
        char * percent_char = NULL;
        char * value = NULL;
        char * next_keyword = NULL;
+       char * out = NULL;
+       int out_len = 0;
+       int word_len;
        int rc = 0;
 
-       if (!options)
+       if (!optionsp || !*optionsp)
                return 1;
-       else
-               data = options;
+       data = *optionsp;
 
        if(verboseflag)
-               printf("parsing options: %s\n", options);
+               printf("parsing options: %s\n", data);
 
        /* BB fixme check for separator override BB */
 
@@ -286,7 +344,7 @@ static int parse_options(char * options, int * filesys_flags)
        
                /* temporarily null terminate end of keyword=value pair */
                if(next_keyword)
-                       *next_keyword = 0;
+                       *next_keyword++ = 0;
 
                /* temporarily null terminate keyword to make keyword and value distinct */
                if ((value = strchr(data, '=')) != NULL) {
@@ -296,7 +354,7 @@ static int parse_options(char * options, int * filesys_flags)
 
                if (strncmp(data, "users",5) == 0) {
                        if(!value || !*value) {
-                               strncpy(data,",,,,,",5);
+                               goto nocopy;
                        }
                } else if (strncmp(data, "user_xattr",10) == 0) {
                   /* do nothing - need to skip so not parsed as user name */
@@ -308,10 +366,7 @@ static int parse_options(char * options, int * filesys_flags)
                                                printf("\nskipping empty user mount parameter\n");
                                        /* remove the parm since it would otherwise be confusing
                                        to the kernel code which would think it was a real username */
-                                               data[0] = ',';
-                                               data[1] = ',';
-                                               data[2] = ',';
-                                               data[3] = ',';
+                                       goto nocopy;
                                } else {
                                        printf("username specified with no parameter\n");
                                        return 1;       /* needs_arg; */
@@ -323,7 +378,7 @@ static int parse_options(char * options, int * filesys_flags)
                                        if(percent_char) {
                                                *percent_char = ',';
                                                if(mountpassword == NULL)
-                                                       mountpassword = calloc(65,1);
+                                                       mountpassword = (char *)calloc(65,1);
                                                if(mountpassword) {
                                                        if(got_password)
                                                                printf("\nmount.cifs warning - password specified twice\n");
@@ -363,6 +418,11 @@ static int parse_options(char * options, int * filesys_flags)
                                printf("password too long\n");
                                return 1;
                        }
+               } else if (strncmp(data, "sec", 3) == 0) {
+                       if (value) {
+                               if (!strcmp(value, "none"))
+                                       got_password = 1;
+                       }
                } else if (strncmp(data, "ip", 2) == 0) {
                        if (!value || !*value) {
                                printf("target ip address argument missing");
@@ -430,10 +490,34 @@ static int parse_options(char * options, int * filesys_flags)
                } else if (strncmp(data, "uid", 3) == 0) {
                        if (value && *value) {
                                got_uid = 1;
+                               if (!isdigit(*value)) {
+                                       struct passwd *pw;
+                                       static char temp[32];
+
+                                       if (!(pw = getpwnam(value))) {
+                                               printf("bad user name \"%s\"\n", value);
+                                               exit(1);
+                                       }
+                                       sprintf(temp, "%u", pw->pw_uid);
+                                       value = temp;
+                                       endpwent();
+                               }
                        }
                } else if (strncmp(data, "gid", 3) == 0) {
                        if (value && *value) {
                                got_gid = 1;
+                               if (!isdigit(*value)) {
+                                       struct group *gr;
+                                       static char temp[32];
+
+                                       if (!(gr = getgrnam(value))) {
+                                               printf("bad group name \"%s\"\n", value);
+                                               exit(1);
+                                       }
+                                       sprintf(temp, "%u", gr->gr_gid);
+                                       value = temp;
+                                       endpwent();
+                               }
                        }
        /* fmask and dmask synonyms for people used to smbfs syntax */
                } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
@@ -476,6 +560,9 @@ static int parse_options(char * options, int * filesys_flags)
                        *filesys_flags &= ~MS_NOSUID;
                } else if (strncmp(data, "nodev", 5) == 0) {
                        *filesys_flags |= MS_NODEV;
+               } else if ((strncmp(data, "nobrl", 5) == 0) || 
+                          (strncmp(data, "nolock", 6) == 0)) {
+                       *filesys_flags &= ~MS_MANDLOCK;
                } else if (strncmp(data, "dev", 3) == 0) {
                        *filesys_flags &= ~MS_NODEV;
                } else if (strncmp(data, "noexec", 6) == 0) {
@@ -484,16 +571,12 @@ static int parse_options(char * options, int * filesys_flags)
                        *filesys_flags &= ~MS_NOEXEC;
                } else if (strncmp(data, "guest", 5) == 0) {
                        got_password=1;
-                        /* remove the parm since it would otherwise be logged by kern */
-                       data[0] = ',';
-                        data[1] = ',';
-                        data[2] = ',';
-                       data[3] = ',';
-                       data[4] = ',';
                } else if (strncmp(data, "ro", 2) == 0) {
                        *filesys_flags |= MS_RDONLY;
                } else if (strncmp(data, "rw", 2) == 0) {
                        *filesys_flags &= ~MS_RDONLY;
+                } else if (strncmp(data, "remount", 7) == 0) {
+                        *filesys_flags |= MS_REMOUNT;
                } /* else if (strnicmp(data, "port", 4) == 0) {
                        if (value && *value) {
                                vol->port =
@@ -515,21 +598,30 @@ static int parse_options(char * options, int * filesys_flags)
                } */ /* nothing to do on those four mount options above.
                        Just pass to kernel and ignore them here */
 
-                       /* move to next option */
-               data = next_keyword+1;
+               /* Copy (possibly modified) option to out */
+               word_len = strlen(data);
+               if (value)
+                       word_len += 1 + strlen(value);
 
-               /* put overwritten equals sign back */
-               if(value) {
-                       value--;
-                       *value = '=';
+               out = (char *)realloc(out, out_len + word_len + 2);
+               if (out == NULL) {
+                       perror("malloc");
+                       exit(1);
                }
-       
-               /* put previous overwritten comma back */
-               if(next_keyword)
-                       *next_keyword = ','; /* BB handle sep= */
+
+               if (out_len)
+                       out[out_len++] = ',';
+               if (value)
+                       sprintf(out + out_len, "%s=%s", data, value);
                else
-                       data = NULL;
+                       sprintf(out + out_len, "%s", data);
+               out_len = strlen(out);
+
+nocopy:
+               data = next_keyword;
        }
+       free(*optionsp);
+       *optionsp = out;
        return 0;
 }
 
@@ -540,13 +632,15 @@ static void check_for_comma(char ** ppasswrd)
        char *pass;
        int i,j;
        int number_of_commas = 0;
-       int len = strlen(*ppasswrd);
+       int len;
 
        if(ppasswrd == NULL)
                return;
        else 
                (pass = *ppasswrd);
 
+       len = strlen(pass);
+
        for(i=0;i<len;i++)  {
                if(pass[i] == ',')
                        number_of_commas++;
@@ -560,7 +654,7 @@ static void check_for_comma(char ** ppasswrd)
                return;
        }
 
-       new_pass_buf = malloc(len+number_of_commas+1);
+       new_pass_buf = (char *)malloc(len+number_of_commas+1);
        if(new_pass_buf == NULL)
                return;
 
@@ -624,7 +718,7 @@ static char * check_for_domain(char **ppuser)
        len = strlen(domainnm);
        /* reset domainm to new buffer, and copy
        domain name into it */
-       domainnm = malloc(len+1);
+       domainnm = (char *)malloc(len+1);
        if(domainnm == NULL)
                return NULL;
 
@@ -660,9 +754,8 @@ static char * parse_server(char ** punc_name)
        int length = strnlen(unc_name,1024);
        char * share;
        char * ipaddress_string = NULL;
-       struct hostent * host_entry;
+       struct hostent * host_entry = NULL;
        struct in_addr server_ipaddr;
-       int rc;
 
        if(length > 1023) {
                printf("mount error: UNC name too long");
@@ -676,7 +769,7 @@ static char * parse_server(char ** punc_name)
 
        if(length < 3) {
                /* BB add code to find DFS root here */
-               printf("\nMounting the DFS root for domain not implemented yet");
+               printf("\nMounting the DFS root for domain not implemented yet\n");
                return NULL;
        } else {
                if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
@@ -684,7 +777,14 @@ static char * parse_server(char ** punc_name)
                        share = strchr(unc_name,':');
                        if(share) {
                                free_share_name = 1;
-                               *punc_name = malloc(length+3);
+                               *punc_name = (char *)malloc(length+3);
+                               if(*punc_name == NULL) {
+                                       /* put the original string back  if 
+                                          no memory left */
+                                       *punc_name = unc_name;
+                                       return NULL;
+                               }
+                                       
                                *share = '/';
                                strncpy((*punc_name)+2,unc_name,length);
                                unc_name = *punc_name;
@@ -708,14 +808,18 @@ continue_unc_parsing:
                                        host_entry = gethostbyname(unc_name);
                                }
                                *(share - 1) = '/'; /* put the slash back */
+                               if ((prefixpath = strchr(share, '/'))) {
+                                       *prefixpath = 0;  /* permanently terminate the string */
+                                       if (!strlen(++prefixpath))
+                                               prefixpath = NULL; /* this needs to be done explicitly */
+                               }
                                if(got_ip) {
                                        if(verboseflag)
                                                printf("ip address specified explicitly\n");
                                        return NULL;
                                }
                                if(host_entry == NULL) {
-                                       printf("mount error: could not find target server. TCP name %s not found ", unc_name);
-                                       printf(" rc = %d\n",rc);
+                                       printf("mount error: could not find target server. TCP name %s not found\n", unc_name);
                                        return NULL;
                                } else {
                                        /* BB should we pass an alternate version of the share name as Unicode */
@@ -777,9 +881,9 @@ int main(int argc, char ** argv)
        char * share_name = NULL;
        char * ipaddr = NULL;
        char * uuid = NULL;
-       char * mountpoint;
-       char * options;
-       char * resolved_path;
+       char * mountpoint = NULL;
+       char * options = NULL;
+       char * resolved_path = NULL;
        char * temp;
        int rc;
        int rsize = 0;
@@ -801,7 +905,11 @@ int main(int argc, char ** argv)
 
        if(argc && argv) {
                thisprogram = argv[0];
+       } else {
+               mount_cifs_usage();
+               exit(1);
        }
+
        if(thisprogram == NULL)
                thisprogram = "mount.cifs";
 
@@ -811,9 +919,10 @@ int main(int argc, char ** argv)
 /* #ifdef _GNU_SOURCE
        printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
 #endif */
-
-       share_name = argv[1];
-       mountpoint = argv[2];
+       if(argc > 2) {
+               share_name = argv[1];
+               mountpoint = argv[2];
+       }
 
        /* add sharename in opts string as unc= parm */
 
@@ -839,10 +948,20 @@ int main(int argc, char ** argv)
                    ++nomtab;
                    break;
                case 'b':
+#ifdef MS_BIND
                        flags |= MS_BIND;
+#else
+                       fprintf(stderr,
+                               "option 'b' (MS_BIND) not supported\n");
+#endif
                        break;
                case 'm':
+#ifdef MS_MOVE               
                        flags |= MS_MOVE;
+#else
+                       fprintf(stderr,
+                               "option 'm' (MS_MOVE) not supported\n");
+#endif
                        break;
                case 'o':
                        orgoptions = strdup(optarg);
@@ -875,10 +994,44 @@ int main(int argc, char ** argv)
                        wsize = atoi(optarg);
                        break;
                case '1':
-                       uid = atoi(optarg);
+                       if (isdigit(*optarg)) {
+                               char *ep;
+
+                               uid = strtoul(optarg, &ep, 10);
+                               if (*ep) {
+                                       printf("bad uid value \"%s\"\n", optarg);
+                                       exit(1);
+                               }
+                       } else {
+                               struct passwd *pw;
+
+                               if (!(pw = getpwnam(optarg))) {
+                                       printf("bad user name \"%s\"\n", optarg);
+                                       exit(1);
+                               }
+                               uid = pw->pw_uid;
+                               endpwent();
+                       }
                        break;
                case '2':
-                       gid = atoi(optarg);
+                       if (isdigit(*optarg)) {
+                               char *ep;
+
+                               gid = strtoul(optarg, &ep, 10);
+                               if (*ep) {
+                                       printf("bad gid value \"%s\"\n", optarg);
+                                       exit(1);
+                               }
+                       } else {
+                               struct group *gr;
+
+                               if (!(gr = getgrnam(optarg))) {
+                                       printf("bad user name \"%s\"\n", optarg);
+                                       exit(1);
+                               }
+                               gid = gr->gr_gid;
+                               endpwent();
+                       }
                        break;
                case 'u':
                        got_user = 1;
@@ -886,10 +1039,11 @@ int main(int argc, char ** argv)
                        break;
                case 'd':
                        domain_name = optarg; /* BB fix this - currently ignored */
+                       got_domain = 1;
                        break;
                case 'p':
                        if(mountpassword == NULL)
-                               mountpassword = calloc(65,1);
+                               mountpassword = (char *)calloc(65,1);
                        if(mountpassword) {
                                got_password = 1;
                                strncpy(mountpassword,optarg,64);
@@ -907,12 +1061,14 @@ int main(int argc, char ** argv)
                }
        }
 
-       if(argc < 3)
+       if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
                mount_cifs_usage();
+               exit(1);
+       }
 
        if (getenv("PASSWD")) {
                if(mountpassword == NULL)
-                       mountpassword = calloc(65,1);
+                       mountpassword = (char *)calloc(65,1);
                if(mountpassword) {
                        strncpy(mountpassword,getenv("PASSWD"),64);
                        got_password = 1;
@@ -923,16 +1079,19 @@ int main(int argc, char ** argv)
                get_password_from_file(0, getenv("PASSWD_FILE"));
        }
 
-        if (orgoptions && parse_options(orgoptions, &flags))
-                return -1;
+        if (orgoptions && parse_options(&orgoptions, &flags)) {
+                rc = -1;
+               goto mount_exit;
+       }
        ipaddr = parse_server(&share_name);
        if((ipaddr == NULL) && (got_ip == 0)) {
                printf("No ip address specified and hostname not found\n");
-               return -1;
+               rc = -1;
+               goto mount_exit;
        }
        
        /* BB save off path and pop after mount returns? */
-       resolved_path = malloc(PATH_MAX+1);
+       resolved_path = (char *)malloc(PATH_MAX+1);
        if(resolved_path) {
                /* Note that if we can not canonicalize the name, we get
                another chance to see if it is valid when we chdir to it */
@@ -942,17 +1101,20 @@ int main(int argc, char ** argv)
        }
        if(chdir(mountpoint)) {
                printf("mount error: can not change directory into mount target %s\n",mountpoint);
-               return -1;
+               rc = -1;
+               goto mount_exit;
        }
 
        if(stat (".", &statbuf)) {
                printf("mount error: mount point %s does not exist\n",mountpoint);
-               return -1;
+               rc = -1;
+               goto mount_exit;
        }
 
        if (S_ISDIR(statbuf.st_mode) == 0) {
                printf("mount error: mount point %s is not a directory\n",mountpoint);
-               return -1;
+               rc = -1;
+               goto mount_exit;
        }
 
        if((getuid() != 0) && (geteuid() == 0)) {
@@ -987,13 +1149,20 @@ mount_retry:
                optlen = 0;
        if(share_name)
                optlen += strlen(share_name) + 4;
+       else {
+               printf("No server share name specified\n");
+               printf("\nMounting the DFS root for server not implemented yet\n");
+                exit(1);
+       }
        if(user_name)
                optlen += strlen(user_name) + 6;
        if(ipaddr)
                optlen += strlen(ipaddr) + 4;
        if(mountpassword)
                optlen += strlen(mountpassword) + 6;
-       options = malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain=  , domain name itself was counted as part of the length username string above */);
+       if(options)
+               free(options);
+       options = (char *)malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain=  , domain name itself was counted as part of the length username string above */);
 
        if(options == NULL) {
                printf("Could not allocate memory for mount options\n");
@@ -1015,7 +1184,8 @@ mount_retry:
 
        if(user_name) {
                /* check for syntax like user=domain\user */
-               domain_name = check_for_domain(&user_name);
+               if(got_domain == 0)
+                       domain_name = check_for_domain(&user_name);
                strncat(options,",user=",6);
                strcat(options,user_name);
        }
@@ -1043,6 +1213,10 @@ mount_retry:
                strcat(options,",");
                strcat(options,orgoptions);
        }
+       if(prefixpath) {
+               strncat(options,",prefixpath=",12);
+               strcat(options,prefixpath); /* no need to cat the / */
+       }       
        if(verboseflag)
                printf("\nmount.cifs kernel mount options %s \n",options);
        if(mount(share_name, mountpoint, "cifs", flags, options)) {
@@ -1070,21 +1244,18 @@ mount_retry:
                                }
                        }
                default:
-                       
                        printf("mount error %d = %s\n",errno,strerror(errno));
                }
                printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
-               if(mountpassword) {
-                       memset(mountpassword,0,64);
-               }
-               return -1;
+               rc = -1;
+               goto mount_exit;
        } else {
                pmntfile = setmntent(MOUNTED, "a+");
                if(pmntfile) {
                        mountent.mnt_fsname = share_name;
                        mountent.mnt_dir = mountpoint; 
-                       mountent.mnt_type = "cifs"
-                       mountent.mnt_opts = malloc(220);
+                       mountent.mnt_type = CONST_DISCARD(char *,"cifs")
+                       mountent.mnt_opts = (char *)malloc(220);
                        if(mountent.mnt_opts) {
                                char * mount_user = getusername();
                                memset(mountent.mnt_opts,0,200);
@@ -1094,8 +1265,6 @@ mount_retry:
                                        strcat(mountent.mnt_opts,"rw");
                                if(flags & MS_MANDLOCK)
                                        strcat(mountent.mnt_opts,",mand");
-                               else
-                                       strcat(mountent.mnt_opts,",nomand");
                                if(flags & MS_NOEXEC)
                                        strcat(mountent.mnt_opts,",noexec");
                                if(flags & MS_NOSUID)
@@ -1109,7 +1278,7 @@ mount_retry:
                                                strcat(mountent.mnt_opts,",user=");
                                                strcat(mountent.mnt_opts,mount_user);
                                        }
-                                       free(mount_user);
+                                       /* free(mount_user); do not free static mem */
                                }
                        }
                        mountent.mnt_freq = 0;
@@ -1122,6 +1291,8 @@ mount_retry:
                    printf("could not update mount table\n");
                }
        }
+       rc = 0;
+mount_exit:
        if(mountpassword) {
                int len = strlen(mountpassword);
                memset(mountpassword,0,len);
@@ -1144,6 +1315,6 @@ mount_retry:
        if(free_share_name) {
                free(share_name);
                }
-       return 0;
+       return rc;
 }