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. */
28 #include <sys/types.h>
29 #include <sys/mount.h>
31 #include <sys/utsname.h>
32 #include <sys/socket.h>
33 #include <arpa/inet.h>
41 #define MOUNT_CIFS_VERSION_MAJOR "1"
42 #define MOUNT_CIFS_VERSION_MINOR "7"
44 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
45 #define MOUNT_CIFS_VENDOR_SUFFIX ""
54 static int got_password
= 0;
55 static int got_user
= 0;
56 static int got_domain
= 0;
57 static int got_ip
= 0;
58 static int got_unc
= 0;
59 static int got_uid
= 0;
60 static int got_gid
= 0;
61 static int free_share_name
= 0;
62 static char * user_name
= NULL
;
63 static char * mountpassword
= NULL
;
64 char * domain_name
= NULL
;
70 open nofollow - avoid symlink exposure?
71 get owner of dir see if matches self or if root
72 call system(umount argv) etc.
76 static char * check_for_domain(char **);
79 static void mount_cifs_usage(void)
81 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram
);
82 printf("\nMount the remote target, specified as a UNC name,");
83 printf(" to a local directory.\n\nOptions:\n");
84 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
85 printf("\nLess commonly used options:");
86 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,\n\tdirectio,mapchars,nomapchars");
87 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions\n\t(e.g. most Samba versions):");
88 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>");
89 printf("\n\nRarely used options:");
90 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,\n\tdev,nodev,nouser_xattr,netbiosname,hard,soft,intr,nointr,noacl");
91 printf("\n\nOptions are described in more detail in the manual page");
92 printf("\n\tman 8 mount.cifs\n");
93 printf("\nTo display the version number of the mount helper:");
94 printf("\n\t%s -V\n",thisprogram
);
97 memset(mountpassword
,0,64);
103 /* caller frees username if necessary */
104 static char * getusername(void) {
105 char *username
= NULL
;
106 struct passwd
*password
= getpwuid(getuid());
109 username
= password
->pw_name
;
114 static char * parse_cifs_url(char * unc_name
)
116 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name
);
120 static int open_cred_file(char * file_name
)
126 fs
= fopen(file_name
,"r");
129 line_buf
= malloc(4096);
133 while(fgets(line_buf
,4096,fs
)) {
134 /* parse line from credential file */
136 /* eat leading white space */
137 for(i
=0;i
<4086;i
++) {
138 if((line_buf
[i
] != ' ') && (line_buf
[i
] != '\t'))
140 /* if whitespace - skip past it */
142 if (strncasecmp("username",line_buf
+i
,8) == 0) {
143 temp_val
= strchr(line_buf
+ i
,'=');
145 /* go past equals sign */
147 for(length
= 0;length
<4087;length
++) {
148 if(temp_val
[length
] == '\n')
152 printf("mount.cifs failed due to malformed username in credentials file");
153 memset(line_buf
,0,4096);
155 memset(mountpassword
,0,64);
160 user_name
= calloc(1 + length
,1);
161 /* BB adding free of user_name string before exit,
162 not really necessary but would be cleaner */
163 strncpy(user_name
,temp_val
, length
);
166 } else if (strncasecmp("password",line_buf
+i
,8) == 0) {
167 temp_val
= strchr(line_buf
+i
,'=');
169 /* go past equals sign */
171 for(length
= 0;length
<65;length
++) {
172 if(temp_val
[length
] == '\n')
176 printf("mount.cifs failed: password in credentials file too long\n");
177 memset(line_buf
,0, 4096);
179 memset(mountpassword
,0,64);
183 if(mountpassword
== NULL
) {
184 mountpassword
= calloc(65,1);
186 memset(mountpassword
,0,64);
188 /* BB add handling for commas in password here */
189 strncpy(mountpassword
,temp_val
,length
);
198 memset(line_buf
,0,4096);
204 static int get_password_from_file(int file_descript
, char * filename
)
210 if(mountpassword
== NULL
)
211 mountpassword
= calloc(65,1);
213 memset(mountpassword
, 0, 64);
215 if(filename
!= NULL
) {
216 file_descript
= open(filename
, O_RDONLY
);
217 if(file_descript
< 0) {
218 printf("mount.cifs failed. %s attempting to open password file %s\n",
219 strerror(errno
),filename
);
223 /* else file already open and fd provided */
226 rc
= read(file_descript
,&c
,1);
228 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno
));
229 memset(mountpassword
,0,64);
231 close(file_descript
);
234 if(mountpassword
[0] == 0) {
236 printf("\nWarning: null password used since cifs password file empty");
239 } else /* read valid character */ {
240 if((c
== 0) || (c
== '\n')) {
243 mountpassword
[i
] = c
;
246 if((i
== 64) && (verboseflag
)) {
247 printf("\nWarning: password longer than 64 characters specified in cifs password file");
250 if(filename
!= NULL
) {
251 close(file_descript
);
257 static int parse_options(char * options
, int * filesys_flags
)
260 char * percent_char
= NULL
;
262 char * next_keyword
= NULL
;
271 printf("parsing options: %s\n", options
);
273 /* BB fixme check for separator override BB */
275 /* while ((data = strsep(&options, ",")) != NULL) { */
276 while(data
!= NULL
) {
277 /* check if ends with trailing comma */
281 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
282 /* data = next keyword */
283 /* value = next value ie stuff after equal sign */
285 next_keyword
= strchr(data
,','); /* BB handle sep= */
287 /* temporarily null terminate end of keyword=value pair */
291 /* temporarily null terminate keyword to make keyword and value distinct */
292 if ((value
= strchr(data
, '=')) != NULL
) {
297 if (strncmp(data
, "users",5) == 0) {
298 if(!value
|| !*value
) {
299 strncpy(data
,",,,,,",5);
301 } else if (strncmp(data
, "user_xattr",10) == 0) {
302 /* do nothing - need to skip so not parsed as user name */
303 } else if (strncmp(data
, "user", 4) == 0) {
305 if (!value
|| !*value
) {
306 if(data
[4] == '\0') {
308 printf("\nskipping empty user mount parameter\n");
309 /* remove the parm since it would otherwise be confusing
310 to the kernel code which would think it was a real username */
316 printf("username specified with no parameter\n");
317 return 1; /* needs_arg; */
320 if (strnlen(value
, 260) < 260) {
322 percent_char
= strchr(value
,'%');
325 if(mountpassword
== NULL
)
326 mountpassword
= calloc(65,1);
329 printf("\nmount.cifs warning - password specified twice\n");
332 strncpy(mountpassword
, percent_char
,64);
333 /* remove password from username */
334 while(*percent_char
!= 0) {
340 /* this is only case in which the user
341 name buf is not malloc - so we have to
342 check for domain name embedded within
343 the user name here since the later
344 call to check_for_domain will not be
346 domain_name
= check_for_domain(&value
);
348 printf("username too long\n");
352 } else if (strncmp(data
, "pass", 4) == 0) {
353 if (!value
|| !*value
) {
355 printf("\npassword specified twice, ignoring second\n");
358 } else if (strnlen(value
, 17) < 17) {
360 printf("\nmount.cifs warning - password specified twice\n");
363 printf("password too long\n");
366 } else if (strncmp(data
, "ip", 2) == 0) {
367 if (!value
|| !*value
) {
368 printf("target ip address argument missing");
369 } else if (strnlen(value
, 35) < 35) {
371 printf("ip address %s override specified\n",value
);
374 printf("ip address too long\n");
377 } else if ((strncmp(data
, "unc", 3) == 0)
378 || (strncmp(data
, "target", 6) == 0)
379 || (strncmp(data
, "path", 4) == 0)) {
380 if (!value
|| !*value
) {
381 printf("invalid path to network resource\n");
382 return 1; /* needs_arg; */
383 } else if(strnlen(value
,5) < 5) {
384 printf("UNC name too short");
387 if (strnlen(value
, 300) < 300) {
389 if (strncmp(value
, "//", 2) == 0) {
391 printf("unc name specified twice, ignoring second\n");
394 } else if (strncmp(value
, "\\\\", 2) != 0) {
395 printf("UNC Path does not begin with // or \\\\ \n");
399 printf("unc name specified twice, ignoring second\n");
404 printf("CIFS: UNC name too long\n");
407 } else if ((strncmp(data
, "domain", 3) == 0)
408 || (strncmp(data
, "workgroup", 5) == 0)) {
409 if (!value
|| !*value
) {
410 printf("CIFS: invalid domain name\n");
411 return 1; /* needs_arg; */
413 if (strnlen(value
, 65) < 65) {
416 printf("domain name too long\n");
419 } else if (strncmp(data
, "cred", 4) == 0) {
420 if (value
&& *value
) {
421 rc
= open_cred_file(value
);
423 printf("error %d opening credential file %s\n",rc
, value
);
427 printf("invalid credential file name specified\n");
430 } else if (strncmp(data
, "uid", 3) == 0) {
431 if (value
&& *value
) {
434 } else if (strncmp(data
, "gid", 3) == 0) {
435 if (value
&& *value
) {
438 /* fmask and dmask synonyms for people used to smbfs syntax */
439 } else if (strcmp(data
, "file_mode") == 0 || strcmp(data
, "fmask")==0) {
440 if (!value
|| !*value
) {
441 printf ("Option '%s' requires a numerical argument\n", data
);
445 if (value
[0] != '0') {
446 printf ("WARNING: '%s' not expressed in octal.\n", data
);
449 if (strcmp (data
, "fmask") == 0) {
450 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
451 data
= "file_mode"; /* BB fix this */
453 } else if (strcmp(data
, "dir_mode") == 0 || strcmp(data
, "dmask")==0) {
454 if (!value
|| !*value
) {
455 printf ("Option '%s' requires a numerical argument\n", data
);
459 if (value
[0] != '0') {
460 printf ("WARNING: '%s' not expressed in octal.\n", data
);
463 if (strcmp (data
, "dmask") == 0) {
464 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
467 /* the following eight mount options should be
468 stripped out from what is passed into the kernel
469 since these eight options are best passed as the
470 mount flags rather than redundantly to the kernel
471 and could generate spurious warnings depending on the
472 level of the corresponding cifs vfs kernel code */
473 } else if (strncmp(data
, "nosuid", 6) == 0) {
474 *filesys_flags
|= MS_NOSUID
;
475 } else if (strncmp(data
, "suid", 4) == 0) {
476 *filesys_flags
&= ~MS_NOSUID
;
477 } else if (strncmp(data
, "nodev", 5) == 0) {
478 *filesys_flags
|= MS_NODEV
;
479 } else if (strncmp(data
, "dev", 3) == 0) {
480 *filesys_flags
&= ~MS_NODEV
;
481 } else if (strncmp(data
, "noexec", 6) == 0) {
482 *filesys_flags
|= MS_NOEXEC
;
483 } else if (strncmp(data
, "exec", 4) == 0) {
484 *filesys_flags
&= ~MS_NOEXEC
;
485 } else if (strncmp(data
, "guest", 5) == 0) {
487 /* remove the parm since it would otherwise be logged by kern */
493 } else if (strncmp(data
, "ro", 2) == 0) {
494 *filesys_flags
|= MS_RDONLY
;
495 } else if (strncmp(data
, "rw", 2) == 0) {
496 *filesys_flags
&= ~MS_RDONLY
;
497 } else if (strncmp(data
, "remount", 7) == 0) {
498 *filesys_flags
|= MS_REMOUNT
;
499 } /* else if (strnicmp(data, "port", 4) == 0) {
500 if (value && *value) {
502 simple_strtoul(value, &value, 0);
504 } else if (strnicmp(data, "rsize", 5) == 0) {
505 if (value && *value) {
507 simple_strtoul(value, &value, 0);
509 } else if (strnicmp(data, "wsize", 5) == 0) {
510 if (value && *value) {
512 simple_strtoul(value, &value, 0);
514 } else if (strnicmp(data, "version", 3) == 0) {
516 printf("CIFS: Unknown mount option %s\n",data);
517 } */ /* nothing to do on those four mount options above.
518 Just pass to kernel and ignore them here */
520 /* move to next option */
521 data
= next_keyword
+1;
523 /* put overwritten equals sign back */
529 /* put previous overwritten comma back */
531 *next_keyword
= ','; /* BB handle sep= */
538 /* replace all (one or more) commas with double commas */
539 static void check_for_comma(char ** ppasswrd
)
544 int number_of_commas
= 0;
545 int len
= strlen(*ppasswrd
);
557 if(number_of_commas
== 0)
559 if(number_of_commas
> 64) {
560 /* would otherwise overflow the mount options buffer */
561 printf("\nInvalid password. Password contains too many commas.\n");
565 new_pass_buf
= malloc(len
+number_of_commas
+1);
566 if(new_pass_buf
== NULL
)
569 for(i
=0,j
=0;i
<len
;i
++,j
++) {
570 new_pass_buf
[j
] = pass
[i
];
573 new_pass_buf
[j
] = pass
[i
];
576 new_pass_buf
[len
+number_of_commas
] = 0;
579 *ppasswrd
= new_pass_buf
;
584 /* Usernames can not have backslash in them and we use
585 [BB check if usernames can have forward slash in them BB]
586 backslash as domain\user separator character
588 static char * check_for_domain(char **ppuser
)
590 char * original_string
;
600 original_string
= *ppuser
;
602 if (original_string
== NULL
)
605 original_len
= strlen(original_string
);
607 usernm
= strchr(*ppuser
,'/');
608 if (usernm
== NULL
) {
609 usernm
= strchr(*ppuser
,'\\');
615 printf("Domain name specified twice. Username probably malformed\n");
621 if (domainnm
[0] != 0) {
624 printf("null domain\n");
626 len
= strlen(domainnm
);
627 /* reset domainm to new buffer, and copy
628 domain name into it */
629 domainnm
= malloc(len
+1);
633 strcpy(domainnm
,*ppuser
);
635 /* move_string(*ppuser, usernm+1) */
636 len
= strlen(usernm
+1);
638 if(len
>= original_len
) {
639 /* should not happen */
643 for(i
=0;i
<original_len
;i
++) {
645 original_string
[i
] = usernm
[i
+1];
646 else /* stuff with commas to remove last parm */
647 original_string
[i
] = ',';
650 /* BB add check for more than one slash?
658 /* Note that caller frees the returned buffer if necessary */
659 static char * parse_server(char ** punc_name
)
661 char * unc_name
= *punc_name
;
662 int length
= strnlen(unc_name
,1024);
664 char * ipaddress_string
= NULL
;
665 struct hostent
* host_entry
;
666 struct in_addr server_ipaddr
;
670 printf("mount error: UNC name too long");
673 if (strncasecmp("cifs://",unc_name
,7) == 0)
674 return parse_cifs_url(unc_name
+7);
675 if (strncasecmp("smb://",unc_name
,6) == 0) {
676 return parse_cifs_url(unc_name
+6);
680 /* BB add code to find DFS root here */
681 printf("\nMounting the DFS root for domain not implemented yet");
684 if(strncmp(unc_name
,"//",2) && strncmp(unc_name
,"\\\\",2)) {
685 /* check for nfs syntax ie server:share */
686 share
= strchr(unc_name
,':');
689 *punc_name
= malloc(length
+3);
691 strncpy((*punc_name
)+2,unc_name
,length
);
692 unc_name
= *punc_name
;
693 unc_name
[length
+2] = 0;
694 goto continue_unc_parsing
;
696 printf("mount error: improperly formatted UNC name.");
697 printf(" %s does not begin with \\\\ or //\n",unc_name
);
701 continue_unc_parsing
:
705 if ((share
= strchr(unc_name
, '/')) ||
706 (share
= strchr(unc_name
,'\\'))) {
707 *share
= 0; /* temporarily terminate the string */
710 host_entry
= gethostbyname(unc_name
);
712 *(share
- 1) = '/'; /* put the slash back */
715 printf("ip address specified explicitly\n");
718 if(host_entry
== NULL
) {
719 printf("mount error: could not find target server. TCP name %s not found ", unc_name
);
720 printf(" rc = %d\n",rc
);
723 /* BB should we pass an alternate version of the share name as Unicode */
724 /* BB what about ipv6? BB */
725 /* BB add retries with alternate servers in list */
727 memcpy(&server_ipaddr
.s_addr
, host_entry
->h_addr
, 4);
729 ipaddress_string
= inet_ntoa(server_ipaddr
);
730 if(ipaddress_string
== NULL
) {
731 printf("mount error: could not get valid ip address for target server\n");
734 return ipaddress_string
;
737 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
738 printf("Mounting the DFS root for a particular server not implemented yet\n");
745 static struct option longopts
[] = {
746 { "all", 0, NULL
, 'a' },
747 { "help",0, NULL
, 'h' },
748 { "move",0, NULL
, 'm' },
749 { "bind",0, NULL
, 'b' },
750 { "read-only", 0, NULL
, 'r' },
751 { "ro", 0, NULL
, 'r' },
752 { "verbose", 0, NULL
, 'v' },
753 { "version", 0, NULL
, 'V' },
754 { "read-write", 0, NULL
, 'w' },
755 { "rw", 0, NULL
, 'w' },
756 { "options", 1, NULL
, 'o' },
757 { "type", 1, NULL
, 't' },
758 { "rsize",1, NULL
, 'R' },
759 { "wsize",1, NULL
, 'W' },
760 { "uid", 1, NULL
, '1'},
761 { "gid", 1, NULL
, '2'},
762 { "user",1,NULL
,'u'},
763 { "username",1,NULL
,'u'},
765 { "domain",1,NULL
,'d'},
766 { "password",1,NULL
,'p'},
767 { "pass",1,NULL
,'p'},
768 { "credentials",1,NULL
,'c'},
769 { "port",1,NULL
,'P'},
770 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
774 int main(int argc
, char ** argv
)
777 int flags
= MS_MANDLOCK
; /* no need to set legacy MS_MGC_VAL */
778 char * orgoptions
= NULL
;
779 char * share_name
= NULL
;
780 char * ipaddr
= NULL
;
784 char * resolved_path
;
794 int retry
= 0; /* set when we have to retry mount with uppercase */
796 struct utsname sysinfo
;
797 struct mntent mountent
;
800 /* setlocale(LC_ALL, "");
801 bindtextdomain(PACKAGE, LOCALEDIR);
802 textdomain(PACKAGE); */
805 thisprogram
= argv
[0];
807 if(thisprogram
== NULL
)
808 thisprogram
= "mount.cifs";
811 /* BB add workstation name and domain and pass down */
813 /* #ifdef _GNU_SOURCE
814 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
817 share_name
= argv
[1];
818 mountpoint
= argv
[2];
820 /* add sharename in opts string as unc= parm */
822 while ((c
= getopt_long (argc
, argv
, "afFhilL:no:O:rsSU:vVwt:",
823 longopts
, NULL
)) != -1) {
825 /* No code to do the following options yet */
827 list_with_volumelabel = 1;
830 volumelabel = optarg;
850 orgoptions
= strdup(optarg
);
852 case 'r': /* mount readonly */
862 printf ("mount.cifs version: %s.%s%s\n",
863 MOUNT_CIFS_VERSION_MAJOR
,
864 MOUNT_CIFS_VERSION_MINOR
,
865 MOUNT_CIFS_VENDOR_SUFFIX
);
867 memset(mountpassword
,0,64);
874 rsize
= atoi(optarg
) ;
877 wsize
= atoi(optarg
);
890 domain_name
= optarg
; /* BB fix this - currently ignored */
893 if(mountpassword
== NULL
)
894 mountpassword
= calloc(65,1);
897 strncpy(mountpassword
,optarg
,64);
901 get_password_from_file(0 /* stdin */,NULL
);
906 printf("unknown mount option %c\n",c
);
915 if (getenv("PASSWD")) {
916 if(mountpassword
== NULL
)
917 mountpassword
= calloc(65,1);
919 strncpy(mountpassword
,getenv("PASSWD"),64);
922 } else if (getenv("PASSWD_FD")) {
923 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL
);
924 } else if (getenv("PASSWD_FILE")) {
925 get_password_from_file(0, getenv("PASSWD_FILE"));
928 if (orgoptions
&& parse_options(orgoptions
, &flags
))
930 ipaddr
= parse_server(&share_name
);
931 if((ipaddr
== NULL
) && (got_ip
== 0)) {
932 printf("No ip address specified and hostname not found\n");
936 /* BB save off path and pop after mount returns? */
937 resolved_path
= malloc(PATH_MAX
+1);
939 /* Note that if we can not canonicalize the name, we get
940 another chance to see if it is valid when we chdir to it */
941 if (realpath(mountpoint
, resolved_path
)) {
942 mountpoint
= resolved_path
;
945 if(chdir(mountpoint
)) {
946 printf("mount error: can not change directory into mount target %s\n",mountpoint
);
950 if(stat (".", &statbuf
)) {
951 printf("mount error: mount point %s does not exist\n",mountpoint
);
955 if (S_ISDIR(statbuf
.st_mode
) == 0) {
956 printf("mount error: mount point %s is not a directory\n",mountpoint
);
960 if((getuid() != 0) && (geteuid() == 0)) {
961 if((statbuf
.st_uid
== getuid()) && (S_IRWXU
== (statbuf
.st_mode
& S_IRWXU
))) {
962 #ifndef CIFS_ALLOW_USR_SUID
963 /* Do not allow user mounts to control suid flag
964 for mount unless explicitly built that way */
965 flags
|= MS_NOSUID
| MS_NODEV
;
968 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
974 user_name
= getusername();
978 if(got_password
== 0) {
979 mountpassword
= getpass("Password: "); /* BB obsolete */
982 /* FIXME launch daemon (handles dfs name resolution and credential change)
983 remember to clear parms and overwrite password field before launching */
986 optlen
= strlen(orgoptions
);
991 optlen
+= strlen(share_name
) + 4;
993 optlen
+= strlen(user_name
) + 6;
995 optlen
+= strlen(ipaddr
) + 4;
997 optlen
+= strlen(mountpassword
) + 6;
998 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 */);
1000 if(options
== NULL
) {
1001 printf("Could not allocate memory for mount options\n");
1007 strncat(options
,"unc=",4);
1008 strcat(options
,share_name
);
1009 /* scan backwards and reverse direction of slash */
1010 temp
= strrchr(options
, '/');
1011 if(temp
> options
+ 6)
1014 strncat(options
,",ip=",4);
1015 strcat(options
,ipaddr
);
1019 /* check for syntax like user=domain\user */
1020 domain_name
= check_for_domain(&user_name
);
1021 strncat(options
,",user=",6);
1022 strcat(options
,user_name
);
1026 /* extra length accounted for in option string above */
1027 strncat(options
,",domain=",8);
1028 strcat(options
,domain_name
);
1032 /* Commas have to be doubled, or else they will
1033 look like the parameter separator */
1034 /* if(sep is not set)*/
1036 check_for_comma(&mountpassword
);
1037 strncat(options
,",pass=",6);
1038 strcat(options
,mountpassword
);
1041 strncat(options
,",ver=",5);
1042 strcat(options
,MOUNT_CIFS_VERSION_MAJOR
);
1045 strcat(options
,",");
1046 strcat(options
,orgoptions
);
1049 printf("\nmount.cifs kernel mount options %s \n",options
);
1050 if(mount(share_name
, mountpoint
, "cifs", flags
, options
)) {
1051 /* remember to kill daemon on error */
1056 printf("mount failed but no error number set\n");
1059 printf("mount error: cifs filesystem not supported by the system\n");
1065 while (*tmp
&& !(((unsigned char)tmp
[0]) & 0x80)) {
1066 *tmp
= toupper((unsigned char)*tmp
);
1070 printf("retrying with upper case share name\n");
1076 printf("mount error %d = %s\n",errno
,strerror(errno
));
1078 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1080 memset(mountpassword
,0,64);
1084 pmntfile
= setmntent(MOUNTED
, "a+");
1086 mountent
.mnt_fsname
= share_name
;
1087 mountent
.mnt_dir
= mountpoint
;
1088 mountent
.mnt_type
= "cifs";
1089 mountent
.mnt_opts
= malloc(220);
1090 if(mountent
.mnt_opts
) {
1091 char * mount_user
= getusername();
1092 memset(mountent
.mnt_opts
,0,200);
1093 if(flags
& MS_RDONLY
)
1094 strcat(mountent
.mnt_opts
,"ro");
1096 strcat(mountent
.mnt_opts
,"rw");
1097 if(flags
& MS_MANDLOCK
)
1098 strcat(mountent
.mnt_opts
,",mand");
1100 strcat(mountent
.mnt_opts
,",nomand");
1101 if(flags
& MS_NOEXEC
)
1102 strcat(mountent
.mnt_opts
,",noexec");
1103 if(flags
& MS_NOSUID
)
1104 strcat(mountent
.mnt_opts
,",nosuid");
1105 if(flags
& MS_NODEV
)
1106 strcat(mountent
.mnt_opts
,",nodev");
1107 if(flags
& MS_SYNCHRONOUS
)
1108 strcat(mountent
.mnt_opts
,",synch");
1111 strcat(mountent
.mnt_opts
,",user=");
1112 strcat(mountent
.mnt_opts
,mount_user
);
1117 mountent
.mnt_freq
= 0;
1118 mountent
.mnt_passno
= 0;
1119 rc
= addmntent(pmntfile
,&mountent
);
1120 endmntent(pmntfile
);
1121 if(mountent
.mnt_opts
)
1122 free(mountent
.mnt_opts
);
1124 printf("could not update mount table\n");
1128 int len
= strlen(mountpassword
);
1129 memset(mountpassword
,0,len
);
1130 free(mountpassword
);
1134 memset(options
,0,optlen
);
1139 memset(orgoptions
,0,orgoptlen
);
1143 free(resolved_path
);
1146 if(free_share_name
) {