Add Book to My BookshelfPurchase This Book Online

Appendix B - Accessing Filesystem Data Structures

UNIX Systems Programming for SVR4
David A. Curry
 Copyright © 1996 O'Reilly & Associates, Inc.

Obtaining Filesystem Statistics
Several filesystem statistics are of interest to system administration programs, including the amount of space used or available in the filesystem, the number of files in the filesystem, and so forth. The statvfs and fstatvfs functions can be used to obtain this information:
    #include <sys/types.h>
    #include <sys/statvfs.h>
    int statvfs(const char *path, struct statvfs *stats);
    int fstatvfs(int fd, struct statvfs *stats);
The statvfs function obtains statistics about the filesystem in which the file named by path resides, and returns them in the area pointed to by stats. The fstatvfs function does the same thing, but uses a file descriptor instead of a pathname to refer to the file. Both functions return 0 on success; if an error occurs, -1 is returned and errno is set to indicate the error.
Both of these functions return statistics in a structure of type struct statvfs:
    typedef struct statvfs {
        u_long    f_bsize;
        u_long    f_frsize;
        u_long    f_blocks;
        u_long    f_bfree;
        u_long    f_bavail;
        u_long    f_files;
        u_long    f_ffree;
        u_long    f_favail;
        u_long    f_fsid;
        char      f_basetype[FSTYPSZ];
        u_long    f_flag;
        u_long    f_namemax;
        char      f_fstr[32];
        u_long    f_filler[16];
    } statvfs_t;
The fields of this structure are:
f_bsize
The preferred filesystem block size.
Reads and writes on the filesystem should use this block size for optimum performance.
f_frsize
The fundamental filesystem block size.
This is also called the fragment size. This is the smallest unit of disk space that can be consumed by a file (i.e., even if a file is smaller than this value, it consumes a block of this size on the disk).
f_blocks
The total number of blocks that can be used in the filesystem, in units of f_frsize.
f_bfree
The total number of free blocks in the filesystem.
f_bavail
The number of free blocks in the filesystem available to non-privileged processes.
The system reserves a small amount (usually ten percent) of the space for use only by the superuser.
f_files
The total number of files (i-nodes) that can be created in the filesystem.
This value is not available for filesystems mounted via NFS.
f_ffree
The total number of free files (i-nodes) in the filesystem.
This value is not available for filesystems mounted via NFS.
f_avail
The number of free files (i-nodes) in the filesystem available to non-privileged processes.
The system can reserve a small number of these for use only by the superuser, although this is rarely done. This value is not available for filesystems mounted via NFS.
f_fsid
A unique identifier for the filesystem.
f_basetype
The filesystem type name.
f_flag
A bit mask of flags.
Possible values are:
ST_RDONLY
The filesystem is read-only.
ST_NOSUID
The filesystem does not support set-user-id and set-group-id bit semantics.
ST_NOTRUNC
The filesystem does not truncate filenames longer than the maximum length.
f_namemax
The maximum length of a filename on this filesystem.
f_str
A filesystem specific string used only by the kernel.
Example B-1 shows a program that reads the mounted filesystem table and, for each filesystem, prints out the information stored for it in the table. It also looks up the filesystem in the filesystem defaults table and prints any information it finds there. Finally, it uses statvfs to obtain statistics about the filesystem, and prints them out.
Example B-1:  fsysinfo
#include <sys/types.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <sys/mnttab.h>
#include <sys/vfstab.h>
char    *mnttabFile = "/etc/mnttab";
char    *vfstabFile = "/etc/vfstab";
struct statvfs  *getfsInfo(char *);
struct mnttab   *getmnttabEntry(FILE *);
struct vfstab   *getvfstabEntry(FILE *, struct mnttab *);
int
main(void)
{
    time_t clock;
    struct mnttab *mnt;
    struct vfstab *vfs;
    struct statvfs *stats;
    FILE *mnttabFP, *vfstabFP;
    /*
     * Open the mounted file system table.
     */
    if ((mnttabFP = fopen(mnttabFile, "r")) == NULL) {
        perror(mnttabFile);
        exit(1);
    }
    /*
     * Open the file system defaults file.
     */
    if ((vfstabFP = fopen(vfstabFile, "r")) == NULL) {
        perror(vfstabFile);
        exit(1);
    }
    /*
     * For each file system...
     */
    while ((mnt = getmnttabEntry(mnttabFP)) != NULL) {
        /*
         * If it's not an "ignore" file system, look it
         * up in the defaults file and get its current
         * stats.
         */
        if (hasmntopt(mnt, "ignore") == 0) {
            vfs = getvfstabEntry(vfstabFP, mnt);
            stats = getfsInfo(mnt->mnt_mountp);
        }
        else {
            stats = NULL;
            vfs = NULL;
        }
        clock = atoi(mnt->mnt_time);
        /*
         * Print the mnttab structure.
         */
        printf("%s:\n", mnt->mnt_mountp);
        printf("  %s information:\n", mnttabFile);
        printf("    file system type:     %s\n", mnt->mnt_fstype);
        printf("    mounted on device:    %s\n", mnt->mnt_special);
        printf("    mounted with options: %s\n", mnt->mnt_mntopts);
        printf("    mounted since:        %s", ctime(&clock));
        /*
         * Print the vfstab structure.
         */
        if (vfs != NULL) {
            printf("  %s information:\n", vfstabFile);
            printf("    file system type:     %s\n",
                   vfs->vfs_fstype ? vfs->vfs_fstype : "");
            printf("    mount device:         %s\n",
                   vfs->vfs_special ? vfs->vfs_special : "");
            printf("    fsck device:          %s\n",
                   vfs->vfs_fsckdev ? vfs->vfs_fsckdev : "");
            printf("    fsck pass number:     %s\n",
                   vfs->vfs_fsckpass ? vfs->vfs_fsckpass : "");
            printf("    mount at boot time:   %s\n",
                   vfs->vfs_automnt ? vfs->vfs_automnt : "");
            printf("    mount with options:   %s\n",
                   vfs->vfs_mntopts ? vfs->vfs_mntopts : "");
        }
        /*
         * Print the statvfs structure.
         */
        if (stats != NULL) {
            printf("  statvfs information:\n");
            printf("    maximum name length:  %u\n", stats->f_namemax);
            printf("    preferred block size: %u\n", stats->f_bsize);
            printf("    fundam. block size:   %u\n", stats->f_frsize);
            printf("    total blocks:         %u\n", stats->f_blocks);
            printf("    total blocks free:    %u\n", stats->f_bfree);
            printf("    total blocks avail:   %u\n", stats->f_bavail);
            printf("    total files:          %u\n", stats->f_files);
            printf("    total files free:     %u\n", stats->f_ffree);
            printf("    total files avail:    %u\n", stats->f_favail);
        }
        putchar('\n');
    }
    /*
     * All done.
     */
    fclose(mnttabFP);
    fclose(vfstabFP);
    exit(0);
}
/*
* getmnttabEntry - read an entry from the mount table.
*/
struct mnttab *
getmnttabEntry(FILE *fp)
{
    int n;
    static int line = 0;
    static struct mnttab mnt;
    /*
     * Until we get a good entry...
     */
    for (;;) {
        /*
         * Read the next entry.
         */
        n = getmntent(fp, &mnt);
        line++;
        switch (n) {
        case 0:             /* okay             */
            return(&mnt);
        case -1:            /* end of file      */
            return(NULL);
        case MNT_TOOLONG:
            fprintf(stderr, "%s: %d: line too long.\n", mnttabFile, line);
            break;
        case MNT_TOOMANY:
            fprintf(stderr, "%s: %d: too many fields.\n", mnttabFile, line);
            break;
        case MNT_TOOFEW:
            fprintf(stderr, "%s: %d: not enough fields.\n", mnttabFile, line);
            break;
        }
    }
}
/*
* getvfstabEntry - look up the file system defaults for the file system
*          described by mnt.
*/
struct vfstab *
getvfstabEntry(FILE *fp, struct mnttab *mnt)
{
    struct vfstab vfsref;
    static struct vfstab vfs;
    /*
     * Have to rewind each time.
     */
    rewind(fp);
    /*
     * Zero out the reference structure.
     */
    memset((char *) &vfsref, 0, sizeof(struct vfstab));
    /*
     * Look for an entry that has the same special device,
     * mount point, and file system type.
     */
    vfsref.vfs_special = mnt->mnt_special;
    vfsref.vfs_mountp = mnt->mnt_mountp;
    vfsref.vfs_fstype = mnt->mnt_fstype;
    /*
     * Look it up.
     */
    if (getvfsany(fp, &vfs, &vfsref) == 0)
        return(&vfs);
    return(NULL);
}
/*
* getfsInfo - look up information about the file system.
*/
struct statvfs *
getfsInfo(char *filsys)
{
    static struct statvfs stats;
    if (statvfs(filsys, &stats) < 0) {
        perror(filsys);
        return(NULL);
    }
    return(&stats);
}
    % fsysinfo
    /:
      /etc/mnttab information:
        filesystem type:     ufs
        mounted on device:    /dev/dsk/c0t3d0s0
        mounted with options: rw,suid
        mounted since:        Mon Dec  5 09:05:28 1994
      /etc/vfstab information:
        filesystem type:     ufs
        mount device:         /dev/dsk/c0t3d0s0
        fsck device:          /dev/rdsk/c0t3d0s0
        fsck pass number:     1
        mount at boot time:   no
        mount with options:  
      statvfs information:
        maximum name length:  255
        preferred block size: 8192
        fundam. block size:   1024
        total blocks:         23063
        total blocks free:    7696
        total blocks avail:   5396
        total files:          13440
        total files free:     10936
        total files avail:    10936
   
    /usr:
      /etc/mnttab information:
        filesystem type:     ufs
        mounted on device:    /dev/dsk/c0t3d0s5
        mounted with options: rw,suid
        mounted since:        Mon Dec  5 09:05:28 1994
      /etc/vfstab information:
        filesystem type:     ufs
        mount device:         /dev/dsk/c0t3d0s5
        fsck device:          /dev/rdsk/c0t3d0s5
        fsck pass number:     2
        mount at boot time:   no
        mount with options:  
      statvfs information:
        maximum name length:  255
        preferred block size: 8192
        fundam. block size:   1024
        total blocks:         129775
        total blocks free:    15669
        total blocks avail:   2699
        total files:          64512
        total files free:     53128
        total files avail:    53128
   
    ·
    ·
    ·
   
    /vol:
      /etc/mnttab information:
        filesystem type:     nfs
        mounted on device:    msw:vold(pid174)
        mounted with options: ignore
        mounted since:        Mon Dec  5 09:06:33 1994

Previous SectionNext Section
Books24x7.com, Inc © 2000 –  Feedback