-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgetdisk.c
353 lines (299 loc) · 10.1 KB
/
getdisk.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#ident "@(#)getdisk.c $Id: getdisk.c,v 4.4 2004/11/08 20:10:27 gert Exp $ Copyright (c) 1994 Elegant Communications Inc."
/*
This software is graciously provided by Elegant Communications Inc.,
on the proviso that it is only used in Gert Doering's
mgetty+sendfax program.
getdiskstats() - disk partition statistics function.
The key to configuration is choosing the right one of the
following five types:
BSDSTATFS - BSD/hp-ux/SunOS/Dynix/vrios/OSF-1
2-parameter statfs()
ULTRIXSTATFS - Ultrix wacko statfs
SVR4 - SVR4 statvfs()
SVR3 - SVR3/88k/Apollo 4-parameter statfs()
USTAT - ustat(), no statfs etc.
The first section of code uses symbolic names to indicate which
platform needs which type of partition grabbing. In mgetty, this
source will automatically choose the right variant with ISC, AIX,
HP/UX, 3b1, sun and linux (I hope). If your system doesn't
automatically select by itself, try defining the "v*" macro from
below that seems closest to your system. For example, if you have a
3b2, insert "vu3b2" into CCFLAGS in the top-level makefile. If
you succeed, please let us know: which "v*" macro you used, and
whether your C compiler predefines a macro designating your system.
Eg: HP/UX predefines "__hpux" - instead of a "vhpux" macro,
we key on "__hpux".
If all else fails, try USTAT which is fairly generic, but
doesn't return as much information as stat[v]fs does.
getdiskstats(char * path, mntinf *mi)
path: pointer to file on partition to be statfs/ustat'd
mi: pointer to mntinf structure that will filled to
contain the partition statistics of the partition
that has file "path".
returns: 0 on success.
*/
#include <stdio.h>
#include "policy.h"
#include "mgetty.h"
/* some systems define this in an include file somewhere below, and mgetty.h
defines it as well. So just #undef it, we don't need it here anyway
*/
#undef MAXPATH
/* for the most part, these defines are simply used to show which
systems need which type of statfs/ustat(). They can all be
removed if the correct one of the 5 selectors is chosen
(say) in Makefile. There are, after these defines, a few
more #ifs that further figure out inclusions and other
things where the 5 selectors themselves are inadequate - in
many cases, they'll just turn out to be the defines that they
use on their systems already. For example, "vu3b2" is just
our jargon for a 3b2.
*/
#if defined(vmiti) || defined(vtandem) || defined(vmips) || defined(ISC) || \
defined(M_UNIX) || defined(m88k) || \
defined(vm68k) || defined(vu3b2) || \
defined(vxps) || defined(vu6050) || defined(vs5k80) || \
defined(vs5k50) || defined(vdpx2) || defined(vdynptx) || \
defined(venc)
# define SVR3
#endif
#if defined(vpyr) || defined(vsnxdyn) || defined(__hpux) || defined(vdynix) || \
defined(vaix) || defined(_AIX) || defined(vaixps2) || defined(sunos4) || \
defined(linux) || defined(__osf__) || defined(BSD)
# define BSDSTATFS /* as used from the att universe of Pyramid! :-) */
#endif
/* If your system is SVR4, the mgetty+sendfax Makefile should already
predefine SVR4
*/
#if defined(vdrs) || defined(vdrs6k) || defined(vdcosx) || defined(vamiga) || \
defined(vnecews) || defined(vnecup) || defined(vnecnpx) || \
defined(vsnx386) || defined(vsnxmips) || defined(vsolaris)
# define SVR4
#endif
#ifdef ultrix
# define ULTRIXSTATFS
#endif
#if defined(_3B1_)
# define USTAT
#endif
/* imported from NetBSD pkgsrc */
#if defined(__NetBSD__) && (__NetBSD_Version__ > 200030000)
#undef BSDSTATFS
#define SVR4
#endif
#if defined(SVR4)
# define SVR3
#endif
#if defined(BSDSTATFS) || defined(ULTRIXSTATFS) || \
defined(SVR3) || defined(SVR4) || defined(USTAT)
# define HASDISKSTAT
#endif
/* END OF STATFS type fiddling */
/* this is the beginning of getdiskstats() proper
*/
#ifdef ULTRIXSTATFS
# include <sys/param.h>
#endif
#ifdef HASDISKSTAT
# if !defined(vsnxdyn) && !defined(vdomain) && !defined(_AIX)
# include <sys/types.h>
# include <sys/param.h>
# include <sys/mount.h>
# endif
# ifdef BSDSTATFS
# ifdef _AIX
# include <sys/statfs.h>
# else
# ifdef __osf__
# include <sys/mount.h>
# else
# if !defined(BSD) || defined(NeXT)
# include <sys/vfs.h>
# endif /* !BSD */
# endif /* !__osf__ */
# endif /* _AIX */
# define MYSTATFS(a,b) statfs(a,b)
# define STATFSS statfs
# else /* !BSDSTATFS */
# ifdef ULTRIXSTATFS /* oh grotty, oh stupid, oh-nonstandard one */
# define MYSTATFS(a,b) statfs(a,b)
# define STATFSS fs_data
# define f_bavail fd_req.bfreen
# define f_ffree fd_req.gfree
# define f_bfree fd_req.bfree
# define f_frsize fd_req.bsize
# define f_bsize fd_req.bsize
# define f_blocks fd_req.btot
# define f_files fd_req.gtot
# else
# ifdef USTAT
# include <sys/stat.h>
# include <ustat.h>
# define STATFSS ustat
# define MYSTATFS(a,b) (stat(a, &stb) == 0 ? ustat(stb.st_dev, b) : -1)
# define f_bfree f_tfree
# define f_bavail f_tfree
# define f_ffree f_tinode
# endif
# ifdef SVR4
# include <sys/statvfs.h>
# define STATFSS statvfs
# define MYSTATFS(a,b) statvfs(a,b)
# else
# if defined(SVR3) || defined(vdomain) /* eg: Apollo/88k */
# include <sys/statfs.h>
# include <sys/param.h>
# define f_bavail f_bfree
# define STATFSS statfs
# define MYSTATFS(a,b) statfs(a,b,sizeof(struct STATFSS),0)
# endif /* SVR3 */
# endif /* SVR4 */
# endif /* ULTRIXSTATFS */
# endif /* BSDSTATFS */
#endif /* HASDISKSTAT */
long minfreespace = MINFREESPACE;
/* returns how many "minfreesize" hunks will fit onto the freespace
left on the partition that contains "path".
Ie: if you have 2.5Mb free, and minfreespace is 1Mb, you get
back "2".
*/
#ifndef TESTDISK
int checkspace _P1 ((path), char *path)
{
#ifdef HASDISKSTAT
struct mountinfo mi;
unsigned int kbytes;
if (getdiskstats(path, &mi))
return(1);
/* the "shift" stuff is actually a division by 1024, to get "kbytes"
* instead of bytes. But if we do it that way, we risk 32bit overflows
* on disks > 4G, or "0" if mi_bsize is 512 or 256.
*/
kbytes = (mi.mi_bavail>>2) * (mi.mi_bsize>>8);
lprintf( L_NOISE, "%d Mb free on %s", kbytes/1024, path );
return( kbytes / minfreespace);
#else
return(1);
#endif
}
#endif
/* All of the configuration crap above is simply so that this function
compiles.
Returns 0 on success, 1 otherwise.
a "mntinf" structure is passed back containing the stat[v]fs/ustat
information on the partition containing "path".
*/
int
getdiskstats _P2 ((path, mi), char *path, mntinf *mi)
{
#ifdef HASDISKSTAT
struct STATFSS info;
#ifdef USTAT
struct stat stb;
#endif
if (MYSTATFS(path, &info) < 0) {
return(1);
}
/* Systems known to lie & have NBPSCTR */
#if defined(ISC) || defined(M_UNIX) || defined(m88k)
/*
* Interactive 1.0.6 lies - it says bsize is 1024, but returns a frag
* size of zero instead of 512. NBPSCTR (Number of Bytes per Physical
* SeCToR) is defined as 512 in <sys/param.h>. This "bug" is probably
* due to 386/ix 1.0.6's default to only support 1024 byte filesystems
* (FsTYPE == 2), both in the kernel, and out, in which case BSIZE is
* 1024 too! (Smarter systems define FsTYPE to 3 outside of the kernel.)
*
* SCO Unix 3.2.2 also lies.
*/
mi->mi_bsize = (info.f_frsize > 0) ? info.f_frsize : NBPSCTR;
#else
# if defined(vmips) || defined(USTAT)
/*
* Mips 4.52 also lies - it claims bsize and frsize both as 1024, but
* it still uses a block size of 512 when reporting total/free blocks.
*/
/*
* classic SVR2 ustat() implementations have no block size in the
* ustat structure, but has NBPSCTR in sys/param.h
*/
mi->mi_bsize = NBPSCTR;
# else
/* Systems that don't define f_frsize at all
* OR give a meaningless value.
*/
# if defined(BSDSTATFS) || defined(m88k)
mi->mi_bsize = info.f_bsize;
# else
/* if frag size is given, it is the units for blocks
* otherwise, it is either bsize or somebody is running
* old code that lies
*/
mi->mi_bsize = (info.f_frsize > 0) ? info.f_frsize : info.f_bsize;
# endif
# endif
#endif
/*
* WARNING: on some systems (vrios & SVR4) the value for f_frsize (or
* f_bsize) may be correct for the remote system's real filesystem when
* used over NFS, but almost every NFS implementation will only return
* f_bfree (and f_bavail) in units of 1 Kb blocks and usually return -1
* for f_files and f_ffree. XRSAdf doesn't really have to be concerned
* with this inconsistancy, though the eXpert handler must be careful.
*/
#ifdef USTAT
mi->mi_blocks = mi->mi_files = -1;
#else
mi->mi_blocks = info.f_blocks;
mi->mi_files = info.f_files;
#endif /* USTAT */
mi->mi_bfree = info.f_bfree;
mi->mi_bavail = info.f_bavail; /* may be duplicate of f_bfree */
mi->mi_ffree = info.f_ffree;
return(0);
#else
return(-1);
#endif /* STATFS */
}
/* Test program */
#ifdef TESTDISK
#if ! defined(HASDISKSTAT)
#include "ERROR: don't know how to get fs info - see Makefile for defines"
#endif
int main(argc, argv) int argc; char **argv; {
struct mountinfo mi;
argv++;
printf("%s personality\n",
#ifdef USTAT
"ustat()"
#endif
#ifdef ULTRIXSTATFS
"ultrix statfs()"
#endif
#ifdef BSDSTATFS
"BSD statfs()"
#endif
#ifdef SVR3
"SVR3 4parameter statfs()"
#endif
#ifdef SVR4
"SVR4 statvfs()"
#endif
);
while(*argv) {
if (getdiskstats(*argv, &mi)) {
fprintf(stderr, "statfs on %s failed\n", *argv);
} else {
printf( "STATFS report on %s:\n", *argv );
printf( "\tfundamental file system block size %ld\n", mi.mi_bsize);
printf( "\ttotal data blocks in file system %ld\n", mi.mi_blocks);
printf( "\tfree block in fs %ld\n", mi.mi_bfree);
printf( "\tfree blocks avail to non-superuser %ld\n", mi.mi_bavail);
printf( "\ttotal file nodes in file system %ld\n", mi.mi_files);
printf( "\tfree file nodes in fs %ld\n", mi.mi_ffree);
}
argv++;
}
exit(0);
}
#endif