1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate * All Rights reserved.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
31*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate * devtab.c
35*7c478bd9Sstevel@tonic-gate *
36*7c478bd9Sstevel@tonic-gate * Contains functions that deal with the device table and are not for
37*7c478bd9Sstevel@tonic-gate * consumption by the general user population.
38*7c478bd9Sstevel@tonic-gate *
39*7c478bd9Sstevel@tonic-gate * Functions defined:
40*7c478bd9Sstevel@tonic-gate * _opendevtab() Opens the device table for commands
41*7c478bd9Sstevel@tonic-gate * _setdevtab() Rewinds the open device table
42*7c478bd9Sstevel@tonic-gate * _enddevtab() Closes the open device table
43*7c478bd9Sstevel@tonic-gate * _getdevtabent() Gets the next entry in the device table
44*7c478bd9Sstevel@tonic-gate * _freedevtabent() Frees memory allocated to a device-table entry
45*7c478bd9Sstevel@tonic-gate * _getdevrec() Gets a specific record from the device table
46*7c478bd9Sstevel@tonic-gate * _devtabpath() Get the pathname of the device table file
47*7c478bd9Sstevel@tonic-gate * _validalias() Is a value a valid alias?
48*7c478bd9Sstevel@tonic-gate */
49*7c478bd9Sstevel@tonic-gate
50*7c478bd9Sstevel@tonic-gate /*
51*7c478bd9Sstevel@tonic-gate * Header files
52*7c478bd9Sstevel@tonic-gate *
53*7c478bd9Sstevel@tonic-gate * <sys/sysmacros.h> System macro definitions
54*7c478bd9Sstevel@tonic-gate * <sys/types.h> System data types
55*7c478bd9Sstevel@tonic-gate * <sys/mkdev.h> Device Macros
56*7c478bd9Sstevel@tonic-gate * <unistd.h> System Symbolic Constants
57*7c478bd9Sstevel@tonic-gate * <stdio.h> Standard I/O definitions
58*7c478bd9Sstevel@tonic-gate * <string.h> String handling definitions
59*7c478bd9Sstevel@tonic-gate * <ctype.h> Character types and macros
60*7c478bd9Sstevel@tonic-gate * <errno.h> Error codes
61*7c478bd9Sstevel@tonic-gate * <sys/stat.h> File status information
62*7c478bd9Sstevel@tonic-gate * <devmgmt.h> Global Device Management definitions
63*7c478bd9Sstevel@tonic-gate * "devtab.h" Local Device Management definitions
64*7c478bd9Sstevel@tonic-gate */
65*7c478bd9Sstevel@tonic-gate
66*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
67*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
68*7c478bd9Sstevel@tonic-gate #ifndef SUNOS41
69*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
70*7c478bd9Sstevel@tonic-gate #endif
71*7c478bd9Sstevel@tonic-gate #include <unistd.h>
72*7c478bd9Sstevel@tonic-gate #include <stdio.h>
73*7c478bd9Sstevel@tonic-gate #include <string.h>
74*7c478bd9Sstevel@tonic-gate #include <ctype.h>
75*7c478bd9Sstevel@tonic-gate #include <errno.h>
76*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
77*7c478bd9Sstevel@tonic-gate #include <devmgmt.h>
78*7c478bd9Sstevel@tonic-gate #include "devtab.h"
79*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
80*7c478bd9Sstevel@tonic-gate
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate * Static data definitions:
83*7c478bd9Sstevel@tonic-gate * dtabrecnum Record number of the current record (0 to n-1)
84*7c478bd9Sstevel@tonic-gate * leftoff Addr of char to begin next parse using
85*7c478bd9Sstevel@tonic-gate * getfld(), getattrval(), getquoted()
86*7c478bd9Sstevel@tonic-gate * recbufsz The size of the buffer used for reading records
87*7c478bd9Sstevel@tonic-gate * recbuf Addr of malloc() buffer for reading records
88*7c478bd9Sstevel@tonic-gate * xtndcnt Number of malloc()/realloc() calls on record buffer
89*7c478bd9Sstevel@tonic-gate */
90*7c478bd9Sstevel@tonic-gate
91*7c478bd9Sstevel@tonic-gate static int xtndcnt = 0;
92*7c478bd9Sstevel@tonic-gate static char *recbuf = NULL;
93*7c478bd9Sstevel@tonic-gate static int recbufsz = 0;
94*7c478bd9Sstevel@tonic-gate
95*7c478bd9Sstevel@tonic-gate static char *leftoff = NULL;
96*7c478bd9Sstevel@tonic-gate static int dtabrecnum = 0;
97*7c478bd9Sstevel@tonic-gate
98*7c478bd9Sstevel@tonic-gate /*
99*7c478bd9Sstevel@tonic-gate * int samedev(x, y)
100*7c478bd9Sstevel@tonic-gate * struct stat x, y
101*7c478bd9Sstevel@tonic-gate *
102*7c478bd9Sstevel@tonic-gate * Compares pertinent information in a stat() structure
103*7c478bd9Sstevel@tonic-gate * to see if the two structures describe the same device.
104*7c478bd9Sstevel@tonic-gate * If the file modes are the same and they have the same
105*7c478bd9Sstevel@tonic-gate * file system and i-node (i.e. they're links) or they
106*7c478bd9Sstevel@tonic-gate * are block or character devices and have the same major
107*7c478bd9Sstevel@tonic-gate * and minor device numbers (i.e. "mknod"s for the same
108*7c478bd9Sstevel@tonic-gate * device), it's the same device.
109*7c478bd9Sstevel@tonic-gate *
110*7c478bd9Sstevel@tonic-gate * Returns: int
111*7c478bd9Sstevel@tonic-gate * TRUE if the two structures describe the same device
112*7c478bd9Sstevel@tonic-gate * FALSE otherwise
113*7c478bd9Sstevel@tonic-gate */
114*7c478bd9Sstevel@tonic-gate
115*7c478bd9Sstevel@tonic-gate static int
samedev(struct stat64 x,struct stat64 y)116*7c478bd9Sstevel@tonic-gate samedev(struct stat64 x, struct stat64 y)
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate int same;
119*7c478bd9Sstevel@tonic-gate
120*7c478bd9Sstevel@tonic-gate
121*7c478bd9Sstevel@tonic-gate /* If the devices are of the same type ... */
122*7c478bd9Sstevel@tonic-gate if ((x.st_mode & 0170000) == (y.st_mode & 0170000)) {
123*7c478bd9Sstevel@tonic-gate
124*7c478bd9Sstevel@tonic-gate /*
125*7c478bd9Sstevel@tonic-gate * If they are described by the same inode on the same device,
126*7c478bd9Sstevel@tonic-gate * the two devices are the same. Otherwise, if the devices are
127*7c478bd9Sstevel@tonic-gate * character-special or block-special devices, try to match by
128*7c478bd9Sstevel@tonic-gate * device type and major and minor device numbers.
129*7c478bd9Sstevel@tonic-gate */
130*7c478bd9Sstevel@tonic-gate
131*7c478bd9Sstevel@tonic-gate if ((x.st_dev == y.st_dev) && (x.st_ino == y.st_ino)) same = TRUE;
132*7c478bd9Sstevel@tonic-gate else
133*7c478bd9Sstevel@tonic-gate if (((x.st_mode & 0170000) == 0020000) ||
134*7c478bd9Sstevel@tonic-gate ((x.st_mode & 0170000) == 0060000)) {
135*7c478bd9Sstevel@tonic-gate if ((major(x.st_rdev) == major(y.st_rdev)) &&
136*7c478bd9Sstevel@tonic-gate (minor(x.st_rdev) == minor(y.st_rdev))) same = TRUE;
137*7c478bd9Sstevel@tonic-gate else same = FALSE;
138*7c478bd9Sstevel@tonic-gate } else same = FALSE;
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate } else same = FALSE;
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gate return (same);
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate * void _setdevtab()
147*7c478bd9Sstevel@tonic-gate *
148*7c478bd9Sstevel@tonic-gate * This function rewinds the open device table so that the next
149*7c478bd9Sstevel@tonic-gate * _getdevtabent() returns the first record in the device table.
150*7c478bd9Sstevel@tonic-gate *
151*7c478bd9Sstevel@tonic-gate * Arguments: None
152*7c478bd9Sstevel@tonic-gate *
153*7c478bd9Sstevel@tonic-gate * Returns: Void
154*7c478bd9Sstevel@tonic-gate */
155*7c478bd9Sstevel@tonic-gate
156*7c478bd9Sstevel@tonic-gate void
_setdevtab(void)157*7c478bd9Sstevel@tonic-gate _setdevtab(void)
158*7c478bd9Sstevel@tonic-gate {
159*7c478bd9Sstevel@tonic-gate /* If the device table file is open, rewind the file */
160*7c478bd9Sstevel@tonic-gate if (oam_devtab != NULL) {
161*7c478bd9Sstevel@tonic-gate rewind(oam_devtab);
162*7c478bd9Sstevel@tonic-gate dtabrecnum = 0;
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate * void _enddevtab()
168*7c478bd9Sstevel@tonic-gate *
169*7c478bd9Sstevel@tonic-gate * This function closes the open device table. It resets the
170*7c478bd9Sstevel@tonic-gate * open device table external variable to NULL.
171*7c478bd9Sstevel@tonic-gate *
172*7c478bd9Sstevel@tonic-gate * Arguments: None
173*7c478bd9Sstevel@tonic-gate *
174*7c478bd9Sstevel@tonic-gate * Returns: Void
175*7c478bd9Sstevel@tonic-gate */
176*7c478bd9Sstevel@tonic-gate
177*7c478bd9Sstevel@tonic-gate void
_enddevtab(void)178*7c478bd9Sstevel@tonic-gate _enddevtab(void)
179*7c478bd9Sstevel@tonic-gate {
180*7c478bd9Sstevel@tonic-gate /* If the device table file is open, close it */
181*7c478bd9Sstevel@tonic-gate if (oam_devtab != NULL) {
182*7c478bd9Sstevel@tonic-gate (void) fclose(oam_devtab);
183*7c478bd9Sstevel@tonic-gate oam_devtab = NULL;
184*7c478bd9Sstevel@tonic-gate dtabrecnum = 0;
185*7c478bd9Sstevel@tonic-gate }
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate
188*7c478bd9Sstevel@tonic-gate /*
189*7c478bd9Sstevel@tonic-gate * char *getfld(ptr, delims)
190*7c478bd9Sstevel@tonic-gate * char *ptr
191*7c478bd9Sstevel@tonic-gate * char *delims
192*7c478bd9Sstevel@tonic-gate *
193*7c478bd9Sstevel@tonic-gate * Notes:
194*7c478bd9Sstevel@tonic-gate * - Can't use "strtok()" because of its use of static data. The caller
195*7c478bd9Sstevel@tonic-gate * may be using strtok() and we'll really mess them up.
196*7c478bd9Sstevel@tonic-gate * - The function returns NULL if it didn't find any token -- '\0' can't
197*7c478bd9Sstevel@tonic-gate * be a delimiter using this algorithm.
198*7c478bd9Sstevel@tonic-gate */
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate static char *
getfld(char * ptr,char * delims)201*7c478bd9Sstevel@tonic-gate getfld(
202*7c478bd9Sstevel@tonic-gate char *ptr, /* String to parse */
203*7c478bd9Sstevel@tonic-gate char *delims) /* List of delimiters */
204*7c478bd9Sstevel@tonic-gate {
205*7c478bd9Sstevel@tonic-gate int done; /* TRUE if we're finished */
206*7c478bd9Sstevel@tonic-gate char *p, *q; /* Temp pointers */
207*7c478bd9Sstevel@tonic-gate
208*7c478bd9Sstevel@tonic-gate /*
209*7c478bd9Sstevel@tonic-gate * Figure out where to start.
210*7c478bd9Sstevel@tonic-gate * If given a pointer, use that.
211*7c478bd9Sstevel@tonic-gate * Otherwise, use where we left off.
212*7c478bd9Sstevel@tonic-gate */
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate p = ptr ? ptr : leftoff;
215*7c478bd9Sstevel@tonic-gate
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate * If there's anything to parse, search the string for the first
219*7c478bd9Sstevel@tonic-gate * occurrence of any of the delimiters. If one is found, change it
220*7c478bd9Sstevel@tonic-gate * to '\0' and remember the place to start for next time. If not
221*7c478bd9Sstevel@tonic-gate * found, forget the restart address and prepare to return NULL.
222*7c478bd9Sstevel@tonic-gate * Don't terminate on "escaped" characters.
223*7c478bd9Sstevel@tonic-gate */
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate if (p) { /* Anything to do ?? */
226*7c478bd9Sstevel@tonic-gate q = p; /* Where to begin */
227*7c478bd9Sstevel@tonic-gate done = FALSE; /* We're not done yet */
228*7c478bd9Sstevel@tonic-gate while (*q && !done) { /* Any more chars */
229*7c478bd9Sstevel@tonic-gate if (*q == '\\') { /* Escaped ? */
230*7c478bd9Sstevel@tonic-gate if (*(++q)) q++; /* Skip escaped char */
231*7c478bd9Sstevel@tonic-gate } else /* Not escaped */
232*7c478bd9Sstevel@tonic-gate if (!strchr(delims, *q)) q++; /* Skip non-delim */
233*7c478bd9Sstevel@tonic-gate else done = TRUE; /* Otherwise, done */
234*7c478bd9Sstevel@tonic-gate }
235*7c478bd9Sstevel@tonic-gate if (*q) { /* Terminator found? */
236*7c478bd9Sstevel@tonic-gate *q++ = '\0'; /* Null-terminate token */
237*7c478bd9Sstevel@tonic-gate leftoff = q; /* Remember restart pt. */
238*7c478bd9Sstevel@tonic-gate } else
239*7c478bd9Sstevel@tonic-gate leftoff = p = NULL; /* Nothin found or left */
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate /* Finished */
243*7c478bd9Sstevel@tonic-gate return (p); /* Return ptr to token */
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate
246*7c478bd9Sstevel@tonic-gate /*
247*7c478bd9Sstevel@tonic-gate * char *getquoted(ptr)
248*7c478bd9Sstevel@tonic-gate * char *ptr;
249*7c478bd9Sstevel@tonic-gate *
250*7c478bd9Sstevel@tonic-gate * This function extracts a quoted string from the string pointed
251*7c478bd9Sstevel@tonic-gate * to by <ptr>, or, if <ptr> is NULL, wherever we left off
252*7c478bd9Sstevel@tonic-gate * last time.
253*7c478bd9Sstevel@tonic-gate *
254*7c478bd9Sstevel@tonic-gate * Arguments:
255*7c478bd9Sstevel@tonic-gate * char *ptr Pointer to the character-string to parse, or
256*7c478bd9Sstevel@tonic-gate * (char *) NULL if we're to pick up where we
257*7c478bd9Sstevel@tonic-gate * [getquoted(), getfld(), and getattrval()] left off.
258*7c478bd9Sstevel@tonic-gate *
259*7c478bd9Sstevel@tonic-gate * Returns: char *
260*7c478bd9Sstevel@tonic-gate * The address of malloc()ed space that contains the possibly quoted
261*7c478bd9Sstevel@tonic-gate * string.
262*7c478bd9Sstevel@tonic-gate *
263*7c478bd9Sstevel@tonic-gate * Notes:
264*7c478bd9Sstevel@tonic-gate * - This code only works if it can assume that the last character in
265*7c478bd9Sstevel@tonic-gate * the string it's parsing is a '\n', something that is guarenteed
266*7c478bd9Sstevel@tonic-gate * by the getnextrec() function.
267*7c478bd9Sstevel@tonic-gate */
268*7c478bd9Sstevel@tonic-gate
269*7c478bd9Sstevel@tonic-gate static char *
getquoted(char * ptr)270*7c478bd9Sstevel@tonic-gate getquoted(char *ptr)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate /* Automatic data */
273*7c478bd9Sstevel@tonic-gate char *rtn; /* Value to return */
274*7c478bd9Sstevel@tonic-gate char *p, *q; /* Temps */
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate /* Figure out where to start off */
277*7c478bd9Sstevel@tonic-gate p = ptr ? ptr : leftoff;
278*7c478bd9Sstevel@tonic-gate
279*7c478bd9Sstevel@tonic-gate /* If there's anything to parse and it's a quoted string ... */
280*7c478bd9Sstevel@tonic-gate if ((p) && (*p == '"') && (p = getfld(p+1, "\""))) {
281*7c478bd9Sstevel@tonic-gate
282*7c478bd9Sstevel@tonic-gate /* Copy string for the caller */
283*7c478bd9Sstevel@tonic-gate if (rtn = malloc(strlen(p)+1)) { /* Malloc() space */
284*7c478bd9Sstevel@tonic-gate q = rtn; /* Set up temp ptr */
285*7c478bd9Sstevel@tonic-gate do {
286*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; /* Skip escape */
287*7c478bd9Sstevel@tonic-gate *q++ = *p; /* Copy char */
288*7c478bd9Sstevel@tonic-gate } while (*p++); /* While there's chars */
289*7c478bd9Sstevel@tonic-gate } else leftoff = rtn = NULL;
290*7c478bd9Sstevel@tonic-gate } else leftoff = rtn = NULL;
291*7c478bd9Sstevel@tonic-gate
292*7c478bd9Sstevel@tonic-gate /* Fini */
293*7c478bd9Sstevel@tonic-gate return (rtn);
294*7c478bd9Sstevel@tonic-gate }
295*7c478bd9Sstevel@tonic-gate
296*7c478bd9Sstevel@tonic-gate /*
297*7c478bd9Sstevel@tonic-gate * struct attrval *getattrval(ptr)
298*7c478bd9Sstevel@tonic-gate * char *ptr
299*7c478bd9Sstevel@tonic-gate *
300*7c478bd9Sstevel@tonic-gate * This function extracts the next attr=val pair from <ptr> or wherever
301*7c478bd9Sstevel@tonic-gate * getfld() left off...
302*7c478bd9Sstevel@tonic-gate *
303*7c478bd9Sstevel@tonic-gate * Arguments:
304*7c478bd9Sstevel@tonic-gate * char *ptr The string to parse, or (char *) NULL if we're to
305*7c478bd9Sstevel@tonic-gate * begin wherever we left off last time.
306*7c478bd9Sstevel@tonic-gate *
307*7c478bd9Sstevel@tonic-gate * Returns: struct attrval *
308*7c478bd9Sstevel@tonic-gate * The address of a malloc()ed structure containing the attribute and the
309*7c478bd9Sstevel@tonic-gate * value of the attr=val pair extracted.
310*7c478bd9Sstevel@tonic-gate */
311*7c478bd9Sstevel@tonic-gate
312*7c478bd9Sstevel@tonic-gate static struct attrval *
getattrval(char * ptr)313*7c478bd9Sstevel@tonic-gate getattrval(char *ptr)
314*7c478bd9Sstevel@tonic-gate {
315*7c478bd9Sstevel@tonic-gate /* Automatic data */
316*7c478bd9Sstevel@tonic-gate struct attrval *rtn; /* Ptr to struct to return */
317*7c478bd9Sstevel@tonic-gate char *p, *q; /* Temp pointers */
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate
320*7c478bd9Sstevel@tonic-gate /* Use what's given to us or wherever we left off */
321*7c478bd9Sstevel@tonic-gate p = ptr ? ptr : leftoff;
322*7c478bd9Sstevel@tonic-gate
323*7c478bd9Sstevel@tonic-gate /* If there's anything to parse, extract the next attr=val pair */
324*7c478bd9Sstevel@tonic-gate if (p) {
325*7c478bd9Sstevel@tonic-gate
326*7c478bd9Sstevel@tonic-gate /* Eat white space */
327*7c478bd9Sstevel@tonic-gate while (*p && isspace((unsigned char)*p)) p++;
328*7c478bd9Sstevel@tonic-gate
329*7c478bd9Sstevel@tonic-gate /* Extract the attribute name, if any */
330*7c478bd9Sstevel@tonic-gate if (*p && getfld(p, "=")) {
331*7c478bd9Sstevel@tonic-gate
332*7c478bd9Sstevel@tonic-gate /* Allocate space for the structure we're building */
333*7c478bd9Sstevel@tonic-gate if (rtn = malloc(sizeof (struct attrval))) {
334*7c478bd9Sstevel@tonic-gate
335*7c478bd9Sstevel@tonic-gate /* Allocate space for the attribute name */
336*7c478bd9Sstevel@tonic-gate if (rtn->attr = malloc(strlen(p)+1)) {
337*7c478bd9Sstevel@tonic-gate
338*7c478bd9Sstevel@tonic-gate /* Copy the attribute name into alloc'd space */
339*7c478bd9Sstevel@tonic-gate q = rtn->attr; /* Set up temp ptr */
340*7c478bd9Sstevel@tonic-gate do {
341*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; /* Skip escape */
342*7c478bd9Sstevel@tonic-gate *q++ = *p; /* Copy char */
343*7c478bd9Sstevel@tonic-gate } while (*p++); /* While more */
344*7c478bd9Sstevel@tonic-gate
345*7c478bd9Sstevel@tonic-gate /* Extract the value */
346*7c478bd9Sstevel@tonic-gate if (!(rtn->val = getquoted(NULL))) {
347*7c478bd9Sstevel@tonic-gate /* Error getting value, free resources */
348*7c478bd9Sstevel@tonic-gate free(rtn->attr);
349*7c478bd9Sstevel@tonic-gate free(rtn);
350*7c478bd9Sstevel@tonic-gate leftoff = NULL;
351*7c478bd9Sstevel@tonic-gate rtn = NULL;
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate } else {
354*7c478bd9Sstevel@tonic-gate /* Error getting space for attribute, free resources */
355*7c478bd9Sstevel@tonic-gate free(rtn);
356*7c478bd9Sstevel@tonic-gate leftoff = NULL;
357*7c478bd9Sstevel@tonic-gate rtn = NULL;
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate
360*7c478bd9Sstevel@tonic-gate } else {
361*7c478bd9Sstevel@tonic-gate /* No space for attr struct */
362*7c478bd9Sstevel@tonic-gate leftoff = NULL;
363*7c478bd9Sstevel@tonic-gate rtn = NULL;
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate
366*7c478bd9Sstevel@tonic-gate } else {
367*7c478bd9Sstevel@tonic-gate /* No attribute name */
368*7c478bd9Sstevel@tonic-gate leftoff = NULL;
369*7c478bd9Sstevel@tonic-gate rtn = NULL;
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate
372*7c478bd9Sstevel@tonic-gate } else {
373*7c478bd9Sstevel@tonic-gate /* Nothing to parse */
374*7c478bd9Sstevel@tonic-gate leftoff = NULL;
375*7c478bd9Sstevel@tonic-gate rtn = NULL;
376*7c478bd9Sstevel@tonic-gate }
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gate /* Done */
379*7c478bd9Sstevel@tonic-gate return (rtn);
380*7c478bd9Sstevel@tonic-gate }
381*7c478bd9Sstevel@tonic-gate
382*7c478bd9Sstevel@tonic-gate /*
383*7c478bd9Sstevel@tonic-gate * char *getnextrec()
384*7c478bd9Sstevel@tonic-gate *
385*7c478bd9Sstevel@tonic-gate * This function gets the next record from the input stream "oam_devtab"
386*7c478bd9Sstevel@tonic-gate * and puts it in the device-table record buffer (whose address is in
387*7c478bd9Sstevel@tonic-gate * "recbuf"). If the buffer is not allocated or is too small to
388*7c478bd9Sstevel@tonic-gate * accommodate the record, the function allocates more space to the
389*7c478bd9Sstevel@tonic-gate * buffer.
390*7c478bd9Sstevel@tonic-gate *
391*7c478bd9Sstevel@tonic-gate * Arguments: None
392*7c478bd9Sstevel@tonic-gate *
393*7c478bd9Sstevel@tonic-gate * Returns: char *
394*7c478bd9Sstevel@tonic-gate * The address of the buffer containing the record.
395*7c478bd9Sstevel@tonic-gate *
396*7c478bd9Sstevel@tonic-gate * Static Data Referenced:
397*7c478bd9Sstevel@tonic-gate * recbuf Address of the buffer containing records read from the
398*7c478bd9Sstevel@tonic-gate * device table file
399*7c478bd9Sstevel@tonic-gate * recbufsz Current size of the record buffer
400*7c478bd9Sstevel@tonic-gate * xtndcnt Number of times the record buffer has been extended
401*7c478bd9Sstevel@tonic-gate * oam_devtab Device table stream, expected to be open for (at
402*7c478bd9Sstevel@tonic-gate * least) reading
403*7c478bd9Sstevel@tonic-gate *
404*7c478bd9Sstevel@tonic-gate * Notes:
405*7c478bd9Sstevel@tonic-gate * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
406*7c478bd9Sstevel@tonic-gate * character followed by a '\0' (null).
407*7c478bd9Sstevel@tonic-gate */
408*7c478bd9Sstevel@tonic-gate
409*7c478bd9Sstevel@tonic-gate static char *
getnextrec(void)410*7c478bd9Sstevel@tonic-gate getnextrec(void)
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate /* Automatic data */
413*7c478bd9Sstevel@tonic-gate char *recp; /* Value to return */
414*7c478bd9Sstevel@tonic-gate char *p; /* Temp pointer */
415*7c478bd9Sstevel@tonic-gate int done; /* TRUE if we're finished */
416*7c478bd9Sstevel@tonic-gate int reclen; /* Number of chars in record */
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate
419*7c478bd9Sstevel@tonic-gate /* If there's no buffer for records, try to get one */
420*7c478bd9Sstevel@tonic-gate if (!recbuf) {
421*7c478bd9Sstevel@tonic-gate if (recbuf = malloc(DTAB_BUFSIZ)) {
422*7c478bd9Sstevel@tonic-gate recbufsz = DTAB_BUFSIZ;
423*7c478bd9Sstevel@tonic-gate xtndcnt = 0;
424*7c478bd9Sstevel@tonic-gate } else return (NULL);
425*7c478bd9Sstevel@tonic-gate }
426*7c478bd9Sstevel@tonic-gate
427*7c478bd9Sstevel@tonic-gate
428*7c478bd9Sstevel@tonic-gate /* Get the next record */
429*7c478bd9Sstevel@tonic-gate recp = fgets(recbuf, recbufsz, oam_devtab);
430*7c478bd9Sstevel@tonic-gate done = FALSE;
431*7c478bd9Sstevel@tonic-gate
432*7c478bd9Sstevel@tonic-gate /* While we've something to return and we're not finished ... */
433*7c478bd9Sstevel@tonic-gate while (recp && !done) {
434*7c478bd9Sstevel@tonic-gate
435*7c478bd9Sstevel@tonic-gate /* If our return string isn't a null-string ... */
436*7c478bd9Sstevel@tonic-gate if ((reclen = (int)strlen(recp)) != 0) {
437*7c478bd9Sstevel@tonic-gate
438*7c478bd9Sstevel@tonic-gate /* If we have a complete record, we're finished */
439*7c478bd9Sstevel@tonic-gate if ((*(recp+reclen-1) == '\n') &&
440*7c478bd9Sstevel@tonic-gate ((reclen == 1) || (*(recp+reclen-2) != '\\'))) done = TRUE;
441*7c478bd9Sstevel@tonic-gate else while (!done) {
442*7c478bd9Sstevel@tonic-gate
443*7c478bd9Sstevel@tonic-gate /*
444*7c478bd9Sstevel@tonic-gate * Need to complete the record. A complete record is
445*7c478bd9Sstevel@tonic-gate * one which is terminated by an unescaped new-line
446*7c478bd9Sstevel@tonic-gate * character.
447*7c478bd9Sstevel@tonic-gate */
448*7c478bd9Sstevel@tonic-gate
449*7c478bd9Sstevel@tonic-gate /* If the buffer is full, expand it and continue reading */
450*7c478bd9Sstevel@tonic-gate if (reclen == recbufsz-1) {
451*7c478bd9Sstevel@tonic-gate
452*7c478bd9Sstevel@tonic-gate /* Have we reached our maximum extension count? */
453*7c478bd9Sstevel@tonic-gate if (xtndcnt < XTND_MAXCNT) {
454*7c478bd9Sstevel@tonic-gate
455*7c478bd9Sstevel@tonic-gate /* Expand the record buffer */
456*7c478bd9Sstevel@tonic-gate if (p = realloc(recbuf,
457*7c478bd9Sstevel@tonic-gate (size_t)recbufsz+DTAB_BUFINC)) {
458*7c478bd9Sstevel@tonic-gate
459*7c478bd9Sstevel@tonic-gate /* Update buffer information */
460*7c478bd9Sstevel@tonic-gate xtndcnt++;
461*7c478bd9Sstevel@tonic-gate recbuf = p;
462*7c478bd9Sstevel@tonic-gate recbufsz += DTAB_BUFINC;
463*7c478bd9Sstevel@tonic-gate
464*7c478bd9Sstevel@tonic-gate } else {
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate /* Expansion failed */
467*7c478bd9Sstevel@tonic-gate recp = NULL;
468*7c478bd9Sstevel@tonic-gate done = TRUE;
469*7c478bd9Sstevel@tonic-gate }
470*7c478bd9Sstevel@tonic-gate
471*7c478bd9Sstevel@tonic-gate } else {
472*7c478bd9Sstevel@tonic-gate
473*7c478bd9Sstevel@tonic-gate /* Maximum extend count exceeded. Insane table */
474*7c478bd9Sstevel@tonic-gate recp = NULL;
475*7c478bd9Sstevel@tonic-gate done = TRUE;
476*7c478bd9Sstevel@tonic-gate }
477*7c478bd9Sstevel@tonic-gate
478*7c478bd9Sstevel@tonic-gate }
479*7c478bd9Sstevel@tonic-gate
480*7c478bd9Sstevel@tonic-gate /* Complete the record */
481*7c478bd9Sstevel@tonic-gate if (!done) {
482*7c478bd9Sstevel@tonic-gate
483*7c478bd9Sstevel@tonic-gate /* Read stuff into the expanded space */
484*7c478bd9Sstevel@tonic-gate if (fgets(recbuf+reclen, recbufsz-reclen, oam_devtab)) {
485*7c478bd9Sstevel@tonic-gate reclen = (int)strlen(recbuf);
486*7c478bd9Sstevel@tonic-gate recp = recbuf;
487*7c478bd9Sstevel@tonic-gate if ((*(recp+reclen-1) == '\n') &&
488*7c478bd9Sstevel@tonic-gate ((reclen == 1) || (*(recp+reclen-2) != '\\')))
489*7c478bd9Sstevel@tonic-gate done = TRUE;
490*7c478bd9Sstevel@tonic-gate } else {
491*7c478bd9Sstevel@tonic-gate /* Read failed, corrupt record? */
492*7c478bd9Sstevel@tonic-gate recp = NULL;
493*7c478bd9Sstevel@tonic-gate done = TRUE;
494*7c478bd9Sstevel@tonic-gate }
495*7c478bd9Sstevel@tonic-gate }
496*7c478bd9Sstevel@tonic-gate
497*7c478bd9Sstevel@tonic-gate } /* End incomplete record handling */
498*7c478bd9Sstevel@tonic-gate
499*7c478bd9Sstevel@tonic-gate } else {
500*7c478bd9Sstevel@tonic-gate
501*7c478bd9Sstevel@tonic-gate /* Read a null string? (corrupt table) */
502*7c478bd9Sstevel@tonic-gate recp = NULL;
503*7c478bd9Sstevel@tonic-gate done = TRUE;
504*7c478bd9Sstevel@tonic-gate }
505*7c478bd9Sstevel@tonic-gate
506*7c478bd9Sstevel@tonic-gate } /* while (recp && !done) */
507*7c478bd9Sstevel@tonic-gate
508*7c478bd9Sstevel@tonic-gate /* Return what we've got (if anything) */
509*7c478bd9Sstevel@tonic-gate return (recp);
510*7c478bd9Sstevel@tonic-gate }
511*7c478bd9Sstevel@tonic-gate
512*7c478bd9Sstevel@tonic-gate /*
513*7c478bd9Sstevel@tonic-gate * char *_devtabpath()
514*7c478bd9Sstevel@tonic-gate *
515*7c478bd9Sstevel@tonic-gate * Get the pathname of the device table
516*7c478bd9Sstevel@tonic-gate *
517*7c478bd9Sstevel@tonic-gate * Arguments: None
518*7c478bd9Sstevel@tonic-gate *
519*7c478bd9Sstevel@tonic-gate * Returns: char *
520*7c478bd9Sstevel@tonic-gate * Returns the pathname to the device table of NULL if
521*7c478bd9Sstevel@tonic-gate * there was a problem getting the memory needed to contain the
522*7c478bd9Sstevel@tonic-gate * pathname.
523*7c478bd9Sstevel@tonic-gate *
524*7c478bd9Sstevel@tonic-gate * Algorithm:
525*7c478bd9Sstevel@tonic-gate * 1. If OAM_DEVTAB is defined in the environment and is not
526*7c478bd9Sstevel@tonic-gate * defined as "", it returns the value of that environment
527*7c478bd9Sstevel@tonic-gate * variable.
528*7c478bd9Sstevel@tonic-gate * 2. Otherwise, use the value of the environment variable DTAB_PATH.
529*7c478bd9Sstevel@tonic-gate */
530*7c478bd9Sstevel@tonic-gate
531*7c478bd9Sstevel@tonic-gate
532*7c478bd9Sstevel@tonic-gate char *
_devtabpath(void)533*7c478bd9Sstevel@tonic-gate _devtabpath(void)
534*7c478bd9Sstevel@tonic-gate {
535*7c478bd9Sstevel@tonic-gate
536*7c478bd9Sstevel@tonic-gate /* Automatic data */
537*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
538*7c478bd9Sstevel@tonic-gate char *path; /* Ptr to path in environment */
539*7c478bd9Sstevel@tonic-gate #endif
540*7c478bd9Sstevel@tonic-gate char *rtnval; /* Ptr to value to return */
541*7c478bd9Sstevel@tonic-gate
542*7c478bd9Sstevel@tonic-gate
543*7c478bd9Sstevel@tonic-gate /*
544*7c478bd9Sstevel@tonic-gate * If compiled with -DDEBUG=1,
545*7c478bd9Sstevel@tonic-gate * look for the pathname in the environment
546*7c478bd9Sstevel@tonic-gate */
547*7c478bd9Sstevel@tonic-gate
548*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
549*7c478bd9Sstevel@tonic-gate if (((path = getenv(OAM_DEVTAB)) != NULL) && (*path)) {
550*7c478bd9Sstevel@tonic-gate if (rtnval = malloc(strlen(path)+1))
551*7c478bd9Sstevel@tonic-gate (void) strcpy(rtnval, path);
552*7c478bd9Sstevel@tonic-gate } else {
553*7c478bd9Sstevel@tonic-gate #endif
554*7c478bd9Sstevel@tonic-gate /*
555*7c478bd9Sstevel@tonic-gate * Use the standard device table.
556*7c478bd9Sstevel@tonic-gate */
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate if (rtnval = malloc(strlen(DTAB_PATH)+1))
559*7c478bd9Sstevel@tonic-gate (void) strcpy(rtnval, DTAB_PATH);
560*7c478bd9Sstevel@tonic-gate
561*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate #endif
564*7c478bd9Sstevel@tonic-gate
565*7c478bd9Sstevel@tonic-gate /* Finished */
566*7c478bd9Sstevel@tonic-gate return (rtnval);
567*7c478bd9Sstevel@tonic-gate }
568*7c478bd9Sstevel@tonic-gate
569*7c478bd9Sstevel@tonic-gate /*
570*7c478bd9Sstevel@tonic-gate * int _opendevtab(mode)
571*7c478bd9Sstevel@tonic-gate * char *mode
572*7c478bd9Sstevel@tonic-gate *
573*7c478bd9Sstevel@tonic-gate * The _opendevtab() function opens a device table for a command.
574*7c478bd9Sstevel@tonic-gate *
575*7c478bd9Sstevel@tonic-gate * Arguments:
576*7c478bd9Sstevel@tonic-gate * mode The open mode to use to open the file. (i.e. "r" for
577*7c478bd9Sstevel@tonic-gate * reading, "w" for writing. See FOPEN(BA_OS) in SVID.)
578*7c478bd9Sstevel@tonic-gate *
579*7c478bd9Sstevel@tonic-gate * Returns: int
580*7c478bd9Sstevel@tonic-gate * TRUE if it successfully opens the device table file, FALSE otherwise
581*7c478bd9Sstevel@tonic-gate */
582*7c478bd9Sstevel@tonic-gate
583*7c478bd9Sstevel@tonic-gate int
_opendevtab(char * mode)584*7c478bd9Sstevel@tonic-gate _opendevtab(char *mode)
585*7c478bd9Sstevel@tonic-gate {
586*7c478bd9Sstevel@tonic-gate /*
587*7c478bd9Sstevel@tonic-gate * Automatic data
588*7c478bd9Sstevel@tonic-gate */
589*7c478bd9Sstevel@tonic-gate
590*7c478bd9Sstevel@tonic-gate char *devtabname; /* Ptr to the device table name */
591*7c478bd9Sstevel@tonic-gate int rtnval; /* Value to return */
592*7c478bd9Sstevel@tonic-gate
593*7c478bd9Sstevel@tonic-gate
594*7c478bd9Sstevel@tonic-gate rtnval = TRUE;
595*7c478bd9Sstevel@tonic-gate if (devtabname = _devtabpath()) {
596*7c478bd9Sstevel@tonic-gate if (oam_devtab) (void) fclose(oam_devtab);
597*7c478bd9Sstevel@tonic-gate if (oam_devtab = fopen(devtabname, mode))
598*7c478bd9Sstevel@tonic-gate dtabrecnum = 0; /* :-) */
599*7c478bd9Sstevel@tonic-gate else rtnval = FALSE; /* :-( */
600*7c478bd9Sstevel@tonic-gate } else rtnval = FALSE; /* :-( */
601*7c478bd9Sstevel@tonic-gate return (rtnval);
602*7c478bd9Sstevel@tonic-gate }
603*7c478bd9Sstevel@tonic-gate
604*7c478bd9Sstevel@tonic-gate /*
605*7c478bd9Sstevel@tonic-gate * int _validalias(alias)
606*7c478bd9Sstevel@tonic-gate * char *alias
607*7c478bd9Sstevel@tonic-gate *
608*7c478bd9Sstevel@tonic-gate * Determine if <alias> is a valid alias. Returns TRUE if it is
609*7c478bd9Sstevel@tonic-gate * a valid alias, FALSE otherwise.
610*7c478bd9Sstevel@tonic-gate *
611*7c478bd9Sstevel@tonic-gate * Arguments:
612*7c478bd9Sstevel@tonic-gate * alias Value to check out
613*7c478bd9Sstevel@tonic-gate *
614*7c478bd9Sstevel@tonic-gate * Returns: int
615*7c478bd9Sstevel@tonic-gate * TRUE if <alias> is a valid alias, FALSE otherwise.
616*7c478bd9Sstevel@tonic-gate */
617*7c478bd9Sstevel@tonic-gate
618*7c478bd9Sstevel@tonic-gate int
_validalias(char * alias)619*7c478bd9Sstevel@tonic-gate _validalias(char *alias) /* Alias to validate */
620*7c478bd9Sstevel@tonic-gate {
621*7c478bd9Sstevel@tonic-gate /* Automatic data */
622*7c478bd9Sstevel@tonic-gate char *p; /* Temp pointer */
623*7c478bd9Sstevel@tonic-gate size_t len; /* Length of <alias> */
624*7c478bd9Sstevel@tonic-gate int rtn; /* Value to return */
625*7c478bd9Sstevel@tonic-gate
626*7c478bd9Sstevel@tonic-gate
627*7c478bd9Sstevel@tonic-gate /* Assume the worst */
628*7c478bd9Sstevel@tonic-gate rtn = FALSE;
629*7c478bd9Sstevel@tonic-gate
630*7c478bd9Sstevel@tonic-gate /*
631*7c478bd9Sstevel@tonic-gate * A valid alias contains 0 < i <= 14 characters. The first
632*7c478bd9Sstevel@tonic-gate * must be alphanumeric or "@$_." and the rest must be alphanumeric
633*7c478bd9Sstevel@tonic-gate * or "@#$_+-."
634*7c478bd9Sstevel@tonic-gate */
635*7c478bd9Sstevel@tonic-gate
636*7c478bd9Sstevel@tonic-gate /* Check length */
637*7c478bd9Sstevel@tonic-gate if ((alias != NULL) && ((len = strlen(alias)) > 0) && (len <= 14)) {
638*7c478bd9Sstevel@tonic-gate
639*7c478bd9Sstevel@tonic-gate /* Check the first character */
640*7c478bd9Sstevel@tonic-gate p = alias;
641*7c478bd9Sstevel@tonic-gate if (isalnum((unsigned char)*p) || strchr("@$_.", *p)) {
642*7c478bd9Sstevel@tonic-gate
643*7c478bd9Sstevel@tonic-gate /* Check the rest of the characters */
644*7c478bd9Sstevel@tonic-gate for (p++; *p && (isalnum((unsigned char)*p) ||
645*7c478bd9Sstevel@tonic-gate strchr("@#$_-+.", *p)); p++)
646*7c478bd9Sstevel@tonic-gate ;
647*7c478bd9Sstevel@tonic-gate if (!(*p)) rtn = TRUE;
648*7c478bd9Sstevel@tonic-gate }
649*7c478bd9Sstevel@tonic-gate }
650*7c478bd9Sstevel@tonic-gate
651*7c478bd9Sstevel@tonic-gate /* Return indicator... */
652*7c478bd9Sstevel@tonic-gate return (rtn);
653*7c478bd9Sstevel@tonic-gate
654*7c478bd9Sstevel@tonic-gate } /* int _validalias() */
655*7c478bd9Sstevel@tonic-gate
656*7c478bd9Sstevel@tonic-gate /*
657*7c478bd9Sstevel@tonic-gate * struct devtabent *_getdevtabent()
658*7c478bd9Sstevel@tonic-gate *
659*7c478bd9Sstevel@tonic-gate * This function returns the next entry in the device table.
660*7c478bd9Sstevel@tonic-gate * If no device table is open, it opens the standard device table
661*7c478bd9Sstevel@tonic-gate * and returns the first record in the table.
662*7c478bd9Sstevel@tonic-gate *
663*7c478bd9Sstevel@tonic-gate * Arguments: None.
664*7c478bd9Sstevel@tonic-gate *
665*7c478bd9Sstevel@tonic-gate * Returns: struct devtabent *
666*7c478bd9Sstevel@tonic-gate * Pointer to the next record in the device table, or
667*7c478bd9Sstevel@tonic-gate * (struct devtabent *) NULL if it was unable to open the file or there
668*7c478bd9Sstevel@tonic-gate * are no more records to read. "errno" reflects the situation. If
669*7c478bd9Sstevel@tonic-gate * errno is not changed and the function returns NULL, there are no more
670*7c478bd9Sstevel@tonic-gate * records to read. If errno is set, it indicates the error.
671*7c478bd9Sstevel@tonic-gate *
672*7c478bd9Sstevel@tonic-gate * Notes:
673*7c478bd9Sstevel@tonic-gate * - The caller should set "errno" to 0 before calling this function.
674*7c478bd9Sstevel@tonic-gate */
675*7c478bd9Sstevel@tonic-gate
676*7c478bd9Sstevel@tonic-gate struct devtabent *
_getdevtabent(void)677*7c478bd9Sstevel@tonic-gate _getdevtabent(void)
678*7c478bd9Sstevel@tonic-gate {
679*7c478bd9Sstevel@tonic-gate /* Automatic data */
680*7c478bd9Sstevel@tonic-gate struct devtabent *ent; /* Ptr to dev table entry structure */
681*7c478bd9Sstevel@tonic-gate struct attrval *attr; /* Ptr to struct for attr/val pair */
682*7c478bd9Sstevel@tonic-gate struct attrval *t; /* Tmp ptr to attr/val struct */
683*7c478bd9Sstevel@tonic-gate char *record; /* Ptr to the record just read */
684*7c478bd9Sstevel@tonic-gate char *p, *q; /* Tmp char ptrs */
685*7c478bd9Sstevel@tonic-gate int done; /* TRUE if we've built an entry */
686*7c478bd9Sstevel@tonic-gate
687*7c478bd9Sstevel@tonic-gate
688*7c478bd9Sstevel@tonic-gate /* Open the device table if it's not already open */
689*7c478bd9Sstevel@tonic-gate if (oam_devtab == NULL) {
690*7c478bd9Sstevel@tonic-gate if (!_opendevtab("r"))
691*7c478bd9Sstevel@tonic-gate return (NULL);
692*7c478bd9Sstevel@tonic-gate }
693*7c478bd9Sstevel@tonic-gate
694*7c478bd9Sstevel@tonic-gate /* Get space for the structure we're returning */
695*7c478bd9Sstevel@tonic-gate if (!(ent = malloc(sizeof (struct devtabent)))) {
696*7c478bd9Sstevel@tonic-gate return (NULL);
697*7c478bd9Sstevel@tonic-gate }
698*7c478bd9Sstevel@tonic-gate
699*7c478bd9Sstevel@tonic-gate done = FALSE;
700*7c478bd9Sstevel@tonic-gate while (!done && (record = getnextrec())) {
701*7c478bd9Sstevel@tonic-gate
702*7c478bd9Sstevel@tonic-gate /* Save record number in structure */
703*7c478bd9Sstevel@tonic-gate ent->entryno = dtabrecnum++;
704*7c478bd9Sstevel@tonic-gate
705*7c478bd9Sstevel@tonic-gate /* Comment record? If so, just save the value and we're through */
706*7c478bd9Sstevel@tonic-gate if (strchr("#\n", *record) || isspace((unsigned char)*record)) {
707*7c478bd9Sstevel@tonic-gate ent->comment = TRUE;
708*7c478bd9Sstevel@tonic-gate done = TRUE;
709*7c478bd9Sstevel@tonic-gate if (ent->attrstr = malloc(strlen(record)+1)) {
710*7c478bd9Sstevel@tonic-gate q = ent->attrstr;
711*7c478bd9Sstevel@tonic-gate p = record;
712*7c478bd9Sstevel@tonic-gate do {
713*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++;
714*7c478bd9Sstevel@tonic-gate *q++ = *p;
715*7c478bd9Sstevel@tonic-gate } while (*p++);
716*7c478bd9Sstevel@tonic-gate } else {
717*7c478bd9Sstevel@tonic-gate free(ent);
718*7c478bd9Sstevel@tonic-gate ent = NULL;
719*7c478bd9Sstevel@tonic-gate }
720*7c478bd9Sstevel@tonic-gate }
721*7c478bd9Sstevel@tonic-gate
722*7c478bd9Sstevel@tonic-gate else {
723*7c478bd9Sstevel@tonic-gate
724*7c478bd9Sstevel@tonic-gate /* Record is a data record. Parse it. */
725*7c478bd9Sstevel@tonic-gate ent->comment = FALSE;
726*7c478bd9Sstevel@tonic-gate ent->attrstr = NULL; /* For now */
727*7c478bd9Sstevel@tonic-gate
728*7c478bd9Sstevel@tonic-gate /* Extract the device alias */
729*7c478bd9Sstevel@tonic-gate if (p = getfld(record, ":")) {
730*7c478bd9Sstevel@tonic-gate if (*p) {
731*7c478bd9Sstevel@tonic-gate if (ent->alias = malloc(strlen(p)+1)) {
732*7c478bd9Sstevel@tonic-gate q = ent->alias;
733*7c478bd9Sstevel@tonic-gate do {
734*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++;
735*7c478bd9Sstevel@tonic-gate *q++ = *p;
736*7c478bd9Sstevel@tonic-gate } while (*p++);
737*7c478bd9Sstevel@tonic-gate }
738*7c478bd9Sstevel@tonic-gate } else ent->alias = NULL;
739*7c478bd9Sstevel@tonic-gate
740*7c478bd9Sstevel@tonic-gate /* Extract the character-device name */
741*7c478bd9Sstevel@tonic-gate if ((p = getfld(NULL, ":")) == NULL) {
742*7c478bd9Sstevel@tonic-gate if (ent->alias)
743*7c478bd9Sstevel@tonic-gate free(ent->alias);
744*7c478bd9Sstevel@tonic-gate } else {
745*7c478bd9Sstevel@tonic-gate if (*p) {
746*7c478bd9Sstevel@tonic-gate if (ent->cdevice = malloc(strlen(p)+1)) {
747*7c478bd9Sstevel@tonic-gate q = ent->cdevice;
748*7c478bd9Sstevel@tonic-gate do {
749*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++;
750*7c478bd9Sstevel@tonic-gate *q++ = *p;
751*7c478bd9Sstevel@tonic-gate } while (*p++);
752*7c478bd9Sstevel@tonic-gate }
753*7c478bd9Sstevel@tonic-gate } else ent->cdevice = NULL;
754*7c478bd9Sstevel@tonic-gate
755*7c478bd9Sstevel@tonic-gate /* Extract the block-device name */
756*7c478bd9Sstevel@tonic-gate if (!(p = getfld(NULL, ":"))) {
757*7c478bd9Sstevel@tonic-gate if (ent->alias) free(ent->alias);
758*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice);
759*7c478bd9Sstevel@tonic-gate } else {
760*7c478bd9Sstevel@tonic-gate if (*p) {
761*7c478bd9Sstevel@tonic-gate if (ent->bdevice = malloc(strlen(p)+1)) {
762*7c478bd9Sstevel@tonic-gate q = ent->bdevice;
763*7c478bd9Sstevel@tonic-gate do {
764*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++;
765*7c478bd9Sstevel@tonic-gate *q++ = *p;
766*7c478bd9Sstevel@tonic-gate } while (*p++);
767*7c478bd9Sstevel@tonic-gate }
768*7c478bd9Sstevel@tonic-gate } else
769*7c478bd9Sstevel@tonic-gate ent->bdevice = NULL;
770*7c478bd9Sstevel@tonic-gate
771*7c478bd9Sstevel@tonic-gate /* Extract the pathname */
772*7c478bd9Sstevel@tonic-gate if ((p = getfld(NULL, ":\n")) == NULL) {
773*7c478bd9Sstevel@tonic-gate if (ent->alias) free(ent->alias);
774*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice);
775*7c478bd9Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice);
776*7c478bd9Sstevel@tonic-gate } else {
777*7c478bd9Sstevel@tonic-gate if (*p) {
778*7c478bd9Sstevel@tonic-gate if (ent->pathname = malloc(strlen(p)+1)) {
779*7c478bd9Sstevel@tonic-gate q = ent->pathname;
780*7c478bd9Sstevel@tonic-gate do {
781*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++;
782*7c478bd9Sstevel@tonic-gate *q++ = *p;
783*7c478bd9Sstevel@tonic-gate } while (*p++);
784*7c478bd9Sstevel@tonic-gate }
785*7c478bd9Sstevel@tonic-gate } else
786*7c478bd9Sstevel@tonic-gate ent->pathname = NULL;
787*7c478bd9Sstevel@tonic-gate
788*7c478bd9Sstevel@tonic-gate /* Found a valid record */
789*7c478bd9Sstevel@tonic-gate done = TRUE;
790*7c478bd9Sstevel@tonic-gate
791*7c478bd9Sstevel@tonic-gate /*
792*7c478bd9Sstevel@tonic-gate * Extract attributes, build a linked list of
793*7c478bd9Sstevel@tonic-gate * 'em (may be none)
794*7c478bd9Sstevel@tonic-gate */
795*7c478bd9Sstevel@tonic-gate if (attr = getattrval(NULL)) {
796*7c478bd9Sstevel@tonic-gate ent->attrlist = attr;
797*7c478bd9Sstevel@tonic-gate t = attr;
798*7c478bd9Sstevel@tonic-gate while (attr = getattrval(NULL)) {
799*7c478bd9Sstevel@tonic-gate t->next = attr;
800*7c478bd9Sstevel@tonic-gate t = attr;
801*7c478bd9Sstevel@tonic-gate }
802*7c478bd9Sstevel@tonic-gate t->next = NULL;
803*7c478bd9Sstevel@tonic-gate } else
804*7c478bd9Sstevel@tonic-gate ent->attrlist = NULL;
805*7c478bd9Sstevel@tonic-gate
806*7c478bd9Sstevel@tonic-gate } /* pathname extracted */
807*7c478bd9Sstevel@tonic-gate } /* bdevice extracted */
808*7c478bd9Sstevel@tonic-gate } /* cdevice extracted */
809*7c478bd9Sstevel@tonic-gate } /* alias extracted */
810*7c478bd9Sstevel@tonic-gate }
811*7c478bd9Sstevel@tonic-gate } /* !done && record read */
812*7c478bd9Sstevel@tonic-gate
813*7c478bd9Sstevel@tonic-gate /* If no entry was read, free space allocated to the structure */
814*7c478bd9Sstevel@tonic-gate if (!done) {
815*7c478bd9Sstevel@tonic-gate free(ent);
816*7c478bd9Sstevel@tonic-gate ent = NULL;
817*7c478bd9Sstevel@tonic-gate }
818*7c478bd9Sstevel@tonic-gate
819*7c478bd9Sstevel@tonic-gate return (ent);
820*7c478bd9Sstevel@tonic-gate }
821*7c478bd9Sstevel@tonic-gate
822*7c478bd9Sstevel@tonic-gate /*
823*7c478bd9Sstevel@tonic-gate * void _freedevtabent(devtabent)
824*7c478bd9Sstevel@tonic-gate * struct devtabent *devtabent;
825*7c478bd9Sstevel@tonic-gate *
826*7c478bd9Sstevel@tonic-gate * This function frees space allocated to a device table entry.
827*7c478bd9Sstevel@tonic-gate *
828*7c478bd9Sstevel@tonic-gate * Arguments:
829*7c478bd9Sstevel@tonic-gate * struct devtabent *devtabent The structure whose space is to be
830*7c478bd9Sstevel@tonic-gate * freed.
831*7c478bd9Sstevel@tonic-gate *
832*7c478bd9Sstevel@tonic-gate * Returns: void
833*7c478bd9Sstevel@tonic-gate */
834*7c478bd9Sstevel@tonic-gate
835*7c478bd9Sstevel@tonic-gate void
_freedevtabent(struct devtabent * ent)836*7c478bd9Sstevel@tonic-gate _freedevtabent(struct devtabent *ent)
837*7c478bd9Sstevel@tonic-gate {
838*7c478bd9Sstevel@tonic-gate /*
839*7c478bd9Sstevel@tonic-gate * Automatic data
840*7c478bd9Sstevel@tonic-gate */
841*7c478bd9Sstevel@tonic-gate
842*7c478bd9Sstevel@tonic-gate struct attrval *p; /* Structure being freed */
843*7c478bd9Sstevel@tonic-gate struct attrval *q; /* Next structure to free */
844*7c478bd9Sstevel@tonic-gate
845*7c478bd9Sstevel@tonic-gate if (!ent->comment) {
846*7c478bd9Sstevel@tonic-gate
847*7c478bd9Sstevel@tonic-gate /*
848*7c478bd9Sstevel@tonic-gate * Free the attribute list. For each item in the attribute
849*7c478bd9Sstevel@tonic-gate * list,
850*7c478bd9Sstevel@tonic-gate * 1. Free the attribute name (always defined),
851*7c478bd9Sstevel@tonic-gate * 2. Free the value (if any -- it's not defined if we're
852*7c478bd9Sstevel@tonic-gate * changing an existing attribute),
853*7c478bd9Sstevel@tonic-gate * 3. Free the space allocated to the structure.
854*7c478bd9Sstevel@tonic-gate */
855*7c478bd9Sstevel@tonic-gate
856*7c478bd9Sstevel@tonic-gate q = ent->attrlist;
857*7c478bd9Sstevel@tonic-gate if (q)
858*7c478bd9Sstevel@tonic-gate do {
859*7c478bd9Sstevel@tonic-gate p = q;
860*7c478bd9Sstevel@tonic-gate q = p->next;
861*7c478bd9Sstevel@tonic-gate free(p->attr);
862*7c478bd9Sstevel@tonic-gate if (p->val) free(p->val);
863*7c478bd9Sstevel@tonic-gate free(p);
864*7c478bd9Sstevel@tonic-gate } while (q);
865*7c478bd9Sstevel@tonic-gate
866*7c478bd9Sstevel@tonic-gate /* Free the standard fields (alias, cdevice, bdevice, pathname) */
867*7c478bd9Sstevel@tonic-gate if (ent->alias) free(ent->alias);
868*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice);
869*7c478bd9Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice);
870*7c478bd9Sstevel@tonic-gate if (ent->pathname) free(ent->pathname);
871*7c478bd9Sstevel@tonic-gate }
872*7c478bd9Sstevel@tonic-gate
873*7c478bd9Sstevel@tonic-gate /* Free the attribute string */
874*7c478bd9Sstevel@tonic-gate if (ent->attrstr) free(ent->attrstr);
875*7c478bd9Sstevel@tonic-gate
876*7c478bd9Sstevel@tonic-gate /* Free the space allocated to the structure */
877*7c478bd9Sstevel@tonic-gate free(ent);
878*7c478bd9Sstevel@tonic-gate }
879*7c478bd9Sstevel@tonic-gate
880*7c478bd9Sstevel@tonic-gate /*
881*7c478bd9Sstevel@tonic-gate * struct devtabent *_getdevrec(device)
882*7c478bd9Sstevel@tonic-gate * char *device
883*7c478bd9Sstevel@tonic-gate *
884*7c478bd9Sstevel@tonic-gate * Thie _getdevrec() function returns a pointer to a structure that
885*7c478bd9Sstevel@tonic-gate * contains the information in the device-table entry that describes
886*7c478bd9Sstevel@tonic-gate * the device <device>.
887*7c478bd9Sstevel@tonic-gate *
888*7c478bd9Sstevel@tonic-gate * The device <device> can be a device alias, a pathname contained in
889*7c478bd9Sstevel@tonic-gate * the entry as the "cdevice", "bdevice", or "pathname" attribute,
890*7c478bd9Sstevel@tonic-gate * or a pathname to a device described using the "cdevice", "bdevice",
891*7c478bd9Sstevel@tonic-gate * or "pathname" attribute (depending on whether the pathname references
892*7c478bd9Sstevel@tonic-gate * a character-special file, block-special file, or something else,
893*7c478bd9Sstevel@tonic-gate * respectively.
894*7c478bd9Sstevel@tonic-gate *
895*7c478bd9Sstevel@tonic-gate * Arguments:
896*7c478bd9Sstevel@tonic-gate * char *device A character-string describing the device whose record
897*7c478bd9Sstevel@tonic-gate * is to be retrieved from the device table.
898*7c478bd9Sstevel@tonic-gate *
899*7c478bd9Sstevel@tonic-gate * Returns: struct devtabent *
900*7c478bd9Sstevel@tonic-gate * A pointer to a structure describing the device.
901*7c478bd9Sstevel@tonic-gate *
902*7c478bd9Sstevel@tonic-gate * Notes:
903*7c478bd9Sstevel@tonic-gate * - Someday, add a cache so that repeated requests for the same record
904*7c478bd9Sstevel@tonic-gate * don't require going to the filesystem. (Maybe -- this might belong
905*7c478bd9Sstevel@tonic-gate * in devattr()...)
906*7c478bd9Sstevel@tonic-gate */
907*7c478bd9Sstevel@tonic-gate
908*7c478bd9Sstevel@tonic-gate struct devtabent *
_getdevrec(char * device)909*7c478bd9Sstevel@tonic-gate _getdevrec(char *device) /* The device to search for */
910*7c478bd9Sstevel@tonic-gate {
911*7c478bd9Sstevel@tonic-gate /*
912*7c478bd9Sstevel@tonic-gate * Automatic data
913*7c478bd9Sstevel@tonic-gate */
914*7c478bd9Sstevel@tonic-gate
915*7c478bd9Sstevel@tonic-gate struct stat64 devstatbuf; /* Stat struct, <device> */
916*7c478bd9Sstevel@tonic-gate struct stat64 tblstatbuf; /* Stat struct, tbl entry */
917*7c478bd9Sstevel@tonic-gate struct devtabent *devrec; /* Pointer to current record */
918*7c478bd9Sstevel@tonic-gate int found; /* TRUE if record found */
919*7c478bd9Sstevel@tonic-gate int olderrno; /* Old value of errno */
920*7c478bd9Sstevel@tonic-gate
921*7c478bd9Sstevel@tonic-gate
922*7c478bd9Sstevel@tonic-gate /*
923*7c478bd9Sstevel@tonic-gate * Search the device table looking for the requested device
924*7c478bd9Sstevel@tonic-gate */
925*7c478bd9Sstevel@tonic-gate
926*7c478bd9Sstevel@tonic-gate _setdevtab();
927*7c478bd9Sstevel@tonic-gate olderrno = errno;
928*7c478bd9Sstevel@tonic-gate found = FALSE;
929*7c478bd9Sstevel@tonic-gate if ((device != NULL) && !_validalias(device)) {
930*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) {
931*7c478bd9Sstevel@tonic-gate if (!devrec->comment) {
932*7c478bd9Sstevel@tonic-gate if (devrec->cdevice)
933*7c478bd9Sstevel@tonic-gate if (strcmp(device, devrec->cdevice) == 0) found = TRUE;
934*7c478bd9Sstevel@tonic-gate if (devrec->bdevice)
935*7c478bd9Sstevel@tonic-gate if (strcmp(device, devrec->bdevice) == 0) found = TRUE;
936*7c478bd9Sstevel@tonic-gate if (devrec->pathname)
937*7c478bd9Sstevel@tonic-gate if (strcmp(device, devrec->pathname) == 0) found = TRUE;
938*7c478bd9Sstevel@tonic-gate } else _freedevtabent(devrec);
939*7c478bd9Sstevel@tonic-gate }
940*7c478bd9Sstevel@tonic-gate
941*7c478bd9Sstevel@tonic-gate /*
942*7c478bd9Sstevel@tonic-gate * If the device <device> wasn't named explicitly in the device
943*7c478bd9Sstevel@tonic-gate * table, compare it against like entries by comparing file-
944*7c478bd9Sstevel@tonic-gate * system, major device number, and minor device number
945*7c478bd9Sstevel@tonic-gate */
946*7c478bd9Sstevel@tonic-gate
947*7c478bd9Sstevel@tonic-gate if (!found) {
948*7c478bd9Sstevel@tonic-gate _setdevtab();
949*7c478bd9Sstevel@tonic-gate
950*7c478bd9Sstevel@tonic-gate /* Status the file <device>. If fails, invalid device */
951*7c478bd9Sstevel@tonic-gate if (stat64(device, &devstatbuf) != 0) errno = ENODEV;
952*7c478bd9Sstevel@tonic-gate else {
953*7c478bd9Sstevel@tonic-gate
954*7c478bd9Sstevel@tonic-gate /*
955*7c478bd9Sstevel@tonic-gate * If <device> is a block-special device. See if it is
956*7c478bd9Sstevel@tonic-gate * in the table by matching its file-system indicator
957*7c478bd9Sstevel@tonic-gate * and major/minor device numbers against the
958*7c478bd9Sstevel@tonic-gate * file-system and major/minor device numbers of the
959*7c478bd9Sstevel@tonic-gate * "bdevice" entries.
960*7c478bd9Sstevel@tonic-gate */
961*7c478bd9Sstevel@tonic-gate
962*7c478bd9Sstevel@tonic-gate if ((devstatbuf.st_mode & 0170000) == 0020000) {
963*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) {
964*7c478bd9Sstevel@tonic-gate if (!devrec->comment &&
965*7c478bd9Sstevel@tonic-gate (devrec->cdevice != NULL))
966*7c478bd9Sstevel@tonic-gate if (stat64(devrec->cdevice, &tblstatbuf) == 0) {
967*7c478bd9Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf))
968*7c478bd9Sstevel@tonic-gate found = TRUE;
969*7c478bd9Sstevel@tonic-gate } else {
970*7c478bd9Sstevel@tonic-gate /* Ignore stat() errs */
971*7c478bd9Sstevel@tonic-gate errno = olderrno;
972*7c478bd9Sstevel@tonic-gate }
973*7c478bd9Sstevel@tonic-gate if (!found) _freedevtabent(devrec);
974*7c478bd9Sstevel@tonic-gate }
975*7c478bd9Sstevel@tonic-gate }
976*7c478bd9Sstevel@tonic-gate
977*7c478bd9Sstevel@tonic-gate /*
978*7c478bd9Sstevel@tonic-gate * If <device> is a block-special device. See if it is
979*7c478bd9Sstevel@tonic-gate * in the table by matching its file-system indicator
980*7c478bd9Sstevel@tonic-gate * and major/minor device numbers against the
981*7c478bd9Sstevel@tonic-gate * file-system and major/minor device numbers of the
982*7c478bd9Sstevel@tonic-gate * "bdevice" entries.
983*7c478bd9Sstevel@tonic-gate */
984*7c478bd9Sstevel@tonic-gate
985*7c478bd9Sstevel@tonic-gate else if ((devstatbuf.st_mode & 0170000) == 0060000) {
986*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) {
987*7c478bd9Sstevel@tonic-gate if (!devrec->comment &&
988*7c478bd9Sstevel@tonic-gate (devrec->bdevice != NULL))
989*7c478bd9Sstevel@tonic-gate if (stat64(devrec->bdevice, &tblstatbuf) == 0) {
990*7c478bd9Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf))
991*7c478bd9Sstevel@tonic-gate found = TRUE;
992*7c478bd9Sstevel@tonic-gate } else {
993*7c478bd9Sstevel@tonic-gate /* Ignore stat() errs */
994*7c478bd9Sstevel@tonic-gate errno = olderrno;
995*7c478bd9Sstevel@tonic-gate }
996*7c478bd9Sstevel@tonic-gate if (!found) _freedevtabent(devrec);
997*7c478bd9Sstevel@tonic-gate }
998*7c478bd9Sstevel@tonic-gate }
999*7c478bd9Sstevel@tonic-gate
1000*7c478bd9Sstevel@tonic-gate /*
1001*7c478bd9Sstevel@tonic-gate * If <device> is neither a block-special or character-
1002*7c478bd9Sstevel@tonic-gate * special device. See if it is in the table by
1003*7c478bd9Sstevel@tonic-gate * matching its file-system indicator and major/minor
1004*7c478bd9Sstevel@tonic-gate * device numbers against the file-system and
1005*7c478bd9Sstevel@tonic-gate * major/minor device numbers of the "pathname" entries.
1006*7c478bd9Sstevel@tonic-gate */
1007*7c478bd9Sstevel@tonic-gate
1008*7c478bd9Sstevel@tonic-gate else {
1009*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) {
1010*7c478bd9Sstevel@tonic-gate if (!devrec->comment &&
1011*7c478bd9Sstevel@tonic-gate (devrec->pathname != NULL))
1012*7c478bd9Sstevel@tonic-gate if (stat64(devrec->pathname,
1013*7c478bd9Sstevel@tonic-gate &tblstatbuf) == 0) {
1014*7c478bd9Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf))
1015*7c478bd9Sstevel@tonic-gate found = TRUE;
1016*7c478bd9Sstevel@tonic-gate } else {
1017*7c478bd9Sstevel@tonic-gate /* Ignore stat() errs */
1018*7c478bd9Sstevel@tonic-gate errno = olderrno;
1019*7c478bd9Sstevel@tonic-gate }
1020*7c478bd9Sstevel@tonic-gate if (!found) _freedevtabent(devrec);
1021*7c478bd9Sstevel@tonic-gate }
1022*7c478bd9Sstevel@tonic-gate }
1023*7c478bd9Sstevel@tonic-gate
1024*7c478bd9Sstevel@tonic-gate if (!found) {
1025*7c478bd9Sstevel@tonic-gate devrec = NULL;
1026*7c478bd9Sstevel@tonic-gate errno = ENODEV;
1027*7c478bd9Sstevel@tonic-gate }
1028*7c478bd9Sstevel@tonic-gate
1029*7c478bd9Sstevel@tonic-gate } /* End case where stat() on the <device> succeeded */
1030*7c478bd9Sstevel@tonic-gate
1031*7c478bd9Sstevel@tonic-gate } /* End case handling pathname not explicitly in device table */
1032*7c478bd9Sstevel@tonic-gate
1033*7c478bd9Sstevel@tonic-gate } /* End case handling <device> as a fully-qualified pathname */
1034*7c478bd9Sstevel@tonic-gate
1035*7c478bd9Sstevel@tonic-gate
1036*7c478bd9Sstevel@tonic-gate /*
1037*7c478bd9Sstevel@tonic-gate * Otherwise the device <device> is an alias.
1038*7c478bd9Sstevel@tonic-gate * Search the table for a record that has as the "alias" attribute
1039*7c478bd9Sstevel@tonic-gate * the value <device>.
1040*7c478bd9Sstevel@tonic-gate */
1041*7c478bd9Sstevel@tonic-gate
1042*7c478bd9Sstevel@tonic-gate else {
1043*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) {
1044*7c478bd9Sstevel@tonic-gate if (!devrec->comment && (device != NULL) &&
1045*7c478bd9Sstevel@tonic-gate strcmp(device, devrec->alias) == 0)
1046*7c478bd9Sstevel@tonic-gate found = TRUE;
1047*7c478bd9Sstevel@tonic-gate else _freedevtabent(devrec);
1048*7c478bd9Sstevel@tonic-gate }
1049*7c478bd9Sstevel@tonic-gate if (!found) {
1050*7c478bd9Sstevel@tonic-gate devrec = NULL;
1051*7c478bd9Sstevel@tonic-gate errno = ENODEV;
1052*7c478bd9Sstevel@tonic-gate }
1053*7c478bd9Sstevel@tonic-gate }
1054*7c478bd9Sstevel@tonic-gate
1055*7c478bd9Sstevel@tonic-gate /* Fini */
1056*7c478bd9Sstevel@tonic-gate return (devrec);
1057*7c478bd9Sstevel@tonic-gate }
1058