dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libadm / common / devtab.c
blob36f2c3dbb066cb00867f511ec25de5bd790546b4
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
24 * All Rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 /*LINTLIBRARY*/
33 * devtab.c
35 * Contains functions that deal with the device table and are not for
36 * consumption by the general user population.
38 * Functions defined:
39 * _opendevtab() Opens the device table for commands
40 * _setdevtab() Rewinds the open device table
41 * _enddevtab() Closes the open device table
42 * _getdevtabent() Gets the next entry in the device table
43 * _freedevtabent() Frees memory allocated to a device-table entry
44 * _getdevrec() Gets a specific record from the device table
45 * _devtabpath() Get the pathname of the device table file
46 * _validalias() Is a value a valid alias?
50 * Header files
52 * <sys/sysmacros.h> System macro definitions
53 * <sys/types.h> System data types
54 * <sys/mkdev.h> Device Macros
55 * <unistd.h> System Symbolic Constants
56 * <stdio.h> Standard I/O definitions
57 * <string.h> String handling definitions
58 * <ctype.h> Character types and macros
59 * <errno.h> Error codes
60 * <sys/stat.h> File status information
61 * <devmgmt.h> Global Device Management definitions
62 * "devtab.h" Local Device Management definitions
65 #include <sys/sysmacros.h>
66 #include <sys/types.h>
67 #ifndef SUNOS41
68 #include <sys/mkdev.h>
69 #endif
70 #include <unistd.h>
71 #include <stdio.h>
72 #include <string.h>
73 #include <ctype.h>
74 #include <errno.h>
75 #include <sys/stat.h>
76 #include <devmgmt.h>
77 #include "devtab.h"
78 #include <stdlib.h>
81 * Static data definitions:
82 * dtabrecnum Record number of the current record (0 to n-1)
83 * leftoff Addr of char to begin next parse using
84 * getfld(), getattrval(), getquoted()
85 * recbufsz The size of the buffer used for reading records
86 * recbuf Addr of malloc() buffer for reading records
87 * xtndcnt Number of malloc()/realloc() calls on record buffer
90 static int xtndcnt = 0;
91 static char *recbuf = NULL;
92 static int recbufsz = 0;
94 static char *leftoff = NULL;
95 static int dtabrecnum = 0;
98 * int samedev(x, y)
99 * struct stat x, y
101 * Compares pertinent information in a stat() structure
102 * to see if the two structures describe the same device.
103 * If the file modes are the same and they have the same
104 * file system and i-node (i.e. they're links) or they
105 * are block or character devices and have the same major
106 * and minor device numbers (i.e. "mknod"s for the same
107 * device), it's the same device.
109 * Returns: int
110 * TRUE if the two structures describe the same device
111 * FALSE otherwise
114 static int
115 samedev(struct stat64 x, struct stat64 y)
117 int same;
120 /* If the devices are of the same type ... */
121 if ((x.st_mode & 0170000) == (y.st_mode & 0170000)) {
124 * If they are described by the same inode on the same device,
125 * the two devices are the same. Otherwise, if the devices are
126 * character-special or block-special devices, try to match by
127 * device type and major and minor device numbers.
130 if ((x.st_dev == y.st_dev) && (x.st_ino == y.st_ino)) same = TRUE;
131 else
132 if (((x.st_mode & 0170000) == 0020000) ||
133 ((x.st_mode & 0170000) == 0060000)) {
134 if ((major(x.st_rdev) == major(y.st_rdev)) &&
135 (minor(x.st_rdev) == minor(y.st_rdev))) same = TRUE;
136 else same = FALSE;
137 } else same = FALSE;
139 } else same = FALSE;
141 return (same);
145 * void _setdevtab()
147 * This function rewinds the open device table so that the next
148 * _getdevtabent() returns the first record in the device table.
150 * Arguments: None
152 * Returns: Void
155 void
156 _setdevtab(void)
158 /* If the device table file is open, rewind the file */
159 if (oam_devtab != NULL) {
160 rewind(oam_devtab);
161 dtabrecnum = 0;
166 * void _enddevtab()
168 * This function closes the open device table. It resets the
169 * open device table external variable to NULL.
171 * Arguments: None
173 * Returns: Void
176 void
177 _enddevtab(void)
179 /* If the device table file is open, close it */
180 if (oam_devtab != NULL) {
181 (void) fclose(oam_devtab);
182 oam_devtab = NULL;
183 dtabrecnum = 0;
188 * char *getfld(ptr, delims)
189 * char *ptr
190 * char *delims
192 * Notes:
193 * - Can't use "strtok()" because of its use of static data. The caller
194 * may be using strtok() and we'll really mess them up.
195 * - The function returns NULL if it didn't find any token -- '\0' can't
196 * be a delimiter using this algorithm.
199 static char *
200 getfld(
201 char *ptr, /* String to parse */
202 char *delims) /* List of delimiters */
204 int done; /* TRUE if we're finished */
205 char *p, *q; /* Temp pointers */
208 * Figure out where to start.
209 * If given a pointer, use that.
210 * Otherwise, use where we left off.
213 p = ptr ? ptr : leftoff;
217 * If there's anything to parse, search the string for the first
218 * occurrence of any of the delimiters. If one is found, change it
219 * to '\0' and remember the place to start for next time. If not
220 * found, forget the restart address and prepare to return NULL.
221 * Don't terminate on "escaped" characters.
224 if (p) { /* Anything to do ?? */
225 q = p; /* Where to begin */
226 done = FALSE; /* We're not done yet */
227 while (*q && !done) { /* Any more chars */
228 if (*q == '\\') { /* Escaped ? */
229 if (*(++q)) q++; /* Skip escaped char */
230 } else /* Not escaped */
231 if (!strchr(delims, *q)) q++; /* Skip non-delim */
232 else done = TRUE; /* Otherwise, done */
234 if (*q) { /* Terminator found? */
235 *q++ = '\0'; /* Null-terminate token */
236 leftoff = q; /* Remember restart pt. */
237 } else
238 leftoff = p = NULL; /* Nothin found or left */
241 /* Finished */
242 return (p); /* Return ptr to token */
246 * char *getquoted(ptr)
247 * char *ptr;
249 * This function extracts a quoted string from the string pointed
250 * to by <ptr>, or, if <ptr> is NULL, wherever we left off
251 * last time.
253 * Arguments:
254 * char *ptr Pointer to the character-string to parse, or
255 * (char *) NULL if we're to pick up where we
256 * [getquoted(), getfld(), and getattrval()] left off.
258 * Returns: char *
259 * The address of malloc()ed space that contains the possibly quoted
260 * string.
262 * Notes:
263 * - This code only works if it can assume that the last character in
264 * the string it's parsing is a '\n', something that is guarenteed
265 * by the getnextrec() function.
268 static char *
269 getquoted(char *ptr)
271 /* Automatic data */
272 char *rtn; /* Value to return */
273 char *p, *q; /* Temps */
275 /* Figure out where to start off */
276 p = ptr ? ptr : leftoff;
278 /* If there's anything to parse and it's a quoted string ... */
279 if ((p) && (*p == '"') && (p = getfld(p+1, "\""))) {
281 /* Copy string for the caller */
282 if (rtn = malloc(strlen(p)+1)) { /* Malloc() space */
283 q = rtn; /* Set up temp ptr */
284 do {
285 if (*p == '\\') p++; /* Skip escape */
286 *q++ = *p; /* Copy char */
287 } while (*p++); /* While there's chars */
288 } else leftoff = rtn = NULL;
289 } else leftoff = rtn = NULL;
291 /* Fini */
292 return (rtn);
296 * struct attrval *getattrval(ptr)
297 * char *ptr
299 * This function extracts the next attr=val pair from <ptr> or wherever
300 * getfld() left off...
302 * Arguments:
303 * char *ptr The string to parse, or (char *) NULL if we're to
304 * begin wherever we left off last time.
306 * Returns: struct attrval *
307 * The address of a malloc()ed structure containing the attribute and the
308 * value of the attr=val pair extracted.
311 static struct attrval *
312 getattrval(char *ptr)
314 /* Automatic data */
315 struct attrval *rtn; /* Ptr to struct to return */
316 char *p, *q; /* Temp pointers */
319 /* Use what's given to us or wherever we left off */
320 p = ptr ? ptr : leftoff;
322 /* If there's anything to parse, extract the next attr=val pair */
323 if (p) {
325 /* Eat white space */
326 while (*p && isspace((unsigned char)*p)) p++;
328 /* Extract the attribute name, if any */
329 if (*p && getfld(p, "=")) {
331 /* Allocate space for the structure we're building */
332 if (rtn = malloc(sizeof (struct attrval))) {
334 /* Allocate space for the attribute name */
335 if (rtn->attr = malloc(strlen(p)+1)) {
337 /* Copy the attribute name into alloc'd space */
338 q = rtn->attr; /* Set up temp ptr */
339 do {
340 if (*p == '\\') p++; /* Skip escape */
341 *q++ = *p; /* Copy char */
342 } while (*p++); /* While more */
344 /* Extract the value */
345 if (!(rtn->val = getquoted(NULL))) {
346 /* Error getting value, free resources */
347 free(rtn->attr);
348 free(rtn);
349 leftoff = NULL;
350 rtn = NULL;
352 } else {
353 /* Error getting space for attribute, free resources */
354 free(rtn);
355 leftoff = NULL;
356 rtn = NULL;
359 } else {
360 /* No space for attr struct */
361 leftoff = NULL;
362 rtn = NULL;
365 } else {
366 /* No attribute name */
367 leftoff = NULL;
368 rtn = NULL;
371 } else {
372 /* Nothing to parse */
373 leftoff = NULL;
374 rtn = NULL;
377 /* Done */
378 return (rtn);
382 * char *getnextrec()
384 * This function gets the next record from the input stream "oam_devtab"
385 * and puts it in the device-table record buffer (whose address is in
386 * "recbuf"). If the buffer is not allocated or is too small to
387 * accommodate the record, the function allocates more space to the
388 * buffer.
390 * Arguments: None
392 * Returns: char *
393 * The address of the buffer containing the record.
395 * Static Data Referenced:
396 * recbuf Address of the buffer containing records read from the
397 * device table file
398 * recbufsz Current size of the record buffer
399 * xtndcnt Number of times the record buffer has been extended
400 * oam_devtab Device table stream, expected to be open for (at
401 * least) reading
403 * Notes:
404 * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
405 * character followed by a '\0' (null).
408 static char *
409 getnextrec(void)
411 /* Automatic data */
412 char *recp; /* Value to return */
413 char *p; /* Temp pointer */
414 int done; /* TRUE if we're finished */
415 int reclen; /* Number of chars in record */
418 /* If there's no buffer for records, try to get one */
419 if (!recbuf) {
420 if (recbuf = malloc(DTAB_BUFSIZ)) {
421 recbufsz = DTAB_BUFSIZ;
422 xtndcnt = 0;
423 } else return (NULL);
427 /* Get the next record */
428 recp = fgets(recbuf, recbufsz, oam_devtab);
429 done = FALSE;
431 /* While we've something to return and we're not finished ... */
432 while (recp && !done) {
434 /* If our return string isn't a null-string ... */
435 if ((reclen = (int)strlen(recp)) != 0) {
437 /* If we have a complete record, we're finished */
438 if ((*(recp+reclen-1) == '\n') &&
439 ((reclen == 1) || (*(recp+reclen-2) != '\\'))) done = TRUE;
440 else while (!done) {
443 * Need to complete the record. A complete record is
444 * one which is terminated by an unescaped new-line
445 * character.
448 /* If the buffer is full, expand it and continue reading */
449 if (reclen == recbufsz-1) {
451 /* Have we reached our maximum extension count? */
452 if (xtndcnt < XTND_MAXCNT) {
454 /* Expand the record buffer */
455 if (p = realloc(recbuf,
456 (size_t)recbufsz+DTAB_BUFINC)) {
458 /* Update buffer information */
459 xtndcnt++;
460 recbuf = p;
461 recbufsz += DTAB_BUFINC;
463 } else {
465 /* Expansion failed */
466 recp = NULL;
467 done = TRUE;
470 } else {
472 /* Maximum extend count exceeded. Insane table */
473 recp = NULL;
474 done = TRUE;
479 /* Complete the record */
480 if (!done) {
482 /* Read stuff into the expanded space */
483 if (fgets(recbuf+reclen, recbufsz-reclen, oam_devtab)) {
484 reclen = (int)strlen(recbuf);
485 recp = recbuf;
486 if ((*(recp+reclen-1) == '\n') &&
487 ((reclen == 1) || (*(recp+reclen-2) != '\\')))
488 done = TRUE;
489 } else {
490 /* Read failed, corrupt record? */
491 recp = NULL;
492 done = TRUE;
496 } /* End incomplete record handling */
498 } else {
500 /* Read a null string? (corrupt table) */
501 recp = NULL;
502 done = TRUE;
505 } /* while (recp && !done) */
507 /* Return what we've got (if anything) */
508 return (recp);
512 * char *_devtabpath()
514 * Get the pathname of the device table
516 * Arguments: None
518 * Returns: char *
519 * Returns the pathname to the device table of NULL if
520 * there was a problem getting the memory needed to contain the
521 * pathname.
523 * Algorithm:
524 * 1. If OAM_DEVTAB is defined in the environment and is not
525 * defined as "", it returns the value of that environment
526 * variable.
527 * 2. Otherwise, use the value of the environment variable DTAB_PATH.
531 char *
532 _devtabpath(void)
535 /* Automatic data */
536 #ifdef DEBUG
537 char *path; /* Ptr to path in environment */
538 #endif
539 char *rtnval; /* Ptr to value to return */
543 * If compiled with -DDEBUG=1,
544 * look for the pathname in the environment
547 #ifdef DEBUG
548 if (((path = getenv(OAM_DEVTAB)) != NULL) && (*path)) {
549 if (rtnval = malloc(strlen(path)+1))
550 (void) strcpy(rtnval, path);
551 } else {
552 #endif
554 * Use the standard device table.
557 if (rtnval = malloc(strlen(DTAB_PATH)+1))
558 (void) strcpy(rtnval, DTAB_PATH);
560 #ifdef DEBUG
562 #endif
564 /* Finished */
565 return (rtnval);
569 * int _opendevtab(mode)
570 * char *mode
572 * The _opendevtab() function opens a device table for a command.
574 * Arguments:
575 * mode The open mode to use to open the file. (i.e. "r" for
576 * reading, "w" for writing. See FOPEN(BA_OS) in SVID.)
578 * Returns: int
579 * TRUE if it successfully opens the device table file, FALSE otherwise
583 _opendevtab(char *mode)
586 * Automatic data
589 char *devtabname; /* Ptr to the device table name */
590 int rtnval; /* Value to return */
593 rtnval = TRUE;
594 if (devtabname = _devtabpath()) {
595 if (oam_devtab) (void) fclose(oam_devtab);
596 if (oam_devtab = fopen(devtabname, mode))
597 dtabrecnum = 0; /* :-) */
598 else rtnval = FALSE; /* :-( */
599 } else rtnval = FALSE; /* :-( */
600 return (rtnval);
604 * int _validalias(alias)
605 * char *alias
607 * Determine if <alias> is a valid alias. Returns TRUE if it is
608 * a valid alias, FALSE otherwise.
610 * Arguments:
611 * alias Value to check out
613 * Returns: int
614 * TRUE if <alias> is a valid alias, FALSE otherwise.
618 _validalias(char *alias) /* Alias to validate */
620 /* Automatic data */
621 char *p; /* Temp pointer */
622 size_t len; /* Length of <alias> */
623 int rtn; /* Value to return */
626 /* Assume the worst */
627 rtn = FALSE;
630 * A valid alias contains 0 < i <= 14 characters. The first
631 * must be alphanumeric or "@$_." and the rest must be alphanumeric
632 * or "@#$_+-."
635 /* Check length */
636 if ((alias != NULL) && ((len = strlen(alias)) > 0) && (len <= 14)) {
638 /* Check the first character */
639 p = alias;
640 if (isalnum((unsigned char)*p) || strchr("@$_.", *p)) {
642 /* Check the rest of the characters */
643 for (p++; *p && (isalnum((unsigned char)*p) ||
644 strchr("@#$_-+.", *p)); p++)
646 if (!(*p)) rtn = TRUE;
650 /* Return indicator... */
651 return (rtn);
653 } /* int _validalias() */
656 * struct devtabent *_getdevtabent()
658 * This function returns the next entry in the device table.
659 * If no device table is open, it opens the standard device table
660 * and returns the first record in the table.
662 * Arguments: None.
664 * Returns: struct devtabent *
665 * Pointer to the next record in the device table, or
666 * NULL if it was unable to open the file or there
667 * are no more records to read. "errno" reflects the situation. If
668 * errno is not changed and the function returns NULL, there are no more
669 * records to read. If errno is set, it indicates the error.
671 * Notes:
672 * - The caller should set "errno" to 0 before calling this function.
675 struct devtabent *
676 _getdevtabent(void)
678 /* Automatic data */
679 struct devtabent *ent; /* Ptr to dev table entry structure */
680 struct attrval *attr; /* Ptr to struct for attr/val pair */
681 struct attrval *t; /* Tmp ptr to attr/val struct */
682 char *record; /* Ptr to the record just read */
683 char *p, *q; /* Tmp char ptrs */
684 int done; /* TRUE if we've built an entry */
687 /* Open the device table if it's not already open */
688 if (oam_devtab == NULL) {
689 if (!_opendevtab("r"))
690 return (NULL);
693 /* Get space for the structure we're returning */
694 if (!(ent = malloc(sizeof (struct devtabent)))) {
695 return (NULL);
698 done = FALSE;
699 while (!done && (record = getnextrec())) {
701 /* Save record number in structure */
702 ent->entryno = dtabrecnum++;
704 /* Comment record? If so, just save the value and we're through */
705 if (strchr("#\n", *record) || isspace((unsigned char)*record)) {
706 ent->comment = TRUE;
707 done = TRUE;
708 if (ent->attrstr = malloc(strlen(record)+1)) {
709 q = ent->attrstr;
710 p = record;
711 do {
712 if (*p == '\\') p++;
713 *q++ = *p;
714 } while (*p++);
715 } else {
716 free(ent);
717 ent = NULL;
721 else {
723 /* Record is a data record. Parse it. */
724 ent->comment = FALSE;
725 ent->attrstr = NULL; /* For now */
727 /* Extract the device alias */
728 if (p = getfld(record, ":")) {
729 if (*p) {
730 if (ent->alias = malloc(strlen(p)+1)) {
731 q = ent->alias;
732 do {
733 if (*p == '\\') p++;
734 *q++ = *p;
735 } while (*p++);
737 } else ent->alias = NULL;
739 /* Extract the character-device name */
740 if ((p = getfld(NULL, ":")) == NULL) {
741 free(ent->alias);
742 } else {
743 if (*p) {
744 if (ent->cdevice = malloc(strlen(p)+1)) {
745 q = ent->cdevice;
746 do {
747 if (*p == '\\') p++;
748 *q++ = *p;
749 } while (*p++);
751 } else ent->cdevice = NULL;
753 /* Extract the block-device name */
754 if (!(p = getfld(NULL, ":"))) {
755 free(ent->alias);
756 free(ent->cdevice);
757 } else {
758 if (*p) {
759 if (ent->bdevice = malloc(strlen(p)+1)) {
760 q = ent->bdevice;
761 do {
762 if (*p == '\\') p++;
763 *q++ = *p;
764 } while (*p++);
766 } else
767 ent->bdevice = NULL;
769 /* Extract the pathname */
770 if ((p = getfld(NULL, ":\n")) == NULL) {
771 free(ent->alias);
772 free(ent->cdevice);
773 free(ent->bdevice);
774 } else {
775 if (*p) {
776 if (ent->pathname = malloc(strlen(p)+1)) {
777 q = ent->pathname;
778 do {
779 if (*p == '\\') p++;
780 *q++ = *p;
781 } while (*p++);
783 } else
784 ent->pathname = NULL;
786 /* Found a valid record */
787 done = TRUE;
790 * Extract attributes, build a linked list of
791 * 'em (may be none)
793 if (attr = getattrval(NULL)) {
794 ent->attrlist = attr;
795 t = attr;
796 while (attr = getattrval(NULL)) {
797 t->next = attr;
798 t = attr;
800 t->next = NULL;
801 } else
802 ent->attrlist = NULL;
804 } /* pathname extracted */
805 } /* bdevice extracted */
806 } /* cdevice extracted */
807 } /* alias extracted */
809 } /* !done && record read */
811 /* If no entry was read, free space allocated to the structure */
812 if (!done) {
813 free(ent);
814 ent = NULL;
817 return (ent);
821 * void _freedevtabent(devtabent)
822 * struct devtabent *devtabent;
824 * This function frees space allocated to a device table entry.
826 * Arguments:
827 * struct devtabent *devtabent The structure whose space is to be
828 * freed.
830 * Returns: void
833 void
834 _freedevtabent(struct devtabent *ent)
837 * Automatic data
840 struct attrval *p; /* Structure being freed */
841 struct attrval *q; /* Next structure to free */
843 if (!ent->comment) {
846 * Free the attribute list. For each item in the attribute
847 * list,
848 * 1. Free the attribute name (always defined),
849 * 2. Free the value (if any -- it's not defined if we're
850 * changing an existing attribute),
851 * 3. Free the space allocated to the structure.
854 q = ent->attrlist;
855 if (q)
856 do {
857 p = q;
858 q = p->next;
859 free(p->attr);
860 free(p->val);
861 free(p);
862 } while (q);
864 /* Free the standard fields (alias, cdevice, bdevice, pathname) */
865 free(ent->alias);
866 free(ent->cdevice);
867 free(ent->bdevice);
868 free(ent->pathname);
871 /* Free the attribute string */
872 free(ent->attrstr);
874 /* Free the space allocated to the structure */
875 free(ent);
879 * struct devtabent *_getdevrec(device)
880 * char *device
882 * Thie _getdevrec() function returns a pointer to a structure that
883 * contains the information in the device-table entry that describes
884 * the device <device>.
886 * The device <device> can be a device alias, a pathname contained in
887 * the entry as the "cdevice", "bdevice", or "pathname" attribute,
888 * or a pathname to a device described using the "cdevice", "bdevice",
889 * or "pathname" attribute (depending on whether the pathname references
890 * a character-special file, block-special file, or something else,
891 * respectively.
893 * Arguments:
894 * char *device A character-string describing the device whose record
895 * is to be retrieved from the device table.
897 * Returns: struct devtabent *
898 * A pointer to a structure describing the device.
900 * Notes:
901 * - Someday, add a cache so that repeated requests for the same record
902 * don't require going to the filesystem. (Maybe -- this might belong
903 * in devattr()...)
906 struct devtabent *
907 _getdevrec(char *device) /* The device to search for */
910 * Automatic data
913 struct stat64 devstatbuf; /* Stat struct, <device> */
914 struct stat64 tblstatbuf; /* Stat struct, tbl entry */
915 struct devtabent *devrec; /* Pointer to current record */
916 int found; /* TRUE if record found */
917 int olderrno; /* Old value of errno */
921 * Search the device table looking for the requested device
924 _setdevtab();
925 olderrno = errno;
926 found = FALSE;
927 if ((device != NULL) && !_validalias(device)) {
928 while (!found && (devrec = _getdevtabent())) {
929 if (!devrec->comment) {
930 if (devrec->cdevice)
931 if (strcmp(device, devrec->cdevice) == 0) found = TRUE;
932 if (devrec->bdevice)
933 if (strcmp(device, devrec->bdevice) == 0) found = TRUE;
934 if (devrec->pathname)
935 if (strcmp(device, devrec->pathname) == 0) found = TRUE;
936 } else _freedevtabent(devrec);
940 * If the device <device> wasn't named explicitly in the device
941 * table, compare it against like entries by comparing file-
942 * system, major device number, and minor device number
945 if (!found) {
946 _setdevtab();
948 /* Status the file <device>. If fails, invalid device */
949 if (stat64(device, &devstatbuf) != 0) errno = ENODEV;
950 else {
953 * If <device> is a block-special device. See if it is
954 * in the table by matching its file-system indicator
955 * and major/minor device numbers against the
956 * file-system and major/minor device numbers of the
957 * "bdevice" entries.
960 if ((devstatbuf.st_mode & 0170000) == 0020000) {
961 while (!found && (devrec = _getdevtabent())) {
962 if (!devrec->comment &&
963 (devrec->cdevice != NULL))
964 if (stat64(devrec->cdevice, &tblstatbuf) == 0) {
965 if (samedev(tblstatbuf, devstatbuf))
966 found = TRUE;
967 } else {
968 /* Ignore stat() errs */
969 errno = olderrno;
971 if (!found) _freedevtabent(devrec);
976 * If <device> is a block-special device. See if it is
977 * in the table by matching its file-system indicator
978 * and major/minor device numbers against the
979 * file-system and major/minor device numbers of the
980 * "bdevice" entries.
983 else if ((devstatbuf.st_mode & 0170000) == 0060000) {
984 while (!found && (devrec = _getdevtabent())) {
985 if (!devrec->comment &&
986 (devrec->bdevice != NULL))
987 if (stat64(devrec->bdevice, &tblstatbuf) == 0) {
988 if (samedev(tblstatbuf, devstatbuf))
989 found = TRUE;
990 } else {
991 /* Ignore stat() errs */
992 errno = olderrno;
994 if (!found) _freedevtabent(devrec);
999 * If <device> is neither a block-special or character-
1000 * special device. See if it is in the table by
1001 * matching its file-system indicator and major/minor
1002 * device numbers against the file-system and
1003 * major/minor device numbers of the "pathname" entries.
1006 else {
1007 while (!found && (devrec = _getdevtabent())) {
1008 if (!devrec->comment &&
1009 (devrec->pathname != NULL))
1010 if (stat64(devrec->pathname,
1011 &tblstatbuf) == 0) {
1012 if (samedev(tblstatbuf, devstatbuf))
1013 found = TRUE;
1014 } else {
1015 /* Ignore stat() errs */
1016 errno = olderrno;
1018 if (!found) _freedevtabent(devrec);
1022 if (!found) {
1023 devrec = NULL;
1024 errno = ENODEV;
1027 } /* End case where stat() on the <device> succeeded */
1029 } /* End case handling pathname not explicitly in device table */
1031 } /* End case handling <device> as a fully-qualified pathname */
1035 * Otherwise the device <device> is an alias.
1036 * Search the table for a record that has as the "alias" attribute
1037 * the value <device>.
1040 else {
1041 while (!found && (devrec = _getdevtabent())) {
1042 if (!devrec->comment && (device != NULL) &&
1043 strcmp(device, devrec->alias) == 0)
1044 found = TRUE;
1045 else _freedevtabent(devrec);
1047 if (!found) {
1048 devrec = NULL;
1049 errno = ENODEV;
1053 /* Fini */
1054 return (devrec);