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 * 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 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