#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'di.c' <<'END_OF_FILE' X#ifndef lint Xstatic char di_c_sccsid [] = X"@(#)di.c 1.21"; Xstatic char di_c_rcsid [] = X"$Id$"; Xstatic char di_c_source [] = X"$Source$"; Xstatic char copyright [] = X"Copyright 1994-1999 Brad Lanam, Walnut Creek, CA"; X#endif X X/* X * di.c X * X * Copyright 1994-1999 Brad Lanam, Walnut Creek, CA X * X * Warning: Do not replace your systems 'df' command with this program. X * You will in all likelihood break your installation procedures. X * X * Usage: di -AafntwWx [file [...]] X * -A : print all fields (used for debugging) X * -a : print all mounted devices; normally, those X * with 0 total blocks are not printed. e.g. X * /dev/proc, /dev/fd. X * -d x : size to print blocks in (p, k, m, g, ) X * -f x : use format string X * -i x : ignore filesystem type(s) x, where x is a comma X * separated list. X * -I x : include only filesystem type(s) x, where x is a X * separated list. X * -l : local filesystems only X * -n : don't print header X * -s t : sort type X * -t : print totals X * -w n : use for the block print width (default 8). X * -W n : use for the inode print width (default 7). X * -x n : debug level X * X * All values are reported in K (1024 bytes). X * X * Sort types (by name is default): X * n - none (mount order) X * s - special X * r - reverse sort X * X * Format string values: X * m - mount point X * M - mount point, full length X * b - total kbytes X * B - total kbytes available for use by the user. X * [ (tot - (free - avail) ] X * u - kbytes used (actual number of kbytes used) [ (tot - free) ] X * c - calculated number of kbytes used [ (tot - avail) ] X * f - kbytes free X * v - kbytes available X * p - percentage not available for use. X * (number of blocks not available for use / total disk space) X * [ (tot - avail) / tot ] X * 1 - percentage used. X * (actual number of blocks used / total disk space) X * [ (tot - free) / tot ] X * 2 - percentage of user-available space in use (bsd style). X * Note that values over 100% are possible. X * (actual number of blocks used / disk space available to user) X * [ (tot - free) / (tot - (free - avail)) ] X * i - total i-nodes (files) X * U - used i-nodes X * F - free i-nodes X * P - percent i-nodes used [ (tot - avail) / tot ] X * s - filesystem name (special) X * S - filesystem name (special), full length X * t - disk partition type X * T - disk partition type (full length) X * I - mount time X * O - mount options. X * X * System V.4 `/usr/bin/df -v` Has format: msbuf1 (w/-d512 option: 512 byte blocks) X * System V.4 `/usr/bin/df -k` Has format: sbcvpm X * System V.4 `/usr/ucb/df` Has format: sbuv2m X * X * The default format string for this program is: smbuvpT X * X * The environment variable "DIFMT" may be set to the desired format X * string. X * X * Note that for filesystems that do not have (S512K fs) or systems (SysV.3) X * that do not report available blocks, the number of available blocks is X * equal to the number of free blocks. X * X * HISTORY: X * 24 feb 2000 bll X * Updated for BeOS. This required changes to support c++ X * compilation (ansi style functions). Fixes for linux. X * 17 dec 99 bll X * Added sys/fs_types.h (Digital Unix (tru64)). X * 3 jan 99 bll X * Finalize changes for metaconfig. X * Always get stat() for disk device. X * Remove duplicate disks from display. X * Add NetBSD, Unicos, IRIX changes X * 8 sep 97 bll X * Solaris large file version; AIX typo fix X * 15 aug 95 bll X * Ignore will check the file system type beforehand if possible. X * Fixed local mount stuff for osf1. X * 9 aug 95 bll X * Changed totals to use double; the totals can now be displayed with X * any wanted block size; sizes > one k have a single decimal point. X * -d option specifies block size. X * -l option for local file systems only. X * 7 aug 95 bll X * convex fix. X * 29 jul 95 bll X * Fixed bsdi variants. The fragment size wasn't being supported. X * 22 jul 95 bll X * fix problem with display widths in conjunction with ignore/include X * 20 feb 95 bll X * added ignore/include file system type lists. X * 8 jan 95 bll X * Added FreeBsd 2.x X * 6 dec 94 bll X * sco nfs 'nothing' fix. X * 28 nov 94 bll X * bsdi [bag@clipper.cs.kiev.ua (Andrey Blochintsev)] X * 24 nov 94 bll X * Added FreeBsd - like OSF/1, but w/o nice mount name table. X * 1 may 94 bll X * removed ill conceived mount options stuff. Added AIX X * (Erik O'Shaughnessy eriko@risc.austin.ibm.com). X * Added coherent. X * 9 apr 94 bll X * T format from Bill Davidsen. SunOS file system type. X * mount options. X * 7 apr 94 bll X * cdrom under solaris returning -1 in addition to -2. X * Changed the test to test for any negative value. X * 5 apr 94 pm X * Filesystem type info, and whether its read-write, readonly X * etc is in the mntent structure. Added code to support it. X * [Pat Myrto ] X * 25 mar 94 bll X * sun had f_bfree instead of f_bavail! X * Xenix, linux. X * -w, -W options, -B option, fixed width for -f M, -f S. X * Usage. Allow other characters in format string. X * 4 mar 94 bll X * -f B, bug fixes. bcopy. X * Solaris cdrom reports total, not free or avail. X * Allow command line specification of file names. X * 3 mar 94 bll X * support for OSF/1 and ULTRIX, -F, -f M, -f S X * [mogul@wrl.dec.com (Jeffrey Mogul)] X * 3 mar 94 bll X * Allow command line specification of filename (s). X * Sort output. Test of nonexistent return code removed. X * 1 mar 94 bll X * # of inodes can be -1L if unreportable. X * [jjb@jagware.bcc.com (J.J.Bailey)] X * [Mark Neale ] X * getDiskInfo () returning garbage X * [costales@ICSI.Berkeley.EDU (Bryan Costales)] X * [Mark Neale ] X * pyramid #ifdefs X * [vogelke@c-17igp.wpafb.af.mil (Contr Karl Vogel)] X * name must be maxpathlen X * [Mark Neale ] X * error prints/compile warnings. X * [Mark Neale ] X * X */ X X#include "config.h" X X#include X#include X#include X#if defined (I_STDLIB) X# include X#endif X#if defined (I_SYS_TYPES) X# include X#endif X#if defined (I_LIMITS) X# include X#endif X#if defined (I_STRING) X# include X#else X# include X#endif X#if defined (I_MEMORY) X# include X#endif X#if defined (I_MALLOC) X# include X#endif X#if defined (I_UNISTD) X# include X#endif X#if defined (I_TIME) X# include X#endif X#if defined (I_SYS_TIME) X# include X#endif X#if defined (I_SYS_STAT) X# include X#endif X#if defined (I_SYS_PARAM) X# include X#endif X X#if defined (I_SYS_MNTTAB) X# include X#endif X#if defined (I_MNTTAB) X# include X#endif X#if defined (I_MNTENT) X# include X#endif X#if defined (I_SYS_MNTENT) X# include X#endif X#if defined (I_SYS_MOUNT) X# include X#endif X#if defined (I_SYS_FSTYPES) X# include X#endif X#if defined (I_SYS_FS_TYPES) X# include X#endif X#if defined (I_SYS_MNTCTL) X# include X#endif X#if defined (I_SYS_VMOUNT) X# include X#endif X#if defined (I_SYS_STATFS) && ! defined (I_SYS_STATVFS) X# include X#endif X#if defined (I_FSHELP) X# include X#endif X#if defined (I_SYS_STATVFS) X# include X#endif X#if defined (I_SYS_FSTYP) X# include X# define DI_TYPE_LEN FSTYPSZ X#endif X#if defined (I_SYS_VFS) X# include X#endif X#if defined (I_SYS_VFSTAB) X# include X# if ! defined (DI_TYPE_LEN) X# define DI_TYPE_LEN FSTYPSZ X# endif X#endif X#if defined (I_FSHELP) X# include X#endif X X#if defined (I_WINDOWS) X# include /* windows */ X#endif X#if defined (I_KERNFSINFO) X# include X#endif X#if defined (I_STOR_DIRECTORY) X# include X#endif X#if defined (I_STOR_ENTRY) X# include X#endif X/*#if defined (I_STOR_NODE) X# include X#endif */ X#if defined (I_STOR_PATH) X# include X#endif X X#if ! defined (HAS_MEMCPY) && ! defined (memcpy) X# if ! defined (HAS_BCOPY) X error No memcpy/bcopy available. X# else X# define memcpy(dst, src, cnt) (bcopy((src), (dst), (cnt)), dst) X# endif X#endif X X#if ! defined (MAXPATHLEN) X# if defined (_POSIX_PATH_MAX) X# define MAXPATHLEN _POSIX_PATH_MAX X# else X# if defined (PATH_MAX) X# define MAXPATHLEN PATH_MAX X# endif X# if defined (LPNMAX) X# define MAXPATHLEN LPNMAX X# endif X# endif X#endif X X#if ! defined (DI_TYPE_LEN) X# define DI_TYPE_LEN 16 X#endif X X#define DI_FSMAGIC 5 /* base AIX configuration has 5 file systems */ X X#if defined (HAS_STATFS_SYSV3) && ! defined (HAS_STATVFS) && \ X ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT) /* SYSV.3 */ X# if defined (Ubsize) && Ubsize != "" X# define UBSIZE Ubsize X# endif X# if ! defined (UBSIZE) X# define UBSIZE 512 X# endif X#endif X X#if (defined (HAS_GETMNTENT) || defined (HAS_STATFS_BSD) || \ X defined (HAS_STATFS_SYSV3)) && ! defined (HAS_GETMNTINFO) && \ X ! defined (HAS_GETMNT) X# if defined (MOUNTED) X# define DI_MOUNT_FILE MOUNTED X# else X# if defined (MNTTAB) X# define DI_MOUNT_FILE MNTTAB X# else X# define DI_MOUNT_FILE "/etc/mnttab" X# endif X# endif X#endif X X#if ! defined (HAS_MEMSET) && ! defined (memset) X# if ! defined (HAS_BZERO) X error No memset/bzero available. X# else X# define memset(s,c,n) (bzero ((s), (n)), s) X# endif X#endif X X#if defined (NEED_GETENV_DEF) X extern char *getenv _((char *)); X#endif X X#if defined (NEED_STATFS_DEFS) X extern int statfs _((char *, struct statfs *)); X#endif X X#if defined (NEED_ERRNO_DEFS) Xextern int errno; X#endif X X#if (defined (_LARGEFILE_SOURCE) || defined (_LARGEFILE64_SOURCE)) && \ X _FILE_OFFSET_BITS == 64 X# define HAS_64BIT_STATFS_FLDS 1 X#endif X X#if defined (HAS_64BIT_STATFS_FLDS) Xtypedef unsigned long long _fs_size_t; Xtypedef long long _s_fs_size_t; X#else Xtypedef unsigned long _fs_size_t; Xtypedef long _s_fs_size_t; X#endif X X#if ! defined (HAS_OPTIND) X extern int optind; X extern char *optarg; X#endif X X/* end of system specific includes/configurations */ X X#if ! defined (TRUE) X# define TRUE 1 X#endif X#if ! defined (FALSE) X# define FALSE 0 X#endif X X#define DI_F_ALL 0x00000001 X#define DI_F_LOCAL_ONLY 0x00000002 X#define DI_F_TOTAL 0x00000010 X#define DI_F_NO_HEADER 0x00000020 X#define DI_F_DEBUG_HDR 0x00000040 X X /* mount information */ X#define DI_FMT_MOUNT 'm' X#define DI_FMT_MOUNT_FULL 'M' X#define DI_FMT_SPECIAL 's' X#define DI_FMT_SPECIAL_FULL 'S' X#define DI_FMT_TYPE 't' X#define DI_FMT_TYPE_FULL 'T' X X /* disk information */ X#define DI_FMT_BTOT 'b' X#define DI_FMT_BTOT_AVAIL 'B' X#define DI_FMT_BUSED 'u' X#define DI_FMT_BCUSED 'c' X#define DI_FMT_BFREE 'f' X#define DI_FMT_BAVAIL 'v' X#define DI_FMT_BPERC_AVAIL 'p' X#define DI_FMT_BPERC_FREE '1' X#define DI_FMT_BPERC_BSD '2' X#define DI_FMT_ITOT 'i' X#define DI_FMT_IUSED 'U' X#define DI_FMT_IFREE 'F' X#define DI_FMT_IPERC 'P' X#define DI_FMT_MOUNT_TIME 'I' X#define DI_FMT_MOUNT_OPTIONS 'O' X X#define DI_IGNORE 0 X#define DI_OK 1 X#define DI_BAD 2 X X#define DI_SORT_NONE 0 X#define DI_SORT_NAME 1 X#define DI_SORT_SPECIAL 2 X X#define DI_SORT_ASCENDING 1 X#define DI_SORT_DESCENDING -1 X X#define DI_UNKNOWN_DEV -1L X#define DI_LIST_SEP "," X X#define DI_ALL_FORMAT "MTS\n\tIO\n\tbuf1\n\tbcvp\n\tBuv2\n\tiUFP" X X#define DI_HALF_K 512.0 X#define DI_ONE_K 1024.0 X#define DI_ONE_MEG 1048576.0 X#define DI_ONE_GIG 1073241824.0 X X#if ! defined (MAXPATHLEN) X# define MAXPATHLEN 255 X#endif X#define DI_SPEC_NAME_LEN MAXPATHLEN X#define DI_OPT_LEN MAXPATHLEN X#define DI_MNT_TIME_LEN 24 X X#define DI_RETRY_COUNT 5 X#define DI_MAX_REMOTE_TYPES 20 X X /* you may want to change some of these values. Be sure to change all */ X /* related entries. */ X/* #define DI_DEFAULT_FORMAT "mbuvpiUFP" */ X#if ! defined (DI_DEFAULT_FORMAT) X# define DI_DEFAULT_FORMAT "smbuvpT" X#endif X#if defined (HAS_MNT_TIME) X# define DI_DEF_MOUNT_FORMAT "MSTIO" X#else X# define DI_DEF_MOUNT_FORMAT "MSTO" X#endif X#define DI_PERC_FMT "%3.0f%% " X#define DI_PERC_LBL_FMT "%5s" X#define DI_NAME_LEN MAXPATHLEN X#define DI_FSTYPE_FMT "%-7.7s" X#define DI_MOUNT_FMT "%-15.15s" X#define DI_SPEC_FMT "%-18.18s" X X#define DI_UNKNOWN_FSTYPE "Unknown fstyp %.2d" X Xtypedef unsigned long _ulong; Xtypedef int (*DI_SORT_FUNC) _((char *, char *)); X Xtypedef struct X{ X double totalBlocks; X double freeBlocks; X double availBlocks; X _fs_size_t totalInodes; X _fs_size_t freeInodes; X _fs_size_t availInodes; X _ulong st_dev; /* disk device number */ X _ulong sp_dev; /* special device number*/ X _ulong sp_rdev; /* special rdev # */ X char printFlag; /* do we want to print */ X /* this entry? */ X char isLocal; /* is this mount point */ X /* local? */ X char name [DI_NAME_LEN + 1]; /* mount point */ X char special [DI_SPEC_NAME_LEN + 1]; /* special device name */ X char fsType [DI_TYPE_LEN + 1]; /* type of file system */ X char options [DI_OPT_LEN + 1]; X char mountTime [DI_MNT_TIME_LEN + 1]; X} DiskInfo; X Xstatic DiskInfo *diskInfo = { (DiskInfo *) NULL }; Xstatic int diCount = { 0 }; Xstatic int debug = { 0 }; Xstatic _ulong flags = { 0 }; Xstatic int sortType = { DI_SORT_NAME }; Xstatic int sortOrder = { DI_SORT_ASCENDING }; Xstatic char *formatString = { DI_DEFAULT_FORMAT }; Xstatic char mountFormat [20]; X static char specialFormat [20]; Xstatic char typeFormat [20]; Xstatic char optFormat [20]; Xstatic char mTimeFormat [20]; Xstatic int width = { 8 }; Xstatic int inodeWidth = { 7 }; Xstatic char blockFormat [20]; Xstatic char blockLabelFormat [20]; Xstatic char inodeFormat [20]; Xstatic char inodeLabelFormat [20]; Xstatic char **ignoreList = { (char **) NULL }; Xstatic char **includeList = { (char **) NULL }; Xstatic double dispBlockSize = { DI_ONE_MEG }; Xstatic int remoteFileSystemCount = { 0 }; Xstatic char remoteFileSystemTypes [DI_MAX_REMOTE_TYPES][DI_TYPE_LEN]; X X Xstatic void cleanup _((void)); Xstatic void printDiskInfo _((void)); Xstatic void printInfo _((DiskInfo *)); Xstatic void addTotals _((DiskInfo *, DiskInfo *)); Xstatic void printTitle _((void)); Xstatic void printPerc _((double, double, char *)); Xstatic char *Realloc _((char *, long)); Xstatic void sortArray _((char *, int, int, DI_SORT_FUNC)); Xstatic int diCompare _((char *, char *)); Xstatic void getDiskStatInfo _((void)); Xstatic void getDiskSpecialInfo _((void)); Xstatic void printFileInfo _((int, int, char *[])); Xstatic void checkDiskInfo _((void)); Xstatic void usage _((void)); Xstatic void processArgs _((int, char *[])); Xstatic void parseList _((char ***, char *)); Xstatic void checkIgnoreList _((DiskInfo *)); Xstatic void checkIncludeList _((DiskInfo *)); X Xstatic int getDiskEntries _((void)); Xstatic void getDiskInfo _((void)); X Xint X#if defined (CAN_PROTOTYPE) Xmain (int argc, char *argv []) X#else Xmain (argc, argv) X int argc; X char *argv []; X#endif X{ X char *ptr; X X X ptr = argv [0] + strlen (argv [0]) - 2; X if (memcmp (ptr, MPROG, 2) == 0) X { X formatString = DI_DEF_MOUNT_FORMAT; X } X else /* don't use DIFMT env var if running mi. */ X { X if ((ptr = getenv ("DIFMT")) != (char *) NULL) X { X formatString = ptr; X } X } X X processArgs (argc, argv); X if (debug > 0) X { X printf ("di ver $Revision$\n"); X } X X if (getDiskEntries () < 0) X { X cleanup (); X exit (1); X } X X getDiskInfo (); X getDiskSpecialInfo (); X checkDiskInfo (); X if (optind < argc) X { X getDiskStatInfo (); X printFileInfo (optind, argc, argv); X } X else X { X printDiskInfo (); X } X X cleanup (); X exit (0); X} X X/* X * cleanup X * X * free up allocated memory X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) Xcleanup (void) X#else Xcleanup () X#endif X{ X char **lptr; X X X if (diskInfo != (DiskInfo *) NULL) X { X free ((char *) diskInfo); X } X X if (ignoreList != (char **) NULL) X { X lptr = ignoreList; X while (*lptr != (char *) NULL) X { X free ((char *) *lptr); X ++lptr; X } X free ((char *) ignoreList); X } X X if (includeList != (char **) NULL) X { X lptr = includeList; X while (*lptr != (char *) NULL) X { X free ((char *) *lptr); X ++lptr; X } X free ((char *) includeList); X } X} X X/* X * printDiskInfo X * X * Print out the disk information table. X * Loops through all mounted disks, prints and calculates totals. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XprintDiskInfo (void) X#else XprintDiskInfo () X#endif X{ X int i; X DiskInfo totals; X X X memset ((char *) &totals, '\0', sizeof (DiskInfo)); X strcpy (totals.name, "Total"); X totals.printFlag = DI_OK; X X if ((flags & DI_F_NO_HEADER) != DI_F_NO_HEADER) X { X printTitle (); X } X X if (sortType != DI_SORT_NONE) X { X sortArray ((char *) diskInfo, sizeof (DiskInfo), diCount, diCompare); X } X X for (i = 0; i < diCount; ++i) X { X if (( (flags & DI_F_ALL) == DI_F_ALL && X diskInfo [i].printFlag != DI_BAD) || X diskInfo [i].printFlag == DI_OK) X { X printInfo (&diskInfo [i]); X addTotals (&diskInfo [i], &totals); X } X } X X if ((flags & DI_F_TOTAL) == DI_F_TOTAL && X (flags & DI_F_NO_HEADER) != DI_F_NO_HEADER) X { X printInfo (&totals); X } X} X X/* X * printInfo X * X * Print the information for a single partition. Loop through the X * format string and print the particular items wanted. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XprintInfo (DiskInfo *diskInfo) X#else XprintInfo (diskInfo) X DiskInfo *diskInfo; X#endif X{ X double used; X double totAvail; X char *ptr; X int valid; X X X ptr = formatString; X while (*ptr) X { X valid = TRUE; X X switch (*ptr) X { X case DI_FMT_MOUNT: X { X printf (DI_MOUNT_FMT, diskInfo->name); X break; X } X X case DI_FMT_MOUNT_FULL: X { X printf (mountFormat, diskInfo->name); X break; X } X X case DI_FMT_BTOT: X { X printf (blockFormat, diskInfo->totalBlocks); X break; X } X X case DI_FMT_BTOT_AVAIL: X { X printf (blockFormat, diskInfo->totalBlocks - X (diskInfo->freeBlocks - diskInfo->availBlocks)); X break; X } X X case DI_FMT_BUSED: X { X printf (blockFormat, diskInfo->totalBlocks - X diskInfo->freeBlocks); X break; X } X X case DI_FMT_BCUSED: X { X printf (blockFormat, diskInfo->totalBlocks - diskInfo->availBlocks); X break; X } X X case DI_FMT_BFREE: X { X printf (blockFormat, diskInfo->freeBlocks); X break; X } X X case DI_FMT_BAVAIL: X { X printf (blockFormat, diskInfo->availBlocks); X break; X } X X case DI_FMT_BPERC_AVAIL: X { X used = diskInfo->totalBlocks - diskInfo->availBlocks; X totAvail = diskInfo->totalBlocks; X printPerc (used, totAvail, DI_PERC_FMT); X break; X } X X case DI_FMT_BPERC_FREE: X { X used = diskInfo->totalBlocks - diskInfo->freeBlocks; X totAvail = diskInfo->totalBlocks; X printPerc (used, totAvail, DI_PERC_FMT); X break; X } X X case DI_FMT_BPERC_BSD: X { X used = diskInfo->totalBlocks - diskInfo->freeBlocks; X totAvail = diskInfo->totalBlocks - X (diskInfo->freeBlocks - diskInfo->availBlocks); X printPerc (used, totAvail, DI_PERC_FMT); X break; X } X X case DI_FMT_ITOT: X { X printf (inodeFormat, diskInfo->totalInodes); X break; X } X X case DI_FMT_IUSED: X { X printf (inodeFormat, diskInfo->totalInodes - diskInfo->freeInodes); X break; X } X X case DI_FMT_IFREE: X { X printf (inodeFormat, diskInfo->freeInodes); X break; X } X X case DI_FMT_IPERC: X { X used = diskInfo->totalInodes - diskInfo->availInodes; X totAvail = diskInfo->totalInodes; X printPerc (used, totAvail, DI_PERC_FMT); X break; X } X X case DI_FMT_SPECIAL: X { X printf (DI_SPEC_FMT, diskInfo->special); X break; X } X X case DI_FMT_SPECIAL_FULL: X { X printf (specialFormat, diskInfo->special); X break; X } X X case DI_FMT_TYPE: X { X printf (DI_FSTYPE_FMT, diskInfo->fsType); X break; X } X X case DI_FMT_TYPE_FULL: X { X printf (typeFormat, diskInfo->fsType); X break; X } X X case DI_FMT_MOUNT_OPTIONS: X { X printf (optFormat, diskInfo->options); X break; X } X X case DI_FMT_MOUNT_TIME: X { X#if defined (HAS_MNT_TIME) X printf (mTimeFormat, diskInfo->mountTime); X#endif X break; X } X X default: X { X printf ("%c", *ptr); X valid = FALSE; X break; X } X } X X ++ptr; X if (*ptr && valid) X { X printf (" "); X } X } X X printf ("\n"); X} X X/* X * addTotals X * X * Add up the totals for the blocks/inodes X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XaddTotals (DiskInfo *diskInfo, DiskInfo *totals) X#else XaddTotals (diskInfo, totals) X DiskInfo *diskInfo; X DiskInfo *totals; X#endif X{ X totals->totalBlocks += diskInfo->totalBlocks; X totals->freeBlocks += diskInfo->freeBlocks; X totals->availBlocks += diskInfo->availBlocks; X totals->totalInodes += diskInfo->totalInodes; X totals->freeInodes += diskInfo->freeInodes; X totals->availInodes += diskInfo->availInodes; X} X X/* X * printTitle X * X * Loop through the format string and print the appropriate headings. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XprintTitle (void) X#else XprintTitle () X#endif X{ X char *ptr; X int valid; X char tbuff [20]; X X if ((flags & DI_F_DEBUG_HDR) == DI_F_DEBUG_HDR) X { X printf ("di ver $Revision$ Default Format: %s\n", X DI_DEFAULT_FORMAT); X } X X ptr = formatString; X X while (*ptr) X { X valid = TRUE; X X switch (*ptr) X { X case DI_FMT_MOUNT: X { X printf (DI_MOUNT_FMT, "Mount"); X break; X } X X case DI_FMT_MOUNT_FULL: X { X printf (mountFormat, "Mount"); X break; X } X X case DI_FMT_BTOT: X case DI_FMT_BTOT_AVAIL: X { X if (dispBlockSize == DI_ONE_K) X { X printf (blockLabelFormat, "Kbytes"); X } X else if (dispBlockSize == DI_ONE_MEG) X { X printf (blockLabelFormat, " Megs"); X } X else if (dispBlockSize == DI_ONE_GIG) X { X printf (blockLabelFormat, " Gigs"); X } X else if (dispBlockSize == DI_HALF_K) X { X printf (blockLabelFormat, " 512b"); X } X else X { X sprintf (tbuff, "%6.0f", dispBlockSize); X printf (blockLabelFormat, tbuff); X } X break; X } X X case DI_FMT_BUSED: X case DI_FMT_BCUSED: X { X printf (blockLabelFormat, "Used"); X break; X } X X case DI_FMT_BFREE: X { X printf (blockLabelFormat, "Free"); X break; X } X X case DI_FMT_BAVAIL: X { X printf (blockLabelFormat, "Avail"); X break; X } X X case DI_FMT_BPERC_AVAIL: X case DI_FMT_BPERC_FREE: X case DI_FMT_BPERC_BSD: X { X printf (DI_PERC_LBL_FMT, "%used"); X break; X } X X case DI_FMT_ITOT: X { X printf (inodeLabelFormat, "Inodes"); X break; X } X X case DI_FMT_IUSED: X { X printf (inodeLabelFormat, "Used"); X break; X } X X case DI_FMT_IFREE: X { X printf (inodeLabelFormat, "Free"); X break; X } X X case DI_FMT_IPERC: X { X printf (DI_PERC_LBL_FMT, "%used"); X break; X } X X case DI_FMT_SPECIAL: X { X printf (DI_SPEC_FMT, "Filesystem"); X break; X } X X case DI_FMT_SPECIAL_FULL: X { X printf (specialFormat, "Filesystem"); X break; X } X X case DI_FMT_TYPE: X { X printf (DI_FSTYPE_FMT, "fsType"); X break; X } X X case DI_FMT_TYPE_FULL: X { X printf (typeFormat, "fs Type"); X break; X } X X case DI_FMT_MOUNT_OPTIONS: X { X printf (optFormat, "Options"); X break; X } X X case DI_FMT_MOUNT_TIME: X { X#if defined (HAS_MNT_TIME) X printf (mTimeFormat, "Mount Time"); X#endif X break; X } X X default: X { X printf ("%c", *ptr); X valid = FALSE; X break; X } X } X X ++ptr; X if (*ptr && valid) X { X printf (" "); X } X } X X printf ("\n"); X} X X/* X * printPerc X * X * Calculate and print a percentage using the values and format passed. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XprintPerc (double used, double totAvail, char *format) X#else XprintPerc (used, totAvail, format) X double used; X double totAvail; X char *format; X#endif X{ X double perc; X X X if (totAvail > 0.0) X { X perc = used / totAvail; X perc *= 100.0; X } X else X { X perc = 0.0; X } X printf (format, perc); X} X X X/* X * Realloc X * X * portable realloc X * X */ X Xstatic char * X#if defined (CAN_PROTOTYPE) XRealloc (char *ptr, long size) X#else XRealloc (ptr, size) X char *ptr; X long size; X#endif X{ X if (ptr == (char *) NULL) X { X ptr = (char *) malloc (size); X } X else X { X ptr = (char *) realloc (ptr, size); X } X X return ptr; X} X X Xstatic void X#if defined (CAN_PROTOTYPE) XprintFileInfo (int optind, int argc, char *argv []) X#else XprintFileInfo (optind, argc, argv) X int optind; X int argc; X char *argv []; X#endif X{ X int i; X int j; X struct stat statBuf; X DiskInfo totals; X X X memset ((char *) &totals, '\0', sizeof (DiskInfo)); X strcpy (totals.name, "Total"); X totals.printFlag = DI_OK; X X if ((flags & DI_F_NO_HEADER) != DI_F_NO_HEADER) X { X printTitle (); X } X X for (i = optind; i < argc; ++i) X { X if (stat (argv [i], &statBuf) == 0) X { X for (j = 0; j < diCount; ++j) X { X if (diskInfo [j].printFlag != DI_BAD && X diskInfo [j].st_dev != DI_UNKNOWN_DEV && X (_ulong) statBuf.st_dev == diskInfo [j].st_dev) X { X printInfo (&diskInfo [j]); X addTotals (&diskInfo [j], &totals); X break; /* out of inner for */ X } X } X } /* if stat ok */ X else X { X fprintf (stderr, "stat: %s ", argv[i]); X perror (""); X } X } /* for each file specified on command line */ X X if ((flags & DI_F_TOTAL) == DI_F_TOTAL && (flags & DI_F_NO_HEADER) != DI_F_NO_HEADER) X { X printInfo (&totals); X } X} X X/* X * sortArray () X * X * shellsort! X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XsortArray (char *data, int dataSize, int count, DI_SORT_FUNC compareFunc) X#else XsortArray (data, dataSize, count, compareFunc) X char *data; X int dataSize; X int count; X DI_SORT_FUNC compareFunc; X#endif X{ X register int j; X char *tempData; X int i; X int gap; X X X if (count <= 1) X { X return; X } X X tempData = (char *) malloc ((unsigned) dataSize); X if (tempData == (char *) NULL) X { X fprintf (stderr, "malloc failed in sortArray(). errno %d\n", errno); X cleanup (); X exit (1); X } X X gap = 1; X while (gap < count) X { X gap = 3 * gap + 1; X } X X for (gap /= 3; gap > 0; gap /= 3) X { X for (i = gap; i < count; ++i) X { X memcpy ((char *) tempData, (char *) &(data [i * dataSize]), X dataSize); X j = i - gap; X X while (j >= 0 && X compareFunc (&(data [j * dataSize]), tempData) > 0) X { X memcpy ((char *) &(data [(j + gap) * dataSize]), X (char *) &(data [j * dataSize]), dataSize); X j -= gap; X } X X j += gap; X if (j != i) X { X memcpy ((char *) &(data [j * dataSize]), X (char *) tempData, dataSize); X } X } X } X X free ((char *) tempData); X} X X Xstatic int X#if defined (CAN_PROTOTYPE) XdiCompare (char *a, char *b) X#else XdiCompare (a, b) X char *a; X char *b; X#endif X{ X DiskInfo *di1; X DiskInfo *di2; X X X di1 = (DiskInfo *) a; X di2 = (DiskInfo *) b; X X X switch (sortType) X { X case DI_SORT_NONE: X { X break; X } X X case DI_SORT_NAME: X { X return (strcmp (di1->name, di2->name) * sortOrder); X } X X case DI_SORT_SPECIAL: X { X return (strcmp (di1->special, di2->special) * sortOrder); X } X } /* switch on sort type */ X X return 0; X} X X X/* X * getDiskStatInfo X * X * gets the disk device number for each entry. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XgetDiskStatInfo (void) X#else XgetDiskStatInfo () X#endif X{ X int i; X struct stat statBuf; X X for (i = 0; i < diCount; ++i) X { X diskInfo [i].st_dev = (_ulong) DI_UNKNOWN_DEV; X X if (stat (diskInfo [i].name, &statBuf) == 0) X { X diskInfo [i].st_dev = (_ulong) statBuf.st_dev; X if (debug > 2) X { X printf ("dev: %s: %ld\n", diskInfo [i].name, X diskInfo [i].st_dev); X } X } X else X { X fprintf (stderr, "stat: %s ", diskInfo [i].name); X perror (""); X } X } X} X X/* X * getDiskSpecialInfo X * X * gets the disk device number for each entry. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XgetDiskSpecialInfo (void) X#else XgetDiskSpecialInfo () X#endif X{ X int i; X struct stat statBuf; X X for (i = 0; i < diCount; ++i) X { X if (stat (diskInfo [i].special, &statBuf) == 0) X { X diskInfo [i].sp_dev = (_ulong) statBuf.st_dev; X diskInfo [i].sp_rdev = (_ulong) statBuf.st_rdev; X if (debug > 2) X { X printf ("special dev: %s: %ld rdev: %ld\n", diskInfo [i].special, X diskInfo [i].sp_dev, diskInfo [i].sp_rdev); X } X } X else X { X diskInfo [i].sp_dev = 0; X diskInfo [i].sp_rdev = 0; X } X } X} X X/* X * checkDiskInfo X * X * checks the disk information returned for various return values. X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) XcheckDiskInfo (void) X#else XcheckDiskInfo () X#endif X{ X int i; X int j; X int dupCount; X int len; X int maxMountString; X int maxSpecialString; X int maxTypeString; X int maxOptString; X int maxMntTimeString; X _fs_size_t temp; X _ulong sp_dev; X _ulong sp_rdev; X X X maxMountString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 5; X maxSpecialString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 10; X maxTypeString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 7; X maxOptString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 7; X maxMntTimeString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 26; X X for (i = 0; i < diCount; ++i) X { X /* Solaris reports a cdrom as having no free blocks, */ X /* no available. Their df doesn't always work right! */ X /* -1 is returned. */ X if (debug > 2) X { X printf ("chk: %s free: %f\n", diskInfo [i].name, X diskInfo [i].freeBlocks); X } X if (diskInfo [i].freeBlocks < 0.0) X { X diskInfo [i].freeBlocks = 0.0; X } X if (diskInfo [i].availBlocks < 0.0) X { X diskInfo [i].availBlocks = 0.0; X } X X temp = ~ 0; X if (diskInfo [i].totalInodes == temp) X { X diskInfo [i].totalInodes = 0; X diskInfo [i].freeInodes = 0; X diskInfo [i].availInodes = 0; X } X X if (debug > 2) X { X printf ("chk: %s total: %f\n", diskInfo [i].name, X diskInfo [i].totalBlocks); X } X if (diskInfo [i].totalBlocks <= 0.0 && X diskInfo [i].printFlag != DI_BAD) X { X diskInfo [i].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("chk: ignore: totalBlocks <= 0: %s\n", X diskInfo [i].name); X } X } X X checkIgnoreList (&diskInfo [i]); X checkIncludeList (&diskInfo [i]); X } /* for all disks */ X X /* this loop sets duplicate entries to be ignored. */ X for (i = 0; i < diCount; ++i) X { X /* don't need to bother checking real partitions */ X /* don't bother if already ignored */ X if (diskInfo [i].sp_rdev != 0 && X (diskInfo [i].printFlag == DI_OK || X ((flags & DI_F_ALL) == DI_F_ALL && X diskInfo [i].printFlag != DI_BAD))) X { X sp_dev = diskInfo [i].sp_dev; X sp_rdev = diskInfo [i].sp_rdev; X dupCount = 0; X X for (j = 0; j < diCount; ++j) X { X if (diskInfo [j].sp_dev == sp_rdev) X { X ++dupCount; X } X } X X if (debug > 2) X { X printf ("dup: chk: %s %ld %ld dup: %d\n", diskInfo [i].name, X sp_dev, sp_rdev, dupCount); X } X X for (j = 0; dupCount > 0 && j < diCount; ++j) X { X if (diskInfo [j].sp_rdev == 0 && X diskInfo [j].sp_dev == sp_rdev) X { X diskInfo [j].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("chk: ignore: duplicate: %s\n", X diskInfo [j].name); X } X } X } /* duplicate check for each disk */ X } /* if this is a printable disk */ X else X { X if (debug > 2) X { X printf ("chk: dup: not checked: %s prnt: %d dev: %ld rdev: %ld\n", X diskInfo [i].name, diskInfo [i].printFlag, X diskInfo [i].sp_dev, diskInfo [i].sp_rdev); X } X } X } /* for each disk */ X X /* this loop gets the max string lengths */ X for (i = 0; i < diCount; ++i) X { X if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL) X { X len = strlen (diskInfo [i].name); X if (len > maxMountString) X { X maxMountString = len; X } X X len = strlen (diskInfo [i].special); X if (len > maxSpecialString) X { X maxSpecialString = len; X } X X len = strlen (diskInfo [i].fsType); X if (len > maxTypeString) X { X maxTypeString = len; X } X X len = strlen (diskInfo [i].options); X if (len > maxOptString) X { X maxOptString = len; X } X X len = strlen (diskInfo [i].mountTime); X if (len > maxMntTimeString) X { X maxMntTimeString = len; X } X } /* if we are printing this item */ X } /* for all disks */ X X sprintf (mountFormat, "%%-%d.%ds", maxMountString, maxMountString); X sprintf (specialFormat, "%%-%d.%ds", maxSpecialString, X maxSpecialString); X sprintf (typeFormat, "%%-%d.%ds", maxTypeString, maxTypeString); X sprintf (optFormat, "%%-%d.%ds", maxOptString, maxOptString); X sprintf (mTimeFormat, "%%-%d.%ds", maxMntTimeString, maxMntTimeString); X X if (dispBlockSize <= DI_ONE_K) X { X sprintf (blockFormat, "%%%d.0f", width); X } X else X { X sprintf (blockFormat, "%%%d.1f", width); X } X sprintf (blockLabelFormat, "%%%ds", width); X#if defined (HAS_64BIT_STATFS_FLDS) X sprintf (inodeFormat, "%%%dllu", inodeWidth); X#else X sprintf (inodeFormat, "%%%dlu", inodeWidth); X#endif X sprintf (inodeLabelFormat, "%%%ds", inodeWidth); X} X X/* X * usage X * X */ X Xstatic void X#if defined (CAN_PROTOTYPE) Xusage (void) X#else Xusage () X#endif X{ X printf ("di ver $Revision$ Default Format: %s\n", DI_DEFAULT_FORMAT); X /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ X printf ("Usage: di [-ant] [-f format] [-s sort-type] [-i ignore-fstyp-list]\n"); X printf (" [-I include-fstyp-list] [-w kbyte-width] [-W inode-width] [file [...]]\n"); X printf (" -a : print all mounted devices; normally, those with 0 total blocks are\n"); X printf (" not printed. e.g. /dev/proc, /dev/fd.\n"); X printf (" -d x : size to print blocks in (p - posix (512), k - kbytes,\n"); X printf (" m - megabytes, g - gigabytes, - numeric size).\n"); X printf (" -f x : use format string \n"); X printf (" -i x : ignore file system types in \n"); X printf (" -I x : include only file system types in \n"); X printf (" -l : display local filesystems only\n"); X printf (" -n : don't print header\n"); X printf (" -s t : sort type; n - no sort, s - by special device, r - reverse\n"); X printf (" -t : print totals\n"); X printf (" -w n : use width for kbytes\n"); X printf (" -W n : use width for i-nodes\n"); X printf (" Format string values:\n"); X printf (" m - mount point M - mount point, full length\n"); X printf (" b - total kbytes B - kbytes available for use\n"); X printf (" u - used kbytes c - calculated kbytes in use\n"); X printf (" f - kbytes free v - kbytes available\n"); X printf (" p - percentage not avail. for use 1 - percentage used\n"); X printf (" 2 - percentage of user-available space in use.\n"); X printf (" i - total file slots (i-nodes) U - used file slots\n"); X printf (" F - free file slots P - percentage file slots used\n"); X printf (" s - filesystem name S - filesystem name, full length\n"); X printf (" t - disk partition type T - partition type, full length\n"); X} X X Xstatic void X#if defined (CAN_PROTOTYPE) XprocessArgs (int argc, char *argv []) X#else XprocessArgs (argc, argv) X int argc; X char *argv []; X#endif X{ X int ch; X X X while ((ch = getopt (argc, argv, "Aad:f:hi:I:Flns:tw:W:x:")) != -1) X { X switch (ch) X { X case 'A': X { X formatString = DI_ALL_FORMAT; X flags |= DI_F_ALL | DI_F_DEBUG_HDR | DI_F_TOTAL; X flags &= ~ DI_F_NO_HEADER; X width = 10; X inodeWidth = 10; X break; X } X X case 'a': X { X flags |= DI_F_ALL; X break; X } X X case 'd': X { X switch (tolower (*optarg)) X { X case 'p': X { X dispBlockSize = DI_HALF_K; X break; X } X X case 'k': X { X dispBlockSize = DI_ONE_K; X break; X } X X case 'm': X { X dispBlockSize = DI_ONE_MEG; X break; X } X X case 'g': X { X dispBlockSize = DI_ONE_GIG; X break; X } X X default: X { X if (isdigit ((int) (*optarg))) X { X dispBlockSize = atof (optarg); X } X break; X } X } X break; X } X X case 'f': X { X formatString = optarg; X break; X } X X case 'h': X { X usage (); X cleanup (); X exit (0); X } X X case 'i': X { X parseList (&ignoreList, optarg); X break; X } X X case 'I': X { X parseList (&includeList, optarg); X break; X } X X case 'l': X { X flags |= DI_F_LOCAL_ONLY; X break; X } X X case 'n': X { X flags |= DI_F_NO_HEADER; X break; X } X X case 's': X { X switch (ch) X { X case 's': X { X sortType = DI_SORT_SPECIAL; X break; X } X X case 'n': X { X sortType = DI_SORT_NONE; X break; X } X X case 'r': X { X sortOrder = DI_SORT_DESCENDING; X break; X } X } X break; X } X X case 't': X { X flags |= DI_F_TOTAL; X break; X } X X case 'w': X { X width = atoi (optarg); X break; X } X X case 'W': X { X inodeWidth = atoi (optarg); X break; X } X X case 'x': X { X debug = atoi (optarg); X break; X } X X case '?': X { X usage (); X cleanup (); X exit (1); X } X } X } X} X X /* list is assumed to be global */ Xstatic void X#if defined (CAN_PROTOTYPE) XparseList (char ***list, char *str) X#else XparseList (list, str) X char ***list; X char *str; X#endif X{ X char *dstr; X char *ptr; X char **lptr; X int count; X int i; X int len; X X i = strlen (str); X dstr = (char *) malloc (i + 1); X if (dstr == (char *) NULL) X { X fprintf (stderr, "malloc failed in parseList() (1). errno %d\n", errno); X cleanup (); X exit (1); X } X X memcpy (dstr, str, i + 1); X X ptr = strtok (dstr, DI_LIST_SEP); X count = 0; X while (ptr != (char *) NULL) X { X ++count; X ptr = strtok ((char *) NULL, DI_LIST_SEP); X } X X *list = (char **) malloc ((count + 1) * sizeof (char *)); X if (*list == (char **) NULL) X { X fprintf (stderr, "malloc failed in parseList() (2). errno %d\n", errno); X cleanup (); X exit (1); X } X X ptr = dstr; X lptr = *list; X for (i = 0; i < count; ++i) X { X len = strlen (ptr); X *lptr = (char *) malloc (len + 1); X if (*lptr == (char *) NULL) X { X fprintf (stderr, "malloc failed in parseList() (3). errno %d\n", X errno); X cleanup (); X exit (1); X } X strcpy (*lptr, ptr); X ptr += len + 1; X ++lptr; X } X X *lptr = (char *) NULL; X free ((char *) dstr); X} X X Xstatic void X#if defined (CAN_PROTOTYPE) XcheckIgnoreList (DiskInfo *diskInfo) X#else XcheckIgnoreList (diskInfo) X DiskInfo *diskInfo; X#endif X{ X char **ptr; X X /* if the file system type is in the ignore list, skip it */ X if (ignoreList != (char **) NULL) X { X ptr = ignoreList; X while (*ptr != (char *) NULL) X { X if (strcmp (*ptr, diskInfo->fsType) == 0) X { X diskInfo->printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("chkign: ignore: fstype %s match: %s\n", *ptr, X diskInfo->name); X } X break; X } X ++ptr; X } X } /* if an ignore list was specified */ X} X Xstatic void X#if defined (CAN_PROTOTYPE) XcheckIncludeList (DiskInfo *diskInfo) X#else XcheckIncludeList (diskInfo) X DiskInfo *diskInfo; X#endif X{ X char **ptr; X X /* if the file system type is not in the include list, skip it */ X if (includeList != (char **) NULL) X { X ptr = includeList; X while (*ptr != (char *) NULL) X { X if (strcmp (*ptr, diskInfo->fsType) == 0) X { X diskInfo->printFlag = DI_OK; X break; X } X else X { X diskInfo->printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("chkinc: ! include: fstype %s match: %s\n", *ptr, X diskInfo->name); X } X } X ++ptr; X } X } /* if an include list was specified */ X} X X X#if defined (HAS_FS_INFO) X X/* X * getDiskEntries X * X * For BeOS. X * X */ X Xstatic int XgetDiskEntries (void) X{ X status_t stat; X int idx; X int32 count; X dev_t dev; X char buff [B_FILE_NAME_LENGTH]; X fs_info fsinfo; X double mult; X node_ref nref; X BDirectory *dir; X BEntry entry; X BPath path; X X count = 0; X while ((dev = next_dev (&count)) != B_BAD_VALUE) X { X if ((stat = fs_stat_dev (dev, &fsinfo)) == B_BAD_VALUE) X { X break; X } X X idx = diCount; X ++diCount; X diskInfo = (DiskInfo *) Realloc ((char *) diskInfo, X sizeof (DiskInfo) * diCount); X memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo)); X diskInfo [idx].printFlag = DI_OK; X *buff = '\0'; X nref.device = dev; X nref.node = fsinfo.root; X dir = new BDirectory (&nref); X stat = dir->GetEntry (&entry); X stat = entry.GetPath (&path); X strncpy (diskInfo [idx].name, path.Path (), DI_NAME_LEN); X strncpy (diskInfo [idx].special, fsinfo.device_name, DI_SPEC_NAME_LEN); X strncpy (diskInfo [idx].fsType, fsinfo.fsh_name, DI_TYPE_LEN); X diskInfo [idx].isLocal = TRUE; X mult = (double) (long) fsinfo.block_size / dispBlockSize; X diskInfo [idx].totalBlocks = X ((double) (_s_fs_size_t) fsinfo.total_blocks * mult); X diskInfo [idx].freeBlocks = X ((double) (_s_fs_size_t) fsinfo.free_blocks * mult); X diskInfo [idx].availBlocks = X ((double) (_s_fs_size_t) fsinfo.free_blocks * mult); X diskInfo [idx].totalInodes = fsinfo.total_nodes; X diskInfo [idx].freeInodes = fsinfo.free_nodes; X diskInfo [idx].availInodes = fsinfo.free_nodes; X X checkIgnoreList (&diskInfo [idx]); X checkIncludeList (&diskInfo [idx]); X X if (debug > 0) X { X printf ("mnt:%s - %s\n", diskInfo [idx].name, X diskInfo [idx].special); X printf ("dev:%d fs:%s\n", dev, diskInfo [idx].fsType); X } X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType); X printf ("\tmult:%f\n", mult); X printf ("\tblocks: tot:%ld free:%ld\n", X fsinfo.total_blocks, fsinfo.free_blocks); X printf ("\tinodes: tot:%ld free:%ld\n", X fsinfo.total_nodes, fsinfo.free_nodes); X } X } X return 0; X} X Xstatic void XgetDiskInfo (void) X{ X return; X} X X#endif X X#if defined (HAS_GETMNTENT) && ! defined (HAS_SETMNTENT) X X# define DFS_FS_TABLE "/etc/dfs/fstypes" X X/* X * getDiskEntries X * X * For SysV.4, we open the file and call getmntent () repeatedly. X * X */ X Xstatic int XgetDiskEntries () X{ X FILE *f; X int idx; X int i; X struct mnttab mntEntry; X char buff [80]; X time_t mtime; X char *devp; /* local ptr to dev entry */ X X X if ((flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY) X { X i = remoteFileSystemCount; X X if ((f = fopen (DFS_FS_TABLE, "r")) != (FILE *) NULL) X { X fgets (buff, 80, f); X if (debug > 1) X { X printf ("remote file system type: %s\n", buff); X } X sscanf (buff, "%s", remoteFileSystemTypes [i++]); X fclose (f); X } X X remoteFileSystemCount = i; X } X X if ((f = fopen (DI_MOUNT_FILE, "r")) == (FILE *) NULL) X { X fprintf (stderr, "Unable to open: %s errno %d\n", DI_MOUNT_FILE, errno); X return -1; X } X X while (getmntent (f, &mntEntry) == 0) X { X idx = diCount; X ++diCount; X diskInfo = (DiskInfo *) Realloc ((char *) diskInfo, X sizeof (DiskInfo) * diCount); X memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo)); X diskInfo [idx].printFlag = DI_OK; X X strncpy (diskInfo [idx].special, mntEntry.mnt_special, X DI_SPEC_NAME_LEN); X strncpy (diskInfo [idx].name, mntEntry.mnt_mountp, DI_NAME_LEN); X# if defined (MNTOPT_IGNORE) X if (strstr (mntEntry.mnt_mntopts, MNTOPT_IGNORE) != (char *) NULL) X# else X if (strstr (mntEntry.mnt_mntopts, "ignore") != (char *) NULL) X# endif X { X diskInfo [idx].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: mntopt 'ignore': %s\n", X diskInfo [idx].name); X } X } X# if defined (MNTOPT_DEV) X sprintf (buff, "%s=", MNTOPT_DEV); X if ((devp = strstr (mntEntry.mnt_mntopts, buff)) != (char *) NULL) X# else X if ((devp = strstr (mntEntry.mnt_mntopts, "dev=")) != (char *) NULL) X# endif X { X if (devp != mntEntry.mnt_mntopts) X { X --devp; X } X *devp = 0; /* point to preceeding comma and cut off */ X } X strncpy (diskInfo [idx].options, mntEntry.mnt_mntopts, DI_OPT_LEN); X mtime = atol (mntEntry.mnt_time); X strncpy (diskInfo [idx].mountTime, ctime (&mtime), DI_MNT_TIME_LEN); X X /* get the file system type now... */ X strncpy (diskInfo [idx].fsType, mntEntry.mnt_fstype, DI_TYPE_LEN); X X diskInfo [idx].isLocal = TRUE; X for (i = 0; i < remoteFileSystemCount; ++i) X { X if (strcmp (diskInfo [idx].fsType, remoteFileSystemTypes [i]) == 0) X { X diskInfo [idx].isLocal = FALSE; X } X } X X checkIgnoreList (&diskInfo [idx]); X checkIncludeList (&diskInfo [idx]); X X if (debug > 0) X { X printf ("mnt:%s - %s\n", diskInfo [idx].name, X diskInfo [idx].special); X } X } X X fclose (f); X return 0; X} X X#endif /* HAS_GETMNTENT */ X X#if ! defined (HAS_GETMNTENT) && ! defined (HAS_MNTCTL) && \ X ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT) && \ X ! defined (HAS_GETDISKFREESPACE) && ! defined (HAS_FS_INFO) X X/* X * getDiskEntries X * X * For SysV.3 we open the file and read it ourselves. X * X */ X Xstatic int XgetDiskEntries () X{ X FILE *f; X int idx; X struct mnttab mntEntry; X X X if ((f = fopen (DI_MOUNT_FILE, "r")) == (FILE *) NULL) X { X fprintf (stderr, "Unable to open: %s errno %d\n", DI_MOUNT_FILE, errno); X return -1; X } X X while (fread ((char *) &mntEntry, sizeof (struct mnttab), 1, f) == 1) X { X /* xenix allows null mount table entries */ X /* sco nfs background mounts are marked as "nothing" */ X if (mntEntry.mt_filsys [0] && X strcmp (mntEntry.mt_filsys, "nothing") != 0) X { X idx = diCount; X ++diCount; X diskInfo = (DiskInfo *) Realloc ((char *) diskInfo, X sizeof (DiskInfo) * diCount); X memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo)); X diskInfo [idx].printFlag = DI_OK; X diskInfo [idx].isLocal = TRUE; X X# if defined (COHERENT) X /* Coherent seems to have these fields reversed. oh well. */ X strncpy (diskInfo [idx].name, mntEntry.mt_dev, DI_NAME_LEN); X strncpy (diskInfo [idx].special, mntEntry.mt_filsys, DI_SPEC_NAME_LEN); X# else X strncpy (diskInfo [idx].special, mntEntry.mt_dev, DI_SPEC_NAME_LEN); X strncpy (diskInfo [idx].name, mntEntry.mt_filsys, DI_NAME_LEN); X# endif X strncpy (diskInfo [idx].options, mntEntry.mnt_mntopts, DI_OPT_LEN); X strncpy (diskInfo [idx].mountTime, mntEntry.mnt_time, X DI_MNT_TIME_LEN); X } X X if (debug > 0) X { X printf ("mnt:%s - %s\n", diskInfo [idx].name, X diskInfo [idx].special); X } X } X X fclose (f); X return 0; X} X X#endif /* Sys V.3 */ X X#if defined (HAS_GETMNTENT) && defined (HAS_SETMNTENT) && \ X defined (HAS_ENDMNTENT) X X/* X * getDiskEntries X * X * SunOS supplies an open and close routine for the mount table. X * X */ X Xstatic int XgetDiskEntries () X{ X FILE *f; X int idx; X struct mntent *mntEntry; X char *devp; /* local ptr to dev entry */ X X X#if defined (HAS_SETMNTENT_ONE_ARG) X if ((f = setmntent (DI_MOUNT_FILE)) == (FILE *) NULL) X#else X if ((f = setmntent (DI_MOUNT_FILE, "r")) == (FILE *) NULL) X#endif X { X fprintf (stderr, "Unable to open: %s errno %d\n", DI_MOUNT_FILE, errno); X return -1; X } X X while ((mntEntry = getmntent (f)) != (struct mntent *) NULL) X { X idx = diCount; X ++diCount; X diskInfo = (DiskInfo *) Realloc ((char *) diskInfo, X sizeof (DiskInfo) * diCount); X memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo)); X diskInfo [idx].printFlag = DI_OK; X diskInfo [idx].isLocal = TRUE; X X strncpy (diskInfo [idx].special, mntEntry->mnt_fsname, DI_SPEC_NAME_LEN); X strncpy (diskInfo [idx].name, mntEntry->mnt_dir, DI_NAME_LEN); X strncpy (diskInfo [idx].fsType, mntEntry->mnt_type, DI_TYPE_LEN); X X if (strcmp (mntEntry->mnt_type, MNTTYPE_IGNORE) == 0) X { X diskInfo [idx].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: mntopt 'ignore': %s\n", X diskInfo [idx].name); X } X } X X if ((devp = strstr (mntEntry->mnt_opts, "dev=")) != (char *) NULL) X { X if (devp != mntEntry->mnt_opts) X { X --devp; X } X *devp = 0; /* point to preceeding comma and cut off */ X } X strncpy (diskInfo [idx].options, mntEntry->mnt_opts, DI_OPT_LEN); X X checkIgnoreList (&diskInfo [idx]); X checkIncludeList (&diskInfo [idx]); X X if (debug > 0) X { X printf ("mnt:%s - %s : %s\n", diskInfo [idx].name, X diskInfo [idx].special, diskInfo [idx].fsType); X } X } X X endmntent (f); X return 0; X} X X#endif /* HAS_GETMNTENT && HAS_SETMNTENT && HAS_ENDMNTENT */ X X#if defined (HAS_GETMNTINFO) X X/* X * getDiskEntries X * X * OSF/1 does this with a system call and library routine X * X * [mogul@wrl.dec.com (Jeffrey Mogul)] X */ X X#if defined (INITMOUNTNAMES) Xstatic char *mnt_names [] = INITMOUNTNAMES; X# define MNT_NUMTYPES (MOUNT_MAXTYPE + 1) X#endif X X /* osf/1 mount flags start w/M_ vs. MNT_ */ X /* this saves us from lots of duplicate code */ X#if defined (M_RDONLY) X# define MNT_RDONLY M_RDONLY X#endif X#if defined (M_SYNCHRONOUS) X# define MNT_SYNCHRONOUS M_SYNCHRONOUS X#endif X#if defined (M_NOEXEC) X# define MNT_NOEXEC M_NOEXEC X#endif X#if defined (M_NOSUID) X# define MNT_NOSUID M_NOSUID X#endif X#if defined (M_NODEV) X# define MNT_NODEV M_NODEV X#endif X#if defined (M_GRPID) X# define MNT_GRPID M_GRPID X#endif X#if defined (M_EXPORTED) X# define MNT_EXPORTED M_EXPORTED X#endif X#if defined (M_EXRDONLY) X# define MNT_EXRDONLY M_EXRDONLY X#endif X#if defined (M_EXRDMOSTLY) X# define MNT_EXRDMOSTLY M_EXRDMOSTLY X#endif X#if defined (M_SECURE) X# define MNT_SECURE M_SECURE X#endif X#if defined (M_LOCAL) X# define MNT_LOCAL M_LOCAL X#endif X#if defined (M_QUOTA) X# define MNT_QUOTA M_QUOTA X#endif X Xstatic int XgetDiskEntries () X{ X int count; X int idx; X int len; X short fstype; X struct statfs *mntbufp; X double mult; X X count = getmntinfo (&mntbufp, MNT_WAIT); X if (count < 1) X { X fprintf (stderr, "Unable to do getmntinfo () errno %d\n", errno); X return -1; X } X X diCount = count; X diskInfo = (DiskInfo *) malloc (sizeof (DiskInfo) * count); X if (diskInfo == (DiskInfo *) NULL) X { X fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno); X return -1; X } X memset ((char *) diskInfo, '\0', sizeof (DiskInfo) * count); X X if (debug > 1) X { X printf ("type_len %d name_len %d spec_name_len %d\n", DI_TYPE_LEN, X DI_NAME_LEN, DI_SPEC_NAME_LEN); X } X X for (idx = 0; idx < count; idx++) X { X diskInfo [idx].printFlag = DI_OK; X diskInfo [idx].isLocal = FALSE; X#if defined (MNT_LOCAL) X if ((mntbufp [idx].f_flags & MNT_LOCAL) == MNT_LOCAL) X { X diskInfo [idx].isLocal = TRUE; X } X#endif X X if (diskInfo [idx].isLocal == FALSE && X (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY) X { X diskInfo [idx].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: remote: %s\n", X diskInfo [idx].name); X } X } X X strncpy (diskInfo [idx].special, mntbufp [idx].f_mntfromname, X DI_SPEC_NAME_LEN); X strncpy (diskInfo [idx].name, mntbufp [idx].f_mntonname, DI_NAME_LEN); X X mult = 1.0; X X# if defined (HAS_GETMNTINFO_FSIZE) /* 1.x */ X mult = (double) mntbufp [idx].f_fsize / dispBlockSize; X# endif X# if defined (HAS_GETMNTINFO_BSIZE) /* 2.x */ X mult = (double) mntbufp [idx].f_bsize / dispBlockSize; X# endif X diskInfo [idx].totalBlocks = ((double) (_s_fs_size_t) mntbufp [idx].f_blocks * mult); X diskInfo [idx].freeBlocks = ((double) (_s_fs_size_t) mntbufp [idx].f_bfree * mult); X diskInfo [idx].availBlocks = ((double) (_s_fs_size_t) mntbufp [idx].f_bavail * mult); X X diskInfo [idx].totalInodes = mntbufp [idx].f_files; X diskInfo [idx].freeInodes = mntbufp [idx].f_ffree; X diskInfo [idx].availInodes = mntbufp [idx].f_ffree; X X fstype = mntbufp [idx].f_type; X# if ! defined (I_SYS_FSTYP) && ! defined (INITMOUNTNAMES) && \ X ! defined (HAS_GETMNTINFO_FSTYPENAME) X if ((fstype >= 0) && (fstype <= MOUNT_MAXTYPE)) X { X switch (fstype) X { X# if defined (MOUNT_NONE) X case MOUNT_NONE: /* No Filesystem */ X { X strncpy (diskInfo [idx].fsType, "none", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_UFS) X case MOUNT_UFS: /* UNIX "Fast" Filesystem */ X { X strncpy (diskInfo [idx].fsType, "ufs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_NFS) X case MOUNT_NFS: /* Network Filesystem */ X { X strncpy (diskInfo [idx].fsType, "nfs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_MFS) X case MOUNT_MFS: /* Memory Filesystem */ X { X strncpy (diskInfo [idx].fsType, "mfs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_MSDOS) X case MOUNT_MSDOS: /* MSDOS Filesystem */ X { X strncpy (diskInfo [idx].fsType, "msdos", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_LFS) X case MOUNT_LFS: X { X strncpy (diskInfo [idx].fsType, "lfs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_LOFS) X case MOUNT_LOFS: X { X strncpy (diskInfo [idx].fsType, "lofs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_FDESC) X case MOUNT_FDESC: X { X strncpy (diskInfo [idx].fsType, "fdesc", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_PORTAL) X case MOUNT_PORTAL: X { X strncpy (diskInfo [idx].fsType, "portal", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_NULL) X case MOUNT_NULL: X { X strncpy (diskInfo [idx].fsType, "null", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_UMAP) X case MOUNT_UMAP: X { X strncpy (diskInfo [idx].fsType, "umap", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_KERNFS) X case MOUNT_KERNFS: X { X strncpy (diskInfo [idx].fsType, "kernfs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_PROCFS) X case MOUNT_PROCFS: /* proc filesystem */ X { X strncpy (diskInfo [idx].fsType, "pfs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_AFS) X case MOUNT_AFS: X { X strncpy (diskInfo [idx].fsType, "afs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_ISOFS) X case MOUNT_ISOFS: /* iso9660 cdrom */ X { X strncpy (diskInfo [idx].fsType, "iso9660fs", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_ISO9660) && ! defined (MOUNT_CD9660) X case MOUNT_ISO9660: /* iso9660 cdrom */ X { X strncpy (diskInfo [idx].fsType, "iso9660", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_CD9660) X case MOUNT_CD9660: /* iso9660 cdrom */ X { X strncpy (diskInfo [idx].fsType, "cd9660", DI_TYPE_LEN); X break; X } X# endif X X# if defined (MOUNT_UNION) X case MOUNT_UNION: X { X strncpy (diskInfo [idx].fsType, "union", DI_TYPE_LEN); X break; X } X# endif X } /* switch on mount type */ X } X# else X# if defined (HAS_GETMNTINFO_FSTYPENAME) X strncpy (diskInfo [idx].fsType, mntbufp [idx].f_fstypename, DI_TYPE_LEN); X# else X /* could use getvfsbytype here... */ X if ((fstype >= 0) && (fstype < MNT_NUMTYPES)) X { X strncpy (diskInfo [idx].fsType, mnt_names [fstype], DI_TYPE_LEN); X } X else X { X sprintf (diskInfo [idx].fsType, DI_UNKNOWN_FSTYPE, fstype); X } X# endif X# endif /* has fs_types.h */ X X#if defined (MNT_RDONLY) X if ((mntbufp [idx].f_flags & MNT_RDONLY) == MNT_RDONLY) X { X strcat (diskInfo [idx].options, "ro,"); X } X else X { X strcat (diskInfo [idx].options, "rw,"); X } X#endif X#if defined (MNT_SYNCHRONOUS) X if ((mntbufp [idx].f_flags & MNT_SYNCHRONOUS) == MNT_SYNCHRONOUS) X { X strcat (diskInfo [idx].options, "sync,"); X } X#endif X#if defined (MNT_NOEXEC) X if ((mntbufp [idx].f_flags & MNT_NOEXEC) == MNT_NOEXEC) X { X strcat (diskInfo [idx].options, "noexec,"); X } X#endif X#if defined (MNT_NOSUID) X if ((mntbufp [idx].f_flags & MNT_NOSUID) != MNT_NOSUID) X { X strcat (diskInfo [idx].options, "suid,"); X } X#endif X#if defined (MNT_NODEV) X if ((mntbufp [idx].f_flags & MNT_NODEV) == MNT_NODEV) X { X strcat (diskInfo [idx].options, "nodev,"); X } X#endif X#if defined (MNT_GRPID) X if ((mntbufp [idx].f_flags & MNT_GRPID) == MNT_GRPID) X { X strcat (diskInfo [idx].options, "grpid,"); X } X#endif X#if defined (MNT_UNION) X if ((mntbufp [idx].f_flags & MNT_UNION) == MNT_UNION) X { X strcat (diskInfo [idx].options, "union,"); X } X#endif X#if defined (MNT_ASYNC) X if ((mntbufp [idx].f_flags & MNT_ASYNC) == MNT_ASYNC) X { X strcat (diskInfo [idx].options, "async,"); X } X#endif X#if defined (MNT_EXRDONLY) X if ((mntbufp [idx].f_flags & MNT_EXRDONLY) == MNT_EXRDONLY) X { X strcat (diskInfo [idx].options, "exported ro,"); X } X#endif X#if defined (MNT_EXPORTED) X if ((mntbufp [idx].f_flags & MNT_EXPORTED) == MNT_EXPORTED) X { X strcat (diskInfo [idx].options, "exported,"); X } X#endif X#if defined (MNT_EXRDMOSTLY) X if ((mntbufp [idx].f_flags & MNT_EXRDMOSTLY) == MNT_EXRDMOSTLY) X { X /* what's read-mostly ? */ X strcat (diskInfo [idx].options, "exported read-mostly,"); X } X#endif X#if defined (MNT_DEFEXPORTED) X if ((mntbufp [idx].f_flags & MNT_DEFEXPORTED) == MNT_DEFEXPORTED) X { X /* what's this ? */ X strcat (diskInfo [idx].options, "exported world,"); X } X#endif X#if defined (MNT_EXPORTANON) X if ((mntbufp [idx].f_flags & MNT_EXPORTANON) == MNT_EXPORTANON) X { X strcat (diskInfo [idx].options, "exported anon,"); X } X#endif X#if defined (MNT_EXKERB) X if ((mntbufp [idx].f_flags & MNT_EXKERB) == MNT_EXKERB) X { X strcat (diskInfo [idx].options, "exported kerberos,"); X } X#endif X#if defined (MNT_LOCAL) X if ((mntbufp [idx].f_flags & MNT_LOCAL) == MNT_LOCAL) X { X strcat (diskInfo [idx].options, "local,"); X } X#endif X#if defined (MNT_QUOTA) X if ((mntbufp [idx].f_flags & MNT_QUOTA) == MNT_QUOTA) X { X strcat (diskInfo [idx].options, "quota,"); X } X#endif X#if defined (MNT_ROOTFS) X if ((mntbufp [idx].f_flags & MNT_ROOTFS) == MNT_ROOTFS) X { X strcat (diskInfo [idx].options, "root,"); X } X#endif X#if defined (MNT_USER) X if ((mntbufp [idx].f_flags & MNT_USER) == MNT_USER) X { X strcat (diskInfo [idx].options, "user,"); X } X#endif X#if defined (MNT_SECURE) X if ((mntbufp [idx].f_flags & MNT_SECURE) == MNT_SECURE) X { X strcat (diskInfo [idx].options, "secure,"); X } X#endif X X len = strlen (diskInfo [idx].options); X if (len > 0) X { X --len; X } X if (diskInfo [idx].options [len]==',') X { X diskInfo [idx].options [len] = '\0'; X } X X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType); X printf ("\tblocks: tot:%ld free:%ld avail:%ld\n", X mntbufp [idx].f_blocks, mntbufp [idx].f_bfree, X mntbufp [idx].f_bavail); X printf ("\tmult: %f\n", mult); X# if defined (HAS_GETMNTINFO_FSIZE) X printf ("\tfsize:%ld \n", mntbufp [idx].f_fsize); X printf ("\tbsize:%ld \n", mntbufp [idx].f_bsize); X# endif X# if defined (HAS_GETMNTINFO_BSIZE) X printf ("\tbsize:%ld \n", mntbufp [idx].f_bsize); X printf ("\tiosize:%ld \n", mntbufp [idx].f_iosize); X# endif X printf ("\tinodes: tot:%ld free:%ld\n", X mntbufp [idx].f_files, mntbufp [idx].f_ffree); X } X } X X free ((char *) mntbufp); /* man page says this can't be freed. */ X /* is it ok to try? */ X return 0; X} X X/* this is a no-op; we have already done all the work */ Xstatic void XgetDiskInfo () X{ X} X X#endif /* HAS_GETMNTINFO */ X X#if defined (HAS_GETMNT) X X/* X * getDiskEntries X * X * ULTRIX does this with a system call. The system call allows one X * to retrieve the information in a series of calls, but coding that X * looks a little tricky; I just allocate a huge buffer and do it in X * one shot. X * X * [mogul@wrl.dec.com (Jeffrey Mogul)] X */ X Xstatic int XgetDiskEntries () X{ X int count; X int bufsize; X int idx; X short fstype; X struct fs_data *fsdbuf; X int start; X int len; X X X bufsize = NMOUNT * sizeof (struct fs_data); /* enough for max # mounts */ X fsdbuf = (struct fs_data *) malloc (bufsize); X if (fsdbuf == (struct fs_data *) NULL) X { X fprintf (stderr, "malloc (%d) for getmnt () failed errno %d\n", X bufsize, errno); X return -1; X } X X start = 0; X count = getmnt (&start, fsdbuf, bufsize, STAT_MANY, 0); X if (count < 1) X { X fprintf (stderr, "Unable to do getmnt () [= %d] errno %d\n", X count, errno); X free ((char *) fsdbuf); X return -1; X } X X diCount = count; X diskInfo = (DiskInfo *) malloc (sizeof (DiskInfo) * count); X if (diskInfo == (DiskInfo *) NULL) X { X fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno); X free ((char *) fsdbuf); X return -1; X } X memset ((char *) diskInfo, '\0', sizeof (DiskInfo) * count); X X for (idx = 0; idx < count; idx++) X { X diskInfo [idx].printFlag = DI_OK; X diskInfo [idx].isLocal = TRUE; X X if ((fsdbuf [idx].fd_req.flags & M_LOCAL) != M_LOCAL) X { X diskInfo [idx].isLocal = FALSE; X } X X if (diskInfo [idx].isLocal == FALSE && X (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY) X { X diskInfo [idx].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: remote: %s\n", X diskInfo [idx].name); X } X } X X strncpy (diskInfo [idx].special, fsdbuf [idx].fd_devname, DI_SPEC_NAME_LEN); X strncpy (diskInfo [idx].name, fsdbuf [idx].fd_path, DI_NAME_LEN); X X /* ULTRIX keeps these fields in units of 1K byte */ X diskInfo [idx].totalBlocks = fsdbuf [idx].fd_btot; X diskInfo [idx].freeBlocks = fsdbuf [idx].fd_bfree; X diskInfo [idx].availBlocks = (int) fsdbuf [idx].fd_bfreen; X X diskInfo [idx].totalInodes = fsdbuf [idx].fd_gtot; X diskInfo [idx].freeInodes = fsdbuf [idx].fd_gfree; X diskInfo [idx].availInodes = fsdbuf [idx].fd_gfree; X X fstype = fsdbuf [idx].fd_fstype; X if (fstype == GT_UNKWN) X { X diskInfo [idx].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: disk type unknown: %s\n", X diskInfo [idx].name); X } X } X else if ((fstype > 0) && (fstype < GT_NUMTYPES)) X { X strncpy (diskInfo [idx].fsType, gt_names [fstype], DI_TYPE_LEN); X } X else X { X sprintf (diskInfo [idx].fsType, "Unknown fstyp %.2d", fstype); X } X X if ((fsdbuf [idx].fd_req.flags & M_RONLY) == M_RONLY) X { X strcat (diskInfo [idx].options, "ro,"); X } X else X { X strcat (diskInfo [idx].options, "rw,"); X } X if ((fsdbuf [idx].fd_req.flags & M_NOSUID) != M_NOSUID) X { X strcat (diskInfo [idx].options, "suid,"); X } X if ((fsdbuf [idx].fd_req.flags & M_QUOTA) == M_QUOTA) X { X strcat (diskInfo [idx].options, "quota,"); X } X if ((fsdbuf [idx].fd_req.flags & M_LOCAL) != M_LOCAL) X { X strcat (diskInfo [idx].options, "remote,"); X } X if ((fsdbuf [idx].fd_req.flags & M_NODEV) == M_NODEV) X { X strcat (diskInfo [idx].options, "nodev,"); X } X if ((fsdbuf [idx].fd_req.flags & M_FORCE) == M_FORCE) X { X strcat (diskInfo [idx].options, "force,"); X } X if ((fsdbuf [idx].fd_req.flags & M_SYNC) == M_SYNC) X { X strcat (diskInfo [idx].options, "sync,"); X } X if ((fsdbuf [idx].fd_req.flags & M_NOCACHE) == M_NOCACHE) X { X strcat (diskInfo [idx].options, "nocache,"); X } X if ((fsdbuf [idx].fd_req.flags & M_EXPORTED) == M_EXPORTED) X { X strcat (diskInfo [idx].options, "exported," ); X } X if ((fsdbuf [idx].fd_req.flags & M_EXRONLY) == M_EXRONLY) X { X strcat (diskInfo [idx].options, "exported ro,"); X } X if ((fsdbuf [idx].fd_req.flags & M_NOEXEC) == M_NOEXEC) X { X strcat (diskInfo [idx].options, "noexec,"); X } X X len = strlen (diskInfo [idx].options); X if (len > 0) X { X --len; X } X if (diskInfo [idx].options [len]==',') X { X diskInfo [idx].options [len] = '\0'; X } X X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType); X printf ("\tblocks: tot:%ld free:%ld avail:%ld\n", X fsdbuf [idx].fd_btot, fsdbuf [idx].fd_bfree, X (int) fsdbuf [idx].fd_bfreen); X printf ("\tinodes: tot:%ld free:%ld\n", X fsdbuf [idx].fd_gtot, fsdbuf [idx].fd_gfree); X } X } X X free ((char *) fsdbuf); X return 0; X} X X/* this is a no-op; we have already done all the work */ Xstatic void XgetDiskInfo () X{ X} X X#endif /* HAS_GETMNT */ X X X#if defined (HAS_MNTCTL) X X/* X * getDiskEntries X * X * AIX V3.2 uses mntctl to find out about mounted file systems X * X */ X X# define NUM_AIX_FSTYPES 6 Xstatic char *AIX_fsType [NUM_AIX_FSTYPES] = X { "oaix", "", "nfs", "jfs", "", "cdrom" }; X X/* X * from xfsm-1.80: X * X * MNT_AIX - "aix" X * MNT_NFS - "nfs" X * MNT_JFS - "jfs" X * MNT_CDROM - "cdrom" X * other - "user defined" X * X */ X Xstatic int XgetDiskEntries () X{ X int num; /* number of vmount structs returned */ X char *vmbuf; /* buffer for vmount structs returned */ X int vmbufsz; /* size in bytes of vmbuf */ X int i; /* index for looping and stuff */ X char *bufp; /* pointer into vmbuf */ X struct vmount *vmtp; /* pointer into vmbuf */ X struct vfs_ent *ve; /* pointer for file system type entry */ X int len; X X X i = 0; X vmbufsz = sizeof (struct vmount) * DI_FSMAGIC; /* initial vmount buffer */ X X do X { X if ((vmbuf = (char *) malloc (vmbufsz)) == (char *) NULL) X { X fprintf (stderr, "malloc (%d) for mntctl() failed errno %d\n", X vmbufsz, errno); X return -1; X } X X num = mntctl (MCTL_QUERY, vmbufsz, vmbuf); X /* X * vmbuf is too small, could happen for X * following reasons: X * - inital buffer is too small X * - newly mounted file system X */ X if (num == 0) X { X memcpy (&vmbufsz, vmbuf, sizeof (vmbufsz)); /* see mntctl(2) */ X if (debug > 0) X { X printf ("vmbufsz too small, new size: %d\n", vmbufsz); X } X free ((char *) vmbuf); /* free this last, it's still being used! */ X ++i; X } X } while (num == 0 && i < DI_RETRY_COUNT); X X if (i >= DI_RETRY_COUNT) X { X free ((char *) vmbuf); X fprintf (stderr, "unable to allocate adequate buffer for mntctl\n"); X return -1; X } X X switch (num) X { X /* error happened, probably null vmbuf */ X case -1: X { X free ((char *) vmbuf); X fprintf (stderr,"%s errno %d\n", strerror (errno), errno); X return -1; X } X X /* 'num' vmount structs returned in vmbuf */ X default: X { X diCount = num; X diskInfo = (DiskInfo *) calloc (sizeof (DiskInfo), diCount); X if (diskInfo == (DiskInfo *) NULL) X { X fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno); X return -1; X } X X bufp = vmbuf; X for (i = 0; i < num; i++) X { X vmtp = (struct vmount *) bufp; X diskInfo [i].printFlag = DI_OK; X diskInfo [i].isLocal = TRUE; X X strncpy (diskInfo [i].special, X (char *) vmt2dataptr (vmtp, VMT_OBJECT), X DI_SPEC_NAME_LEN); X strncpy (diskInfo [i].name, X (char *) vmt2dataptr (vmtp, VMT_STUB), DI_NAME_LEN); X X ve = getvfsbytype (vmtp->vmt_gfstype); X if (ve == (struct vfs_ent *) NULL || *ve->vfsent_name == '\0') X { X if (vmtp->vmt_gfstype >= 0 && X (vmtp->vmt_gfstype < NUM_AIX_FSTYPES)) X { X strncpy (diskInfo [i].fsType, X AIX_fsType [vmtp->vmt_gfstype], DI_TYPE_LEN); X } X } X else X { X strncpy (diskInfo [i].fsType, ve->vfsent_name, DI_TYPE_LEN); X } X X if ((vmtp->vmt_flags & MNT_READONLY) == MNT_READONLY) X { X strcat (diskInfo [i].options, "ro,"); X } X else X { X strcat (diskInfo [i].options, "rw,"); X } X if ((vmtp->vmt_flags & MNT_NOSUID) != MNT_NOSUID) X { X strcat (diskInfo [i].options, "suid,"); X } X if ((vmtp->vmt_flags & MNT_REMOVABLE) == MNT_REMOVABLE) X { X strcat (diskInfo [i].options, "removable,"); X } X if ((vmtp->vmt_flags & MNT_DEVICE) == MNT_DEVICE) X { X strcat (diskInfo [i].options, "device,"); X } X if ((vmtp->vmt_flags & MNT_REMOTE) == MNT_REMOTE) X { X strcat (diskInfo [i].options, "remote,"); X diskInfo [i].isLocal = FALSE; X } X if ((vmtp->vmt_flags & MNT_UNMOUNTING) == MNT_UNMOUNTING) X { X strcat (diskInfo [i].options, "unmounting,"); X } X if ((vmtp->vmt_flags & MNT_SYSV_MOUNT) == MNT_SYSV_MOUNT) X { X strcat (diskInfo [i].options, "sysv mount,"); X } X if ((vmtp->vmt_flags & MNT_NODEV) == MNT_NODEV) X { X strcat (diskInfo [i].options, "nodev,"); X } X X /* remove trailing comma */ X len = strlen (diskInfo [i].options); X if (len > 0) X { X --len; X } X if (diskInfo [i].options [len] == ',') X { X diskInfo [i].options [len] = '\0'; X } X X strncpy (diskInfo [i].mountTime, ctime (&vmtp->vmt_time), X DI_MNT_TIME_LEN); X X if (diskInfo [i].isLocal == FALSE && X (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY) X { X diskInfo [i].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: remote: %s\n", X diskInfo [i].name); X } X } X X bufp += vmtp->vmt_length; X } X X if (debug > 0) X { X printf ("mnt:%s - %s : %s\n", diskInfo [i].name, X diskInfo [i].special, diskInfo [i].fsType); X printf ("\t%s\n", (char *) vmt2dataptr (vmtp, VMT_ARGS)); X } X X break; X } /* valid value returned */ X } /* switch on num */ X} X X#endif /* HAS_MNTCTL */ X X X#if defined (HAS_STATVFS) X X/* X * getDiskInfo X * X * SysV.4. statvfs () returns both the free and available blocks. X * X */ X Xstatic void XgetDiskInfo () X{ X int i; X double mult; X struct statvfs statBuf; X X for (i = 0; i < diCount; ++i) X { X if (diskInfo [i].isLocal == FALSE && X (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY) X { X diskInfo [i].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: remote: %s\n", X diskInfo [i].name); X } X } X X if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL) X { X if (statvfs (diskInfo [i].name, &statBuf) == 0) X { X /* data general DG/UX 5.4R3.00 sometime returns 0 */ X /* in the fragment size field. */ X if (statBuf.f_frsize == 0 && statBuf.f_bsize != 0) X { X mult = (double) (long) statBuf.f_bsize / dispBlockSize; X } X else X { X mult = (double) (long) statBuf.f_frsize / dispBlockSize; X } X X diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) statBuf.f_blocks * mult); X diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult); X diskInfo [i].availBlocks = ((double) (_s_fs_size_t) statBuf.f_bavail * mult); X X diskInfo [i].totalInodes = statBuf.f_files; X diskInfo [i].freeInodes = statBuf.f_ffree; X diskInfo [i].availInodes = statBuf.f_favail; X X#if defined (HAS_STATVFS_BASETYPE) X strncpy (diskInfo [i].fsType, statBuf.f_basetype, DI_TYPE_LEN); X#endif X X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType); X printf ("\tmult:%f\n", mult); X printf ("\tbsize:%ld frsize:%ld\n", statBuf.f_bsize, X statBuf.f_frsize); X#if defined (HAS_64BIT_STATFS_FLDS) X printf ("\tblocks: tot:%llu free:%lld avail:%llu\n", X statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail); X printf ("\tinodes: tot:%llu free:%lld avail:%llu\n", X statBuf.f_files, statBuf.f_ffree, statBuf.f_favail); X#else X printf ("\tblocks: tot:%lu free:%ld avail:%lu\n", X statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail); X printf ("\tinodes: tot:%lu free:%ld avail:%lu\n", X statBuf.f_files, statBuf.f_ffree, statBuf.f_favail); X#endif X } X } X else X { X fprintf (stderr, "statvfs: %s ", diskInfo [i].name); X perror (""); X } X } X } /* for each entry */ X} X X#endif /* HAS_STATVFS */ X X X#if defined (HAS_STATFS_BSD) && ! defined (HAS_STATVFS) && \ X ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT) X X/* X * getDiskInfo X * X * SunOS/BSD/Pyramid X * X */ X Xstatic void XgetDiskInfo () X{ X int i; X double mult; X struct statfs statBuf; X X for (i = 0; i < diCount; ++i) X { X if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL) X { X if (statfs (diskInfo [i].name, &statBuf) == 0) X { X mult = (double) statBuf.f_bsize / dispBlockSize; X diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) statBuf.f_blocks * mult); X diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult); X diskInfo [i].availBlocks = ((double) (_s_fs_size_t) statBuf.f_bavail * mult); X X diskInfo [i].totalInodes = statBuf.f_files; X diskInfo [i].freeInodes = statBuf.f_ffree; X diskInfo [i].availInodes = statBuf.f_ffree; X# if defined (HAS_SYSFS) X sysfs (GETFSTYP, statBuf.f_fstyp, diskInfo [i].fsType); X# endif X X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType); X printf ("\tmult:%f\n", mult); X printf ("\tbsize:%ld\n", statBuf.f_bsize); X printf ("\tblocks: tot:%ld free:%ld avail:%ld\n", X statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail); X printf ("\tinodes: tot:%ld free:%ld\n", X statBuf.f_files, statBuf.f_ffree); X } X } /* if we got the info */ X else X { X fprintf (stderr, "statfs: %s ", diskInfo [i].name); X perror (""); X } X } X } /* for each entry */ X} X X#endif /* HAS_STATFS_BSD */ X X#if defined (HAS_STATFS_SYSV3) && ! defined (HAS_STATVFS) && \ X ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT) X X/* X * getDiskInfo X * X * SysV.3. We don't have available blocks; just set it to free blocks. X * The sysfs () call is used to get the disk type name. X * X */ X Xstatic void XgetDiskInfo () X{ X int i; X double mult; X struct statfs statBuf; X X for (i = 0; i < diCount; ++i) X { X if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL) X { X if (statfs (diskInfo [i].name, &statBuf, sizeof (statBuf), 0) == 0) X { X# if defined (HAS_STATFS_FRSIZE) X if (statBuf.f_frsize == 0 && statBuf.f_bsize != 0) X { X mult = (double) (long) statBuf.f_bsize / dispBlockSize; X } X else X { X mult = (double) (long) statBuf.f_frsize / dispBlockSize; X } X# else X mult = (double) UBSIZE / dispBlockSize; X# endif X diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) statBuf.f_blocks * mult); X diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult); X diskInfo [i].availBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult); X X diskInfo [i].totalInodes = statBuf.f_files; X diskInfo [i].freeInodes = statBuf.f_ffree; X diskInfo [i].availInodes = statBuf.f_ffree; X# if defined (HAS_SYSFS) X sysfs (GETFSTYP, statBuf.f_fstyp, diskInfo [i].fsType); X# endif X X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType); X printf ("\tmult:%f\n", mult); X# if defined (HAS_STATFS_FRSIZE) X printf ("\tbsize:%ld\n", statBuf.f_bsize); X printf ("\tfrsize:%ld\n", statBuf.f_frsize); X# else X printf ("\tUBSIZE:%ld\n", UBSIZE); X# endif X printf ("\tblocks: tot:%ld free:%ld\n", X statBuf.f_blocks, statBuf.f_bfree); X printf ("\tinodes: tot:%ld free:%ld\n", X statBuf.f_files, statBuf.f_ffree); X } X } /* if we got the info */ X else X { X fprintf (stderr, "statfs: %s ", diskInfo [i].name); X perror (""); X } X } X } /* for each entry */ X} X X#endif /* HAS_STATFS_SYSV3 */ X X X#if defined (HAS_GETDISKFREESPACE) X X/* X * getDiskInfo X * X * Windows X * X */ X X# define NUM_MSDOS_FSTYPES 7 Xstatic char *MSDOS_diskType [NUM_MSDOS_FSTYPES] = X { "unknown", "", "removable", "fixed", "remote", "cdrom", "ramdisk" }; X# define MSDOS_BUFFER_SIZE 128 X# define BYTES_PER_LOGICAL_DRIVE 4 X Xstatic int XgetDiskEntries () X{ X int i; X int diskflag; X int rc; X char *p; X char buff [MSDOS_BUFFER_SIZE]; X X X diskflag = DI_IGNORE; X rc = GetLogicalDriveStrings (MSDOS_BUFFER_SIZE, buff); X diCount = rc / BYTES_PER_LOGICAL_DRIVE; X X diskInfo = (DiskInfo *) calloc (sizeof (DiskInfo), diCount); X if (diskInfo == (DiskInfo *) NULL) X { X fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno); X return -1; X } X X for (i = 0; i < diCount; ++i) X { X p = buff + (BYTES_PER_LOGICAL_DRIVE * i); X strncpy (diskInfo [i].name, p, DI_NAME_LEN); X rc = GetDriveType (p); X diskInfo [i].printFlag = DI_OK; X X if (rc == DRIVE_NO_ROOT_DIR) X { X diskInfo [i].printFlag = DI_BAD; X } X X /* assume that any removable drives before the */ X /* first non-removable disk are floppies... */ X else if (rc == DRIVE_REMOVABLE) X { X diskInfo [i].printFlag = diskflag; X } X else X { X diskflag = DI_OK; X } X X if (rc != DRIVE_REMOTE) X { X diskInfo [i].isLocal = TRUE; X } X /* strncpy (diskInfo [i].fsType, MSDOS_diskType [rc], DI_TYPE_LEN); */ X } /* for each mounted drive */ X X return diCount; X} X X/* X * getDiskInfo X * X * Windows X * X */ X Xstatic void XgetDiskInfo () X{ X int i; X int rc; X double mult; X unsigned long sectorspercluster; X unsigned long bytespersector; X unsigned long totalclusters; X unsigned long freeclusters; X char tbuff [MSDOS_BUFFER_SIZE]; X char volName [MSDOS_BUFFER_SIZE]; X char fsName [MSDOS_BUFFER_SIZE]; X DWORD serialNo; X DWORD maxCompLen; X DWORD fsFlags; X X X for (i = 0; i < diCount; ++i) X { X if (diskInfo [i].isLocal == FALSE && X (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY) X { X diskInfo [i].printFlag = DI_IGNORE; X if (debug > 2) X { X printf ("mnt: ignore: remote: %s\n", X diskInfo [i].name); X } X } X X if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL) X { X rc = GetVolumeInformation (diskInfo [i].name, X volName, MSDOS_BUFFER_SIZE, &serialNo, &maxCompLen, X &fsFlags, fsName, MSDOS_BUFFER_SIZE); X /* strcpy (tbuff, diskInfo [i].fsType); */ X /* strcat (tbuff, " "); */ X strncpy (diskInfo [i].fsType, fsName, DI_TYPE_LEN); X strncpy (diskInfo [i].special, volName, DI_SPEC_NAME_LEN); X X rc = GetDiskFreeSpace (diskInfo [i].name, X (LPDWORD) §orspercluster, (LPDWORD) &bytespersector, X (LPDWORD) &freeclusters, (LPDWORD) &totalclusters); X X if (rc > 0) X { X mult = (double) (sectorspercluster * X bytespersector) / dispBlockSize; X diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) totalclusters * mult); X diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) freeclusters * mult); X diskInfo [i].availBlocks = ((double) (_s_fs_size_t) freeclusters * mult); X X diskInfo [i].totalInodes = 0; X diskInfo [i].freeInodes = 0; X diskInfo [i].availInodes = 0; X X if (debug > 1) X { X printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType); X printf ("\ts/c:%ld b/s:%ld\n", sectorspercluster, X bytespersector); X printf ("\tmult:%f\n", mult); X printf ("\tclusters: tot:%ld free:%ld\n", X totalclusters, freeclusters); X } X } X else X { X diskInfo [i].printFlag = DI_BAD; X if (debug) X { X printf ("disk %s; could not get disk space\n", X diskInfo [i].name); X } X } X } /* if printable drive */ X } /* for each mounted drive */ X} X X#endif /* HAS_GETDISKFREESPACE */ END_OF_FILE if test 97566 -ne `wc -c <'di.c'`; then echo shar: \"'di.c'\" unpacked with wrong size! fi # end of 'di.c' fi echo shar: End of archive 2 \(of 3\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0