diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2008-01-27 11:37:44 +0100 |
---|---|---|
committer | Tobias Klauser <tklauser@xenon.tklauser.home> | 2008-01-27 11:37:44 +0100 |
commit | 7e0f021a9aec35fd8e6725e87e3313b101d26f5e (patch) | |
tree | b1cacc4b24393f517aeb4610e9e1021f954307a8 /reference/C/CONTRIB/OR_USING_C/13.2.c |
Initial import (2.0.2-6)2.0.2-6
Diffstat (limited to 'reference/C/CONTRIB/OR_USING_C/13.2.c')
-rw-r--r-- | reference/C/CONTRIB/OR_USING_C/13.2.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/OR_USING_C/13.2.c b/reference/C/CONTRIB/OR_USING_C/13.2.c new file mode 100644 index 0000000..023041a --- /dev/null +++ b/reference/C/CONTRIB/OR_USING_C/13.2.c @@ -0,0 +1,267 @@ +/* + * Reads the i-node structures from a raw disk device and + * then sums up the disk usage for each user. Prints out + * the number of blocks each user is using. + * + * If you are on a Sun workstation or other system using Sun's + * Network File System (NFS), be sure to define the constant + * NFS so that the proper files get included. + */ +#ifdef sun +#define NFS 1 +#endif +#ifdef NFS +#include <sys/param.h> +#include <sys/time.h> +#include <sys/vnode.h> +#include <ufs/inode.h> +#include <sys/file.h> +#include <ufs/fs.h> +#include <stdio.h> +#include <pwd.h> +#else +#include <sys/param.h> +#include <sys/inode.h> +#include <sys/file.h> +#include <sys/fs.h> +#include <stdio.h> +#include <pwd.h> +#endif +/* + * Maximum user id. + */ +#ifndef MAXUID +#define MAXUID 32768 +#endif + +#define sblock sb_un.u_sblock + +/* + * The super block. We allow enough room for + * a complete disk block. + */ +union { + struct fs u_sblock; + char dummy[SBSIZE]; +} sb_un; + +int nfiles; /* number of files in file system */ + +char *pname; /* program name (argv[0]) */ +char *device; /* name of the disk device given */ +char *filsys; /* name of the file system on device */ + +size_t blocks[MAXUID]; /* count of blocks used */ +struct dinode *dinode; /* will hold all the i-node structures */ + +main(argc, argv) +int argc; +char **argv; +{ + int i, fd; + register ino_t ino; + register struct dinode *di; + + /* + * Save the program name and check our arguments. + */ + pname = *argv; + + if (argc != 2) { + fprintf(stderr, "Usage: %s raw-disk-device\n", pname); + exit(1); + } + + /* + * Open the device for reading. + */ + device = *++argv; + + if ((fd = open(device, O_RDONLY)) < 0) { + perror(device); + exit(1); + } + + /* + * Get the super-block from the device. + */ + getsblock(fd); + + /* + * Get the i-node structures from the device. + */ + getinodes(fd); + close(fd); + + /* + * Zero the block counts. + */ + for (i = 0; i < MAXUID; i++) + blocks[i] = 0; + + /* + * Add up the number of blocks being used by + * each user id. + */ + for (ino = 0; ino < nfiles; ino++) { + /* + * ROOTINO is the first i-node; skip any + * before it. + */ + if (ino < ROOTINO) + continue; + + di = &dinode[ino]; + + /* + * If this is zero, the i-node is free (not + * in use). + */ + if ((di->di_mode & IFMT) == 0) + continue; + + /* + * Count the number of blocks being used by + * this file. + */ + blocks[di->di_uid] += di->di_blocks; + } + + /* + * Print out what we added up. + */ + printusage(); + exit(0); +} + +/* + * getsblock--get the super-block from the device + * referred to by fd. + */ +getsblock(fd) +int fd; +{ + /* + * Make sure the disk information is current. + * This causes all disk writes to be scheduled. + */ + sync(); + + /* + * Read in the super-block. It is stored at file + * system block number SBLOCK. + */ + bread(fd, SBLOCK, &sblock, SBSIZE); + + /* + * The number of files (i-nodes) is calculated by + * multiplying the number of i-nodes per cylinder + * group by the number of cylinder groups. + */ + nfiles = sblock.fs_ipg * sblock.fs_ncg; + + /* + * Save the name of the file system. + */ + filsys = sblock.fs_fsmnt; +} + +/* + * getinodes--read in the i-node structures from the device + * referred to by fd. + */ +getinodes(fd) +int fd; +{ + register ino_t ino; + register daddr_t iblk; + struct dinode *malloc(); + + /* + * Allocate space for them all. + */ + dinode = malloc(nfiles * sizeof(struct dinode)); + + if (dinode == NULL) { + fprintf(stderr, "%s: out of memory.\n", pname); + exit(1); + } + + /* + * We read in i-nodes a disk block-full at a time. + * The INOPB macro returns the number of i-nodes + * in a block; it uses the super-block to determine + * the file system block size. + */ + for (ino = 0; ino < nfiles; ino += INOPB(&sblock)) { + /* + * The i-node file system block number is given by + * the itod macro. The disk block number is computed + * from the file system block number by the fsbtodb macro. + */ + + iblk = fsbtodb(&sblock, itod(&sblock, ino)); + + /* + * Read in this block of i-nodes. + */ + bread(fd, iblk, &dinode[ino], sblock.fs_bsize); + } +} + +/* + * bread-read cnt bytes form fd into buf, starting at + * address bno. + */ +bread(fd, bno, buf, cnt) +daddr_t bno; +char *buf; +int cnt; +{ + int n; + + /* + * Seek to the proper block. The dtob macro converts + * the block number to a byte address. + */ + lseek(fd, (long) dtob(bno), L_SET); + + /* + * Round cnt up to a multiple of the device block size. + */ + cnt = roundup(cnt, DEV_BSIZE); + + /* + * Read in the data. + */ + if ((n = read(fd, buf, cnt)) != cnt) { + perror(filsys); + exit(1); + } +} + +/* + * printusage-print out the disk usage in blocks. + */ +printusage() +{ + register int i; + struct passwd *pwd; + + printf("%s (%s):\n", device, filsys); + printf(" Blocks \\t User\n"); + + for (i=0; i < MAXUID; i++) { + if (blocks[i] == 0) + continue; + + /* + * Look up the login name, and use it if we find it. + */ + if ((pwd = getpwuid(i)) != NULL) + printf("%8d\\t%s\n", blocks[i], pwd->pw_name); + else + printf("%8d\\t#%d\n", blocks[i], i); + } +} + |