1 #ident "@(#)getdisk.c $Id: getdisk.c,v 4.4 2004/11/08 20:10:27 gert Exp $ Copyright (c) 1994 Elegant Communications Inc."
5 This software is graciously provided by Elegant Communications Inc.,
6 on the proviso that it is only used in Gert Doering's
7 mgetty+sendfax program.
9 getdiskstats() - disk partition statistics function.
11 The key to configuration is choosing the right one of the
13 BSDSTATFS - BSD/hp-ux/SunOS/Dynix/vrios/OSF-1
15 ULTRIXSTATFS - Ultrix wacko statfs
17 SVR3 - SVR3/88k/Apollo 4-parameter statfs()
18 USTAT - ustat(), no statfs etc.
20 The first section of code uses symbolic names to indicate which
21 platform needs which type of partition grabbing. In mgetty, this
22 source will automatically choose the right variant with ISC, AIX,
23 HP/UX, 3b1, sun and linux (I hope). If your system doesn't
24 automatically select by itself, try defining the "v*" macro from
25 below that seems closest to your system. For example, if you have a
26 3b2, insert "vu3b2" into CCFLAGS in the top-level makefile. If
27 you succeed, please let us know: which "v*" macro you used, and
28 whether your C compiler predefines a macro designating your system.
29 Eg: HP/UX predefines "__hpux" - instead of a "vhpux" macro,
32 If all else fails, try USTAT which is fairly generic, but
33 doesn't return as much information as stat[v]fs does.
35 getdiskstats(char * path, mntinf *mi)
37 path: pointer to file on partition to be statfs/ustat'd
38 mi: pointer to mntinf structure that will filled to
39 contain the partition statistics of the partition
41 returns: 0 on success.
49 /* some systems define this in an include file somewhere below, and mgetty.h
50 defines it as well. So just #undef it, we don't need it here anyway
55 /* for the most part, these defines are simply used to show which
56 systems need which type of statfs/ustat(). They can all be
57 removed if the correct one of the 5 selectors is chosen
58 (say) in Makefile. There are, after these defines, a few
59 more #ifs that further figure out inclusions and other
60 things where the 5 selectors themselves are inadequate - in
61 many cases, they'll just turn out to be the defines that they
62 use on their systems already. For example, "vu3b2" is just
65 #if defined(vmiti) || defined(vtandem) || defined(vmips) || defined(ISC) || \
66 defined(M_UNIX) || defined(m88k) || \
67 defined(vm68k) || defined(vu3b2) || \
68 defined(vxps) || defined(vu6050) || defined(vs5k80) || \
69 defined(vs5k50) || defined(vdpx2) || defined(vdynptx) || \
74 #if defined(vpyr) || defined(vsnxdyn) || defined(__hpux) || defined(vdynix) || \
75 defined(vaix) || defined(_AIX) || defined(vaixps2) || defined(sunos4) || \
76 defined(linux) || defined(__osf__) || defined(BSD)
77 # define BSDSTATFS /* as used from the att universe of Pyramid! :-) */
80 /* If your system is SVR4, the mgetty+sendfax Makefile should already
83 #if defined(vdrs) || defined(vdrs6k) || defined(vdcosx) || defined(vamiga) || \
84 defined(vnecews) || defined(vnecup) || defined(vnecnpx) || \
85 defined(vsnx386) || defined(vsnxmips) || defined(vsolaris)
97 /* imported from NetBSD pkgsrc */
98 #if defined(__NetBSD__) && (__NetBSD_Version__ > 200030000)
107 #if defined(BSDSTATFS) || defined(ULTRIXSTATFS) || \
108 defined(SVR3) || defined(SVR4) || defined(USTAT)
112 /* END OF STATFS type fiddling */
114 /* this is the beginning of getdiskstats() proper
118 # include <sys/param.h>
122 # if !defined(vsnxdyn) && !defined(vdomain) && !defined(_AIX)
123 # include <sys/types.h>
124 # include <sys/param.h>
125 # include <sys/mount.h>
130 # include <sys/statfs.h>
133 # include <sys/mount.h>
135 # if !defined(BSD) || defined(NeXT)
136 # include <sys/vfs.h>
138 # endif /* !__osf__ */
141 # define MYSTATFS(a,b) statfs(a,b)
142 # define STATFSS statfs
144 # else /* !BSDSTATFS */
146 # ifdef ULTRIXSTATFS /* oh grotty, oh stupid, oh-nonstandard one */
147 # define MYSTATFS(a,b) statfs(a,b)
148 # define STATFSS fs_data
149 # define f_bavail fd_req.bfreen
150 # define f_ffree fd_req.gfree
151 # define f_bfree fd_req.bfree
152 # define f_frsize fd_req.bsize
153 # define f_bsize fd_req.bsize
154 # define f_blocks fd_req.btot
155 # define f_files fd_req.gtot
160 # include <sys/stat.h>
163 # define STATFSS ustat
164 # define MYSTATFS(a,b) (stat(a, &stb) == 0 ? ustat(stb.st_dev, b) : -1)
165 # define f_bfree f_tfree
166 # define f_bavail f_tfree
167 # define f_ffree f_tinode
172 # include <sys/statvfs.h>
173 # define STATFSS statvfs
174 # define MYSTATFS(a,b) statvfs(a,b)
178 # if defined(SVR3) || defined(vdomain) /* eg: Apollo/88k */
180 # include <sys/statfs.h>
181 # include <sys/param.h>
182 # define f_bavail f_bfree
183 # define STATFSS statfs
184 # define MYSTATFS(a,b) statfs(a,b,sizeof(struct STATFSS),0)
188 # endif /* ULTRIXSTATFS */
189 # endif /* BSDSTATFS */
190 #endif /* HASDISKSTAT */
192 long minfreespace = MINFREESPACE;
194 /* returns how many "minfreesize" hunks will fit onto the freespace
195 left on the partition that contains "path".
196 Ie: if you have 2.5Mb free, and minfreespace is 1Mb, you get
201 int checkspace _P1 ((path), char *path)
207 if (getdiskstats(path, &mi))
210 /* the "shift" stuff is actually a division by 1024, to get "kbytes"
211 * instead of bytes. But if we do it that way, we risk 32bit overflows
212 * on disks > 4G, or "0" if mi_bsize is 512 or 256.
214 kbytes = (mi.mi_bavail>>2) * (mi.mi_bsize>>8);
216 lprintf( L_NOISE, "%d Mb free on %s", kbytes/1024, path );
217 return( kbytes / minfreespace);
224 /* All of the configuration crap above is simply so that this function
227 Returns 0 on success, 1 otherwise.
228 a "mntinf" structure is passed back containing the stat[v]fs/ustat
229 information on the partition containing "path".
233 getdiskstats _P2 ((path, mi), char *path, mntinf *mi)
242 if (MYSTATFS(path, &info) < 0) {
245 /* Systems known to lie & have NBPSCTR */
246 #if defined(ISC) || defined(M_UNIX) || defined(m88k)
248 * Interactive 1.0.6 lies - it says bsize is 1024, but returns a frag
249 * size of zero instead of 512. NBPSCTR (Number of Bytes per Physical
250 * SeCToR) is defined as 512 in <sys/param.h>. This "bug" is probably
251 * due to 386/ix 1.0.6's default to only support 1024 byte filesystems
252 * (FsTYPE == 2), both in the kernel, and out, in which case BSIZE is
253 * 1024 too! (Smarter systems define FsTYPE to 3 outside of the kernel.)
255 * SCO Unix 3.2.2 also lies.
257 mi->mi_bsize = (info.f_frsize > 0) ? info.f_frsize : NBPSCTR;
259 # if defined(vmips) || defined(USTAT)
261 * Mips 4.52 also lies - it claims bsize and frsize both as 1024, but
262 * it still uses a block size of 512 when reporting total/free blocks.
265 * classic SVR2 ustat() implementations have no block size in the
266 * ustat structure, but has NBPSCTR in sys/param.h
268 mi->mi_bsize = NBPSCTR;
270 /* Systems that don't define f_frsize at all
271 * OR give a meaningless value.
273 # if defined(BSDSTATFS) || defined(m88k)
274 mi->mi_bsize = info.f_bsize;
276 /* if frag size is given, it is the units for blocks
277 * otherwise, it is either bsize or somebody is running
280 mi->mi_bsize = (info.f_frsize > 0) ? info.f_frsize : info.f_bsize;
285 * WARNING: on some systems (vrios & SVR4) the value for f_frsize (or
286 * f_bsize) may be correct for the remote system's real filesystem when
287 * used over NFS, but almost every NFS implementation will only return
288 * f_bfree (and f_bavail) in units of 1 Kb blocks and usually return -1
289 * for f_files and f_ffree. XRSAdf doesn't really have to be concerned
290 * with this inconsistancy, though the eXpert handler must be careful.
293 mi->mi_blocks = mi->mi_files = -1;
295 mi->mi_blocks = info.f_blocks;
296 mi->mi_files = info.f_files;
298 mi->mi_bfree = info.f_bfree;
299 mi->mi_bavail = info.f_bavail; /* may be duplicate of f_bfree */
300 mi->mi_ffree = info.f_ffree;
312 #if ! defined(HASDISKSTAT)
313 #include "ERROR: don't know how to get fs info - see Makefile for defines"
316 int main(argc, argv) int argc; char **argv; {
320 printf("%s personality\n",
331 "SVR3 4parameter statfs()"
338 if (getdiskstats(*argv, &mi)) {
339 fprintf(stderr, "statfs on %s failed\n", *argv);
341 printf( "STATFS report on %s:\n", *argv );
342 printf( "\tfundamental file system block size %ld\n", mi.mi_bsize);
343 printf( "\ttotal data blocks in file system %ld\n", mi.mi_blocks);
344 printf( "\tfree block in fs %ld\n", mi.mi_bfree);
345 printf( "\tfree blocks avail to non-superuser %ld\n", mi.mi_bavail);
346 printf( "\ttotal file nodes in file system %ld\n", mi.mi_files);
347 printf( "\tfree file nodes in fs %ld\n", mi.mi_ffree);