xref: /csrg-svn/lib/libc/gen/devname.c (revision 45158)
140966Smarc /*
240966Smarc  * Copyright (c) 1989 The Regents of the University of California.
340966Smarc  * All rights reserved.
440966Smarc  *
542537Sbostic  * %sccs.include.redist.c%
640966Smarc  */
740966Smarc 
840966Smarc #if defined(LIBC_SCCS) && !defined(lint)
9*45158Smarc static char sccsid[] = "@(#)devname.c	5.7 (Berkeley) 08/30/90";
1040966Smarc #endif /* LIBC_SCCS and not lint */
1140966Smarc 
1240258Smarc #include <sys/types.h>
1340258Smarc #include <sys/stat.h>
1440966Smarc #include <sys/file.h>
1540966Smarc #include <dirent.h>
16*45158Smarc #include <stdio.h>
17*45158Smarc #include <stdlib.h>
18*45158Smarc #include <string.h>
1940966Smarc #include <paths.h>
2040258Smarc 
21*45158Smarc /*
22*45158Smarc  * Routine to convert a major+minor device number (st_rdev field)
23*45158Smarc  * plus a mode (S_IFCHR or S_IFBLK) into a name relative to /dev.
24*45158Smarc  *
25*45158Smarc  * We build a hash table of everything in /dev, with the hash being
26*45158Smarc  * a function of the number and mode.
27*45158Smarc  */
28*45158Smarc 
29*45158Smarc #define	HASHSIZ	512		/* MUST BE A POWER OF 2 */
30*45158Smarc #define	hash(x, t)	((((t) >> 14) + 4*minor(x) + major(x)) & (HASHSIZ-1))
31*45158Smarc 
32*45158Smarc struct devs {
3340966Smarc 	struct	devs *next;
3440258Smarc 	dev_t	dev;
3540971Smarc 	mode_t	type;
36*45158Smarc 	char	name[MAXNAMLEN + 1];
3740258Smarc };
3840258Smarc 
39*45158Smarc static struct devs *devhash[HASHSIZ];
4040258Smarc 
41*45158Smarc #ifdef TEST
42*45158Smarc int	chainlen[HASHSIZ];
43*45158Smarc int	verbose;
44*45158Smarc #endif
4540258Smarc 
46*45158Smarc static int
47*45158Smarc add(type, dev, name)
48*45158Smarc 	mode_t type;
49*45158Smarc 	dev_t dev;
50*45158Smarc 	char *name;
51*45158Smarc {
52*45158Smarc 	register struct devs *devp, **p;
53*45158Smarc 	int h;
54*45158Smarc 
55*45158Smarc 	devp = (struct devs *)malloc(sizeof *devp);
56*45158Smarc 	if (devp == NULL)
57*45158Smarc 		return (0);
58*45158Smarc 	devp->next = NULL;
59*45158Smarc 	devp->dev = dev;
60*45158Smarc 	devp->type = type;
61*45158Smarc 	(void) strcpy(devp->name, name);
62*45158Smarc 	h = hash(dev, type);
63*45158Smarc 	for (p = &devhash[h]; *p; p = &(*p)->next)
64*45158Smarc 		/* void */;
65*45158Smarc 	*p = devp;
66*45158Smarc #ifdef TEST
67*45158Smarc 	chainlen[h]++;
68*45158Smarc 	if (verbose)
69*45158Smarc 		(void) printf("adding %c %d,%d %s (hash=%d)\n",
70*45158Smarc 		    type == S_IFBLK ? 'b': 'c', major(dev), minor(dev),
71*45158Smarc 		    name, h);
72*45158Smarc #endif
73*45158Smarc 	return (1);
74*45158Smarc }
75*45158Smarc 
76*45158Smarc static int
77*45158Smarc init_by_stat()
78*45158Smarc {
79*45158Smarc 	register struct dirent *entry;
80*45158Smarc 	struct stat sb;
81*45158Smarc 	DIR *dp;
82*45158Smarc 	int savewd;
83*45158Smarc 	mode_t specialtype;
84*45158Smarc 
85*45158Smarc 	if ((savewd = open(".", O_RDONLY, 0)) == -1)
86*45158Smarc 		return (0);
87*45158Smarc 	if (chdir(_PATH_DEV) == -1) {
88*45158Smarc 		(void) close(savewd);
89*45158Smarc 		return (0);
90*45158Smarc 	}
91*45158Smarc 	if ((dp = opendir(".")) == NULL) {
92*45158Smarc 		(void) fchdir(savewd);
93*45158Smarc 		(void) close(savewd);
94*45158Smarc 		return (0);
95*45158Smarc 	}
96*45158Smarc 	while ((entry = readdir(dp)) != NULL) {
97*45158Smarc 		if (stat(entry->d_name, &sb) == -1)
98*45158Smarc 			continue;
99*45158Smarc 		switch (sb.st_mode & S_IFMT) {
100*45158Smarc 		case S_IFCHR:
101*45158Smarc 			specialtype = S_IFCHR;
102*45158Smarc 			break;
103*45158Smarc 		case S_IFBLK:
104*45158Smarc 			specialtype = S_IFBLK;
105*45158Smarc 			break;
106*45158Smarc 		default:
107*45158Smarc 			continue;
108*45158Smarc 		}
109*45158Smarc 		if (!add(specialtype, sb.st_rdev, entry->d_name))
110*45158Smarc 			break;
111*45158Smarc 	}
112*45158Smarc 	(void) fchdir(savewd);
113*45158Smarc 	(void) close(savewd);
114*45158Smarc 	(void) closedir(dp);
115*45158Smarc 	return (1);
116*45158Smarc }
117*45158Smarc 
118*45158Smarc static int
119*45158Smarc init_by_db()
120*45158Smarc {
121*45158Smarc 	register FILE *fp;
122*45158Smarc 	char type, name[MAXNAMLEN + 1];
123*45158Smarc 	int maj, min;
124*45158Smarc #define specialtype(c) ((c) == 'b' ? (mode_t)S_IFBLK : (mode_t)S_IFCHR)
125*45158Smarc 
126*45158Smarc 	if ((fp = fopen("/var/run/devdatabase", "r")) == NULL)
127*45158Smarc 		return (0);
128*45158Smarc 	while (fscanf(fp, " %c %d,%d %s", &type, &maj, &min, name) == 4)
129*45158Smarc 		if (!add(specialtype(type), makedev(maj, min), name))
130*45158Smarc 			break;
131*45158Smarc 	(void) fclose(fp);
132*45158Smarc 	return (1);
133*45158Smarc #undef specialtype
134*45158Smarc }
135*45158Smarc 
13640258Smarc char *
13740966Smarc devname(dev, type)
13840258Smarc 	dev_t dev;
13940971Smarc 	mode_t type;
14040258Smarc {
141*45158Smarc 	register struct devs *devp;
142*45158Smarc 	static int devinit;
14340258Smarc 
144*45158Smarc 	if (!devinit) {
145*45158Smarc 		if (!init_by_db() && !init_by_stat())
14640258Smarc 			return (NULL);
14740966Smarc 		devinit = 1;
14840258Smarc 	}
149*45158Smarc 	for (devp = devhash[hash(dev, type)]; devp != NULL; devp = devp->next)
15040966Smarc 		if (dev == devp->dev && type == devp->type)
151*45158Smarc 			return (devp->name);
15240258Smarc 
15340258Smarc 	return (NULL);
15440258Smarc }
15540258Smarc 
15640258Smarc #ifdef TEST
157*45158Smarc main(argc, argv)
158*45158Smarc 	int argc;
159*45158Smarc 	char **argv;
160*45158Smarc {
161*45158Smarc 	register int i, sum, longest;
162*45158Smarc 	struct stat st;
163*45158Smarc 	char *p, *ttyname();
164*45158Smarc 
165*45158Smarc 	if (argc > 1 && strcmp(argv[1], "-v") == 0)
166*45158Smarc 		verbose = 1, argc--, argv++;
167*45158Smarc 	p = argc > 1 ? argv[1] : ttyname(0);
168*45158Smarc 	(void) stat(p, &st);
169*45158Smarc 	(void) printf(" %s \n", devname(st.st_rdev, (mode_t)S_IFCHR));
170*45158Smarc 	longest = sum = 0;
171*45158Smarc 	for (i = 0; i < HASHSIZ; i++) {
172*45158Smarc 		sum += chainlen[i];
173*45158Smarc 		if (chainlen[i] > longest)
174*45158Smarc 			longest = chainlen[i];
175*45158Smarc 	}
176*45158Smarc 	(void) printf("average hash chain length %.2f, longest %d\n",
177*45158Smarc 	    (double)sum / HASHSIZ, longest);
17840258Smarc }
17940258Smarc #endif
180