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