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