char * volmgt_getfullrawname(char *n) { extern char *getfullrawname(char *); char *rval; char namebuf[MAXPATHLEN+1]; char *s; char c; char *res; #ifdef DEBUG denter("volmgt_getfullrawname(%s): entering\n", n); #endif /* try to get full char-spcl device name */ rval = getfullrawname(n); if ((rval != NULL) && (*rval != NULLC)) { /* found it */ res = rval; goto dun; } /* we have a null-string result */ if (rval != NULL) { /* free null string */ free(rval); } /* ok, so we either have a bad device or a floppy */ /* try the "fd", "diskette", and the "dsk" form */ if (((s = strstr(n, "/fd")) != NULL) || ((s = strstr(n, "/diskette")) != NULL) || ((s = strstr(n, "/dsk/")) != NULL)) { /* * ensure we have room to add one more char */ if (strlen(n) < (MAXPATHLEN - 1)) { c = *++s; /* save the first char */ *s = NULLC; /* replace it with a null */ (void) strcpy(namebuf, n); /* save first part of str */ *s = c; /* put first charback */ (void) strcat(namebuf, "r"); /* insert an 'r' */ (void) strcat(namebuf, s); /* copy rest of str */ res = strdup(namebuf); goto dun; } } /* no match found */ res = strdup(""); dun: #ifdef DEBUG dexit("volmgt_getfullrawname: returning %s\n", res ? res : "<null ptr>"); #endif return (res); }
/* * 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); }
/* * arc approved interface (pending) * - can not be modified without approval from an arc * * committment level: * public * * description: * media_findname: try to come up with the character device when * provided with a starting point. This interface provides the * application programmer to provide "user friendly" names and * easily determine the "/vol" name. * * arguments: * start - a string describing a device. This string can be: * - a full path name to a device (insures it's a * character device by using getfullrawname()). * - a full path name to a volume management media name * with partitions (will return the lowest numbered * raw partition. * - the name of a piece of media (e.g. "fred"). * - a symbolic device name (e.g. floppy0, cdrom0, etc) * - a name like "floppy" or "cdrom". Will pick the lowest * numbered device with media in it. * * return value(s): * A pointer to a string that contains the character device * most appropriate to the "start" argument. * * NULL indicates that we were unable to find media based on "start". * * The string must be free(3)'d. * * preconditions: * none. */ char * media_findname(char *start) { static char *media_findname_work(char *); char *s = NULL; /* * This is just a wrapper to implement the volmgt_check nastyness. */ #ifdef DEBUG denter("media_findname(%s): entering\n", start ? start : "<null ptr>"); #endif if (start == NULL) { errno = EFAULT; goto dun; } /* * If we don't get positive results, we kick volume management * to ask it to look in the floppy drive. * * XXX: maybe this should be configurable ??? */ if ((s = media_findname_work(start)) == NULL) { #ifdef DEBUG dprintf("media_findname: calling volcheck and trying again\n"); #endif (void) volmgt_check(NULL); s = media_findname_work(start); } dun: #ifdef DEBUG dexit("media_findname: returning \"%s\"\n", s ? s : "<null ptr>"); #endif return (s); }
/* * 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); }
/* * 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); }
/* * arc approved interface * - can not be modified without approval from an arc * * committment level: * uncommitted * * description: * volmgt_acquire: try to acquire the volmgt advisory device reservation * for a specific device. * * arguments: * dev - a device name to attempt reserving. This string can be: * - a full path name to a device * - a symbolic device name (e.g. floppy0) * * id - a reservation string that hopefully describes the application * making this reservation. * * pid - a pointer to a pid_t type. If this argument is not NULL * and the requested device is already reserved, the process * id of the reservation owner will be returned in this * location. * * ovr - an override indicator. If set to non-zero, the caller requests * that this reservation be made unconditionally. * * err - the address of a pointer to a string which is to receive the * id argument used when the current device was reserved. This * is only used when the current reservation attempt fails due * to an already existing reservation for this device. * * return value(s): * A non-zero indicator if successful. * * A zero indicator if unsuccessful. If errno is EBUSY, then the err * argument will be set to point to the string that the process currently * holding the reservation supplied when reserving the device. It is up * to the caller to release the storage occupied by the string via * free(3C) when no longer needed. * * preconditions: * none */ int volmgt_acquire(char *dev, char *id, int ovr, char **err, pid_t *pidp) { char *targ_name = NULL; struct stat sb; dev_t idev; vol_dbid_t dbid = (vol_dbid_t)-1; vol_db_entry_t dbe; vol_db_entry_t *dbp; int retval = 0; /* default return => ERROR */ int reterr = 0; #ifdef DEBUG denter("volmgt_acquire(\"%s\", \"%s\", %s, %#p, %#p): entering\n", dev ? dev : "<null ptr>", id ? id : "<null ptr>", ovr ? "TRUE" : "FALSE", err, pidp); #endif /* * the supplied arguments must not be NULL */ if ((dev == NULL) || (id == NULL) || (err == NULL)) { errno = EINVAL; goto dun; } /* * the id string must not be longer than the maximum allowable * number of characters */ if (strlen(id) > VOL_RSV_MAXIDLEN) { errno = E2BIG; goto dun; } if ((targ_name = fsi_xlate_name(dev)) == NULL) { goto dun; } /* * convert 'char *dev' to major/minor pair */ if (stat(targ_name, &sb) < 0) { goto dun; } idev = sb.st_rdev; /* * open the database file */ if ((dbid = vol_db_open()) < 0) { goto dun; } if ((dbp = vol_db_find(dbid, idev)) == NULL) { /* * the entry wasn't found, so reserve it */ dbe.dev_major = major(idev); dbe.dev_minor = minor(idev); dbe.pid = getpid(); dbe.id_tag = id; if (vol_db_insert(dbid, &dbe) != 0) { retval = 1; /* success! */ } } else { if (ovr || (vol_db_proc_find(dbp->pid) == 0)) { /* * the entry exists but either override was specified * or the process holding the reservation is no longer * active * * in either case we'll usurp the reservation */ if (vol_db_remove(dbid, idev) != 0) { /* reserve the device */ dbe.dev_major = major(idev); dbe.dev_minor = minor(idev); dbe.pid = getpid(); dbe.id_tag = id; if (vol_db_insert(dbid, &dbe) != 0) { retval = 1; } } } else { /* * the entry exists and override was NOT specified */ /* * optionally return the pid of the reservation * owner */ if (pidp != NULL) { *pidp = dbp->pid; } *err = strdup(dbp->id_tag); reterr = EBUSY; } vol_db_free(dbp); /* Release the entry */ } /* * if an error was encountered (currently only EBUSY supported) * set errno to reflect it */ if (reterr != 0) { errno = reterr; } dun: if ((int)dbid >= 0) { (void) vol_db_close(dbid); } if (targ_name != NULL) { free(targ_name); } #ifdef DEBUG dexit("volmgt_acquire: returning %s\n", retval ? "TRUE" : "FALSE"); #endif return (retval); }
/* * arc approved interface * - can not be modified without approval from an arc * * committment level: * uncommitted * * description: * volmgt_release: try to release the volmgt advisory device reservation * for a specific device. * * arguments: * dev - a device name to attempt reserving. This string can be: * - a full path name to a device * - a symbolic device name (e.g. floppy0) * * return value(s): * A non-zero indicator if successful * A zero indicator if unsuccessful * * preconditions: * none */ int volmgt_release(char *dev) { char *targ_name = NULL; struct stat sb; long idev; vol_dbid_t dbid; vol_db_entry_t *dbp; int retval = 0; /* default return => FAILURE */ int reterr = 0; #ifdef DEBUG denter("volmgt_release(\"%s\"): entering\n", dev ? dev : "<null ptr>"); #endif /* * first let's do some minimal validation of the supplied arguments */ /* * the supplied argument must not be NULL */ if (dev == NULL) { errno = EINVAL; goto dun; } if ((targ_name = fsi_xlate_name(dev)) == NULL) { goto dun; } /* * convert 'char *dev' to major/minor pair */ if (stat(targ_name, &sb) < 0) { goto dun; } idev = sb.st_rdev; /* * open the database file */ if ((dbid = vol_db_open()) < 0) { goto dun; } if ((dbp = vol_db_find(dbid, idev)) == NULL) { /* the entry wasn't found so I can't clear reservation */ errno = ENOENT; goto dun; } /* the entry was found so make sure I can clear it */ if (dbp->pid == getpid()) { /* * the reservation was made by me, clear it */ if (vol_db_remove(dbid, idev) != 0) { retval = 1; } } else { /* * the entry wasn't made by me */ reterr = EBUSY; } vol_db_free(dbp); /* * if an error was encountered (currently only EBUSY supported) * set errno to reflect it */ if (reterr != 0) { errno = reterr; } dun: if ((int)dbid >= 0) { (void) vol_db_close(dbid); } if (targ_name != NULL) { free(targ_name); } #ifdef DEBUG dexit("volmgt_release: returning %s\n", retval ? "TRUE" : "FALSE"); #endif return (retval); }
/* * This is an ON Consolidation Private interface. */ char * _media_oldaliases(char *start) { struct alias *s, *ns; char *p; char *res; #ifdef DEBUG denter("_media_oldaliases(%s): entering\n", start); #endif for (s = device_aliases; *s->alias != NULLC; s++) { if (strcmp(start, s->alias) == 0) { break; } } /* we don't recognize that alias at all */ if (*s->alias == NULLC) { #ifdef DEBUG dprintf("_media_oldaliases: failed\n"); #endif res = NULL; goto dun; } /* if volume management isn't running at all, give him back the name */ if (!volmgt_running()) { #ifdef DEBUG dprintf("_media_oldaliases: no vold!\n"); #endif res = strdup(s->name); goto dun; } /* * If volume management is managing that device, look up the * volume management name. */ if (volmgt_inuse(s->name)) { for (s = volmgt_aliases; *s->alias != NULLC; s++) { if (strcmp(start, s->alias) == 0) { res = strdup(s->name); goto dun; } } #ifdef DEBUG dprintf("_media_oldaliases: failed\n"); #endif res = NULL; goto dun; } /* * If volume management isn't managing the device, it's possible * that he's given us an alias that we should recognize, but the * default name is wrong. For example a user might have his * cdrom on controller 1, being managed by volume management, * but we would think it isn't because volmgt_inuse just told * us that c0t6d0s2 isn't being managed. So, before we return * the /dev name, we'll test the alias out using media_findname. * If media_findname can't make sense out of the alias, it probably * means that we really, really aren't managing the device and * should just return the /dev name. Whew. Isn't this grody? */ for (ns = volmgt_aliases; *ns->alias != NULLC; ns++) { if (strcmp(start, ns->alias) == 0) { if ((p = media_findname_work(ns->name))) { res = p; goto dun; } else { break; } } } res = strdup(s->name); dun: #ifdef DEBUG dexit("_media_oldaliases: returning %s\n", res ? res : "<null ptr>"); #endif return (res); }
/* * 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); }