Fix credential file mountinf for cifs vfs
[Samba/bjacke.git] / source / client / mount.cifs.c
bloba2f9ebf45cabc98efac759cc8696ceda104c7951
1 /*
2 Mount helper utility for Linux CIFS VFS (virtual filesystem) client
3 Copyright (C) 2003 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. */
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <pwd.h>
27 #include <sys/types.h>
28 #include <sys/mount.h>
29 #include <sys/stat.h>
30 #include <sys/utsname.h>
31 #include <sys/socket.h>
32 #include <arpa/inet.h>
33 #include <getopt.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <string.h>
37 #include <mntent.h>
38 #include <fcntl.h>
40 #define MOUNT_CIFS_VERSION_MAJOR "1"
41 #define MOUNT_CIFS_VERSION_MINOR "2"
43 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
44 #define MOUNT_CIFS_VENDOR_SUFFIX ""
45 #endif
47 #ifndef MS_MOVE
48 #define MS_MOVE 8192
49 #endif
51 char * thisprogram;
52 int verboseflag = 0;
53 static int got_password = 0;
54 static int got_user = 0;
55 static int got_domain = 0;
56 static int got_ip = 0;
57 static int got_unc = 0;
58 static int got_uid = 0;
59 static int got_gid = 0;
60 static char * user_name = NULL;
61 char * mountpassword = NULL;
64 /* BB finish BB
66 cifs_umount
67 open nofollow - avoid symlink exposure?
68 get owner of dir see if matches self or if root
69 call system(umount argv) etc.
71 BB end finish BB */
73 static void mount_cifs_usage(void)
75 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
76 printf("\nMount the remote target, specified as a UNC name,");
77 printf(" to a local directory.\n");
78 if(mountpassword) {
79 memset(mountpassword,0,64);
80 free(mountpassword);
82 exit(1);
85 /* caller frees username if necessary */
86 static char * getusername(void) {
87 char *username = NULL;
88 struct passwd *password = getpwuid(getuid());
90 if (password) {
91 username = password->pw_name;
93 return username;
96 char * parse_cifs_url(char * unc_name)
98 printf("\ncifs url %s\n",unc_name);
99 return NULL;
102 static int open_cred_file(char * file_name)
104 char * line_buf;
105 char * temp_val;
106 FILE * fs;
107 int i, length;
108 fs = fopen(file_name,"r");
109 if(fs == NULL)
110 return errno;
111 line_buf = malloc(4096);
112 if(line_buf == NULL)
113 return -ENOMEM;
115 while(fgets(line_buf,4096,fs)) {
116 /* parse line from credential file */
118 /* eat leading white space */
119 for(i=0;i<4096;i++) {
120 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
121 break;
122 /* if whitespace - skip past it */
123 line_buf++;
125 if (strncasecmp("username",line_buf,8) == 0) {
126 temp_val = strchr(line_buf + i,'=');
127 if(temp_val) {
128 /* go past equals sign */
129 temp_val++;
130 for(length = 0;length<4087;length++) {
131 if(temp_val[length] == '\n')
132 break;
134 if(length > 4086) {
135 printf("cifs.mount failed due to malformed username in credentials file");
136 memset(line_buf,0,4096);
137 if(mountpassword) {
138 memset(mountpassword,0,64);
140 exit(1);
141 } else {
142 got_user = 1;
143 user_name = calloc(1 + length,1);
144 /* BB adding free of user_name string before exit,
145 not really necessary but would be cleaner */
146 strncpy(user_name,temp_val, length);
149 } else if (strncasecmp("password",line_buf,8) == 0) {
150 temp_val = strchr(line_buf+i,'=');
151 if(temp_val) {
152 /* go past equals sign */
153 temp_val++;
154 for(length = 0;length<65;length++) {
155 if(temp_val[length] == '\n')
156 break;
158 if(length > 64) {
159 printf("cifs.mount failed: password in credentials file too long\n");
160 memset(line_buf,0, 4096);
161 if(mountpassword) {
162 memset(mountpassword,0,64);
164 exit(1);
165 } else {
166 if(mountpassword == NULL) {
167 mountpassword = calloc(65,1);
168 } else
169 memset(mountpassword,0,64);
170 if(mountpassword) {
171 /* BB add handling for commas in password here */
172 strncpy(mountpassword,temp_val,length);
173 got_password = 1;
179 fclose(fs);
180 if(line_buf) {
181 memset(line_buf,0,4096);
182 free(line_buf);
184 return 0;
187 static int get_password_from_file(int file_descript, char * filename)
189 int rc = 0;
190 int i;
191 char c;
193 if(mountpassword == NULL)
194 mountpassword = calloc(65,1);
195 else
196 memset(mountpassword, 0, 64);
198 if(filename != NULL) {
199 file_descript = open(filename, O_RDONLY);
200 if(file_descript < 0) {
201 printf("cifs.mount failed. %s attempting to open password file %s\n",
202 strerror(errno),filename);
203 exit(1);
206 /* else file already open and fd provided */
208 for(i=0;i<64;i++) {
209 rc = read(file_descript,&c,1);
210 if(rc < 0) {
211 printf("cifs.mount failed. Error %s reading password file\n",strerror(errno));
212 memset(mountpassword,0,64);
213 if(filename != NULL)
214 close(file_descript);
215 exit(1);
216 } else if(rc == 0) {
217 if(mountpassword[0] == 0) {
218 if(verboseflag)
219 printf("\nWarning: null password used since cifs password file empty");
221 break;
222 } else /* read valid character */ {
223 if((c == 0) || (c == '\n')) {
224 break;
225 } else
226 mountpassword[i] = c;
229 if((i == 64) && (verboseflag)) {
230 printf("\nWarning: password longer than 64 characters specified in cifs password file");
232 got_password = 1;
233 if(filename != NULL) {
234 close(file_descript);
237 return rc;
240 static int parse_options(char * options, int * filesys_flags)
242 char * data;
243 char * percent_char = 0;
244 char * value = 0;
245 char * next_keyword = 0;
246 int rc = 0;
248 if (!options)
249 return 1;
250 else
251 data = options;
253 if(verboseflag)
254 printf("\n parsing options: %s", options);
256 /* while ((data = strsep(&options, ",")) != NULL) { */
257 while(data != NULL) {
258 /* check if ends with trailing comma */
259 if(*data == 0)
260 break;
262 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
263 /* data = next keyword */
264 /* value = next value ie stuff after equal sign */
266 next_keyword = strchr(data,',');
268 /* temporarily null terminate end of keyword=value pair */
269 if(next_keyword)
270 *next_keyword = 0;
272 /* if (!*data)
273 continue; */
275 /* temporarily null terminate keyword to make keyword and value distinct */
276 if ((value = strchr(data, '=')) != NULL) {
277 *value = '\0';
278 value++;
281 if (strncmp(data, "user", 4) == 0) {
282 if (!value || !*value) {
283 printf("invalid or missing username\n");
284 return 1; /* needs_arg; */
286 if (strnlen(value, 260) < 260) {
287 got_user=1;
288 percent_char = strchr(value,'%');
289 if(percent_char) {
290 *percent_char = ',';
291 if(mountpassword == NULL)
292 mountpassword = calloc(65,1);
293 if(mountpassword) {
294 if(got_password)
295 printf("\ncifs.mount warning - password specified twice\n");
296 got_password = 1;
297 percent_char++;
298 strncpy(mountpassword, percent_char,64);
299 /* remove password from username */
300 while(*percent_char != 0) {
301 *percent_char = ',';
302 percent_char++;
306 } else {
307 printf("username too long\n");
308 return 1;
310 } else if (strncmp(data, "pass", 4) == 0) {
311 if (!value || !*value) {
312 if(got_password) {
313 printf("\npassword specified twice, ignoring second\n");
314 } else
315 got_password = 1;
316 } else if (strnlen(value, 17) < 17) {
317 if(got_password)
318 printf("\ncifs.mount warning - password specified twice\n");
319 got_password = 1;
320 } else {
321 printf("password too long\n");
322 return 1;
324 } else if (strncmp(data, "ip", 2) == 0) {
325 if (!value || !*value) {
326 printf("target ip address argument missing");
327 } else if (strnlen(value, 35) < 35) {
328 got_ip = 1;
329 } else {
330 printf("ip address too long\n");
331 return 1;
333 } else if ((strncmp(data, "unc", 3) == 0)
334 || (strncmp(data, "target", 6) == 0)
335 || (strncmp(data, "path", 4) == 0)) {
336 if (!value || !*value) {
337 printf("invalid path to network resource\n");
338 return 1; /* needs_arg; */
339 } else if(strnlen(value,5) < 5) {
340 printf("UNC name too short");
343 if (strnlen(value, 300) < 300) {
344 got_unc = 1;
345 if (strncmp(value, "//", 2) == 0) {
346 if(got_unc)
347 printf("unc name specified twice, ignoring second\n");
348 else
349 got_unc = 1;
350 } else if (strncmp(value, "\\\\", 2) != 0) {
351 printf("UNC Path does not begin with // or \\\\ \n");
352 return 1;
353 } else {
354 if(got_unc)
355 printf("unc name specified twice, ignoring second\n");
356 else
357 got_unc = 1;
359 } else {
360 printf("CIFS: UNC name too long\n");
361 return 1;
363 } else if ((strncmp(data, "domain", 3) == 0)
364 || (strncmp(data, "workgroup", 5) == 0)) {
365 if (!value || !*value) {
366 printf("CIFS: invalid domain name\n");
367 return 1; /* needs_arg; */
369 if (strnlen(value, 65) < 65) {
370 got_domain = 1;
371 } else {
372 printf("domain name too long\n");
373 return 1;
375 } else if (strncmp(data, "cred", 4) == 0) {
376 if (value && *value) {
377 rc = open_cred_file(value);
378 if(rc) {
379 printf("error %d opening credential file %s",rc, value);
380 return 1;
382 } else {
383 printf("invalid credential file name specified\n");
384 return 1;
386 } else if (strncmp(data, "uid", 3) == 0) {
387 if (value && *value) {
388 got_uid = 1;
390 } else if (strncmp(data, "gid", 3) == 0) {
391 if (value && *value) {
392 got_gid = 1;
394 /* fmask and dmask synonyms for people used to smbfs syntax */
395 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
396 if (!value || !*value) {
397 printf ("Option '%s' requires a numerical argument\n", data);
398 return 1;
401 if (value[0] != '0') {
402 printf ("WARNING: '%s' not expressed in octal.\n", data);
405 if (strcmp (data, "fmask") == 0) {
406 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
407 data = "file_mode"; /* BB fix this */
409 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
410 if (!value || !*value) {
411 printf ("Option '%s' requires a numerical argument\n", data);
412 return 1;
415 if (value[0] != '0') {
416 printf ("WARNING: '%s' not expressed in octal.\n", data);
419 if (strcmp (data, "dmask") == 0) {
420 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
421 data = "dir_mode";
423 /* the following eight mount options should be
424 stripped out from what is passed into the kernel
425 since these eight options are best passed as the
426 mount flags rather than redundantly to the kernel
427 and could generate spurious warnings depending on the
428 level of the corresponding cifs vfs kernel code */
429 } else if (strncmp(data, "nosuid", 6) == 0) {
430 *filesys_flags |= MS_NOSUID;
431 } else if (strncmp(data, "suid", 4) == 0) {
432 *filesys_flags &= ~MS_NOSUID;
433 } else if (strncmp(data, "nodev", 5) == 0) {
434 *filesys_flags |= MS_NODEV;
435 } else if (strncmp(data, "dev", 3) == 0) {
436 *filesys_flags &= ~MS_NODEV;
437 } else if (strncmp(data, "noexec", 6) == 0) {
438 *filesys_flags |= MS_NOEXEC;
439 } else if (strncmp(data, "exec", 4) == 0) {
440 *filesys_flags &= ~MS_NOEXEC;
441 } else if (strncmp(data, "ro", 2) == 0) {
442 *filesys_flags |= MS_RDONLY;
443 } else if (strncmp(data, "rw", 2) == 0) {
444 *filesys_flags &= ~MS_RDONLY;
445 } /* else if (strnicmp(data, "port", 4) == 0) {
446 if (value && *value) {
447 vol->port =
448 simple_strtoul(value, &value, 0);
450 } else if (strnicmp(data, "rsize", 5) == 0) {
451 if (value && *value) {
452 vol->rsize =
453 simple_strtoul(value, &value, 0);
455 } else if (strnicmp(data, "wsize", 5) == 0) {
456 if (value && *value) {
457 vol->wsize =
458 simple_strtoul(value, &value, 0);
460 } else if (strnicmp(data, "version", 3) == 0) {
461 } else {
462 printf("CIFS: Unknown mount option %s\n",data);
463 } */ /* nothing to do on those four mount options above.
464 Just pass to kernel and ignore them here */
466 /* move to next option */
467 data = next_keyword+1;
469 /* put overwritten equals sign back */
470 if(value) {
471 value--;
472 *value = '=';
475 /* put previous overwritten comma back */
476 if(next_keyword)
477 *next_keyword = ',';
478 else
479 data = 0;
482 return 0;
485 /* Note that caller frees the returned buffer if necessary */
486 char * parse_server(char * unc_name)
488 int length = strnlen(unc_name,1024);
489 char * share;
490 char * ipaddress_string = NULL;
491 struct hostent * host_entry;
492 struct in_addr server_ipaddr;
493 int rc;
495 if(length > 1023) {
496 printf("mount error: UNC name too long");
497 return 0;
499 if (strncasecmp("cifs://",unc_name,7) == 0)
500 return parse_cifs_url(unc_name+7);
501 if (strncasecmp("smb://",unc_name,6) == 0) {
502 return parse_cifs_url(unc_name+6);
505 if(length < 3) {
506 /* BB add code to find DFS root here */
507 printf("\nMounting the DFS root for domain not implemented yet");
508 return 0;
509 } else {
510 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
511 printf("mount error: improperly formatted UNC name.");
512 printf(" %s does not begin with \\\\ or //\n",unc_name);
513 return 0;
514 } else {
515 unc_name[0] = '\\';
516 unc_name[0] = '/';
517 unc_name[1] = '/';
518 unc_name += 2;
519 if ((share = strchr(unc_name, '/')) ||
520 (share = strchr(unc_name,'\\'))) {
521 *share = 0; /* temporarily terminate the string */
522 share += 1;
523 host_entry = gethostbyname(unc_name);
524 *(share - 1) = '/'; /* put the slash back */
525 /* rc = getipnodebyname(unc_name, AF_INET, AT_ADDRCONFIG ,&rc);*/
526 if(host_entry == NULL) {
527 printf("mount error: could not find target server. TCP name %s not found ", unc_name);
528 printf(" rc = %d\n",rc);
529 return 0;
531 else {
532 /* BB should we pass an alternate version of the share name as Unicode */
533 /* BB what about ipv6? BB */
534 /* BB add retries with alternate servers in list */
536 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
538 ipaddress_string = inet_ntoa(server_ipaddr);
539 if(ipaddress_string == NULL) {
540 printf("mount error: could not get valid ip address for target server\n");
541 return 0;
543 return ipaddress_string;
545 } else {
546 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
547 printf("Mounting the DFS root for a particular server not implemented yet\n");
548 return 0;
554 static struct option longopts[] = {
555 { "all", 0, 0, 'a' },
556 { "help",0, 0, 'h' },
557 { "move",0, 0, 'm' },
558 { "bind",0, 0, 'b' },
559 { "read-only", 0, 0, 'r' },
560 { "ro", 0, 0, 'r' },
561 { "verbose", 0, 0, 'v' },
562 { "version", 0, 0, 'V' },
563 { "read-write", 0, 0, 'w' },
564 { "rw", 0, 0, 'w' },
565 { "options", 1, 0, 'o' },
566 { "type", 1, 0, 't' },
567 { "rsize",1, 0, 'R' },
568 { "wsize",1, 0, 'W' },
569 { "uid", 1, 0, '1'},
570 { "gid", 1, 0, '2'},
571 { "user",1,0,'u'},
572 { "username",1,0,'u'},
573 { "dom",1,0,'d'},
574 { "domain",1,0,'d'},
575 { "password",1,0,'p'},
576 { "pass",1,0,'p'},
577 { "credentials",1,0,'c'},
578 { "port",1,0,'P'},
579 /* { "uuid",1,0,'U'}, */ /* BB unimplemented */
580 { NULL, 0, 0, 0 }
583 int main(int argc, char ** argv)
585 int c;
586 int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
587 char * orgoptions = NULL;
588 char * share_name = NULL;
589 char * domain_name = NULL;
590 char * ipaddr = NULL;
591 char * uuid = NULL;
592 char * mountpoint;
593 char * options;
594 char * temp;
595 int rc;
596 int rsize = 0;
597 int wsize = 0;
598 int nomtab = 0;
599 int uid = 0;
600 int gid = 0;
601 int optlen = 0;
602 int orgoptlen = 0;
603 struct stat statbuf;
604 struct utsname sysinfo;
605 struct mntent mountent;
606 FILE * pmntfile;
608 /* setlocale(LC_ALL, "");
609 bindtextdomain(PACKAGE, LOCALEDIR);
610 textdomain(PACKAGE); */
612 if(argc && argv) {
613 thisprogram = argv[0];
615 if(thisprogram == NULL)
616 thisprogram = "mount.cifs";
618 uname(&sysinfo);
619 /* BB add workstation name and domain and pass down */
621 /* #ifdef _GNU_SOURCE
622 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
623 #endif */
625 share_name = argv[1];
626 mountpoint = argv[2];
628 /* add sharename in opts string as unc= parm */
630 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
631 longopts, NULL)) != -1) {
632 switch (c) {
633 /* No code to do the following options yet */
634 /* case 'l':
635 list_with_volumelabel = 1;
636 break;
637 case 'L':
638 volumelabel = optarg;
639 break; */
640 /* case 'a':
641 ++mount_all;
642 break; */
644 case '?':
645 case 'h': /* help */
646 mount_cifs_usage ();
647 exit(1);
648 case 'n':
649 ++nomtab;
650 break;
651 case 'b':
652 flags |= MS_BIND;
653 break;
654 case 'm':
655 flags |= MS_MOVE;
656 break;
657 case 'o':
658 orgoptions = strdup(optarg);
659 break;
660 case 'r': /* mount readonly */
661 flags |= MS_RDONLY;
662 break;
663 case 'U':
664 uuid = optarg;
665 break;
666 case 'v':
667 ++verboseflag;
668 break;
669 case 'V':
670 printf ("mount.cifs version: %s.%s%s\n",
671 MOUNT_CIFS_VERSION_MAJOR,
672 MOUNT_CIFS_VERSION_MINOR,
673 MOUNT_CIFS_VENDOR_SUFFIX);
674 if(mountpassword) {
675 memset(mountpassword,0,64);
677 exit (0);
678 case 'w':
679 flags &= ~MS_RDONLY;
680 break;
681 case 'R':
682 rsize = atoi(optarg) ;
683 break;
684 case 'W':
685 wsize = atoi(optarg);
686 break;
687 case '1':
688 uid = atoi(optarg);
689 break;
690 case '2':
691 gid = atoi(optarg);
692 break;
693 case 'u':
694 got_user = 1;
695 user_name = optarg;
696 break;
697 case 'd':
698 domain_name = optarg;
699 break;
700 case 'p':
701 if(mountpassword == NULL)
702 mountpassword = calloc(65,1);
703 if(mountpassword) {
704 got_password = 1;
705 strncpy(mountpassword,optarg,64);
707 break;
708 case 't':
709 break;
710 default:
711 printf("unknown mount option %c\n",c);
712 mount_cifs_usage();
713 exit(1);
717 if(argc < 3)
718 mount_cifs_usage();
720 if (getenv("PASSWD")) {
721 if(mountpassword == NULL)
722 mountpassword = calloc(65,1);
723 if(mountpassword) {
724 strncpy(mountpassword,getenv("PASSWD"),64);
725 got_password = 1;
727 } else if (getenv("PASSWD_FD")) {
728 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
729 } else if (getenv("PASSWD_FILE")) {
730 get_password_from_file(0, getenv("PASSWD_FILE"));
733 ipaddr = parse_server(share_name);
735 if (orgoptions && parse_options(orgoptions, &flags))
736 return 1;
738 /* BB save off path and pop after mount returns? */
739 /* BB canonicalize the path in argv[1]? */
741 if(chdir(mountpoint)) {
742 printf("mount error: can not change directory into mount target %s\n",mountpoint);
743 return -1;
746 if(stat (".", &statbuf)) {
747 printf("mount error: mount point %s does not exist\n",mountpoint);
748 return -1;
751 if (S_ISDIR(statbuf.st_mode) == 0) {
752 printf("mount error: mount point %s is not a directory\n",mountpoint);
753 return -1;
756 if((getuid() != 0) && (geteuid() == 0)) {
757 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
758 #ifndef CIFS_ALLOW_USR_SUID
759 /* Do not allow user mounts to control suid flag
760 for mount unless explicitly built that way */
761 flags |= MS_NOSUID | MS_NODEV;
762 #endif
763 } else {
764 printf("mount error: permission denied or not superuser and cifs.mount not installed SUID\n");
765 return -1;
769 if(got_user == 0)
770 user_name = getusername();
772 if(got_password == 0) {
773 mountpassword = getpass("Password: "); /* BB obsolete */
774 got_password = 1;
776 /* FIXME launch daemon (handles dfs name resolution and credential change)
777 remember to clear parms and overwrite password field before launching */
778 if(orgoptions) {
779 optlen = strlen(orgoptions);
780 orgoptlen = optlen;
781 } else
782 optlen = 0;
783 if(share_name)
784 optlen += strlen(share_name) + 4;
785 if(user_name)
786 optlen += strlen(user_name) + 6;
787 if(ipaddr)
788 optlen += strlen(ipaddr) + 4;
789 if(mountpassword)
790 optlen += strlen(mountpassword) + 6;
791 options = malloc(optlen + 10);
793 if(options == NULL) {
794 printf("Could not allocate memory for mount options\n");
795 return -1;
799 options[0] = 0;
800 strncat(options,"unc=",4);
801 strcat(options,share_name);
802 /* scan backwards and reverse direction of slash */
803 temp = strrchr(options, '/');
804 if(temp > options + 6)
805 *temp = '\\';
806 if(ipaddr) {
807 strncat(options,",ip=",4);
808 strcat(options,ipaddr);
810 if(user_name) {
811 strncat(options,",user=",6);
812 strcat(options,user_name);
814 if(mountpassword) {
815 strncat(options,",pass=",6);
816 strcat(options,mountpassword);
818 strncat(options,",ver=",5);
819 strcat(options,MOUNT_CIFS_VERSION_MAJOR);
821 if(orgoptions) {
822 strcat(options,",");
823 strcat(options,orgoptions);
825 if(verboseflag)
826 printf("\ncifs.mount kernel mount options %s \n",options);
827 if(mount(share_name, mountpoint, "cifs", flags, options)) {
828 /* remember to kill daemon on error */
829 switch (errno) {
830 case 0:
831 printf("mount failed but no error number set\n");
832 break;
833 case ENODEV:
834 printf("mount error: cifs filesystem not supported by the system\n");
835 break;
836 default:
837 printf("mount error %d = %s\n",errno,strerror(errno));
839 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
840 if(mountpassword) {
841 memset(mountpassword,0,64);
843 return -1;
844 } else {
845 pmntfile = setmntent(MOUNTED, "a+");
846 if(pmntfile) {
847 mountent.mnt_fsname = share_name;
848 mountent.mnt_dir = mountpoint;
849 mountent.mnt_type = "cifs";
850 mountent.mnt_opts = malloc(200);
851 if(mountent.mnt_opts) {
852 memset(mountent.mnt_opts,0,200);
853 if(flags & MS_RDONLY)
854 strcat(mountent.mnt_opts,"ro");
855 else
856 strcat(mountent.mnt_opts,"rw");
857 if(flags & MS_MANDLOCK)
858 strcat(mountent.mnt_opts,",mand");
859 else
860 strcat(mountent.mnt_opts,",nomand");
861 if(flags & MS_NOEXEC)
862 strcat(mountent.mnt_opts,",noexec");
863 if(flags & MS_NOSUID)
864 strcat(mountent.mnt_opts,",nosuid");
865 if(flags & MS_NODEV)
866 strcat(mountent.mnt_opts,",nodev");
867 if(flags & MS_SYNCHRONOUS)
868 strcat(mountent.mnt_opts,",synch");
870 mountent.mnt_freq = 0;
871 mountent.mnt_passno = 0;
872 rc = addmntent(pmntfile,&mountent);
873 endmntent(pmntfile);
874 if(mountent.mnt_opts)
875 free(mountent.mnt_opts);
876 } else {
877 printf("could not update mount table\n");
880 if(mountpassword) {
881 memset(mountpassword,0,64);
882 free(mountpassword);
885 if(options) {
886 memset(options,0,optlen);
887 free(options);
890 if(orgoptions) {
891 memset(orgoptions,0,orgoptlen);
892 free(orgoptions);
894 return 0;