/* * translate suplied vol name into a pathname * * if volmgt is running, this pathname will be in /vol (or its equiv) * * if volmgt is not running then this path may be anywhere * * in either case the pathname will *not* be verified as a blk/chr dev * * if the return value is non-null then it's been alloced * * NOTE: assume "vol" is not a NULL ptr */ static char * fsi_xlate_name(char *vol) { char *res = NULL; /* result to return */ char *vr; /* volmgt root dir */ bool_t vm_running = volmgt_running(); /* volmgt running? */ #ifdef DEBUG denter("fsi_xlate_name(\"%s\"): entering\n", vol); #endif /* is it an absolute pathname ?? */ if (*vol == '/') { if (vm_running) { /* pathname must be in the /vol namespace */ vr = (char *)volmgt_root(); if (strncmp(vol, vr, strlen(vr)) != 0) { /* not a cool pathname */ errno = EINVAL; /* XXX: is this correct */ goto dun; } } res = strdup(vol); } else { /* * if volmgt is running we can try to dereference it * if volmgt isn't running then just give up */ if (!vm_running) { /* some unknown "name" */ errno = ENOENT; goto dun; } res = volmgt_symdev(vol); } dun: #ifdef DEBUG dexit("fsi_xlate_name: returning %s\n", res ? res : "<null ptr>"); #endif return (res); }
/* * This is an ON Consolidation Private interface. * * Print out the aliases available to the program user. Changes * depending in whether volume management is running. */ void _media_printaliases(void) { struct alias *s; DIR *dirp; struct dirent64 *dp; char pathbuf[MAXPATHLEN+1]; char *p; static const char *vold_root = NULL; if (vold_root == NULL) { vold_root = volmgt_root(); } if (!volmgt_running()) { /* no volume management */ for (s = device_aliases; *s->alias != NULLC; s++) { (void) printf("\t%s -> %s\n", s->alias, s->name); } return; } for (s = volmgt_aliases; *s->alias != NULLC; s++) { (void) printf("\t%s -> %s\n", s->alias, s->name); } (void) concat_paths(pathbuf, (char *)vold_root, ALIAS_DIR, NULL); if ((dirp = opendir(pathbuf)) == NULL) { return; } while (dp = readdir64(dirp)) { if (strcmp(dp->d_name, ".") == 0) { continue; } if (strcmp(dp->d_name, "..") == 0) { continue; } if ((p = media_findname(dp->d_name)) != NULL) { (void) printf("\t%s -> %s\n", dp->d_name, p); } } (void) closedir(dirp); }
/* * this routine will return the volmgt block name given the volmgt * raw (char spcl) name * * if anything but a volmgt raw pathname is supplied that pathname will * be returned * * NOTE: non-null return value will point to static data, overwritten with * each call * * e.g. names starting with "/vol/r" will be changed to start with "/vol/", * and names starting with "vol/dev/r" will be changed to start with * "/vol/dev/" */ static char * eject_getfullblkname(char *path, boolean_t vm_running) { char raw_root[MAXPATHLEN]; const char *vm_root; static char res_buf[MAXPATHLEN]; uint_t raw_root_len; #ifdef DEBUG (void) fprintf(stderr, "eject_getfullblkname(\"%s\", %s): entering\n", path, vm_running ? "B_TRUE" : "B_FALSE"); #endif /* * try different strategies based on whether or not vold is running */ if (vm_running) { /* vold IS running -- look in /vol (or its alternate) */ /* get vm root dir */ vm_root = volmgt_root(); /* get first volmgt root dev directory (and its length) */ (void) snprintf(raw_root, sizeof (raw_root), "%s/r", vm_root); raw_root_len = strlen(raw_root); /* see if we have a raw volmgt pathname (e.g. "/vol/r*") */ if (strncmp(path, raw_root, raw_root_len) == 0) { if (snprintf(res_buf, sizeof (res_buf), "%s/%s", vm_root, path + raw_root_len) >= sizeof (res_buf)) { return (NULL); } goto dun; /* found match in /vol */ } /* get second volmgt root dev directory (and its length) */ (void) snprintf(raw_root, sizeof (raw_root), "%s/dev/r", vm_root); raw_root_len = strlen(raw_root); /* see if we have a raw volmgt pathname (e.g. "/vol/dev/r*") */ if (strncmp(path, raw_root, raw_root_len) == 0) { if (snprintf(res_buf, sizeof (res_buf), "%s/dev/%s", vm_root, path + raw_root_len) >= sizeof (res_buf)) { return (NULL); } goto dun; /* found match in /vol/dev */ } } else { /* vold is NOT running -- look in /dev */ (void) strcpy(raw_root, "/dev/r"); raw_root_len = strlen(raw_root); if (strncmp(path, raw_root, raw_root_len) == 0) { if (snprintf(res_buf, sizeof (res_buf), "/dev/%s", path + raw_root_len) >= sizeof (res_buf)) { return (NULL); } goto dun; /* found match in /dev */ } } /* no match -- return what we got */ (void) strcpy(res_buf, path); dun: #ifdef DEBUG (void) fprintf(stderr, "eject_getfullblkname: returning %s\n", res_buf ? res_buf : "<null ptr>"); #endif return (res_buf); }
/* * This is an ON Consolidation Private interface. * * Forks off rmmount and (in essence) returns the result * * a return value of 0 (FALSE) means failure, non-zero (TRUE) means success */ int _dev_unmount(char *path) { char *bn = NULL; /* block name */ char *mtype = NULL; /* media type */ char *spcl = NULL; /* special dev. path */ char *spcl_failed = NULL; /* spcl that failed */ int ret_val = FALSE; /* what we return */ char *vr; /* volmgt root dir */ int media_info_gotten = 0; int mnum = 0; int volume_is_not_managed; char *pathbuf, *absname; if ((bn = (char *)volmgt_getfullblkname(path)) == NULL) { goto dun; } if ((pathbuf = malloc(PATH_MAX+1)) == NULL) goto dun; absname = bn; if (realpath(bn, pathbuf) != NULL) absname = pathbuf; volume_is_not_managed = !volmgt_running() || (!volmgt_ownspath(absname) && volmgt_symname(bn) == NULL); free(pathbuf); /* decide of we should use rmmount to unmount the media */ if (!volume_is_not_managed) { int use_rmm = FALSE; /* use rmmount?? */ /* at least volmgt is running */ vr = (char *)volmgt_root(); if (strncmp(bn, vr, strlen(vr)) == 0) { /* the block path is rooted in /vol */ use_rmm = TRUE; } /* try to get info about media */ media_info_gotten = get_media_info(bn, &mtype, &mnum, &spcl); ret_val = call_unmount_prog(media_info_gotten, use_rmm, mtype, mnum, spcl, bn); } else { /* volmgt is *not* running */ if (get_media_info(bn, &mtype, &mnum, &spcl)) { /* * volmgt is off and get_media_info() has returned * info on the media -- soo (this is kinda' a hack) * ... we iterate, looking for multiple slices * of (say) a floppy being mounted * * note: if an unmount fails we don't want to try * to unmount the same device on the next try, so * we try to watch for that */ do { /* * don't call the unmount program is we're just * trying to unmount the same device that * failed last time -- if that's the case, * then bail */ if (spcl_failed != NULL) { if (strcmp(spcl, spcl_failed) == 0) { break; } } ret_val = call_unmount_prog(TRUE, FALSE, mtype, mnum, spcl, bn); if (!ret_val) { /* save spcl device name that failed */ spcl_failed = strdup(spcl); } else { /* * unmount succeeded, so clean up */ if (spcl_failed != NULL) { free(spcl_failed); spcl_failed = NULL; } } } while (get_media_info(bn, &mtype, &mnum, &spcl)); } else { /* just do the unmmount cycle once */ ret_val = call_unmount_prog(FALSE, FALSE, NULL, 0, NULL, bn); } } if (mtype != NULL) { free(mtype); } if (spcl != NULL) { free(spcl); } if (spcl_failed != NULL) { free(spcl_failed); } if (bn != NULL) { free(bn); } 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); }