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); }
/* * call the appropriate unmount program, returning its success (TRUE) * or failure (FALSE) */ static int call_unmount_prog(int mi_gotten, int use_rmm, char *mtype, int mnum, char *spcl, char *bn) { pid_t pid; /* forked proc's pid */ int ret_val = FALSE; const char *etc_umount = "/etc/umount"; const char *rmm = "/usr/sbin/rmmount"; int rval; /* proc's return value */ #ifdef DEBUG denter( "call_unmount_prog(%s, %s, \"%s\", %d, \"%s\", \"%s\"): entering\n", mi_gotten ? "TRUE" : "FALSE", use_rmm ? "TRUE" : "FALSE", mtype ? mtype : "<null ptr>", mnum, spcl ? spcl : "<null ptr>", bn); #endif /* create a child to unmount the path */ if ((pid = fork()) < 0) { goto dun; } if (pid == 0) { /* the child */ #ifndef DEBUG int xfd; #endif char env_buf[MAXPATHLEN]; #ifndef DEBUG /* get rid of those nasty err messages */ if ((xfd = open(NULL_PATH, O_RDWR)) >= 0) { (void) dup2(xfd, fileno(stdin)); (void) dup2(xfd, fileno(stdout)); (void) dup2(xfd, fileno(stderr)); } #endif if (use_rmm) { /* set up environment vars */ (void) putenv("VOLUME_ACTION=eject"); (void) putenv(strdup(env_buf)); if (mi_gotten) { (void) sprintf(env_buf, "VOLUME_MEDIATYPE=%s", mtype); (void) putenv(strdup(env_buf)); (void) sprintf(env_buf, "VOLUME_SYMDEV=%s%d", mtype, mnum); (void) putenv(strdup(env_buf)); (void) sprintf(env_buf, "VOLUME_PATH=%s", spcl); (void) putenv(strdup(env_buf)); (void) sprintf(env_buf, "VOLUME_NAME=%s", vol_basename(spcl)); (void) putenv(strdup(env_buf)); } else { (void) sprintf(env_buf, "VOLUME_PATH=%s", bn); (void) putenv(strdup(env_buf)); (void) sprintf(env_buf, "VOLUME_NAME=%s", vol_basename(bn)); (void) putenv(strdup(env_buf)); } #ifdef DEBUG dprintf("call_unmount_prog: calling \"%s -D\"\n", rmm); (void) execl(rmm, rmm, "-D", NULL); #else (void) execl(rmm, rmm, NULL); #endif } else { #ifdef DEBUG dprintf("call_unmount_prog: calling \"%s %s\"\n", etc_umount, mi_gotten ? spcl : bn); #endif (void) execl(etc_umount, etc_umount, mi_gotten ? spcl : bn, NULL); } exit(-1); /*NOTREACHED*/ } /* wait for the umount command to exit */ if (waitpid(pid, &rval, 0) == pid) { if (WIFEXITED(rval)) { if (WEXITSTATUS(rval) == 0) { ret_val = TRUE; /* success */ } } } dun: 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); }