xref: /illumos-gate/usr/src/cmd/acct/lib/devtolin.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.9	*/
27 
28 /*
29  *	convert device to linename (as in /dev/linename)
30  *	return ptr to LSZ-byte string, "?" if not found
31  *	device must be character device
32  *	maintains small list in tlist structure for speed
33  */
34 
35 #include <stdio.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include "acctdef.h"
39 #include <dirent.h>
40 #include <string.h>
41 #include <sys/stat.h>
42 
43 static	tsize1;
44 static struct tlist {
45 	char	tname[LSZ];	/* linename */
46 	dev_t	tdev;		/* device */
47 } tl[TSIZE1];
48 
49 char	*strncpy();
50 dev_t	lintodev();
51 
52 static char dev_dir[] = "/dev";
53 static char *def_srch_dirs[] = { "/dev/term",
54 				 "/dev/pts",
55 				 "/dev/xt",
56 				 NULL };
57 char file_name[MAX_DEV_PATH];	/* name being returned */
58 
59 char *
60 devtolin(device)
61   dev_t device;
62 {
63 	register struct tlist *tp;
64 	char **srch_dirs;	/* priority directories to search first */
65 	int found = 0;
66 	int dirno = 0;
67 
68 	for (tp = tl; tp < &tl[tsize1]; tp++)
69 		if (device == tp->tdev)
70 			return(tp->tname);
71 
72 	srch_dirs = def_srch_dirs;
73 
74 	while ((!found) && (srch_dirs[dirno] != NULL)) {
75 		/* if /dev is one of the priority directories we should only
76 		   search its top level for now (set depth = MAX_SEARCH_DEPTH) */
77 
78 		found = srch_dir(device, srch_dirs[dirno],
79 				 ((strcmp(srch_dirs[dirno], dev_dir) == 0) ?
80 				  MAX_SRCH_DEPTH : 1),
81 				 NULL);
82 		dirno++;
83 	}
84 
85 	/* if not yet found search remaining /dev directory skipping the
86 	   priority directories */
87 
88 	if (!found)
89 		found = srch_dir(device, dev_dir, 0, srch_dirs);
90 
91 	/* if found then put it (without the "/dev/" prefix) in the tlist
92 	   structure and return the path name without the "/dev/" prefix */
93 
94 	if (found) {
95 		if (tsize1 < TSIZE1) {
96 			tp->tdev = device;
97 			CPYN(tp->tname, file_name+5);
98 			tsize1++;
99 		}
100 		return(file_name+5);
101 	} else
102 	/* if not found put "?" in the tlist structure for that device and
103 	   return "?" */
104 
105 		if (tsize1 < TSIZE1) {
106 			tp->tdev = device;
107 			CPYN(tp->tname, "?");
108 			tsize1++;
109 		}
110 		return("?");
111 
112 }
113 
114 static int
115 srch_dir(device, path, depth, skip_dirs)
116   dev_t device;	/* device we are looking for */
117   char *path;	/* current path */
118   int depth;	/* current depth */
119   char *skip_dirs[];	/* directories that don't need searched */
120 {
121 	DIR *fdev;
122 	struct dirent *d;
123 	int dirno = 0;
124 	int found = 0;
125 	int path_len;
126 	char *last_comp;
127 	struct stat sb;
128 
129 	/* do we need to search this directory? */
130 
131 	if ((skip_dirs != NULL) && (depth != 0))
132 		while (skip_dirs[dirno] != NULL)
133 			if (strcmp(skip_dirs[dirno++], path) == 0)
134 				return(0);
135 
136 
137 	/* open the directory */
138 
139 	if ((fdev = opendir(path)) == NULL)
140 		return(0);
141 
142 	/* initialize file name using path name */
143 
144 	path_len = strlen(path);
145 	strcpy(file_name, path);
146 	last_comp = file_name + path_len;
147 	*last_comp++ = '/';
148 
149 	/* start searching this directory */
150 
151 	while ((!found) && ((d = readdir(fdev)) != NULL))
152 		if (d->d_ino != 0) {
153 
154 			/* if name would not be too long append it to
155 			   directory name, otherwise skip this entry */
156 
157 			if ((int) (path_len + strlen(d->d_name) + 2) > MAX_DEV_PATH)
158 				continue;
159 			else
160 				strcpy(last_comp, d->d_name);
161 
162 			/* if this directory entry has the device number we need,
163 			   then the name is found.  Otherwise if it's a directory
164 			   (not . or ..) and we haven't gone too deep, recurse. */
165 
166 			if (lintodev(file_name+5) == device) {
167 				found = 1;
168 				break;
169 			} else if ((depth < MAX_SRCH_DEPTH) &&
170 					  (strcmp(d->d_name, ".") != 0) &&
171 					  (strcmp(d->d_name, "..") != 0) &&
172 					  (stat(file_name, &sb) != -1) &&
173 					  ((sb.st_mode & S_IFMT) == S_IFDIR))
174 				found = srch_dir(device, file_name, depth+1, skip_dirs);
175 		}
176 	closedir(fdev);
177 	return(found);
178 }
179