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