2 Mount helper utility for Linux CIFS VFS (virtual filesystem) client
3 Copyright (C) 2003,2005 Steve French (sfrench@us.ibm.com)
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
29 #include <sys/types.h>
30 #include <sys/mount.h>
32 #include <sys/utsname.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
42 #define MOUNT_CIFS_VERSION_MAJOR "1"
43 #define MOUNT_CIFS_VERSION_MINOR "10"
45 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
47 #include "include/version.h"
48 #ifdef SAMBA_VERSION_VENDOR_SUFFIX
49 #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
51 #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
52 #endif /* SAMBA_VERSION_OFFICIAL_STRING and SAMBA_VERSION_VENDOR_SUFFIX */
54 #define MOUNT_CIFS_VENDOR_SUFFIX ""
55 #endif /* _SAMBA_BUILD_ */
56 #endif /* MOUNT_CIFS_VENDOR_SUFFIX */
66 #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
68 const char *thisprogram
;
70 static int got_password
= 0;
71 static int got_user
= 0;
72 static int got_domain
= 0;
73 static int got_ip
= 0;
74 static int got_unc
= 0;
75 static int got_uid
= 0;
76 static int got_gid
= 0;
77 static int free_share_name
= 0;
78 static char * user_name
= NULL
;
79 static char * mountpassword
= NULL
;
80 char * domain_name
= NULL
;
81 char * prefixpath
= NULL
;
82 char * servern
= NULL
;
87 open nofollow - avoid symlink exposure?
88 get owner of dir see if matches self or if root
89 call system(umount argv) etc.
93 static char * check_for_domain(char **);
96 static void mount_cifs_usage(void)
98 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram
);
99 printf("\nMount the remote target, specified as a UNC name,");
100 printf(" to a local directory.\n\nOptions:\n");
101 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
102 printf("\nLess commonly used options:");
103 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
104 printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
105 printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
106 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
107 printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
108 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
109 printf("\n\nRarely used options:");
110 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
111 printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
112 printf("\n\tnointr,ignorecase,noposixpaths,noacl");
113 printf("\n\nOptions are described in more detail in the manual page");
114 printf("\n\tman 8 mount.cifs\n");
115 printf("\nTo display the version number of the mount helper:");
116 printf("\n\t%s -V\n",thisprogram
);
119 memset(mountpassword
,0,64);
125 /* caller frees username if necessary */
126 static char * getusername(void) {
127 char *username
= NULL
;
128 struct passwd
*password
= getpwuid(getuid());
131 if(password
->pw_name
);
132 username
= strdup(password
->pw_name
);
137 static char * parse_cifs_url(char * unc_name
)
139 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name
);
143 static int open_cred_file(char * file_name
)
149 fs
= fopen(file_name
,"r");
152 line_buf
= (char *)malloc(4096);
153 if(line_buf
== NULL
) {
158 while(fgets(line_buf
,4096,fs
)) {
159 /* parse line from credential file */
161 /* eat leading white space */
162 for(i
=0;i
<4086;i
++) {
163 if((line_buf
[i
] != ' ') && (line_buf
[i
] != '\t'))
165 /* if whitespace - skip past it */
167 if (strncasecmp("username",line_buf
+i
,8) == 0) {
168 temp_val
= strchr(line_buf
+ i
,'=');
170 /* go past equals sign */
172 for(length
= 0;length
<4087;length
++) {
173 if(temp_val
[length
] == '\n')
177 printf("mount.cifs failed due to malformed username in credentials file");
178 memset(line_buf
,0,4096);
180 memset(mountpassword
,0,64);
185 user_name
= (char *)calloc(1 + length
,1);
186 /* BB adding free of user_name string before exit,
187 not really necessary but would be cleaner */
188 strncpy(user_name
,temp_val
, length
);
191 } else if (strncasecmp("password",line_buf
+i
,8) == 0) {
192 temp_val
= strchr(line_buf
+i
,'=');
194 /* go past equals sign */
196 for(length
= 0;length
<65;length
++) {
197 if(temp_val
[length
] == '\n')
201 printf("mount.cifs failed: password in credentials file too long\n");
202 memset(line_buf
,0, 4096);
204 memset(mountpassword
,0,64);
208 if(mountpassword
== NULL
) {
209 mountpassword
= (char *)calloc(65,1);
211 memset(mountpassword
,0,64);
213 strncpy(mountpassword
,temp_val
,length
);
218 } else if (strncasecmp("domain",line_buf
+i
,6) == 0) {
219 temp_val
= strchr(line_buf
+i
,'=');
221 /* go past equals sign */
224 printf("\nDomain %s\n",temp_val
);
225 for(length
= 0;length
<65;length
++) {
226 if(temp_val
[length
] == '\n')
230 printf("mount.cifs failed: domain in credentials file too long\n");
232 memset(mountpassword
,0,64);
236 if(domain_name
== NULL
) {
237 domain_name
= (char *)calloc(65,1);
239 memset(domain_name
,0,64);
241 strncpy(domain_name
,temp_val
,length
);
251 memset(line_buf
,0,4096);
257 static int get_password_from_file(int file_descript
, char * filename
)
263 if(mountpassword
== NULL
)
264 mountpassword
= (char *)calloc(65,1);
266 memset(mountpassword
, 0, 64);
268 if (mountpassword
== NULL
) {
269 printf("malloc failed\n");
273 if(filename
!= NULL
) {
274 file_descript
= open(filename
, O_RDONLY
);
275 if(file_descript
< 0) {
276 printf("mount.cifs failed. %s attempting to open password file %s\n",
277 strerror(errno
),filename
);
281 /* else file already open and fd provided */
284 rc
= read(file_descript
,&c
,1);
286 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno
));
287 memset(mountpassword
,0,64);
289 close(file_descript
);
292 if(mountpassword
[0] == 0) {
294 printf("\nWarning: null password used since cifs password file empty");
297 } else /* read valid character */ {
298 if((c
== 0) || (c
== '\n')) {
301 mountpassword
[i
] = c
;
304 if((i
== 64) && (verboseflag
)) {
305 printf("\nWarning: password longer than 64 characters specified in cifs password file");
308 if(filename
!= NULL
) {
309 close(file_descript
);
315 static int parse_options(char ** optionsp
, int * filesys_flags
)
318 char * percent_char
= NULL
;
320 char * next_keyword
= NULL
;
326 if (!optionsp
|| !*optionsp
)
331 printf("parsing options: %s\n", data
);
333 /* BB fixme check for separator override BB */
335 /* while ((data = strsep(&options, ",")) != NULL) { */
336 while(data
!= NULL
) {
337 /* check if ends with trailing comma */
341 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
342 /* data = next keyword */
343 /* value = next value ie stuff after equal sign */
345 next_keyword
= strchr(data
,','); /* BB handle sep= */
347 /* temporarily null terminate end of keyword=value pair */
351 /* temporarily null terminate keyword to make keyword and value distinct */
352 if ((value
= strchr(data
, '=')) != NULL
) {
357 if (strncmp(data
, "users",5) == 0) {
358 if(!value
|| !*value
) {
361 } else if (strncmp(data
, "user_xattr",10) == 0) {
362 /* do nothing - need to skip so not parsed as user name */
363 } else if (strncmp(data
, "user", 4) == 0) {
365 if (!value
|| !*value
) {
366 if(data
[4] == '\0') {
368 printf("\nskipping empty user mount parameter\n");
369 /* remove the parm since it would otherwise be confusing
370 to the kernel code which would think it was a real username */
373 printf("username specified with no parameter\n");
374 return 1; /* needs_arg; */
377 if (strnlen(value
, 260) < 260) {
379 percent_char
= strchr(value
,'%');
382 if(mountpassword
== NULL
)
383 mountpassword
= (char *)calloc(65,1);
386 printf("\nmount.cifs warning - password specified twice\n");
389 strncpy(mountpassword
, percent_char
,64);
390 /* remove password from username */
391 while(*percent_char
!= 0) {
397 /* this is only case in which the user
398 name buf is not malloc - so we have to
399 check for domain name embedded within
400 the user name here since the later
401 call to check_for_domain will not be
403 domain_name
= check_for_domain(&value
);
405 printf("username too long\n");
409 } else if (strncmp(data
, "pass", 4) == 0) {
410 if (!value
|| !*value
) {
412 printf("\npassword specified twice, ignoring second\n");
415 } else if (strnlen(value
, 17) < 17) {
417 printf("\nmount.cifs warning - password specified twice\n");
420 printf("password too long\n");
423 } else if (strncmp(data
, "sec", 3) == 0) {
425 if (!strcmp(value
, "none"))
428 } else if (strncmp(data
, "ip", 2) == 0) {
429 if (!value
|| !*value
) {
430 printf("target ip address argument missing");
431 } else if (strnlen(value
, 35) < 35) {
433 printf("ip address %s override specified\n",value
);
436 printf("ip address too long\n");
439 } else if ((strncmp(data
, "unc", 3) == 0)
440 || (strncmp(data
, "target", 6) == 0)
441 || (strncmp(data
, "path", 4) == 0)) {
442 if (!value
|| !*value
) {
443 printf("invalid path to network resource\n");
444 return 1; /* needs_arg; */
445 } else if(strnlen(value
,5) < 5) {
446 printf("UNC name too short");
449 if (strnlen(value
, 300) < 300) {
451 if (strncmp(value
, "//", 2) == 0) {
453 printf("unc name specified twice, ignoring second\n");
456 } else if (strncmp(value
, "\\\\", 2) != 0) {
457 printf("UNC Path does not begin with // or \\\\ \n");
461 printf("unc name specified twice, ignoring second\n");
466 printf("CIFS: UNC name too long\n");
469 } else if ((strncmp(data
, "domain", 3) == 0)
470 || (strncmp(data
, "workgroup", 5) == 0)) {
471 if (!value
|| !*value
) {
472 printf("CIFS: invalid domain name\n");
473 return 1; /* needs_arg; */
475 if (strnlen(value
, 65) < 65) {
478 printf("domain name too long\n");
481 } else if (strncmp(data
, "cred", 4) == 0) {
482 if (value
&& *value
) {
483 rc
= open_cred_file(value
);
485 printf("error %d opening credential file %s\n",rc
, value
);
489 printf("invalid credential file name specified\n");
492 } else if (strncmp(data
, "uid", 3) == 0) {
493 if (value
&& *value
) {
495 if (!isdigit(*value
)) {
497 static char temp
[32];
499 if (!(pw
= getpwnam(value
))) {
500 printf("bad user name \"%s\"\n", value
);
503 sprintf(temp
, "%u", pw
->pw_uid
);
508 } else if (strncmp(data
, "gid", 3) == 0) {
509 if (value
&& *value
) {
511 if (!isdigit(*value
)) {
513 static char temp
[32];
515 if (!(gr
= getgrnam(value
))) {
516 printf("bad group name \"%s\"\n", value
);
519 sprintf(temp
, "%u", gr
->gr_gid
);
524 /* fmask and dmask synonyms for people used to smbfs syntax */
525 } else if (strcmp(data
, "file_mode") == 0 || strcmp(data
, "fmask")==0) {
526 if (!value
|| !*value
) {
527 printf ("Option '%s' requires a numerical argument\n", data
);
531 if (value
[0] != '0') {
532 printf ("WARNING: '%s' not expressed in octal.\n", data
);
535 if (strcmp (data
, "fmask") == 0) {
536 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
537 data
= "file_mode"; /* BB fix this */
539 } else if (strcmp(data
, "dir_mode") == 0 || strcmp(data
, "dmask")==0) {
540 if (!value
|| !*value
) {
541 printf ("Option '%s' requires a numerical argument\n", data
);
545 if (value
[0] != '0') {
546 printf ("WARNING: '%s' not expressed in octal.\n", data
);
549 if (strcmp (data
, "dmask") == 0) {
550 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
553 /* the following eight mount options should be
554 stripped out from what is passed into the kernel
555 since these eight options are best passed as the
556 mount flags rather than redundantly to the kernel
557 and could generate spurious warnings depending on the
558 level of the corresponding cifs vfs kernel code */
559 } else if (strncmp(data
, "nosuid", 6) == 0) {
560 *filesys_flags
|= MS_NOSUID
;
561 } else if (strncmp(data
, "suid", 4) == 0) {
562 *filesys_flags
&= ~MS_NOSUID
;
563 } else if (strncmp(data
, "nodev", 5) == 0) {
564 *filesys_flags
|= MS_NODEV
;
565 } else if ((strncmp(data
, "nobrl", 5) == 0) ||
566 (strncmp(data
, "nolock", 6) == 0)) {
567 *filesys_flags
&= ~MS_MANDLOCK
;
568 } else if (strncmp(data
, "dev", 3) == 0) {
569 *filesys_flags
&= ~MS_NODEV
;
570 } else if (strncmp(data
, "noexec", 6) == 0) {
571 *filesys_flags
|= MS_NOEXEC
;
572 } else if (strncmp(data
, "exec", 4) == 0) {
573 *filesys_flags
&= ~MS_NOEXEC
;
574 } else if (strncmp(data
, "guest", 5) == 0) {
576 } else if (strncmp(data
, "ro", 2) == 0) {
577 *filesys_flags
|= MS_RDONLY
;
578 } else if (strncmp(data
, "rw", 2) == 0) {
579 *filesys_flags
&= ~MS_RDONLY
;
580 } else if (strncmp(data
, "remount", 7) == 0) {
581 *filesys_flags
|= MS_REMOUNT
;
582 } /* else if (strnicmp(data, "port", 4) == 0) {
583 if (value && *value) {
585 simple_strtoul(value, &value, 0);
587 } else if (strnicmp(data, "rsize", 5) == 0) {
588 if (value && *value) {
590 simple_strtoul(value, &value, 0);
592 } else if (strnicmp(data, "wsize", 5) == 0) {
593 if (value && *value) {
595 simple_strtoul(value, &value, 0);
597 } else if (strnicmp(data, "version", 3) == 0) {
599 printf("CIFS: Unknown mount option %s\n",data);
600 } */ /* nothing to do on those four mount options above.
601 Just pass to kernel and ignore them here */
603 /* Copy (possibly modified) option to out */
604 word_len
= strlen(data
);
606 word_len
+= 1 + strlen(value
);
608 out
= (char *)realloc(out
, out_len
+ word_len
+ 2);
615 out
[out_len
++] = ',';
617 sprintf(out
+ out_len
, "%s=%s", data
, value
);
619 sprintf(out
+ out_len
, "%s", data
);
620 out_len
= strlen(out
);
630 /* replace all (one or more) commas with double commas */
631 static void check_for_comma(char ** ppasswrd
)
636 int number_of_commas
= 0;
651 if(number_of_commas
== 0)
653 if(number_of_commas
> 64) {
654 /* would otherwise overflow the mount options buffer */
655 printf("\nInvalid password. Password contains too many commas.\n");
659 new_pass_buf
= (char *)malloc(len
+number_of_commas
+1);
660 if(new_pass_buf
== NULL
)
663 for(i
=0,j
=0;i
<len
;i
++,j
++) {
664 new_pass_buf
[j
] = pass
[i
];
667 new_pass_buf
[j
] = pass
[i
];
670 new_pass_buf
[len
+number_of_commas
] = 0;
673 *ppasswrd
= new_pass_buf
;
678 /* Usernames can not have backslash in them and we use
679 [BB check if usernames can have forward slash in them BB]
680 backslash as domain\user separator character
682 static char * check_for_domain(char **ppuser
)
684 char * original_string
;
694 original_string
= *ppuser
;
696 if (original_string
== NULL
)
699 original_len
= strlen(original_string
);
701 usernm
= strchr(*ppuser
,'/');
702 if (usernm
== NULL
) {
703 usernm
= strchr(*ppuser
,'\\');
709 printf("Domain name specified twice. Username probably malformed\n");
715 if (domainnm
[0] != 0) {
718 printf("null domain\n");
720 len
= strlen(domainnm
);
721 /* reset domainm to new buffer, and copy
722 domain name into it */
723 domainnm
= (char *)malloc(len
+1);
727 strcpy(domainnm
,*ppuser
);
729 /* move_string(*ppuser, usernm+1) */
730 len
= strlen(usernm
+1);
732 if(len
>= original_len
) {
733 /* should not happen */
737 for(i
=0;i
<original_len
;i
++) {
739 original_string
[i
] = usernm
[i
+1];
740 else /* stuff with commas to remove last parm */
741 original_string
[i
] = ',';
744 /* BB add check for more than one slash?
752 /* Note that caller frees the returned buffer if necessary */
753 static char * parse_server(char ** punc_name
)
755 char * unc_name
= *punc_name
;
756 int length
= strnlen(unc_name
,1024);
758 char * ipaddress_string
= NULL
;
759 struct hostent
* host_entry
= NULL
;
760 struct in_addr server_ipaddr
;
763 printf("mount error: UNC name too long");
766 if (strncasecmp("cifs://",unc_name
,7) == 0)
767 return parse_cifs_url(unc_name
+7);
768 if (strncasecmp("smb://",unc_name
,6) == 0) {
769 return parse_cifs_url(unc_name
+6);
773 /* BB add code to find DFS root here */
774 printf("\nMounting the DFS root for domain not implemented yet\n");
777 if(strncmp(unc_name
,"//",2) && strncmp(unc_name
,"\\\\",2)) {
778 /* check for nfs syntax ie server:share */
779 share
= strchr(unc_name
,':');
782 *punc_name
= (char *)malloc(length
+3);
783 if(*punc_name
== NULL
) {
784 /* put the original string back if
786 *punc_name
= unc_name
;
791 strncpy((*punc_name
)+2,unc_name
,length
);
792 unc_name
= *punc_name
;
793 unc_name
[length
+2] = 0;
794 goto continue_unc_parsing
;
796 printf("mount error: improperly formatted UNC name.");
797 printf(" %s does not begin with \\\\ or //\n",unc_name
);
801 continue_unc_parsing
:
805 if ((share
= strchr(unc_name
, '/')) ||
806 (share
= strchr(unc_name
,'\\'))) {
807 *share
= 0; /* temporarily terminate the string */
810 host_entry
= gethostbyname(unc_name
);
812 if(strnlen(unc_name
, 16) < 16) {
813 servern
= strdup(unc_name
);
815 *(share
- 1) = '/'; /* put the slash back */
816 if ((prefixpath
= strchr(share
, '/'))) {
817 *prefixpath
= 0; /* permanently terminate the string */
818 if (!strlen(++prefixpath
))
819 prefixpath
= NULL
; /* this needs to be done explicitly */
823 printf("ip address specified explicitly\n");
826 if(host_entry
== NULL
) {
827 printf("mount error: could not find target server. TCP name %s not found\n", unc_name
);
830 /* BB should we pass an alternate version of the share name as Unicode */
831 /* BB what about ipv6? BB */
832 /* BB add retries with alternate servers in list */
834 memcpy(&server_ipaddr
.s_addr
, host_entry
->h_addr
, 4);
836 ipaddress_string
= inet_ntoa(server_ipaddr
);
837 if(ipaddress_string
== NULL
) {
838 printf("mount error: could not get valid ip address for target server\n");
841 return ipaddress_string
;
844 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
845 printf("Mounting the DFS root for a particular server not implemented yet\n");
852 static struct option longopts
[] = {
853 { "all", 0, NULL
, 'a' },
854 { "help",0, NULL
, 'h' },
855 { "move",0, NULL
, 'm' },
856 { "bind",0, NULL
, 'b' },
857 { "read-only", 0, NULL
, 'r' },
858 { "ro", 0, NULL
, 'r' },
859 { "verbose", 0, NULL
, 'v' },
860 { "version", 0, NULL
, 'V' },
861 { "read-write", 0, NULL
, 'w' },
862 { "rw", 0, NULL
, 'w' },
863 { "options", 1, NULL
, 'o' },
864 { "type", 1, NULL
, 't' },
865 { "rsize",1, NULL
, 'R' },
866 { "wsize",1, NULL
, 'W' },
867 { "uid", 1, NULL
, '1'},
868 { "gid", 1, NULL
, '2'},
869 { "user",1,NULL
,'u'},
870 { "username",1,NULL
,'u'},
872 { "domain",1,NULL
,'d'},
873 { "password",1,NULL
,'p'},
874 { "pass",1,NULL
,'p'},
875 { "credentials",1,NULL
,'c'},
876 { "port",1,NULL
,'P'},
877 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
881 int main(int argc
, char ** argv
)
884 int flags
= MS_MANDLOCK
; /* no need to set legacy MS_MGC_VAL */
885 char * orgoptions
= NULL
;
886 char * share_name
= NULL
;
887 char * ipaddr
= NULL
;
889 char * mountpoint
= NULL
;
890 char * options
= NULL
;
891 char * resolved_path
;
901 int retry
= 0; /* set when we have to retry mount with uppercase */
902 int retry_with_rfc1001name
= 0; /* set when we have to retry with netbios name */
904 struct utsname sysinfo
;
905 struct mntent mountent
;
908 /* setlocale(LC_ALL, "");
909 bindtextdomain(PACKAGE, LOCALEDIR);
910 textdomain(PACKAGE); */
913 thisprogram
= argv
[0];
919 if(thisprogram
== NULL
)
920 thisprogram
= "mount.cifs";
923 /* BB add workstation name and domain and pass down */
925 /* #ifdef _GNU_SOURCE
926 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
929 share_name
= argv
[1];
930 mountpoint
= argv
[2];
933 /* add sharename in opts string as unc= parm */
935 while ((c
= getopt_long (argc
, argv
, "afFhilL:no:O:rsSU:vVwt:",
936 longopts
, NULL
)) != -1) {
938 /* No code to do the following options yet */
940 list_with_volumelabel = 1;
943 volumelabel = optarg;
961 "option 'b' (MS_BIND) not supported\n");
969 "option 'm' (MS_MOVE) not supported\n");
973 orgoptions
= strdup(optarg
);
975 case 'r': /* mount readonly */
985 printf ("mount.cifs version: %s.%s%s\n",
986 MOUNT_CIFS_VERSION_MAJOR
,
987 MOUNT_CIFS_VERSION_MINOR
,
988 MOUNT_CIFS_VENDOR_SUFFIX
);
990 memset(mountpassword
,0,64);
997 rsize
= atoi(optarg
) ;
1000 wsize
= atoi(optarg
);
1003 if (isdigit(*optarg
)) {
1006 uid
= strtoul(optarg
, &ep
, 10);
1008 printf("bad uid value \"%s\"\n", optarg
);
1014 if (!(pw
= getpwnam(optarg
))) {
1015 printf("bad user name \"%s\"\n", optarg
);
1023 if (isdigit(*optarg
)) {
1026 gid
= strtoul(optarg
, &ep
, 10);
1028 printf("bad gid value \"%s\"\n", optarg
);
1034 if (!(gr
= getgrnam(optarg
))) {
1035 printf("bad user name \"%s\"\n", optarg
);
1047 domain_name
= optarg
; /* BB fix this - currently ignored */
1051 if(mountpassword
== NULL
)
1052 mountpassword
= (char *)calloc(65,1);
1055 strncpy(mountpassword
,optarg
,64);
1059 get_password_from_file(0 /* stdin */,NULL
);
1064 printf("unknown mount option %c\n",c
);
1070 if((argc
< 3) || (share_name
== NULL
) || (mountpoint
== NULL
)) {
1075 if (getenv("PASSWD")) {
1076 if(mountpassword
== NULL
)
1077 mountpassword
= (char *)calloc(65,1);
1079 strncpy(mountpassword
,getenv("PASSWD"),64);
1082 } else if (getenv("PASSWD_FD")) {
1083 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL
);
1084 } else if (getenv("PASSWD_FILE")) {
1085 get_password_from_file(0, getenv("PASSWD_FILE"));
1088 if (orgoptions
&& parse_options(&orgoptions
, &flags
))
1090 ipaddr
= parse_server(&share_name
);
1091 if((ipaddr
== NULL
) && (got_ip
== 0)) {
1092 printf("No ip address specified and hostname not found\n");
1096 /* BB save off path and pop after mount returns? */
1097 resolved_path
= (char *)malloc(PATH_MAX
+1);
1099 /* Note that if we can not canonicalize the name, we get
1100 another chance to see if it is valid when we chdir to it */
1101 if (realpath(mountpoint
, resolved_path
)) {
1102 mountpoint
= resolved_path
;
1105 if(chdir(mountpoint
)) {
1106 printf("mount error: can not change directory into mount target %s\n",mountpoint
);
1110 if(stat (".", &statbuf
)) {
1111 printf("mount error: mount point %s does not exist\n",mountpoint
);
1115 if (S_ISDIR(statbuf
.st_mode
) == 0) {
1116 printf("mount error: mount point %s is not a directory\n",mountpoint
);
1120 if((getuid() != 0) && (geteuid() == 0)) {
1121 if((statbuf
.st_uid
== getuid()) && (S_IRWXU
== (statbuf
.st_mode
& S_IRWXU
))) {
1122 #ifndef CIFS_ALLOW_USR_SUID
1123 /* Do not allow user mounts to control suid flag
1124 for mount unless explicitly built that way */
1125 flags
|= MS_NOSUID
| MS_NODEV
;
1128 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
1134 user_name
= getusername();
1138 if(got_password
== 0) {
1139 mountpassword
= getpass("Password: "); /* BB obsolete */
1142 /* FIXME launch daemon (handles dfs name resolution and credential change)
1143 remember to clear parms and overwrite password field before launching */
1146 optlen
= strlen(orgoptions
);
1151 optlen
+= strlen(share_name
) + 4;
1153 printf("No server share name specified\n");
1154 printf("\nMounting the DFS root for server not implemented yet\n");
1158 optlen
+= strlen(user_name
) + 6;
1160 optlen
+= strlen(ipaddr
) + 4;
1162 optlen
+= strlen(mountpassword
) + 6;
1164 printf("\norg options %s at %p\n", options
, options
); /* BB removeme BB */
1168 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 */) + 9 /* servern=" */ + 16 /* space for maximum RFC1001 name */;
1169 if(options
== NULL
) {
1170 printf("Could not allocate memory for mount options\n");
1174 printf("\noptions %s at %p\n", options
, options
); /* BB removeme BB */
1175 options
= realloc(options
, 3350); /* BB removeme BB */
1176 printf("\nrealloc seems ok\n"); /* BB removeme BB */
1178 strncat(options
,"unc=",4);
1179 strcat(options
,share_name
);
1180 /* scan backwards and reverse direction of slash */
1181 temp
= strrchr(options
, '/');
1182 options
= realloc(options
, 980); /* BB removeme BB */
1183 printf("\nrealloc seemms very ok\n"); /* BB removeme BB */
1184 if(temp
> options
+ 6)
1187 strncat(options
,",ip=",4);
1188 strcat(options
,ipaddr
);
1190 if((servern
) && retry_with_rfc1001name
) {
1191 strcat(options
, ",servern=");
1192 strcat(options
, servern
);
1194 printf("\noptions1 %s at %p\n", options
, options
); /* BB removeme BB */
1195 options
= realloc(options
, 1000); /* BB removeme BB */
1196 printf("realloc1 ok\n"); /* BB removeme BB */
1198 /* check for syntax like user=domain\user */
1200 domain_name
= check_for_domain(&user_name
);
1201 strncat(options
,",user=",6);
1202 strcat(options
,user_name
);
1206 /* extra length accounted for in option string above */
1207 strncat(options
,",domain=",8);
1208 strcat(options
,domain_name
);
1212 /* Commas have to be doubled, or else they will
1213 look like the parameter separator */
1214 /* if(sep is not set)*/
1216 check_for_comma(&mountpassword
);
1217 strncat(options
,",pass=",6);
1218 strcat(options
,mountpassword
);
1220 printf("\noptions2 %s at %p\n", options
, options
); /* BB removeme BB */
1222 strncat(options
,",ver=",5);
1223 strcat(options
,MOUNT_CIFS_VERSION_MAJOR
);
1226 strcat(options
,",");
1227 strcat(options
,orgoptions
);
1230 printf("\noptions2 at %p\n", options
); /* BB removeme BB */
1233 strncat(options
,",prefixpath=",12);
1234 strcat(options
,prefixpath
); /* no need to cat the / */
1237 printf("\nmount.cifs kernel mount options %s \n",options
);
1238 if(mount(share_name
, mountpoint
, "cifs", flags
, options
)) {
1239 /* remember to kill daemon on error */
1244 printf("mount failed but no error number set\n");
1247 printf("mount error: cifs filesystem not supported by the system\n");
1251 /* If this is so old as to not support *SMBSERVER called
1252 name for RFC1001, we can get this error . We also
1253 need to uppercase the sharename for these old servers
1254 so fall through to retry code below. On retry the
1255 code will add "servern=" */
1257 if((retry
== 0) && tmp
) {
1258 retry_with_rfc1001name
= 1;
1259 while (*tmp
&& !(((unsigned char)tmp
[0]) & 0x80)) {
1260 *tmp
= toupper((unsigned char)*tmp
);
1263 printf("Adding Netbios name of server to mount based on server part of UNC name\n");
1269 while (*tmp
&& !(((unsigned char)tmp
[0]) & 0x80)) {
1270 *tmp
= toupper((unsigned char)*tmp
);
1274 printf("retrying with upper case share name\n");
1279 printf("mount error %d = %s\n",errno
,strerror(errno
));
1281 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1285 pmntfile
= setmntent(MOUNTED
, "a+");
1287 mountent
.mnt_fsname
= share_name
;
1288 mountent
.mnt_dir
= mountpoint
;
1289 mountent
.mnt_type
= CONST_DISCARD(char *,"cifs");
1290 mountent
.mnt_opts
= (char *)malloc(220);
1291 if(mountent
.mnt_opts
) {
1292 char * mount_user
= getusername();
1293 memset(mountent
.mnt_opts
,0,200);
1294 if(flags
& MS_RDONLY
)
1295 strcat(mountent
.mnt_opts
,"ro");
1297 strcat(mountent
.mnt_opts
,"rw");
1298 if(flags
& MS_MANDLOCK
)
1299 strcat(mountent
.mnt_opts
,",mand");
1300 if(flags
& MS_NOEXEC
)
1301 strcat(mountent
.mnt_opts
,",noexec");
1302 if(flags
& MS_NOSUID
)
1303 strcat(mountent
.mnt_opts
,",nosuid");
1304 if(flags
& MS_NODEV
)
1305 strcat(mountent
.mnt_opts
,",nodev");
1306 if(flags
& MS_SYNCHRONOUS
)
1307 strcat(mountent
.mnt_opts
,",synch");
1310 strcat(mountent
.mnt_opts
,",user=");
1311 strcat(mountent
.mnt_opts
,mount_user
);
1316 mountent
.mnt_freq
= 0;
1317 mountent
.mnt_passno
= 0;
1318 rc
= addmntent(pmntfile
,&mountent
);
1319 endmntent(pmntfile
);
1320 if(mountent
.mnt_opts
)
1321 free(mountent
.mnt_opts
);
1323 printf("could not update mount table\n");
1329 int len
= strlen(mountpassword
);
1330 memset(mountpassword
,0,len
);
1331 free(mountpassword
);
1335 options
= realloc(options
, 1000); /* BB removeme BB */
1336 printf("\noptions freed %p\n", options
); /* BB removeme BB */
1337 /* memset(options,0,optlen); */
1342 memset(orgoptions
,0,orgoptlen
);
1346 free(resolved_path
);
1353 if(free_share_name
) {