int main(int argc, char ** argv) { int c; int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */ char * orgoptions = NULL; char * share_name = NULL; const char * ipaddr = NULL; char * uuid = NULL; char * mountpoint = NULL; char * options = NULL; char * optionstail; char * resolved_path = NULL; char * temp; char * dev_name; int rc = 0; int rsize = 0; int wsize = 0; int nomtab = 0; int uid = 0; int gid = 0; int optlen = 0; int orgoptlen = 0; size_t options_size = 0; size_t current_len; int retry = 0; /* set when we have to retry mount with uppercase */ struct addrinfo *addrhead = NULL, *addr; struct stat statbuf; struct utsname sysinfo; struct mntent mountent; struct sockaddr_in *addr4; struct sockaddr_in6 *addr6; FILE * pmntfile; /* setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); */ if(argc && argv) { thisprogram = argv[0]; } else { mount_cifs_usage(); exit(EX_USAGE); } if(thisprogram == NULL) thisprogram = "mount.cifs"; uname(&sysinfo); /* BB add workstation name and domain and pass down */ /* #ifdef _GNU_SOURCE printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname); #endif */ if(argc > 2) { dev_name = argv[1]; share_name = strndup(argv[1], MAX_UNC_LEN); if (share_name == NULL) { fprintf(stderr, "%s: %s", argv[0], strerror(ENOMEM)); exit(EX_SYSERR); } mountpoint = argv[2]; } else if (argc == 2) { if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) { print_cifs_mount_version(); exit(0); } if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "--help") == 0)) { mount_cifs_usage(); exit(0); } mount_cifs_usage(); exit(EX_USAGE); } else { mount_cifs_usage(); exit(EX_USAGE); } /* add sharename in opts string as unc= parm */ while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:", longopts, NULL)) != -1) { switch (c) { /* No code to do the following options yet */ /* case 'l': list_with_volumelabel = 1; break; case 'L': volumelabel = optarg; break; */ /* case 'a': ++mount_all; break; */ case '?': case 'h': /* help */ mount_cifs_usage (); exit(EX_USAGE); case 'n': ++nomtab; break; case 'b': #ifdef MS_BIND flags |= MS_BIND; #else fprintf(stderr, "option 'b' (MS_BIND) not supported\n"); #endif break; case 'm': #ifdef MS_MOVE flags |= MS_MOVE; #else fprintf(stderr, "option 'm' (MS_MOVE) not supported\n"); #endif break; case 'o': orgoptions = strdup(optarg); break; case 'r': /* mount readonly */ flags |= MS_RDONLY; break; case 'U': uuid = optarg; break; case 'v': ++verboseflag; break; case 'V': print_cifs_mount_version(); exit (0); case 'w': flags &= ~MS_RDONLY; break; case 'R': rsize = atoi(optarg) ; break; case 'W': wsize = atoi(optarg); break; case '1': if (isdigit(*optarg)) { char *ep; uid = strtoul(optarg, &ep, 10); if (*ep) { printf("bad uid value \"%s\"\n", optarg); exit(EX_USAGE); } } else { struct passwd *pw; if (!(pw = getpwnam(optarg))) { printf("bad user name \"%s\"\n", optarg); exit(EX_USAGE); } uid = pw->pw_uid; endpwent(); } break; case '2': if (isdigit(*optarg)) { char *ep; gid = strtoul(optarg, &ep, 10); if (*ep) { printf("bad gid value \"%s\"\n", optarg); exit(EX_USAGE); } } else { struct group *gr; if (!(gr = getgrnam(optarg))) { printf("bad user name \"%s\"\n", optarg); exit(EX_USAGE); } gid = gr->gr_gid; endpwent(); } break; case 'u': got_user = 1; user_name = optarg; break; case 'd': domain_name = optarg; /* BB fix this - currently ignored */ got_domain = 1; break; case 'p': if(mountpassword == NULL) mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1); if(mountpassword) { got_password = 1; strlcpy(mountpassword,optarg,MOUNT_PASSWD_SIZE+1); } break; case 'S': get_password_from_file(0 /* stdin */,NULL); break; case 't': break; case 'f': ++fakemnt; break; default: printf("unknown mount option %c\n",c); mount_cifs_usage(); exit(EX_USAGE); } } if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) { mount_cifs_usage(); exit(EX_USAGE); } if (getenv("PASSWD")) { if(mountpassword == NULL) mountpassword = (char *)calloc(MOUNT_PASSWD_SIZE+1,1); if(mountpassword) { strlcpy(mountpassword,getenv("PASSWD"),MOUNT_PASSWD_SIZE+1); got_password = 1; } } else if (getenv("PASSWD_FD")) { get_password_from_file(atoi(getenv("PASSWD_FD")),NULL); } else if (getenv("PASSWD_FILE")) { get_password_from_file(0, getenv("PASSWD_FILE")); } if (orgoptions && parse_options(&orgoptions, &flags)) { rc = EX_USAGE; goto mount_exit; } addrhead = addr = parse_server(&share_name); if((addrhead == NULL) && (got_ip == 0)) { printf("No ip address specified and hostname not found\n"); rc = EX_USAGE; goto mount_exit; } /* BB save off path and pop after mount returns? */ resolved_path = (char *)malloc(PATH_MAX+1); if(resolved_path) { /* Note that if we can not canonicalize the name, we get another chance to see if it is valid when we chdir to it */ if (realpath(mountpoint, resolved_path)) { mountpoint = resolved_path; } } if(chdir(mountpoint)) { printf("mount error: can not change directory into mount target %s\n",mountpoint); rc = EX_USAGE; goto mount_exit; } if(stat (".", &statbuf)) { printf("mount error: mount point %s does not exist\n",mountpoint); rc = EX_USAGE; goto mount_exit; } if (S_ISDIR(statbuf.st_mode) == 0) { printf("mount error: mount point %s is not a directory\n",mountpoint); rc = EX_USAGE; goto mount_exit; } if((getuid() != 0) && (geteuid() == 0)) { if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) { #ifndef CIFS_ALLOW_USR_SUID /* Do not allow user mounts to control suid flag for mount unless explicitly built that way */ flags |= MS_NOSUID | MS_NODEV; #endif } else { printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n"); exit(EX_USAGE); } } if(got_user == 0) { /* Note that the password will not be retrieved from the USER env variable (ie user%password form) as there is already a PASSWD environment varaible */ if (getenv("USER")) user_name = strdup(getenv("USER")); if (user_name == NULL) user_name = getusername(); got_user = 1; } if(got_password == 0) { char *tmp_pass = getpass("Password: "******"Password not entered, exiting\n"); exit(EX_USAGE); } strlcpy(mountpassword, tmp_pass, MOUNT_PASSWD_SIZE+1); got_password = 1; } /* FIXME launch daemon (handles dfs name resolution and credential change) remember to clear parms and overwrite password field before launching */ if(orgoptions) { optlen = strlen(orgoptions); orgoptlen = optlen; } else optlen = 0; if(share_name) optlen += strlen(share_name) + 4; else { printf("No server share name specified\n"); printf("\nMounting the DFS root for server not implemented yet\n"); exit(EX_USAGE); } if(user_name) optlen += strlen(user_name) + 6; optlen += MAX_ADDRESS_LEN + 4; if(mountpassword) optlen += strlen(mountpassword) + 6; mount_retry: SAFE_FREE(options); options_size = optlen + 10 + DOMAIN_SIZE; options = (char *)malloc(options_size /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */); if(options == NULL) { printf("Could not allocate memory for mount options\n"); exit(EX_SYSERR); } strlcpy(options, "unc=", options_size); strlcat(options,share_name,options_size); /* scan backwards and reverse direction of slash */ temp = strrchr(options, '/'); if(temp > options + 6) *temp = '\\'; if(user_name) { /* check for syntax like user=domain\user */ if(got_domain == 0) domain_name = check_for_domain(&user_name); strlcat(options,",user="******",domain=",options_size); strlcat(options,domain_name,options_size); } } strlcat(options,",ver=",options_size); strlcat(options,MOUNT_CIFS_VERSION_MAJOR,options_size); if(orgoptions) { strlcat(options,",",options_size); strlcat(options,orgoptions,options_size); } if(prefixpath) { strlcat(options,",prefixpath=",options_size); strlcat(options,prefixpath,options_size); /* no need to cat the / */ } /* convert all '\\' to '/' in share portion so that /proc/mounts looks pretty */ replace_char(dev_name, '\\', '/', strlen(share_name)); if (!got_ip && addr) { strlcat(options, ",ip=", options_size); current_len = strnlen(options, options_size); optionstail = options + current_len; switch (addr->ai_addr->sa_family) { case AF_INET6: addr6 = (struct sockaddr_in6 *) addr->ai_addr; ipaddr = inet_ntop(AF_INET6, &addr6->sin6_addr, optionstail, options_size - current_len); break; case AF_INET: addr4 = (struct sockaddr_in *) addr->ai_addr; ipaddr = inet_ntop(AF_INET, &addr4->sin_addr, optionstail, options_size - current_len); break; } /* if the address looks bogus, try the next one */ if (!ipaddr) { addr = addr->ai_next; if (addr) goto mount_retry; rc = EX_SYSERR; goto mount_exit; } } if(verboseflag) fprintf(stderr, "\nmount.cifs kernel mount options: %s", options); if (mountpassword) { /* * Commas have to be doubled, or else they will * look like the parameter separator */ if(retry == 0) check_for_comma(&mountpassword); strlcat(options,",pass="******",pass=********"); } if (verboseflag) fprintf(stderr, "\n"); if (!fakemnt && mount(dev_name, mountpoint, "cifs", flags, options)) { switch (errno) { case ECONNREFUSED: case EHOSTUNREACH: if (addr) { addr = addr->ai_next; if (addr) goto mount_retry; } break; case ENODEV: printf("mount error: cifs filesystem not supported by the system\n"); break; case ENXIO: if(retry == 0) { retry = 1; if (uppercase_string(dev_name) && uppercase_string(share_name) && uppercase_string(prefixpath)) { printf("retrying with upper case share name\n"); goto mount_retry; } } } printf("mount error(%d): %s\n", errno, strerror(errno)); printf("Refer to the mount.cifs(8) manual page (e.g. man " "mount.cifs)\n"); rc = EX_FAIL; goto mount_exit; } if (nomtab) goto mount_exit; atexit(unlock_mtab); rc = lock_mtab(); if (rc) { printf("cannot lock mtab"); goto mount_exit; } pmntfile = setmntent(MOUNTED, "a+"); if (!pmntfile) { printf("could not update mount table\n"); unlock_mtab(); rc = EX_FILEIO; goto mount_exit; } mountent.mnt_fsname = dev_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = CONST_DISCARD(char *,"cifs"); mountent.mnt_opts = (char *)malloc(220); if(mountent.mnt_opts) { char * mount_user = getusername(); memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) strlcat(mountent.mnt_opts,"ro",220); else strlcat(mountent.mnt_opts,"rw",220); if(flags & MS_MANDLOCK) strlcat(mountent.mnt_opts,",mand",220); if(flags & MS_NOEXEC) strlcat(mountent.mnt_opts,",noexec",220); if(flags & MS_NOSUID) strlcat(mountent.mnt_opts,",nosuid",220); if(flags & MS_NODEV) strlcat(mountent.mnt_opts,",nodev",220); if(flags & MS_SYNCHRONOUS) strlcat(mountent.mnt_opts,",sync",220); if(mount_user) { if(getuid() != 0) { strlcat(mountent.mnt_opts, ",user=", 220); strlcat(mountent.mnt_opts, mount_user, 220); } } } mountent.mnt_freq = 0; mountent.mnt_passno = 0; rc = addmntent(pmntfile,&mountent); endmntent(pmntfile); unlock_mtab(); SAFE_FREE(mountent.mnt_opts); if (rc) rc = EX_FILEIO; mount_exit: if(mountpassword) { int len = strlen(mountpassword); memset(mountpassword,0,len); SAFE_FREE(mountpassword); } if (addrhead) freeaddrinfo(addrhead); SAFE_FREE(options); SAFE_FREE(orgoptions); SAFE_FREE(resolved_path); SAFE_FREE(share_name); exit(rc); }
int main(int argc, char ** argv) { int c; int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */ char * orgoptions = NULL; char * share_name = NULL; char * ipaddr = NULL; char * uuid = NULL; char * mountpoint = NULL; char * options; char * resolved_path; char * temp; int rc; int rsize = 0; int wsize = 0; int nomtab = 0; int uid = 0; int gid = 0; int optlen = 0; int orgoptlen = 0; int retry = 0; /* set when we have to retry mount with uppercase */ struct stat statbuf; struct utsname sysinfo; struct mntent mountent; FILE * pmntfile; /* setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); */ if(argc && argv) { thisprogram = argv[0]; } else { mount_cifs_usage(); exit(1); } if(thisprogram == NULL) thisprogram = "mount.cifs"; uname(&sysinfo); /* BB add workstation name and domain and pass down */ /* #ifdef _GNU_SOURCE printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname); #endif */ if(argc > 2) { share_name = argv[1]; mountpoint = argv[2]; } /* add sharename in opts string as unc= parm */ while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:", longopts, NULL)) != -1) { switch (c) { /* No code to do the following options yet */ /* case 'l': list_with_volumelabel = 1; break; case 'L': volumelabel = optarg; break; */ /* case 'a': ++mount_all; break; */ case '?': case 'h': /* help */ mount_cifs_usage (); exit(1); case 'n': ++nomtab; break; case 'b': flags |= MS_BIND; break; case 'm': flags |= MS_MOVE; break; case 'o': orgoptions = strdup(optarg); break; case 'r': /* mount readonly */ flags |= MS_RDONLY; break; case 'U': uuid = optarg; break; case 'v': ++verboseflag; break; case 'V': printf ("mount.cifs version: %s.%s%s\n", MOUNT_CIFS_VERSION_MAJOR, MOUNT_CIFS_VERSION_MINOR, MOUNT_CIFS_VENDOR_SUFFIX); if(mountpassword) { memset(mountpassword,0,64); } exit (0); case 'w': flags &= ~MS_RDONLY; break; case 'R': rsize = atoi(optarg) ; break; case 'W': wsize = atoi(optarg); break; case '1': if (isdigit(*optarg)) { char *ep; uid = strtoul(optarg, &ep, 10); if (*ep) { printf("bad uid value \"%s\"\n", optarg); exit(1); } } else { struct passwd *pw; if (!(pw = getpwnam(optarg))) { printf("bad user name \"%s\"\n", optarg); exit(1); } uid = pw->pw_uid; endpwent(); } break; case '2': if (isdigit(*optarg)) { char *ep; gid = strtoul(optarg, &ep, 10); if (*ep) { printf("bad gid value \"%s\"\n", optarg); exit(1); } } else { struct group *gr; if (!(gr = getgrnam(optarg))) { printf("bad user name \"%s\"\n", optarg); exit(1); } gid = gr->gr_gid; endpwent(); } break; case 'u': got_user = 1; user_name = optarg; break; case 'd': domain_name = optarg; /* BB fix this - currently ignored */ got_domain = 1; break; case 'p': if(mountpassword == NULL) mountpassword = calloc(65,1); if(mountpassword) { got_password = 1; strncpy(mountpassword,optarg,64); } break; case 'S': get_password_from_file(0 /* stdin */,NULL); break; case 't': break; default: printf("unknown mount option %c\n",c); mount_cifs_usage(); exit(1); } } if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) { mount_cifs_usage(); exit(1); } if (getenv("PASSWD")) { if(mountpassword == NULL) mountpassword = calloc(65,1); if(mountpassword) { strncpy(mountpassword,getenv("PASSWD"),64); got_password = 1; } } else if (getenv("PASSWD_FD")) { get_password_from_file(atoi(getenv("PASSWD_FD")),NULL); } else if (getenv("PASSWD_FILE")) { get_password_from_file(0, getenv("PASSWD_FILE")); } if (orgoptions && parse_options(&orgoptions, &flags)) return -1; ipaddr = parse_server(&share_name); if((ipaddr == NULL) && (got_ip == 0)) { printf("No ip address specified and hostname not found\n"); return -1; } /* BB save off path and pop after mount returns? */ resolved_path = malloc(PATH_MAX+1); if(resolved_path) { /* Note that if we can not canonicalize the name, we get another chance to see if it is valid when we chdir to it */ if (realpath(mountpoint, resolved_path)) { mountpoint = resolved_path; } } if(chdir(mountpoint)) { printf("mount error: can not change directory into mount target %s\n",mountpoint); return -1; } if(stat (".", &statbuf)) { printf("mount error: mount point %s does not exist\n",mountpoint); return -1; } if (S_ISDIR(statbuf.st_mode) == 0) { printf("mount error: mount point %s is not a directory\n",mountpoint); return -1; } if((getuid() != 0) && (geteuid() == 0)) { if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) { #ifndef CIFS_ALLOW_USR_SUID /* Do not allow user mounts to control suid flag for mount unless explicitly built that way */ flags |= MS_NOSUID | MS_NODEV; #endif } else { printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n"); return -1; } } if(got_user == 0) { user_name = getusername(); got_user = 1; } if(got_password == 0) { mountpassword = getpass("Password: "******"No server share name specified\n"); printf("\nMounting the DFS root for server not implemented yet\n"); exit(1); } if(user_name) optlen += strlen(user_name) + 6; if(ipaddr) optlen += strlen(ipaddr) + 4; if(mountpassword) optlen += strlen(mountpassword) + 6; options = malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */); if(options == NULL) { printf("Could not allocate memory for mount options\n"); return -1; } options[0] = 0; strncat(options,"unc=",4); strcat(options,share_name); /* scan backwards and reverse direction of slash */ temp = strrchr(options, '/'); if(temp > options + 6) *temp = '\\'; if(ipaddr) { strncat(options,",ip=",4); strcat(options,ipaddr); } if(user_name) { /* check for syntax like user=domain\user */ if(got_domain == 0) domain_name = check_for_domain(&user_name); strncat(options,",user="******",domain=",8); strcat(options,domain_name); } } if(mountpassword) { /* Commas have to be doubled, or else they will look like the parameter separator */ /* if(sep is not set)*/ if(retry == 0) check_for_comma(&mountpassword); strncat(options,",pass="******",ver=",5); strcat(options,MOUNT_CIFS_VERSION_MAJOR); if(orgoptions) { strcat(options,","); strcat(options,orgoptions); } if(verboseflag) printf("\nmount.cifs kernel mount options %s \n",options); if(mount(share_name, mountpoint, "cifs", flags, options)) { /* remember to kill daemon on error */ char * tmp; switch (errno) { case 0: printf("mount failed but no error number set\n"); break; case ENODEV: printf("mount error: cifs filesystem not supported by the system\n"); break; case ENXIO: if(retry == 0) { retry = 1; tmp = share_name; while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) { *tmp = toupper((unsigned char)*tmp); tmp++; } if(!*tmp) { printf("retrying with upper case share name\n"); goto mount_retry; } } default: printf("mount error %d = %s\n",errno,strerror(errno)); } printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n"); if(mountpassword) { memset(mountpassword,0,64); } return -1; } else { pmntfile = setmntent(MOUNTED, "a+"); if(pmntfile) { mountent.mnt_fsname = share_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = CONST_DISCARD(char *,"cifs"); mountent.mnt_opts = malloc(220); if(mountent.mnt_opts) { char * mount_user = getusername(); memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) strcat(mountent.mnt_opts,"ro"); else strcat(mountent.mnt_opts,"rw"); if(flags & MS_MANDLOCK) strcat(mountent.mnt_opts,",mand"); if(flags & MS_NOEXEC) strcat(mountent.mnt_opts,",noexec"); if(flags & MS_NOSUID) strcat(mountent.mnt_opts,",nosuid"); if(flags & MS_NODEV) strcat(mountent.mnt_opts,",nodev"); if(flags & MS_SYNCHRONOUS) strcat(mountent.mnt_opts,",synch"); if(mount_user) { if(getuid() != 0) { strcat(mountent.mnt_opts,",user="******"could not update mount table\n"); } }
int main(int argc, char ** argv) { int c; int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */ char * orgoptions = NULL; char * share_name = NULL; char * domain_name = NULL; char * ipaddr = NULL; char * uuid = NULL; char * mountpoint; char * options; char * resolved_path; char * temp; int rc; int rsize = 0; int wsize = 0; int nomtab = 0; int uid = 0; int gid = 0; int optlen = 0; int orgoptlen = 0; struct stat statbuf; struct utsname sysinfo; struct mntent mountent; FILE * pmntfile; /* setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); */ if(argc && argv) { thisprogram = argv[0]; } if(thisprogram == NULL) thisprogram = "mount.cifs"; uname(&sysinfo); /* BB add workstation name and domain and pass down */ /* #ifdef _GNU_SOURCE printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname); #endif */ share_name = argv[1]; mountpoint = argv[2]; /* add sharename in opts string as unc= parm */ while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:", longopts, NULL)) != -1) { switch (c) { /* No code to do the following options yet */ /* case 'l': list_with_volumelabel = 1; break; case 'L': volumelabel = optarg; break; */ /* case 'a': ++mount_all; break; */ case '?': case 'h': /* help */ mount_cifs_usage (); exit(1); case 'n': ++nomtab; break; case 'b': flags |= MS_BIND; break; case 'm': flags |= MS_MOVE; break; case 'o': orgoptions = strdup(optarg); break; case 'r': /* mount readonly */ flags |= MS_RDONLY; break; case 'U': uuid = optarg; break; case 'v': ++verboseflag; break; case 'V': printf ("mount.cifs version: %s.%s%s\n", MOUNT_CIFS_VERSION_MAJOR, MOUNT_CIFS_VERSION_MINOR, MOUNT_CIFS_VENDOR_SUFFIX); if(mountpassword) { memset(mountpassword,0,64); } exit (0); case 'w': flags &= ~MS_RDONLY; break; case 'R': rsize = atoi(optarg) ; break; case 'W': wsize = atoi(optarg); break; case '1': uid = atoi(optarg); break; case '2': gid = atoi(optarg); break; case 'u': got_user = 1; user_name = optarg; break; case 'd': domain_name = optarg; break; case 'p': if(mountpassword == NULL) mountpassword = calloc(65,1); if(mountpassword) { got_password = 1; strncpy(mountpassword,optarg,64); } break; case 't': break; default: printf("unknown mount option %c\n",c); mount_cifs_usage(); exit(1); } } if(argc < 3) mount_cifs_usage(); if (getenv("PASSWD")) { if(mountpassword == NULL) mountpassword = calloc(65,1); if(mountpassword) { strncpy(mountpassword,getenv("PASSWD"),64); got_password = 1; } } else if (getenv("PASSWD_FD")) { get_password_from_file(atoi(getenv("PASSWD_FD")),NULL); } else if (getenv("PASSWD_FILE")) { get_password_from_file(0, getenv("PASSWD_FILE")); } ipaddr = parse_server(share_name); if(ipaddr == NULL) return -1; if (orgoptions && parse_options(orgoptions, &flags)) return -1; /* BB save off path and pop after mount returns? */ resolved_path = malloc(PATH_MAX+1); if(resolved_path) { /* Note that if we can not canonicalize the name, we get another chance to see if it is valid when we chdir to it */ if (realpath(mountpoint, resolved_path)) { mountpoint = resolved_path; } } if(chdir(mountpoint)) { printf("mount error: can not change directory into mount target %s\n",mountpoint); return -1; } if(stat (".", &statbuf)) { printf("mount error: mount point %s does not exist\n",mountpoint); return -1; } if (S_ISDIR(statbuf.st_mode) == 0) { printf("mount error: mount point %s is not a directory\n",mountpoint); return -1; } if((getuid() != 0) && (geteuid() == 0)) { if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) { #ifndef CIFS_ALLOW_USR_SUID /* Do not allow user mounts to control suid flag for mount unless explicitly built that way */ flags |= MS_NOSUID | MS_NODEV; #endif } else { printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n"); return -1; } } if(got_user == 0) user_name = getusername(); if(got_password == 0) { mountpassword = getpass("Password: "******"Could not allocate memory for mount options\n"); return -1; } options[0] = 0; strncat(options,"unc=",4); strcat(options,share_name); /* scan backwards and reverse direction of slash */ temp = strrchr(options, '/'); if(temp > options + 6) *temp = '\\'; if(ipaddr) { strncat(options,",ip=",4); strcat(options,ipaddr); } if(user_name) { strncat(options,",user="******",pass="******",ver=",5); strcat(options,MOUNT_CIFS_VERSION_MAJOR); if(orgoptions) { strcat(options,","); strcat(options,orgoptions); } if(verboseflag) printf("\nmount.cifs kernel mount options %s \n",options); if(mount(share_name, mountpoint, "cifs", flags, options)) { /* remember to kill daemon on error */ switch (errno) { case 0: printf("mount failed but no error number set\n"); break; case ENODEV: printf("mount error: cifs filesystem not supported by the system\n"); break; default: printf("mount error %d = %s\n",errno,strerror(errno)); } printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n"); if(mountpassword) { memset(mountpassword,0,64); } return -1; } else { pmntfile = setmntent(MOUNTED, "a+"); if(pmntfile) { mountent.mnt_fsname = share_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = "cifs"; mountent.mnt_opts = malloc(200); if(mountent.mnt_opts) { memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) strcat(mountent.mnt_opts,"ro"); else strcat(mountent.mnt_opts,"rw"); if(flags & MS_MANDLOCK) strcat(mountent.mnt_opts,",mand"); else strcat(mountent.mnt_opts,",nomand"); if(flags & MS_NOEXEC) strcat(mountent.mnt_opts,",noexec"); if(flags & MS_NOSUID) strcat(mountent.mnt_opts,",nosuid"); if(flags & MS_NODEV) strcat(mountent.mnt_opts,",nodev"); if(flags & MS_SYNCHRONOUS) strcat(mountent.mnt_opts,",synch"); } mountent.mnt_freq = 0; mountent.mnt_passno = 0; rc = addmntent(pmntfile,&mountent); endmntent(pmntfile); if(mountent.mnt_opts) free(mountent.mnt_opts); } else { printf("could not update mount table\n"); } } if(mountpassword) { memset(mountpassword,0,64); free(mountpassword); } if(options) { memset(options,0,optlen); free(options); } if(orgoptions) { memset(orgoptions,0,orgoptlen); free(orgoptions); } if(resolved_path) { free(resolved_path); } return 0; }