/* * 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); }
/* * 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); }
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); }
/* * 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); }