Exemplo n.º 1
0
void update_mtab(const char *dir, struct mntent *instead)
{
	struct mntent *mnt;
	struct mntent *next;
	struct mntent remnt;
	int added = 0;
	mntFILE *mfp, *mftmp;

	if (mtab_does_not_exist() || mtab_is_a_symlink())
		return;

	lock_mtab();

	mfp = my_setmntent(MOUNTED, "r");
	if (mfp == NULL || mfp->mntent_fp == NULL) {
		error("cannot open %s (%s) - mtab not updated", MOUNTED, strerror(errno));
		goto leave;
	}

	mftmp = my_setmntent(MOUNTED_TEMP, "w");
	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
		error("can't open %s (%s) - mtab not updated", MOUNTED_TEMP, strerror(errno));
		goto leave;
	}

	while ((mnt = my_getmntent(mfp))) {
		if (streq(mnt->mnt_dir, dir)) {
			added++;
			if (instead) {	/* a remount */
				remnt = *instead;
				next = &remnt;
				remnt.mnt_fsname = mnt->mnt_fsname;
				remnt.mnt_type = mnt->mnt_type;
				if (instead->mnt_fsname && !streq(mnt->mnt_fsname, instead->mnt_fsname))
					printf("mount: warning: cannot change " "mounted device with a remount\n");
				else if (instead->mnt_type && !streq(instead->mnt_type, "unknown")
					 && !streq(mnt->mnt_type, instead->mnt_type))
					printf("mount: warning: cannot change " "filesystem type with a remount\n");
			} else
				next = NULL;
		} else
			next = mnt;
		if (next && my_addmntent(mftmp, next) == 1)
			die(EX_FILEIO, "error writing %s: %s", MOUNTED_TEMP, strerror(errno));
	}
	if (instead && !added && my_addmntent(mftmp, instead) == 1)
		die(EX_FILEIO, "error writing %s: %s", MOUNTED_TEMP, strerror(errno));

	my_endmntent(mfp);
	if (fchmod(fileno(mftmp->mntent_fp), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)
		fprintf(stderr, "error changing mode of %s: %s\n", MOUNTED_TEMP, strerror(errno));
	my_endmntent(mftmp);

	if (rename(MOUNTED_TEMP, MOUNTED) < 0)
		fprintf(stderr, "can't rename %s to %s: %s\n", MOUNTED_TEMP, MOUNTED, strerror(errno));

 leave:
	unlock_mtab();
}
Exemplo n.º 2
0
/* Fatal error.  Print message and exit.  */
void
die (int err, const char *fmt, ...)
{
  va_list args;

  va_start (args, fmt);
  vfprintf (stderr, fmt, args);
  fprintf (stderr, "\n");
  va_end (args);

  unlock_mtab ();
  exit (err);
}
Exemplo n.º 3
0
/*
 * based on similar function in util-linux-2.12r/mount/mount.c
 */
static void
update_mtab_entry(const char *spec, const char *node, const char *type,
		  const char *opts, int freq, int pass, int addnew)
{
	struct my_mntent mnt;

	mnt.mnt_fsname = canonicalize (spec);
	mnt.mnt_dir = canonicalize (node);
	mnt.mnt_type = xstrdup(type);
	mnt.mnt_opts = xstrdup(opts);
	mnt.mnt_freq = freq;
	mnt.mnt_passno = pass;

	/* We get chatty now rather than after the update to mtab since the
	   mount succeeded, even if the write to /etc/mtab should fail.  */
	if (verbose)
		print_one (&mnt);

	if (!addnew)
		update_mtab (mnt.mnt_dir, &mnt);
	else {
		mntFILE *mfp;

		lock_mtab();
		mfp = my_setmntent(MOUNTED, "a+");
		if (mfp == NULL || mfp->mntent_fp == NULL) {
			int errsv = errno;
			error(_("%s: can't open %s, %s"),
			      progname, MOUNTED, strerror(errsv));
		} else {
			if ((my_addmntent (mfp, &mnt)) == 1) {
				int errsv = errno;
				error(_("%s: error writing %s, %s"),
				      progname, MOUNTED, strerror(errsv));
			}
		}
		my_endmntent(mfp);
		unlock_mtab();
	}
	my_free(mnt.mnt_fsname);
	my_free(mnt.mnt_dir);
	my_free(mnt.mnt_type);
	my_free(mnt.mnt_opts);
}
Exemplo n.º 4
0
/*
 * Code based on similar function in util-linux-2.12p/mount/mount.c
 *
 */
static void update_mtab_entry(char *spec, char *node, char *type, char *opts,
			      int flags, int freq, int pass)
{
	struct my_mntent mnt;

	mnt.mnt_fsname = canonicalize (spec);
	mnt.mnt_dir = canonicalize (node);
	mnt.mnt_type = type;
	mnt.mnt_opts = opts;
	mnt.mnt_freq = freq;
	mnt.mnt_passno = pass;
      
	/* We get chatty now rather than after the update to mtab since the
	   mount succeeded, even if the write to /etc/mtab should fail.  */
	if (verbose)
		print_one (&mnt);

	if (!nomtab && mtab_is_writable()) {
		if (flags & MS_REMOUNT)
			update_mtab (mnt.mnt_dir, &mnt);
		else {
			mntFILE *mfp;

			lock_mtab();

			mfp = my_setmntent(MOUNTED, "a+");
			if (mfp == NULL || mfp->mntent_fp == NULL) {
				com_err(progname, OCFS2_ET_IO, "%s, %s",
					MOUNTED, strerror(errno));
			} else {
				if ((my_addmntent (mfp, &mnt)) == 1) {
					com_err(progname, OCFS2_ET_IO, "%s, %s",
						MOUNTED, strerror(errno));
				}
			}
			my_endmntent(mfp);
			unlock_mtab();
		}
	}
	my_free(mnt.mnt_fsname);
	my_free(mnt.mnt_dir);
}
Exemplo n.º 5
0
static int remove_from_mtab(char * mountpoint)
{
	int rc;
	int num_matches;
	FILE * org_fd;
	FILE * new_fd;
	struct mntent * mount_entry;

	/* Do we need to check if it is a symlink to e.g. /proc/mounts
	in which case we probably do not want to update it? */

	/* Do we first need to check if it is writable? */ 

	atexit(unlock_mtab);
	if (lock_mtab()) {
		printf("Mount table locked\n");
		return -EACCES;
	}
	
	if(verboseflg)
		printf("attempting to remove from mtab\n");

	org_fd = setmntent(MOUNTED, "r");

	if(org_fd == NULL) {
		printf("Can not open %s\n",MOUNTED);
		unlock_mtab();
		return -EIO;
	}

	new_fd = setmntent(MOUNTED_TEMP,"w");
	if(new_fd == NULL) {
		printf("Can not open temp file %s", MOUNTED_TEMP);
		endmntent(org_fd);
		unlock_mtab();
		return -EIO;
	}

	/* BB fix so we only remove the last entry that matches BB */
	num_matches = 0;
	while((mount_entry = getmntent(org_fd)) != NULL) {
		if(strcmp(mount_entry->mnt_dir, mountpoint) == 0) {
			num_matches++;
		}
	}	
	if(verboseflg)
		printf("%d matching entries in mount table\n", num_matches);
		
	/* Is there a better way to seek back to the first entry in mtab? */
	endmntent(org_fd);
	org_fd = setmntent(MOUNTED, "r");

	if(org_fd == NULL) {
		printf("Can not open %s\n",MOUNTED);
		unlock_mtab();
		return -EIO;
	}
	
	while((mount_entry = getmntent(org_fd)) != NULL) {
		if(strcmp(mount_entry->mnt_dir, mountpoint) != 0) {
			addmntent(new_fd, mount_entry);
		} else {
			if(num_matches != 1) {
				addmntent(new_fd, mount_entry);
				num_matches--;
			} else if(verboseflg)
				printf("entry not copied (ie entry is removed)\n");
		}
	}

	if(verboseflg)
		printf("done updating tmp file\n");
	rc = fchmod (fileno (new_fd), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
	if(rc < 0) {
		printf("error %s changing mode of %s\n", strerror(errno),
			MOUNTED_TEMP);
	}
	endmntent(new_fd);

	rc = rename(MOUNTED_TEMP, MOUNTED);

	if(rc < 0) {
		printf("failure %s renaming %s to %s\n",strerror(errno),
			MOUNTED_TEMP, MOUNTED);
		unlock_mtab();
		return -EIO;
	}

	unlock_mtab();
	
	return rc;
}
Exemplo n.º 6
0
void
update_mtab (const char *dir, struct mntent *instead)
{
	mntFILE *mfp, *mftmp;
	const char *fnam = MOUNTED;
	struct mntentchn mtabhead;	/* dummy */
	struct mntentchn *mc, *mc0, *absent = NULL;

	if (mtab_does_not_exist() || !mtab_is_writable())
		return;

	lock_mtab();

	/* having locked mtab, read it again */
	mc0 = mc = &mtabhead;
	mc->nxt = mc->prev = NULL;

	mfp = nfs_setmntent(fnam, "r");
	if (mfp == NULL || mfp->mntent_fp == NULL) {
		int errsv = errno;
		nfs_error (_("cannot open %s (%s) - mtab not updated"),
		       fnam, strerror (errsv));
		goto leave;
	}

	read_mntentchn(mfp, fnam, mc);

	/* find last occurrence of dir */
	for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
		if (streq(mc->m.mnt_dir, dir))
			break;
	if (mc && mc != mc0) {
		if (instead == NULL) {
			/* An umount - remove entry */
			if (mc && mc != mc0) {
				mc->prev->nxt = mc->nxt;
				mc->nxt->prev = mc->prev;
				free(mc);
			}
		} else {
			/* A remount */
			mc->m.mnt_opts = instead->mnt_opts;
		}
	} else if (instead) {
		/* not found, add a new entry */
		absent = xmalloc(sizeof(*absent));
		absent->m = *instead;
		absent->nxt = mc0;
		absent->prev = mc0->prev;
		mc0->prev = absent;
		if (mc0->nxt == NULL)
			mc0->nxt = absent;
	}

	/* write chain to mtemp */
	mftmp = nfs_setmntent (MOUNTED_TEMP, "w");
	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
		int errsv = errno;
		nfs_error (_("cannot open %s (%s) - mtab not updated"),
		       MOUNTED_TEMP, strerror (errsv));
		goto leave;
	}

	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
		if (nfs_addmntent(mftmp, &(mc->m)) == 1) {
			int errsv = errno;
			die (EX_FILEIO, _("error writing %s: %s"),
			     MOUNTED_TEMP, strerror (errsv));
		}
	}

#if 0
	/* the chain might have strings copied from 'instead',
	 * so we cannot safely free it.
	 * And there is no need anyway because we are going to exit
	 * shortly.  So just don't call discard_mntentchn....
	 */
	discard_mntentchn(mc0);
#endif
	if (fchmod (fileno (mftmp->mntent_fp),
		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
		int errsv = errno;
		nfs_error(_("%s: error changing mode of %s: %s"),
				progname, MOUNTED_TEMP, strerror (errsv));
	}
	nfs_endmntent (mftmp);

	{ /*
	   * If mount is setuid and some non-root user mounts sth,
	   * then mtab.tmp might get the group of this user. Copy uid/gid
	   * from the present mtab before renaming.
	   */
	    struct stat sbuf;
	    if (stat (MOUNTED, &sbuf) == 0) {
			if (chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid) < 0) {
				nfs_error(_("%s: error changing owner of %s: %s"),
					progname, MOUNTED_TEMP, strerror (errno));
			}
		}
	}

	/* rename mtemp to mtab */
	if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
		int errsv = errno;
		nfs_error(_("%s: can't rename %s to %s: %s\n"),
				progname, MOUNTED_TEMP, MOUNTED,
				strerror(errsv));
	}

 leave:
	unlock_mtab();
}
Exemplo n.º 7
0
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);
}
Exemplo n.º 8
0
static int mount_fuse(const char *mnt, const char *opts)
{
    int res;
    int fd;
    char *dev;
    const char *type = "fuse";
    struct stat stbuf;
    char *fsname = NULL;
    char *mnt_opts = NULL;
    const char *real_mnt = mnt;
    int currdir_fd = -1;
    int mountpoint_fd = -1;
    int mtablock = -1;

    fd = open_fuse_device(&dev);
    if (fd == -1)
        return -1;

    if (geteuid() == 0)
        mtablock = lock_mtab();

    drop_privs();
    read_conf();

    if (getuid() != 0 && mount_max != -1) {
        int mount_count = count_fuse_fs();
        if (mount_count >= mount_max) {
            fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname);
            close(fd);
            unlock_mtab(mtablock);
            return -1;
        }
    }

    res = check_version(dev);
    if (res != -1) {
        res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd);
        restore_privs();
        if (res != -1)
            res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts,
                           dev, &fsname, &mnt_opts, stbuf.st_size);
    } else
        restore_privs();

    if (currdir_fd != -1) {
        fchdir(currdir_fd);
        close(currdir_fd);
    }
    if (mountpoint_fd != -1)
        close(mountpoint_fd);

    if (res == -1) {
        close(fd);
        unlock_mtab(mtablock);
        return -1;
    }

    if (geteuid() == 0) {
        res = add_mount(fsname, mnt, type, mnt_opts);
        unlock_mtab(mtablock);
        if (res == -1) {
            umount2(mnt, 2); /* lazy umount */
            close(fd);
            return -1;
        }
    }

    free(fsname);
    free(mnt_opts);
    free(dev);

    return fd;
}
Exemplo n.º 9
0
int main(int argc, char *argv[])
{
    int ch;
    int fd;
    int res;
    char *origmnt;
    char *mnt;
    static int unmount = 0;
    static int lazy = 0;
    static int quiet = 0;
    char *commfd;
    int cfd;
    const char *opts = "";

    static const struct option long_opts[] = {
        {"unmount", no_argument, NULL, 'u'},
        {"lazy",    no_argument, NULL, 'z'},
        {"quiet",   no_argument, NULL, 'q'},
        {"help",    no_argument, NULL, 'h'},
        {"version", no_argument, NULL, 'V'},
        {0, 0, 0, 0}};

    progname = strdup(argv[0]);
    if (progname == NULL) {
        fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
        exit(1);
    }

    while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts, NULL)) != -1) {
        switch (ch) {
        case 'h':
            usage();
            break;

        case 'V':
            show_version();
            break;

        case 'o':
            opts = optarg;
            break;

        case 'u':
            unmount = 1;
            break;

        case 'z':
            lazy = 1;
            break;

        case 'q':
            quiet = 1;
            break;

        default:
            exit(1);
        }
    }

    if (lazy && !unmount) {
        fprintf(stderr, "%s: -z can only be used with -u\n", progname);
        exit(1);
    }

    if (optind >= argc) {
        fprintf(stderr, "%s: missing mountpoint argument\n", progname);
        exit(1);
    }

    origmnt = argv[optind];

    drop_privs();
    mnt = resolve_path(origmnt);
    restore_privs();
    if (mnt == NULL)
        exit(1);

    umask(033);
    if (unmount) {
        if (geteuid() == 0) {
            int mtablock = lock_mtab();
            res = unmount_fuse(mnt, quiet, lazy);
            unlock_mtab(mtablock);
        } else
            res = do_unmount(mnt, quiet, lazy);
        if (res == -1)
            exit(1);
        return 0;
    }

    commfd = getenv(FUSE_COMMFD_ENV);
    if (commfd == NULL) {
        fprintf(stderr, "%s: old style mounting not supported\n", progname);
        exit(1);
    }

    fd = mount_fuse(mnt, opts);
    if (fd == -1)
        exit(1);

    cfd = atoi(commfd);
    res = send_fd(cfd, fd);
    if (res == -1)
        exit(1);

    return 0;
}
Exemplo n.º 10
0
void
update_mtab (const char *dir, struct my_mntent *instead) {
	mntFILE *mfp, *mftmp;
	const char *fnam = MOUNTED;
	struct mntentchn mtabhead;	/* dummy */
	struct mntentchn *mc, *mc0, *absent = NULL;

	if (mtab_does_not_exist() || mtab_is_a_symlink())
		return;

	lock_mtab();

	/* having locked mtab, read it again */
	mc0 = mc = &mtabhead;
	mc->nxt = mc->prev = NULL;

	mfp = my_setmntent(fnam, "r");
	if (mfp == NULL || mfp->mntent_fp == NULL) {
		int errsv = errno;
		error (_("cannot open %s (%s) - mtab not updated"),
		       fnam, strerror (errsv));
		goto leave;
	}

	read_mntentchn(mfp, fnam, mc);

	/* find last occurrence of dir */
	for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
		if (streq(mc->m.mnt_dir, dir))
			break;
	if (mc && mc != mc0) {
		if (instead == NULL) {
			/* An umount - remove entry */
			if (mc && mc != mc0) {
				mc->prev->nxt = mc->nxt;
				mc->nxt->prev = mc->prev;
				free(mc);
			}
		} else {
			/* A remount */
			mc->m.mnt_opts = instead->mnt_opts;
		}
	} else if (instead) {
		/* not found, add a new entry */
		absent = xmalloc(sizeof(*absent));
		absent->m = *instead;
		absent->nxt = mc0;
		absent->prev = mc0->prev;
		mc0->prev = absent;
		if (mc0->nxt == NULL)
			mc0->nxt = absent;
	}

	/* write chain to mtemp */
	mftmp = my_setmntent (MOUNTED_TEMP, "w");
	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
		int errsv = errno;
		error (_("cannot open %s (%s) - mtab not updated"),
		       MOUNTED_TEMP, strerror (errsv));
		goto leave;
	}

	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
		if (my_addmntent(mftmp, &(mc->m)) == 1) {
			int errsv = errno;
			die (EX_FILEIO, _("error writing %s: %s"),
			     MOUNTED_TEMP, strerror (errsv));
		}
	}

	discard_mntentchn(mc0);

	if (fchmod (fileno (mftmp->mntent_fp),
		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
		int errsv = errno;
		fprintf(stderr, _("error changing mode of %s: %s\n"),
			MOUNTED_TEMP, strerror (errsv));
	}
	my_endmntent (mftmp);

	{ /*
	   * If mount is setuid and some non-root user mounts sth,
	   * then mtab.tmp might get the group of this user. Copy uid/gid
	   * from the present mtab before renaming.
	   */
	    struct stat sbuf;
	    if (stat (MOUNTED, &sbuf) == 0)
		chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid);
	}

	/* rename mtemp to mtab */
	if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
		int errsv = errno;
		fprintf(stderr, _("can't rename %s to %s: %s\n"),
			MOUNTED_TEMP, MOUNTED, strerror(errsv));
	}

 leave:
	unlock_mtab();
}
Exemplo n.º 11
0
int au_update_mtab(char *mntpnt, int do_remount, int do_verbose)
{
	int err, fd, status, e2;
	pid_t pid;
	ino_t ino;
	struct stat st;
	struct statfs stfs;
	struct flock flock = {
		.l_type		= F_WRLCK,
		.l_whence	= SEEK_SET,
		.l_start	= 0,
		.l_len		= 0
	};
	char pid_file[sizeof(MTab "~.") + 20];
	FILE *fp;

	err = statfs(MTab, &stfs);
	if (stfs.f_type == PROC_SUPER_MAGIC)
		return 0;

	snprintf(pid_file, sizeof(pid_file), MTab "~.%d", getpid());
	fd = open(pid_file, O_RDWR | O_CREAT | O_EXCL,
		  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
	if (fd < 0)
		AuFin("%s", pid_file);
	err = fcntl(fd, F_SETLK, &flock);
	if (err)
		AuFin("%s", pid_file);
	fp = fdopen(fd, "r+");
	if (!fp)
		AuFin("%s", pid_file);

	pid = fork();
	if (!pid) {
		lock_mtab(pid_file);
		update_mtab(fp, mntpnt, do_remount, do_verbose);
		unlock_mtab();
		return 0;
	} else if (pid < 0)
		AuFin("fork");

	err = fstat(fd, &st);
	if (err)
		perror(pid_file);
	ino = st.st_ino;

	err = waitpid(pid, &status, 0);
	if (err < 0) {
		perror(pid_file);
		goto out;
	}
	err = !WIFEXITED(status);
	if (!err)
		err = WEXITSTATUS(status);

	e2 = unlink(pid_file);
	if (e2 && errno != ENOENT)
		perror(pid_file);
	e2 = stat(MTab "~", &st);
	if (!e2) {
		if (st.st_ino == ino) {
			/*
			 * The inode number is same,
			 * it means it is we who made the file.
			 * If someone else removed our file between stat(2) and
			 * unlink(2), it is a breakage of the rule.
			 */
			e2 = unlink(MTab "~");
			if (e2)
				perror(MTab);
		}
	} else if (errno != ENOENT)
		perror(MTab "~");
	fclose(fp);

 out:
	return err;
}