예제 #1
0
/*
 * This is an ON Consolidation Private interface.
 *
 * Is the specified path mounted?
 *
 * This function is really inadequate for ejection testing.  For example,
 * I could have /dev/fd0a mounted and eject /dev/fd0c, and it would be
 * ejected.  There needs to be some better way to make this check, although
 * short of looking up the mounted dev_t in the kernel mount table and
 * building in all kinds of knowledge into this function,  I'm not sure
 * how to do it.
 */
int
_dev_mounted(char *path)
{
	int		fd = -1;
	struct dk_cinfo	info;
	static FILE 	*fp = NULL;		/* mnttab file pointer */
	struct mnttab	mnt;			/* set bug not used */
	char		*cn = NULL;		/* char spcl pathname */
	struct stat64	sb;
	int		ret_val = 0;


	/* ensure we have the block spcl pathname */
	if ((cn = (char *)volmgt_getfullrawname(path)) == NULL) {
		goto dun;
	}

	if ((fp = fopen(MNTTAB, "rF")) == NULL) {
		/* mtab is gone... let him go */
		goto dun;
	}

	if ((fd = open(cn, O_RDONLY|O_NDELAY)) < 0) {
		goto dun;
	}

	if (fstat64(fd, &sb) < 0) {
		goto dun;
	}

	if (ioctl(fd, DKIOCINFO, &info) != 0) {
		goto dun;
	}

	if (vol_getmntdev(fp, &mnt, sb.st_rdev, &info) != 0) {
		ret_val = 1;			/* match found! */
	}

dun:
	if (cn != NULL) {
		free(cn);
	}
	if (fp != NULL) {
		(void) fclose(fp);
	}
	if (fd >= 0) {
		(void) close(fd);
	}
	return (ret_val);
}
예제 #2
0
/*
 * find a mnttab entry that has the same dev as the supplied dev,
 *  returning it and a non-zero value if found, else returning 0
 *
 * this is just like getmntany(), except that it scans based on st_rdev,
 * and it even finds different slices on the same device/unit (thanx to
 * code copied from format.c)
 */
static int
vol_getmntdev(FILE *fp, struct mnttab *mp, dev_t dev, struct dk_cinfo *ip)
{
	int		fd;		/* dev-in-question fd */
	struct stat64	sb;		/* dev-in-question stat struct */
	int		ret_val = 0;	/* default value: no match found */
	char		*cn;		/* char pathname */
	struct dk_cinfo	dkinfo;		/* for testing for slices */


#ifdef	DEBUG
	denter(
	    "vol_getmntdev: entering for %d.%d, ctype/cnum/unit = %d/%d/%d\n",
	    (int)major(dev), (int)minor(dev), ip->dki_ctype, ip->dki_cnum,
	    ip->dki_unit);
#endif

	/* reset the mnttab -- just in case */
	rewind(fp);

	/* scan each entry in mnttab */
	while (getmntent(fp, mp) == 0) {

		/* don't even try unless it's a local pathname */
		if (mp->mnt_special[0] != '/') {
			continue;
		}

		/* get char pathname */
		if ((cn = volmgt_getfullrawname(mp->mnt_special)) == NULL) {
			continue;
		}
		if (cn[0] == NULLC) {
			free(cn);
			continue;	/* couldn't get raw name */
		}

		/* open the device */
		if ((fd = open(cn, O_RDONLY|O_NDELAY)) < 0) {
			/* if we can't open it *assume* it's not a match */
			free(cn);
			continue;
		}

		/* stat the device */
		if (fstat64(fd, &sb) < 0) {
			free(cn);
			(void) close(fd);
			continue;	/* ain't there: can't be a match */
		}

		/* ensure we have a spcl device (a double check) */
		if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode)) {
			free(cn);
			(void) close(fd);
			continue;
		}

		/* (almost) finally -- check the dev_t for equality */
		if (sb.st_rdev == dev) {
			ret_val = 1;		/* match found! */
			free(cn);
			(void) close(fd);
			break;
		}

		/*
		 * check that the major numbers match, since if they
		 * don't then there's no reason to use the DKIOCINFO
		 * ioctl to see if we have to major/minor pairs that
		 * really point to the same device
		 */
		if (major(sb.st_rdev) != major(dev)) {
			/* no use continuing, since major devs are different */
			free(cn);
			(void) close(fd);
			continue;
		}

		/* one last check -- for diff. slices of the same dev/unit */
		if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) {
			free(cn);
			(void) close(fd);
			continue;
		}

		free(cn);		/* all done with raw pathname */
		(void) close(fd);	/* all done with file descriptor */

		/* if ctrler type/number and unit match, it's a match */
		if ((ip->dki_ctype == dkinfo.dki_ctype) &&
		    (ip->dki_cnum == dkinfo.dki_cnum) &&
		    (ip->dki_unit == dkinfo.dki_unit)) {
			/*
			 * even though minor numbers differ we have a
			 * match
			 */
			ret_val = 1;
			break;
		}

		/* go around again */
	}

	return (ret_val);
}
예제 #3
0
static int
get_media_info(char *path, char **mtypep, int *mnump, char **spclp)
{
	FILE		*fp = NULL;
	int		fd = -1;
	char		*cn = NULL;		/* char spcl pathname */
	struct stat64	sb;
	struct dk_cinfo	info;
	struct mnttab	mnt;
	int		ret_val = FALSE;

	if ((fp = fopen(MNTTAB, "rF")) == NULL) {
		/* mtab is gone... let him go */
		goto dun;
	}

	/* get char spcl pathname */
	if ((cn = volmgt_getfullrawname(path)) == NULL) {
		goto dun;
	}
	if (cn[0] == NULLC) {
		goto dun;
	}

	if ((fd = open(cn, O_RDONLY|O_NDELAY)) < 0) {
		goto dun;
	}

	if (fstat64(fd, &sb) < 0) {
		goto dun;
	}

	if (ioctl(fd, DKIOCINFO, &info) != 0) {
		goto dun;
	}

	/* if we found the entry then disect it */
	if (vol_getmntdev(fp, &mnt, sb.st_rdev, &info) != 0) {
		char		*cp;
		char		*mtype;
		char		*mnt_dir;
		int		mtype_len;
		DIR		*dirp = NULL;
		struct dirent64	*dp;
		char		*volname;


		/* return the spcl device name found */
		*spclp = strdup(mnt.mnt_special);

		/*
		 * try to get the media type (e.g. "floppy") from the mount
		 * point (e.g. "/floppy/NAME") if vold is running
		 */

		if (!volmgt_running() ||
		    (!volmgt_ownspath(*spclp) &&
		    volmgt_symname(*spclp) == NULL)) {
			ret_val = TRUE;		/* success (if limited) */
			goto dun;
		}

		/* get the first part of the mount point (e.g. "floppy") */
		cp = mnt.mnt_mountp;
		if (*cp++ != '/') {
			goto dun;
		}
		mtype = cp;
		if ((cp = strchr(mtype, '/')) == NULL) {
			goto dun;
		}
		*cp++ = NULLC;
		mnt_dir = mnt.mnt_mountp;	/* save dir path */

		/* get the volume name (e.g. "unnamed_floppy") */
		volname = cp;

		/* scan for the symlink that points to our volname */
		if ((dirp = opendir(mnt_dir)) == NULL) {
			goto dun;
		}
		mtype_len = strlen(mtype);
		while ((dp = readdir64(dirp)) != NULL) {
			char		lpath[2 * (MAXNAMELEN+1)];
			char		linkbuf[MAXPATHLEN+4];
			int		lb_len;
			struct stat64	sb;


			if (strncmp(dp->d_name, mtype, mtype_len) != 0) {
				continue;	/* not even close */
			}

			(void) sprintf(lpath, "%s/%s", mnt_dir,
			    dp->d_name);
			if (lstat64(lpath, &sb) < 0) {
				continue;	/* what? */
			}
			if (!S_ISLNK(sb.st_mode)) {
				continue;	/* not our baby */
			}
			if ((lb_len = readlink(lpath, linkbuf,
			    sizeof (linkbuf))) < 0) {
				continue;
			}
			linkbuf[lb_len] = NULLC; /* null terminate */
			if ((cp = vol_basename(linkbuf)) == NULL) {
				continue;
			}
			/* now we have the name! */
			if (strcmp(cp, volname) == 0) {
				/* found it !! */
				if (sscanf(dp->d_name + mtype_len, "%d",
				    mnump) == 1) {
					*mtypep = strdup(mtype);
					ret_val = TRUE;
				}
				break;
			}
		}
		(void) closedir(dirp);
	}

dun:
	if (fp != NULL) {
		(void) fclose(fp);
	}
	if (fd >= 0) {
		(void) close(fd);
	}
	if (cn != NULL) {
		free(cn);
	}
#ifdef	DEBUG
	if (ret_val) {
		dexit("get_media_info: returning mtype=%s, mnum=%d, spcl=%s\n",
		    *mtypep == NULL ? "<null ptr>" : *mtypep,
		    *mnump,
		    *spclp == NULL ? "<null ptr>" : *spclp);
	} else {
		dexit("get_media_info: FAILED\n");
	}
#endif
	return (ret_val);
}
예제 #4
0
파일: volname.c 프로젝트: andreiw/polaris
/*
 * Return a raw name, given a starting point.
 *
 * Assume: input string ptr is not null
 */
static char *
media_findname_work(char *start)
{
	extern char		*vol_basename(char *);
	static void		volmgt_deref_link(char *, char *, char *);
	char			pathbuf[MAXPATHLEN+1];
	char			*rv;
	char			*s;
	char			linkbuf[MAXNAMELEN+1];
	char			*nameptr;
	struct stat64		sb;
	int			n;
	int			i;
	static const char	*vold_root = NULL;
	static char		vold_alias_dir[MAXPATHLEN+1];
	char			*res = NULL;
	DIR			*dirp = NULL;
	struct dirent64		*dp;



#ifdef	DEBUG
	denter("media_findname_work(%s): entering\n", start);
#endif

	if (vold_root == NULL) {
		vold_root = volmgt_root();
		(void) concat_paths(vold_alias_dir, (char *)vold_root,
		    (char *)ALIAS_DIR, NULL);
	}

	/*
	 * if this is an absolute path name then
	 *  if it's a symlink deref it
	 *  if it's a raw device then we're done
	 *  else if it's a directory then look for a dev under it
	 */
	if (IS_ABS_PATH(start)) {

		/* try to get data on name passed in */
		if (lstat64(start, &sb) < 0) {
#ifdef	DEBUG
			dprintf(
			"media_findname_work: lstat of \"%s\" (errno %d)\n",
			    start, errno);
#endif
			goto dun;		/* error exit */
		}

		/*
		 * if is this a link to something else (e.g. ".../floppy0")
		 * and it's in the volmgt namespace, then deref it
		 */
		if (S_ISLNK(sb.st_mode) && (strncmp(start, vold_alias_dir,
		    strlen(vold_alias_dir)) == 0)) {

			/* it's a symlink */
			if ((n = readlink(start, linkbuf, MAXNAMELEN)) <= 0) {
				/* we can't read the link */
#ifdef	DEBUG
				dprintf(
		"media_findname_work: readlink(\"%s\") failed (errno %d)\n",
				    start, errno);
#endif
				goto dun;	/* error exit */
			}
			linkbuf[n] = NULLC;

			/* dereference the link */
			volmgt_deref_link(pathbuf, start, linkbuf);

			/* stat where "start" pointed at */
			if (stat64(pathbuf, &sb) < 0) {
#ifdef	DEBUG
				dprintf(
		"media_findname_work: stat failed on \"%s\" (errno %d)\n",
				    pathbuf, errno);
#endif
				goto dun;	/* error exit */
			}
			nameptr = pathbuf;

		} else {
			nameptr = start;
		}

		/* do we already have a char-spcl device ?? */
		if (S_ISCHR(sb.st_mode)) {
			/*
			 * absoluate pathname of a char-spcl device passed in
			 */
			res = strdup(nameptr);
			goto dun;		/* success */
		}

		/* not a char-spcl device -- is it a dir ?? */
		if (S_ISDIR(sb.st_mode)) {
			/* open the dir and find first char-spcl device */
			if ((s = getrawpart0(nameptr)) != NULL) {
				/*
				 * absoluate pathname to a directory passed
				 * in, under which there is at least one
				 * char-spcl device
				 */
				free(s);
				res = strdup(nameptr);
				goto dun;	/* success */
			}
		}

		/*
		 * try to get the char-spcl name if this is a blk-spcl
		 *
		 * XXX: shouldn't we ensure this is a blk spcl device?
		 */
		rv = volmgt_getfullrawname(nameptr);
		if ((rv == NULL) || (*rv == NULLC)) {
			goto dun;		/* error exit */
		}

		/* stat the fullrawname device (to see if it's char-spcl) */
		if (stat64(rv, &sb) < 0) {
#ifdef	DEBUG
			dprintf(
			    "media_findname_work: stat of \"%s\" (errno %d)\n",
			    rv, errno);
#endif
			goto dun;		/* error exit */
		}

		/* have we found the char-spcl device ?? */
		if (S_ISCHR(sb.st_mode)) {
			/*
			 * absolute pathname to block device supplied and
			 * converted to an absoluate pathname to a char device
			 */
			res = rv;		/* already malloc'ed */
			goto dun;		/* success */
		}

		/*
		 * fullrawname not a char-spcl device -- is it a dir ??
		 *
		 * XXX: didn't we already check for a directory name
		 * being supplied above?
		 */
		if (S_ISDIR(sb.st_mode)) {
			/* open dir and find first char-spcl device */
			if ((s = getrawpart0(rv)) != NULL) {
				/*
				 * the absolute pathname of directory
				 * containing at least one char-spcl device
				 * was passed in
				 */
				free(s);
				res = strdup(rv);
				goto dun;	/* success */
			}
		}

		/* having a full pathname didn't help us */
		goto dun;	/* failure -- pathname not found */
	}

	/*
	 * Ok, now we check to see if it's an alias.
	 * Note here that in the case of an alias, we prefer
	 * to return what the alias (symbolic link) points
	 * at, rather than the symbolic link.  Makes for
	 * nicer printouts and such.
	 */
	(void) concat_paths(pathbuf, vold_alias_dir, start, NULL);

#ifdef	DEBUG
	dprintf("media_findname_work: looking for \"%s\"\n", pathbuf);
#endif

	if (stat64(pathbuf, &sb) == 0) {
#ifdef	DEBUG
		dprintf("media_findname_work: is \"%s\" a chr-spcl dev?\n",
		    pathbuf);
#endif
		/* is this a char-spcl device ?? */
		if (S_ISCHR(sb.st_mode)) {
			/* it's probably a link, so ... */
			if ((n = readlink(pathbuf,
			    linkbuf, MAXNAMELEN)) <= 0) {
				/*
				 * error (since we are in the symlink
				 * directory) not a link, but just punt
				 * anyway
				 */
				res = strdup(pathbuf);
			} else {
				/* it was a link */
				linkbuf[n] = NULLC;
				res = strdup(linkbuf);
			}
			goto dun;		/* success */
		}

#ifdef	DEBUG
		dprintf("media_findname_work: not chr-spcl -- is it a dir?\n");
#endif
		/* not a char-spcl device -- is it a dir ?? */
		if (S_ISDIR(sb.st_mode)) {
			/* it's probably a link, so ... */
			if ((n = readlink(pathbuf,
			    linkbuf, MAXNAMELEN)) <= 0) {
				/*
				 * error, but just punt anyway
				 */
				nameptr = pathbuf;
				s = getrawpart0(pathbuf);
			} else {
				/* it was a link */
				linkbuf[n] = NULLC;
				/* open dir, finding first char-spcl dev */
				nameptr = linkbuf;
				s = getrawpart0(linkbuf);
			}
			if (s != NULL) {
				free(s);
				res = strdup(nameptr);
				goto dun;
			}
		}
	}

	/*
	 * check all aliases in the alias dir, to see if any match
	 */
	if ((dirp = opendir(vold_alias_dir)) == NULL) {
		goto try_hack;
	}

	while (dp = readdir64(dirp)) {

		/* skip uninteresting entries */
		if (strcmp(dp->d_name, ".") == 0) {
			continue;
		}
		if (strcmp(dp->d_name, "..") == 0) {
			continue;
		}

#ifdef	DEBUG
		dprintf("media_findname_work: scanning alias \"%s\" ...\n",
		    dp->d_name);
#endif
		/*
		 * open the link and see if it points at our entry
		 */
		(void) concat_paths(pathbuf, vold_alias_dir, dp->d_name,
		    NULL);
		if ((n = readlink(pathbuf, linkbuf, MAXNAMELEN)) <= 0) {
#ifdef	DEBUG
				dprintf(
		"media_findname_work: readlink(\"%s\") failed (errno %d)\n",
				    pathbuf, errno);
#endif
			continue;
		}
		linkbuf[n] = NULLC;

#ifdef	DEBUG
		dprintf("media_findname_work: scanning link \"%s\" ...\n",
		    linkbuf);
#endif
		if (strcmp(vol_basename(linkbuf), start) == 0) {

			/* we *think* we've found a match */

			if (stat64(linkbuf, &sb) == 0) {

				if (S_ISCHR(sb.st_mode)) {
					res = strdup(linkbuf);
					goto dun;
				}

				if (S_ISDIR(sb.st_mode)) {
					res = getrawpart0(linkbuf);
					if (res != NULL) {
						free(res);
						res = strdup(linkbuf);
					}
					goto dun;
				}

			}

		}
	}

try_hack:

	/*
	 * Ok, well maybe that's not it.  Let's try the
	 * hackname alias.
	 */

	/*
	 * This creates the "hack" name.  The model
	 * is that xx# has the alias xx.  So, cdrom#
	 * and floppy# (the most frequent case) can
	 * be referred to as cdrom and floppy.
	 * We poke at what we consider to be a reasonable number of
	 * devices (currently 5) before giving up.
	 */

	for (i = 0; i < HACKNAME_MAX; i++) {
		char	num_buf[NUMBUF_SZ];


		(void) sprintf(num_buf, "%d", i);
		(void) concat_paths(pathbuf, vold_alias_dir, start, num_buf);

		if (stat64(pathbuf, &sb) == 0) {

			/* is it a char-spcl device ?? */
			if (S_ISCHR(sb.st_mode)) {
				/* it's probably a link, so... */
				if ((n = readlink(pathbuf,
				    linkbuf, MAXNAMELEN)) <= 0) {
					/* it wasn't a link */
					res = strdup(pathbuf);
				} else {
					/* it was a link */
					linkbuf[n] = NULLC;
					res = strdup(linkbuf);
				}
				goto dun;
			}

			/* not a char-spcl device -- is it a dir ?? */
			if (S_ISDIR(sb.st_mode)) {
				/* it's probably a link, so ... */
				if ((n = readlink(pathbuf,
				    linkbuf, MAXNAMELEN)) <= 0) {
					/* get fist char-spcl dev in dir */
					nameptr = pathbuf;
					s = getrawpart0(pathbuf);
				} else {
					/* it was a link */
					linkbuf[n] = NULLC;
					/* get fist char-spcl dev in dir */
					nameptr = linkbuf;
					s = getrawpart0(linkbuf);
				}
				if (s != NULL) {
					free(s);
					res = strdup(nameptr);
					goto dun;
				}
			}
		}
	}

#ifdef	DEBUG
	dprintf("media_findname_work: %s didn't match any test!\n", start);
#endif

dun:
	if (dirp != NULL) {
		(void) closedir(dirp);
	}

#ifdef	DEBUG
	dexit("media_findname_work: returning \"%s\"\n",
	    res ? res : "<null ptr>");
#endif
	return (res);
}