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 */
62 #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
64 const char *thisprogram
;
66 static int got_password
= 0;
67 static int got_user
= 0;
68 static int got_domain
= 0;
69 static int got_ip
= 0;
70 static int got_unc
= 0;
71 static int got_uid
= 0;
72 static int got_gid
= 0;
73 static int free_share_name
= 0;
74 static char * user_name
= NULL
;
75 static char * mountpassword
= NULL
;
76 char * domain_name
= NULL
;
82 open nofollow - avoid symlink exposure?
83 get owner of dir see if matches self or if root
84 call system(umount argv) etc.
88 static char * check_for_domain(char **);
91 static void mount_cifs_usage(void)
93 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram
);
94 printf("\nMount the remote target, specified as a UNC name,");
95 printf(" to a local directory.\n\nOptions:\n");
96 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
97 printf("\nLess commonly used options:");
98 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
99 printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
100 printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
101 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
102 printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
103 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
104 printf("\n\nRarely used options:");
105 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
106 printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
107 printf("\n\tnointr,ignorecase,noposixpaths,noacl");
108 printf("\n\nOptions are described in more detail in the manual page");
109 printf("\n\tman 8 mount.cifs\n");
110 printf("\nTo display the version number of the mount helper:");
111 printf("\n\t%s -V\n",thisprogram
);
114 memset(mountpassword
,0,64);
120 /* caller frees username if necessary */
121 static char * getusername(void) {
122 char *username
= NULL
;
123 struct passwd
*password
= getpwuid(getuid());
126 username
= password
->pw_name
;
131 static char * parse_cifs_url(char * unc_name
)
133 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name
);
137 static int open_cred_file(char * file_name
)
143 fs
= fopen(file_name
,"r");
146 line_buf
= malloc(4096);
147 if(line_buf
== NULL
) {
152 while(fgets(line_buf
,4096,fs
)) {
153 /* parse line from credential file */
155 /* eat leading white space */
156 for(i
=0;i
<4086;i
++) {
157 if((line_buf
[i
] != ' ') && (line_buf
[i
] != '\t'))
159 /* if whitespace - skip past it */
161 if (strncasecmp("username",line_buf
+i
,8) == 0) {
162 temp_val
= strchr(line_buf
+ i
,'=');
164 /* go past equals sign */
166 for(length
= 0;length
<4087;length
++) {
167 if(temp_val
[length
] == '\n')
171 printf("mount.cifs failed due to malformed username in credentials file");
172 memset(line_buf
,0,4096);
174 memset(mountpassword
,0,64);
179 user_name
= calloc(1 + length
,1);
180 /* BB adding free of user_name string before exit,
181 not really necessary but would be cleaner */
182 strncpy(user_name
,temp_val
, length
);
185 } else if (strncasecmp("password",line_buf
+i
,8) == 0) {
186 temp_val
= strchr(line_buf
+i
,'=');
188 /* go past equals sign */
190 for(length
= 0;length
<65;length
++) {
191 if(temp_val
[length
] == '\n')
195 printf("mount.cifs failed: password in credentials file too long\n");
196 memset(line_buf
,0, 4096);
198 memset(mountpassword
,0,64);
202 if(mountpassword
== NULL
) {
203 mountpassword
= calloc(65,1);
205 memset(mountpassword
,0,64);
207 strncpy(mountpassword
,temp_val
,length
);
212 } else if (strncasecmp("domain",line_buf
+i
,6) == 0) {
213 temp_val
= strchr(line_buf
+i
,'=');
215 /* go past equals sign */
218 printf("\nDomain %s\n",temp_val
);
219 for(length
= 0;length
<65;length
++) {
220 if(temp_val
[length
] == '\n')
224 printf("mount.cifs failed: domain in credentials file too long\n");
226 memset(mountpassword
,0,64);
230 if(domain_name
== NULL
) {
231 domain_name
= calloc(65,1);
233 memset(domain_name
,0,64);
235 strncpy(domain_name
,temp_val
,length
);
245 memset(line_buf
,0,4096);
251 static int get_password_from_file(int file_descript
, char * filename
)
257 if(mountpassword
== NULL
)
258 mountpassword
= calloc(65,1);
260 memset(mountpassword
, 0, 64);
262 if (mountpassword
== NULL
) {
263 printf("malloc failed\n");
267 if(filename
!= NULL
) {
268 file_descript
= open(filename
, O_RDONLY
);
269 if(file_descript
< 0) {
270 printf("mount.cifs failed. %s attempting to open password file %s\n",
271 strerror(errno
),filename
);
275 /* else file already open and fd provided */
278 rc
= read(file_descript
,&c
,1);
280 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno
));
281 memset(mountpassword
,0,64);
283 close(file_descript
);
286 if(mountpassword
[0] == 0) {
288 printf("\nWarning: null password used since cifs password file empty");
291 } else /* read valid character */ {
292 if((c
== 0) || (c
== '\n')) {
295 mountpassword
[i
] = c
;
298 if((i
== 64) && (verboseflag
)) {
299 printf("\nWarning: password longer than 64 characters specified in cifs password file");
302 if(filename
!= NULL
) {
303 close(file_descript
);
309 static int parse_options(char ** optionsp
, int * filesys_flags
)
312 char * percent_char
= NULL
;
314 char * next_keyword
= NULL
;
320 if (!optionsp
|| !*optionsp
)
325 printf("parsing options: %s\n", data
);
327 /* BB fixme check for separator override BB */
329 /* while ((data = strsep(&options, ",")) != NULL) { */
330 while(data
!= NULL
) {
331 /* check if ends with trailing comma */
335 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
336 /* data = next keyword */
337 /* value = next value ie stuff after equal sign */
339 next_keyword
= strchr(data
,','); /* BB handle sep= */
341 /* temporarily null terminate end of keyword=value pair */
345 /* temporarily null terminate keyword to make keyword and value distinct */
346 if ((value
= strchr(data
, '=')) != NULL
) {
351 if (strncmp(data
, "users",5) == 0) {
352 if(!value
|| !*value
) {
355 } else if (strncmp(data
, "user_xattr",10) == 0) {
356 /* do nothing - need to skip so not parsed as user name */
357 } else if (strncmp(data
, "user", 4) == 0) {
359 if (!value
|| !*value
) {
360 if(data
[4] == '\0') {
362 printf("\nskipping empty user mount parameter\n");
363 /* remove the parm since it would otherwise be confusing
364 to the kernel code which would think it was a real username */
367 printf("username specified with no parameter\n");
368 return 1; /* needs_arg; */
371 if (strnlen(value
, 260) < 260) {
373 percent_char
= strchr(value
,'%');
376 if(mountpassword
== NULL
)
377 mountpassword
= calloc(65,1);
380 printf("\nmount.cifs warning - password specified twice\n");
383 strncpy(mountpassword
, percent_char
,64);
384 /* remove password from username */
385 while(*percent_char
!= 0) {
391 /* this is only case in which the user
392 name buf is not malloc - so we have to
393 check for domain name embedded within
394 the user name here since the later
395 call to check_for_domain will not be
397 domain_name
= check_for_domain(&value
);
399 printf("username too long\n");
403 } else if (strncmp(data
, "pass", 4) == 0) {
404 if (!value
|| !*value
) {
406 printf("\npassword specified twice, ignoring second\n");
409 } else if (strnlen(value
, 17) < 17) {
411 printf("\nmount.cifs warning - password specified twice\n");
414 printf("password too long\n");
417 } else if (strncmp(data
, "ip", 2) == 0) {
418 if (!value
|| !*value
) {
419 printf("target ip address argument missing");
420 } else if (strnlen(value
, 35) < 35) {
422 printf("ip address %s override specified\n",value
);
425 printf("ip address too long\n");
428 } else if ((strncmp(data
, "unc", 3) == 0)
429 || (strncmp(data
, "target", 6) == 0)
430 || (strncmp(data
, "path", 4) == 0)) {
431 if (!value
|| !*value
) {
432 printf("invalid path to network resource\n");
433 return 1; /* needs_arg; */
434 } else if(strnlen(value
,5) < 5) {
435 printf("UNC name too short");
438 if (strnlen(value
, 300) < 300) {
440 if (strncmp(value
, "//", 2) == 0) {
442 printf("unc name specified twice, ignoring second\n");
445 } else if (strncmp(value
, "\\\\", 2) != 0) {
446 printf("UNC Path does not begin with // or \\\\ \n");
450 printf("unc name specified twice, ignoring second\n");
455 printf("CIFS: UNC name too long\n");
458 } else if ((strncmp(data
, "domain", 3) == 0)
459 || (strncmp(data
, "workgroup", 5) == 0)) {
460 if (!value
|| !*value
) {
461 printf("CIFS: invalid domain name\n");
462 return 1; /* needs_arg; */
464 if (strnlen(value
, 65) < 65) {
467 printf("domain name too long\n");
470 } else if (strncmp(data
, "cred", 4) == 0) {
471 if (value
&& *value
) {
472 rc
= open_cred_file(value
);
474 printf("error %d opening credential file %s\n",rc
, value
);
478 printf("invalid credential file name specified\n");
481 } else if (strncmp(data
, "uid", 3) == 0) {
482 if (value
&& *value
) {
484 if (!isdigit(*value
)) {
486 static char temp
[32];
488 if (!(pw
= getpwnam(value
))) {
489 printf("bad user name \"%s\"\n", value
);
492 sprintf(temp
, "%u", pw
->pw_uid
);
497 } else if (strncmp(data
, "gid", 3) == 0) {
498 if (value
&& *value
) {
500 if (!isdigit(*value
)) {
502 static char temp
[32];
504 if (!(gr
= getgrnam(value
))) {
505 printf("bad group name \"%s\"\n", value
);
508 sprintf(temp
, "%u", gr
->gr_gid
);
513 /* fmask and dmask synonyms for people used to smbfs syntax */
514 } else if (strcmp(data
, "file_mode") == 0 || strcmp(data
, "fmask")==0) {
515 if (!value
|| !*value
) {
516 printf ("Option '%s' requires a numerical argument\n", data
);
520 if (value
[0] != '0') {
521 printf ("WARNING: '%s' not expressed in octal.\n", data
);
524 if (strcmp (data
, "fmask") == 0) {
525 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
526 data
= "file_mode"; /* BB fix this */
528 } else if (strcmp(data
, "dir_mode") == 0 || strcmp(data
, "dmask")==0) {
529 if (!value
|| !*value
) {
530 printf ("Option '%s' requires a numerical argument\n", data
);
534 if (value
[0] != '0') {
535 printf ("WARNING: '%s' not expressed in octal.\n", data
);
538 if (strcmp (data
, "dmask") == 0) {
539 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
542 /* the following eight mount options should be
543 stripped out from what is passed into the kernel
544 since these eight options are best passed as the
545 mount flags rather than redundantly to the kernel
546 and could generate spurious warnings depending on the
547 level of the corresponding cifs vfs kernel code */
548 } else if (strncmp(data
, "nosuid", 6) == 0) {
549 *filesys_flags
|= MS_NOSUID
;
550 } else if (strncmp(data
, "suid", 4) == 0) {
551 *filesys_flags
&= ~MS_NOSUID
;
552 } else if (strncmp(data
, "nodev", 5) == 0) {
553 *filesys_flags
|= MS_NODEV
;
554 } else if ((strncmp(data
, "nobrl", 5) == 0) ||
555 (strncmp(data
, "nolock", 6) == 0)) {
556 *filesys_flags
&= ~MS_MANDLOCK
;
557 } else if (strncmp(data
, "dev", 3) == 0) {
558 *filesys_flags
&= ~MS_NODEV
;
559 } else if (strncmp(data
, "noexec", 6) == 0) {
560 *filesys_flags
|= MS_NOEXEC
;
561 } else if (strncmp(data
, "exec", 4) == 0) {
562 *filesys_flags
&= ~MS_NOEXEC
;
563 } else if (strncmp(data
, "guest", 5) == 0) {
565 /* remove the parm since it would otherwise be logged by kern */
567 } else if (strncmp(data
, "ro", 2) == 0) {
568 *filesys_flags
|= MS_RDONLY
;
569 } else if (strncmp(data
, "rw", 2) == 0) {
570 *filesys_flags
&= ~MS_RDONLY
;
571 } else if (strncmp(data
, "remount", 7) == 0) {
572 *filesys_flags
|= MS_REMOUNT
;
573 } /* else if (strnicmp(data, "port", 4) == 0) {
574 if (value && *value) {
576 simple_strtoul(value, &value, 0);
578 } else if (strnicmp(data, "rsize", 5) == 0) {
579 if (value && *value) {
581 simple_strtoul(value, &value, 0);
583 } else if (strnicmp(data, "wsize", 5) == 0) {
584 if (value && *value) {
586 simple_strtoul(value, &value, 0);
588 } else if (strnicmp(data, "version", 3) == 0) {
590 printf("CIFS: Unknown mount option %s\n",data);
591 } */ /* nothing to do on those four mount options above.
592 Just pass to kernel and ignore them here */
594 /* Copy (possibly modified) option to out */
595 word_len
= strlen(data
);
597 word_len
+= 1 + strlen(value
);
599 out
= realloc(out
, out_len
+ word_len
+ 2);
606 out
[out_len
++] = ',';
608 sprintf(out
+ out_len
, "%s=%s", data
, value
);
610 sprintf(out
+ out_len
, "%s", data
);
611 out_len
= strlen(out
);
620 /* replace all (one or more) commas with double commas */
621 static void check_for_comma(char ** ppasswrd
)
626 int number_of_commas
= 0;
641 if(number_of_commas
== 0)
643 if(number_of_commas
> 64) {
644 /* would otherwise overflow the mount options buffer */
645 printf("\nInvalid password. Password contains too many commas.\n");
649 new_pass_buf
= malloc(len
+number_of_commas
+1);
650 if(new_pass_buf
== NULL
)
653 for(i
=0,j
=0;i
<len
;i
++,j
++) {
654 new_pass_buf
[j
] = pass
[i
];
657 new_pass_buf
[j
] = pass
[i
];
660 new_pass_buf
[len
+number_of_commas
] = 0;
663 *ppasswrd
= new_pass_buf
;
668 /* Usernames can not have backslash in them and we use
669 [BB check if usernames can have forward slash in them BB]
670 backslash as domain\user separator character
672 static char * check_for_domain(char **ppuser
)
674 char * original_string
;
684 original_string
= *ppuser
;
686 if (original_string
== NULL
)
689 original_len
= strlen(original_string
);
691 usernm
= strchr(*ppuser
,'/');
692 if (usernm
== NULL
) {
693 usernm
= strchr(*ppuser
,'\\');
699 printf("Domain name specified twice. Username probably malformed\n");
705 if (domainnm
[0] != 0) {
708 printf("null domain\n");
710 len
= strlen(domainnm
);
711 /* reset domainm to new buffer, and copy
712 domain name into it */
713 domainnm
= malloc(len
+1);
717 strcpy(domainnm
,*ppuser
);
719 /* move_string(*ppuser, usernm+1) */
720 len
= strlen(usernm
+1);
722 if(len
>= original_len
) {
723 /* should not happen */
727 for(i
=0;i
<original_len
;i
++) {
729 original_string
[i
] = usernm
[i
+1];
730 else /* stuff with commas to remove last parm */
731 original_string
[i
] = ',';
734 /* BB add check for more than one slash?
742 /* Note that caller frees the returned buffer if necessary */
743 static char * parse_server(char ** punc_name
)
745 char * unc_name
= *punc_name
;
746 int length
= strnlen(unc_name
,1024);
748 char * ipaddress_string
= NULL
;
749 struct hostent
* host_entry
= NULL
;
750 struct in_addr server_ipaddr
;
753 printf("mount error: UNC name too long");
756 if (strncasecmp("cifs://",unc_name
,7) == 0)
757 return parse_cifs_url(unc_name
+7);
758 if (strncasecmp("smb://",unc_name
,6) == 0) {
759 return parse_cifs_url(unc_name
+6);
763 /* BB add code to find DFS root here */
764 printf("\nMounting the DFS root for domain not implemented yet\n");
767 if(strncmp(unc_name
,"//",2) && strncmp(unc_name
,"\\\\",2)) {
768 /* check for nfs syntax ie server:share */
769 share
= strchr(unc_name
,':');
772 *punc_name
= malloc(length
+3);
773 if(*punc_name
== NULL
) {
774 /* put the original string back if
776 *punc_name
= unc_name
;
781 strncpy((*punc_name
)+2,unc_name
,length
);
782 unc_name
= *punc_name
;
783 unc_name
[length
+2] = 0;
784 goto continue_unc_parsing
;
786 printf("mount error: improperly formatted UNC name.");
787 printf(" %s does not begin with \\\\ or //\n",unc_name
);
791 continue_unc_parsing
:
795 if ((share
= strchr(unc_name
, '/')) ||
796 (share
= strchr(unc_name
,'\\'))) {
797 *share
= 0; /* temporarily terminate the string */
800 host_entry
= gethostbyname(unc_name
);
802 *(share
- 1) = '/'; /* put the slash back */
805 printf("ip address specified explicitly\n");
808 if(host_entry
== NULL
) {
809 printf("mount error: could not find target server. TCP name %s not found\n", unc_name
);
812 /* BB should we pass an alternate version of the share name as Unicode */
813 /* BB what about ipv6? BB */
814 /* BB add retries with alternate servers in list */
816 memcpy(&server_ipaddr
.s_addr
, host_entry
->h_addr
, 4);
818 ipaddress_string
= inet_ntoa(server_ipaddr
);
819 if(ipaddress_string
== NULL
) {
820 printf("mount error: could not get valid ip address for target server\n");
823 return ipaddress_string
;
826 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
827 printf("Mounting the DFS root for a particular server not implemented yet\n");
834 static struct option longopts
[] = {
835 { "all", 0, NULL
, 'a' },
836 { "help",0, NULL
, 'h' },
837 { "move",0, NULL
, 'm' },
838 { "bind",0, NULL
, 'b' },
839 { "read-only", 0, NULL
, 'r' },
840 { "ro", 0, NULL
, 'r' },
841 { "verbose", 0, NULL
, 'v' },
842 { "version", 0, NULL
, 'V' },
843 { "read-write", 0, NULL
, 'w' },
844 { "rw", 0, NULL
, 'w' },
845 { "options", 1, NULL
, 'o' },
846 { "type", 1, NULL
, 't' },
847 { "rsize",1, NULL
, 'R' },
848 { "wsize",1, NULL
, 'W' },
849 { "uid", 1, NULL
, '1'},
850 { "gid", 1, NULL
, '2'},
851 { "user",1,NULL
,'u'},
852 { "username",1,NULL
,'u'},
854 { "domain",1,NULL
,'d'},
855 { "password",1,NULL
,'p'},
856 { "pass",1,NULL
,'p'},
857 { "credentials",1,NULL
,'c'},
858 { "port",1,NULL
,'P'},
859 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
863 int main(int argc
, char ** argv
)
866 int flags
= MS_MANDLOCK
; /* no need to set legacy MS_MGC_VAL */
867 char * orgoptions
= NULL
;
868 char * share_name
= NULL
;
869 char * ipaddr
= NULL
;
871 char * mountpoint
= NULL
;
873 char * resolved_path
;
883 int retry
= 0; /* set when we have to retry mount with uppercase */
885 struct utsname sysinfo
;
886 struct mntent mountent
;
889 /* setlocale(LC_ALL, "");
890 bindtextdomain(PACKAGE, LOCALEDIR);
891 textdomain(PACKAGE); */
894 thisprogram
= argv
[0];
900 if(thisprogram
== NULL
)
901 thisprogram
= "mount.cifs";
904 /* BB add workstation name and domain and pass down */
906 /* #ifdef _GNU_SOURCE
907 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
910 share_name
= argv
[1];
911 mountpoint
= argv
[2];
914 /* add sharename in opts string as unc= parm */
916 while ((c
= getopt_long (argc
, argv
, "afFhilL:no:O:rsSU:vVwt:",
917 longopts
, NULL
)) != -1) {
919 /* No code to do the following options yet */
921 list_with_volumelabel = 1;
924 volumelabel = optarg;
944 orgoptions
= strdup(optarg
);
946 case 'r': /* mount readonly */
956 printf ("mount.cifs version: %s.%s%s\n",
957 MOUNT_CIFS_VERSION_MAJOR
,
958 MOUNT_CIFS_VERSION_MINOR
,
959 MOUNT_CIFS_VENDOR_SUFFIX
);
961 memset(mountpassword
,0,64);
968 rsize
= atoi(optarg
) ;
971 wsize
= atoi(optarg
);
974 if (isdigit(*optarg
)) {
977 uid
= strtoul(optarg
, &ep
, 10);
979 printf("bad uid value \"%s\"\n", optarg
);
985 if (!(pw
= getpwnam(optarg
))) {
986 printf("bad user name \"%s\"\n", optarg
);
994 if (isdigit(*optarg
)) {
997 gid
= strtoul(optarg
, &ep
, 10);
999 printf("bad gid value \"%s\"\n", optarg
);
1005 if (!(gr
= getgrnam(optarg
))) {
1006 printf("bad user name \"%s\"\n", optarg
);
1018 domain_name
= optarg
; /* BB fix this - currently ignored */
1022 if(mountpassword
== NULL
)
1023 mountpassword
= calloc(65,1);
1026 strncpy(mountpassword
,optarg
,64);
1030 get_password_from_file(0 /* stdin */,NULL
);
1035 printf("unknown mount option %c\n",c
);
1041 if((argc
< 3) || (share_name
== NULL
) || (mountpoint
== NULL
)) {
1046 if (getenv("PASSWD")) {
1047 if(mountpassword
== NULL
)
1048 mountpassword
= calloc(65,1);
1050 strncpy(mountpassword
,getenv("PASSWD"),64);
1053 } else if (getenv("PASSWD_FD")) {
1054 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL
);
1055 } else if (getenv("PASSWD_FILE")) {
1056 get_password_from_file(0, getenv("PASSWD_FILE"));
1059 if (orgoptions
&& parse_options(&orgoptions
, &flags
))
1061 ipaddr
= parse_server(&share_name
);
1062 if((ipaddr
== NULL
) && (got_ip
== 0)) {
1063 printf("No ip address specified and hostname not found\n");
1067 /* BB save off path and pop after mount returns? */
1068 resolved_path
= malloc(PATH_MAX
+1);
1070 /* Note that if we can not canonicalize the name, we get
1071 another chance to see if it is valid when we chdir to it */
1072 if (realpath(mountpoint
, resolved_path
)) {
1073 mountpoint
= resolved_path
;
1076 if(chdir(mountpoint
)) {
1077 printf("mount error: can not change directory into mount target %s\n",mountpoint
);
1081 if(stat (".", &statbuf
)) {
1082 printf("mount error: mount point %s does not exist\n",mountpoint
);
1086 if (S_ISDIR(statbuf
.st_mode
) == 0) {
1087 printf("mount error: mount point %s is not a directory\n",mountpoint
);
1091 if((getuid() != 0) && (geteuid() == 0)) {
1092 if((statbuf
.st_uid
== getuid()) && (S_IRWXU
== (statbuf
.st_mode
& S_IRWXU
))) {
1093 #ifndef CIFS_ALLOW_USR_SUID
1094 /* Do not allow user mounts to control suid flag
1095 for mount unless explicitly built that way */
1096 flags
|= MS_NOSUID
| MS_NODEV
;
1099 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
1105 user_name
= getusername();
1109 if(got_password
== 0) {
1110 mountpassword
= getpass("Password: "); /* BB obsolete */
1113 /* FIXME launch daemon (handles dfs name resolution and credential change)
1114 remember to clear parms and overwrite password field before launching */
1117 optlen
= strlen(orgoptions
);
1122 optlen
+= strlen(share_name
) + 4;
1124 printf("No server share name specified\n");
1125 printf("\nMounting the DFS root for server not implemented yet\n");
1129 optlen
+= strlen(user_name
) + 6;
1131 optlen
+= strlen(ipaddr
) + 4;
1133 optlen
+= strlen(mountpassword
) + 6;
1134 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 */);
1136 if(options
== NULL
) {
1137 printf("Could not allocate memory for mount options\n");
1143 strncat(options
,"unc=",4);
1144 strcat(options
,share_name
);
1145 /* scan backwards and reverse direction of slash */
1146 temp
= strrchr(options
, '/');
1147 if(temp
> options
+ 6)
1150 strncat(options
,",ip=",4);
1151 strcat(options
,ipaddr
);
1155 /* check for syntax like user=domain\user */
1157 domain_name
= check_for_domain(&user_name
);
1158 strncat(options
,",user=",6);
1159 strcat(options
,user_name
);
1163 /* extra length accounted for in option string above */
1164 strncat(options
,",domain=",8);
1165 strcat(options
,domain_name
);
1169 /* Commas have to be doubled, or else they will
1170 look like the parameter separator */
1171 /* if(sep is not set)*/
1173 check_for_comma(&mountpassword
);
1174 strncat(options
,",pass=",6);
1175 strcat(options
,mountpassword
);
1178 strncat(options
,",ver=",5);
1179 strcat(options
,MOUNT_CIFS_VERSION_MAJOR
);
1182 strcat(options
,",");
1183 strcat(options
,orgoptions
);
1186 printf("\nmount.cifs kernel mount options %s \n",options
);
1187 if(mount(share_name
, mountpoint
, "cifs", flags
, options
)) {
1188 /* remember to kill daemon on error */
1193 printf("mount failed but no error number set\n");
1196 printf("mount error: cifs filesystem not supported by the system\n");
1202 while (*tmp
&& !(((unsigned char)tmp
[0]) & 0x80)) {
1203 *tmp
= toupper((unsigned char)*tmp
);
1207 printf("retrying with upper case share name\n");
1213 printf("mount error %d = %s\n",errno
,strerror(errno
));
1215 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1217 memset(mountpassword
,0,64);
1221 pmntfile
= setmntent(MOUNTED
, "a+");
1223 mountent
.mnt_fsname
= share_name
;
1224 mountent
.mnt_dir
= mountpoint
;
1225 mountent
.mnt_type
= CONST_DISCARD(char *,"cifs");
1226 mountent
.mnt_opts
= malloc(220);
1227 if(mountent
.mnt_opts
) {
1228 char * mount_user
= getusername();
1229 memset(mountent
.mnt_opts
,0,200);
1230 if(flags
& MS_RDONLY
)
1231 strcat(mountent
.mnt_opts
,"ro");
1233 strcat(mountent
.mnt_opts
,"rw");
1234 if(flags
& MS_MANDLOCK
)
1235 strcat(mountent
.mnt_opts
,",mand");
1236 if(flags
& MS_NOEXEC
)
1237 strcat(mountent
.mnt_opts
,",noexec");
1238 if(flags
& MS_NOSUID
)
1239 strcat(mountent
.mnt_opts
,",nosuid");
1240 if(flags
& MS_NODEV
)
1241 strcat(mountent
.mnt_opts
,",nodev");
1242 if(flags
& MS_SYNCHRONOUS
)
1243 strcat(mountent
.mnt_opts
,",synch");
1246 strcat(mountent
.mnt_opts
,",user=");
1247 strcat(mountent
.mnt_opts
,mount_user
);
1252 mountent
.mnt_freq
= 0;
1253 mountent
.mnt_passno
= 0;
1254 rc
= addmntent(pmntfile
,&mountent
);
1255 endmntent(pmntfile
);
1256 if(mountent
.mnt_opts
)
1257 free(mountent
.mnt_opts
);
1259 printf("could not update mount table\n");
1263 int len
= strlen(mountpassword
);
1264 memset(mountpassword
,0,len
);
1265 free(mountpassword
);
1269 memset(options
,0,optlen
);
1274 memset(orgoptions
,0,orgoptlen
);
1278 free(resolved_path
);
1281 if(free_share_name
) {