[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 dd765c340637341c2c9e26d8d30df0cb14e6f8ea..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
 #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;
@@ -72,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
@@ -141,7 +147,7 @@ static int open_cred_file(char * file_name)
        fs = fopen(file_name,"r");
        if(fs == NULL)
                return errno;
-       line_buf = malloc(4096);
+       line_buf = (char *)malloc(4096);
        if(line_buf == NULL) {
                fclose(fs);
                return -ENOMEM;
@@ -174,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);
@@ -198,7 +204,7 @@ 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) {
@@ -226,7 +232,7 @@ static int open_cred_file(char * file_name)
                                         exit(1);
                                 } else {
                                         if(domain_name == NULL) {
-                                                domain_name = calloc(65,1);
+                                                domain_name = (char *)calloc(65,1);
                                         } else
                                                 memset(domain_name,0,64);
                                         if(domain_name) {
@@ -253,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) {
@@ -301,7 +312,7 @@ static int get_password_from_file(int file_descript, char * filename)
 
 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;
@@ -367,7 +378,7 @@ static int parse_options(char ** optionsp, 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");
@@ -407,6 +418,11 @@ static int parse_options(char ** optionsp, 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");
@@ -555,8 +571,6 @@ static int parse_options(char ** optionsp, 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 */
-                       goto nocopy;
                } else if (strncmp(data, "ro", 2) == 0) {
                        *filesys_flags |= MS_RDONLY;
                } else if (strncmp(data, "rw", 2) == 0) {
@@ -589,7 +603,7 @@ static int parse_options(char ** optionsp, int * filesys_flags)
                if (value)
                        word_len += 1 + strlen(value);
 
-               out = realloc(out, out_len + word_len + 2);
+               out = (char *)realloc(out, out_len + word_len + 2);
                if (out == NULL) {
                        perror("malloc");
                        exit(1);
@@ -606,6 +620,7 @@ static int parse_options(char ** optionsp, int * filesys_flags)
 nocopy:
                data = next_keyword;
        }
+       free(*optionsp);
        *optionsp = out;
        return 0;
 }
@@ -639,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;
 
@@ -703,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;
 
@@ -754,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)) {
@@ -762,7 +777,7 @@ 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 */
@@ -793,6 +808,11 @@ 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");
@@ -861,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;
@@ -885,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";
 
@@ -895,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 */
 
@@ -923,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);
@@ -1008,7 +1043,7 @@ int main(int argc, char ** argv)
                        break;
                case 'p':
                        if(mountpassword == NULL)
-                               mountpassword = calloc(65,1);
+                               mountpassword = (char *)calloc(65,1);
                        if(mountpassword) {
                                got_password = 1;
                                strncpy(mountpassword,optarg,64);
@@ -1026,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;
@@ -1042,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 */
@@ -1061,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)) {
@@ -1108,6 +1151,8 @@ mount_retry:
                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;
@@ -1115,7 +1160,9 @@ mount_retry:
                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");
@@ -1166,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)) {
@@ -1193,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);
@@ -1230,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;
@@ -1243,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);
@@ -1265,6 +1315,6 @@ mount_retry:
        if(free_share_name) {
                free(share_name);
                }
-       return 0;
+       return rc;
 }