stat of i-node
Chris Torek
chris at mimsy.UUCP
Sun Sep 3 00:08:25 AEST 1989
>In article <19362 at 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 at bmers58.UUCP> davem at 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 <dev,ino> 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 <dev_t dev, ino_t ino> 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 <stdio.h>
#include <sys/param.h>
#ifdef NFS
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <ufs/fs.h>
#include <ufs/inode.h>
#else
#include <sys/fs.h>
#include <sys/inode.h>
#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 <dev,ino> 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 at mimsy.umd.edu Path: uunet!mimsy!chris
More information about the Comp.unix.wizards
mailing list