volname.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1996 by Sun Microsystems, Inc.
* All rights reserved.
*/
/*LINTLIBRARY*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <unistd.h>
#include <volmgt.h>
#include "volmgt_private.h"
/* a shortcut for checkinf for absolute pathnames */
#define IS_ABS_PATH(p) (*(p) == '/')
/*
* 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
#endif
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 ???
*/
#ifdef DEBUG
dprintf("media_findname: calling volcheck and trying again\n");
#endif
(void) volmgt_check(NULL);
s = media_findname_work(start);
}
dun:
#ifdef DEBUG
#endif
return (s);
}
/*
* 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 *rv;
char *s;
char *nameptr;
int n;
int i;
#ifdef DEBUG
#endif
vold_root = volmgt_root();
}
/*
* 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 */
#ifdef DEBUG
"media_findname_work: lstat of \"%s\" (errno %d)\n",
#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
*/
strlen(vold_alias_dir)) == 0)) {
/* it's a symlink */
/* we can't read the link */
#ifdef DEBUG
"media_findname_work: readlink(\"%s\") failed (errno %d)\n",
#endif
goto dun; /* error exit */
}
/* dereference the link */
/* stat where "start" pointed at */
#ifdef DEBUG
"media_findname_work: stat failed on \"%s\" (errno %d)\n",
#endif
goto dun; /* error exit */
}
} else {
}
/* do we already have a char-spcl device ?? */
/*
* absoluate pathname of a char-spcl device passed in
*/
goto dun; /* success */
}
/* not a char-spcl device -- is it a dir ?? */
/* open the dir and find first char-spcl device */
/*
* absoluate pathname to a directory passed
* in, under which there is at least one
* char-spcl device
*/
free(s);
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?
*/
goto dun; /* error exit */
}
/* stat the fullrawname device (to see if it's char-spcl) */
#ifdef DEBUG
"media_findname_work: stat of \"%s\" (errno %d)\n",
#endif
goto dun; /* error exit */
}
/* have we found the char-spcl device ?? */
/*
* absolute pathname to block device supplied and
* converted to an absoluate pathname to a char device
*/
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?
*/
/* open dir and find first char-spcl device */
/*
* the absolute pathname of directory
* containing at least one char-spcl device
* was passed in
*/
free(s);
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.
*/
#ifdef DEBUG
#endif
#ifdef DEBUG
dprintf("media_findname_work: is \"%s\" a chr-spcl dev?\n",
pathbuf);
#endif
/* is this a char-spcl device ?? */
/* it's probably a link, so ... */
linkbuf, MAXNAMELEN)) <= 0) {
/*
* error (since we are in the symlink
* directory) not a link, but just punt
* anyway
*/
} else {
/* it was a link */
}
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 ?? */
/* it's probably a link, so ... */
linkbuf, MAXNAMELEN)) <= 0) {
/*
* error, but just punt anyway
*/
s = getrawpart0(pathbuf);
} else {
/* it was a link */
/* open dir, finding first char-spcl dev */
s = getrawpart0(linkbuf);
}
if (s != NULL) {
free(s);
goto dun;
}
}
}
/*
* check all aliases in the alias dir, to see if any match
*/
goto try_hack;
}
/* skip uninteresting entries */
continue;
}
continue;
}
#ifdef DEBUG
dprintf("media_findname_work: scanning alias \"%s\" ...\n",
#endif
/*
* open the link and see if it points at our entry
*/
NULL);
#ifdef DEBUG
"media_findname_work: readlink(\"%s\") failed (errno %d)\n",
#endif
continue;
}
#ifdef DEBUG
dprintf("media_findname_work: scanning link \"%s\" ...\n",
linkbuf);
#endif
/* we *think* we've found a match */
goto dun;
}
}
goto dun;
}
}
}
}
/*
* 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++) {
/* is it a char-spcl device ?? */
/* it's probably a link, so... */
linkbuf, MAXNAMELEN)) <= 0) {
/* it wasn't a link */
} else {
/* it was a link */
}
goto dun;
}
/* not a char-spcl device -- is it a dir ?? */
/* it's probably a link, so ... */
linkbuf, MAXNAMELEN)) <= 0) {
/* get fist char-spcl dev in dir */
s = getrawpart0(pathbuf);
} else {
/* it was a link */
/* get fist char-spcl dev in dir */
s = getrawpart0(linkbuf);
}
if (s != NULL) {
free(s);
goto dun;
}
}
}
}
#ifdef DEBUG
#endif
dun:
}
#ifdef DEBUG
dexit("media_findname_work: returning \"%s\"\n",
#endif
return (res);
}
/*
* deref the link (in link_buf) read from path_buf into res_buf
*
* if there's any problem then just return the contents of the link buffer
*/
static void
{
static char *vol_dirname(char *);
char *path_dirname;
if (IS_ABS_PATH(link_buf)) {
/* degenerate case -- link is okay the way it is */
} else {
/* link pathname is relative */
/* get a writable copy of the orig path */
/* get the dir from the orig path */
/* oh oh -- just use the link contents */
} else {
/* concat the orig dir with the link path (if room) */
NULL);
}
}
}
/*
* return the dirname part of a path (i.e. all but last component)
*
* NOTE: may destuctively change "path" (i.e. it may write a null over
* the last slash in the path to convert it into a dirname)
*/
static char *
vol_dirname(char *path)
{
char *cp;
/* find the last seperator in the path */
/* must be just a local name -- use the local dir */
return (".");
}
/* replace the last slash with a null */
/* return all but the last component */
return (path);
}
/*
* This function runs through the list of "old" aliases to
* see if someone is calling a device by an old name before
* the glory of volume management.
*/
struct alias {
char *alias;
char *name;
};
static struct alias volmgt_aliases[] = {
{ "fd", "floppy0" },
{ "fd0", "floppy0" },
{ "fd1", "floppy1" },
{ "diskette", "floppy0" },
{ "diskette0", "floppy0" },
{ "diskette1", "floppy1" },
{ "rdiskette", "floppy0" },
{ "rdiskette0", "floppy0" },
{ "rdiskette1", "floppy1" },
{ "cd", "cdrom0" },
{ "cd0", "cdrom0" },
{ "cd1", "cdrom1" },
{ "sr", "cdrom0" },
{ "sr0", "cdrom0" },
{ "", ""}
};
/*
* "old" aliases -- XXX: only make sense if vold not running?
*/
static struct alias device_aliases[] = {
{ "fd1", "/dev/rdiskette1" },
{ "diskette0", "/dev/rdiskette0" },
{ "diskette1", "/dev/rdiskette1" },
{ "rdiskette0", "/dev/rdiskette0" },
{ "rdiskette1", "/dev/rdiskette1" },
{ "floppy0", "/dev/rdiskette0" },
{ "floppy1", "/dev/rdiskette1" },
{ "cd", "cdrom0" },
{ "cd0", "cdrom0" },
{ "cd1", "cdrom1" },
{ "", ""}
};
/*
* This is an ON Consolidation Private interface.
*/
char *
_media_oldaliases(char *start)
{
char *p;
char *res;
#ifdef DEBUG
#endif
break;
}
}
/* we don't recognize that alias at all */
#ifdef DEBUG
dprintf("_media_oldaliases: failed\n");
#endif
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
goto dun;
}
/*
* If volume management is managing that device, look up the
* volume management name.
*/
if (volmgt_inuse(s->name)) {
goto dun;
}
}
#ifdef DEBUG
dprintf("_media_oldaliases: failed\n");
#endif
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?
*/
res = p;
goto dun;
} else {
break;
}
}
}
dun:
#ifdef DEBUG
#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;
char *p;
vold_root = volmgt_root();
}
if (!volmgt_running()) {
/* no volume management */
}
return;
}
}
return;
}
continue;
}
continue;
}
}
}
}