Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!uflorida!haven!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.wizards Subject: Re: stat of i-node Message-ID: <19383@mimsy.UUCP> Date: 2 Sep 89 14:08:25 GMT References: <172@bmers58.UUCP> <19362@mimsy.UUCP> <179@bmers58.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 148 >In article <19362@mimsy.UUCP> I suggested: >>fstat() is a very cheap operation. stat() is a bit more expensive, but >>(with name cacheing) not all that bad. In article <179@bmers58.UUCP> davem@bmers58.UUCP (Dave Mielke) writes: >The problem with fstat is that it requires an open which also does a >name lookup. This proves to be very slow when the directories get >large. I need a way to get the information that stat would return >without the expense of a name lookup. The i-node is the obvious key to >the data, but I am unaware of any primitive that gives an application >program direct access to the data via its actual key. I would >appreciate any assistence that anyone can offer. Okay, here it is (but you have to be root, and it does not work across NFS). Note that you would have to be root to use any `new' system call that gives information by pairs anyway, because otherwise you could bypass system security. (Find an unreadable directory? Want to know what is in it? Guess what inodes are there, and look them up by number. This gives incomplete information, but it gives more than you get now.) Given the pair, we want to find the inode on the disk device. Use the block device if you want to cooperate with the buffer cache, or the raw device if you do not. (Define RAW, or not, as appropriate.) /* NB: this code is untested */ #include #include #ifdef NFS #include #include #include #include #else #include #include #endif /* * Given a dev_t value, open the corresponding block (or raw) device * by searching mtab and trying devices. */ int get_dev(dev) dev_t dev; { FILE *fp; register char *p1; #ifdef NFS char *p2; #endif int fd; struct stat st; char buf[BUFSIZ]; /* /etc/mtab changes, so just use the mount program */ fp = popen("mount", "r"); /* /etc/mount or /sbin/mount */ if (fp == NULL) return (-1); while (fgets(buf, sizeof buf, fp) != NULL) { #ifdef RAW if (strncmp(buf, "/dev/", 5) != 0) continue; /* strange line from mount */ #endif p1 = strchr(buf, ' '); if (p1 == NULL) break; if (strncmp(p1 + 1, " on ", 4) != 0) continue; /* strange line from mount */ #ifdef NFS p2 = strchr(buf, ':'); if (p2 != NULL && p2 < p1) continue; /* must be an NFS mount */ #endif *p1 = 0; /* buf now `/dev/ra0d', eg */ if ((fd = open(buf, 0)) < 0) continue; if (fstat(fd, &st)) panic("fstat fails"); if (st.st_dev == dev) { #ifdef RAW (void) close(fd); (void) sprintf(p1 + 1, "/dev/r%s", buf + 5); fd = open(p1 + 1, 0); #endif return (fd); } } (void) fclose(fp); return (-1); } /* * Given a pair, find the inode. Store it through *dip. * Return -1 if not found, 0 if found. * * This version is BSD-specific. */ get_inode(dev, ino, dip) dev_t dev; ino_t ino; struct dinode *dip; { static int fd = -1; static dev_t lastdev; static long lastoff; long off; static char buf[DEV_BSIZE]; static union { struct fs usb; char ubuf[SBSIZE]; } u; #define sblock u.usb if (fd < 0 || dev != lastdev) { fd = get_dev(dev); if (fd < 0) return (-1); lastdev = dev; (void) lseek(fd, (long)BBSIZE, 0); if (read(fd, (char *)&sblock, SBSIZE) != SBSIZE || sblock.fs_magic != FS_MAGIC) { (void) close(fd); fd = -1; return (-1); } lastoff = 0; /* safe, because this is boot block */ } off = (long)fsbtodb(&sblock, itod(&sblock, ino)) * DEV_BSIZE; if (off != lastoff) { (void) lseek(fd, off, 0); if (read(fd, buf, sizeof buf) != sizeof buf) { lastoff = 0; return (-1); } lastoff = off; } *dip = ((struct dinode *)buf)[itoo(&sblock, ino)]; return (0); /* got it at last */ } /* For V7 file systems, such as those in SysV, the above is simpler, because the inodes are at a fixed offset, so the `itod'/`itoo' reduces to a single computation to find the inode offset. This should then be converted to a 512-byte block, and the inode fished out as above (except that itoo becomes a relatively simple `%'). */ -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris