OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / mgetty / getdisk.c
1 #ident "@(#)getdisk.c $Id: getdisk.c,v 4.4 2004/11/08 20:10:27 gert Exp $ Copyright (c) 1994 Elegant Communications Inc."
2
3 /*
4
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.
8
9         getdiskstats()  - disk partition statistics function.
10     
11         The key to configuration is choosing the right one of the
12         following five types:
13             BSDSTATFS     - BSD/hp-ux/SunOS/Dynix/vrios/OSF-1
14                             2-parameter statfs()
15             ULTRIXSTATFS  - Ultrix wacko statfs
16             SVR4          - SVR4 statvfs()
17             SVR3          - SVR3/88k/Apollo 4-parameter statfs()
18             USTAT         - ustat(), no statfs etc.
19         
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,
30     we key on "__hpux".
31
32         If all else fails, try USTAT which is fairly generic, but
33         doesn't return as much information as stat[v]fs does.
34         
35         getdiskstats(char * path, mntinf *mi)
36
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
40                     that has file "path".
41                 returns: 0 on success.
42  */
43
44 #include <stdio.h>
45
46 #include "policy.h"
47 #include "mgetty.h"
48
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
51  */
52 #undef MAXPATH
53
54
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
63    our jargon for a 3b2.
64  */
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) || \
70         defined(venc)
71 # define SVR3
72 #endif
73
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! :-) */
78 #endif
79
80 /* If your system is SVR4, the mgetty+sendfax Makefile should already
81    predefine SVR4
82  */
83 #if defined(vdrs) || defined(vdrs6k) || defined(vdcosx) || defined(vamiga) || \
84         defined(vnecews) || defined(vnecup) || defined(vnecnpx) || \
85         defined(vsnx386) || defined(vsnxmips) || defined(vsolaris)
86 # define SVR4
87 #endif
88
89 #ifdef ultrix
90 # define ULTRIXSTATFS
91 #endif
92
93 #if defined(_3B1_)
94 # define USTAT
95 #endif
96
97 /* imported from NetBSD pkgsrc */
98 #if defined(__NetBSD__) && (__NetBSD_Version__ > 200030000)
99 #undef BSDSTATFS
100 #define        SVR4
101 #endif 
102
103 #if defined(SVR4)
104 # define SVR3
105 #endif
106
107 #if defined(BSDSTATFS) || defined(ULTRIXSTATFS) || \
108     defined(SVR3) || defined(SVR4) || defined(USTAT)
109 # define HASDISKSTAT
110 #endif
111
112 /* END OF STATFS type fiddling */
113
114 /* this is the beginning of getdiskstats() proper
115  */
116
117 #ifdef ULTRIXSTATFS
118 #  include <sys/param.h>
119 #endif
120
121 #ifdef HASDISKSTAT
122 # if !defined(vsnxdyn) && !defined(vdomain) && !defined(_AIX)
123 #  include <sys/types.h>
124 #  include <sys/param.h>
125 #  include <sys/mount.h>
126 # endif
127
128 # ifdef BSDSTATFS
129 #  ifdef _AIX
130 #   include <sys/statfs.h>
131 #  else
132 #   ifdef __osf__
133 #    include <sys/mount.h>
134 #   else
135 #    if !defined(BSD) || defined(NeXT)
136 #     include <sys/vfs.h>
137 #    endif      /* !BSD */
138 #   endif       /* !__osf__ */
139 #  endif        /* _AIX */
140
141 #  define MYSTATFS(a,b) statfs(a,b)
142 #  define STATFSS statfs
143
144 # else          /* !BSDSTATFS */
145
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
156
157
158 #  else
159 #   ifdef USTAT
160 #    include <sys/stat.h>
161 #    include <ustat.h>
162
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
168 #   endif
169
170 #   ifdef SVR4
171
172 #    include <sys/statvfs.h>
173 #    define STATFSS statvfs
174 #    define MYSTATFS(a,b) statvfs(a,b)
175
176 #   else
177
178 #    if defined(SVR3) || defined(vdomain)       /* eg: Apollo/88k */
179
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)
185
186 #    endif /* SVR3 */
187 #   endif /* SVR4 */
188 #  endif /* ULTRIXSTATFS */
189 # endif /* BSDSTATFS */
190 #endif /* HASDISKSTAT */
191
192 long minfreespace = MINFREESPACE;
193
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
197    back "2".
198  */
199
200 #ifndef TESTDISK
201 int checkspace _P1 ((path), char *path)
202 {
203 #ifdef HASDISKSTAT
204     struct mountinfo mi;
205     unsigned int kbytes;
206
207     if (getdiskstats(path, &mi))
208         return(1);
209
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.
213      */
214     kbytes = (mi.mi_bavail>>2) * (mi.mi_bsize>>8);
215
216     lprintf( L_NOISE, "%d Mb free on %s", kbytes/1024, path );
217     return( kbytes / minfreespace);
218 #else
219     return(1);
220 #endif
221 }
222 #endif
223
224 /* All of the configuration crap above is simply so that this function
225    compiles.
226    
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".
230  */
231
232 int
233 getdiskstats _P2 ((path, mi), char *path, mntinf *mi)
234 {
235 #ifdef HASDISKSTAT
236     struct STATFSS info;
237
238 #ifdef USTAT
239     struct stat stb;
240 #endif
241
242     if (MYSTATFS(path, &info) < 0) {
243         return(1);
244     }
245     /* Systems known to lie & have NBPSCTR */
246 #if defined(ISC) || defined(M_UNIX) || defined(m88k)
247     /*
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.)
254      *
255      * SCO Unix 3.2.2 also lies.
256      */
257     mi->mi_bsize = (info.f_frsize > 0) ? info.f_frsize : NBPSCTR;
258 #else
259 # if defined(vmips) || defined(USTAT)
260     /*
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.
263      */
264     /*
265      * classic SVR2 ustat() implementations have no block size in the
266      * ustat structure, but has NBPSCTR in sys/param.h
267      */
268     mi->mi_bsize = NBPSCTR;
269 # else
270     /* Systems that don't define f_frsize at all 
271      * OR give a meaningless value.
272      */
273 #  if defined(BSDSTATFS) || defined(m88k)
274     mi->mi_bsize = info.f_bsize;
275 #  else
276     /* if frag size is given, it is the units for blocks
277      * otherwise, it is either bsize or somebody is running
278      * old code that lies
279      */
280     mi->mi_bsize = (info.f_frsize > 0) ? info.f_frsize : info.f_bsize;
281 #  endif
282 # endif
283 #endif
284     /*
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.
291      */
292 #ifdef USTAT
293     mi->mi_blocks = mi->mi_files = -1;
294 #else
295     mi->mi_blocks = info.f_blocks;
296     mi->mi_files = info.f_files;
297 #endif /* USTAT */
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;
301     
302     return(0);
303 #else
304     return(-1);
305 #endif /* STATFS */
306 }
307
308 /* Test program */
309
310 #ifdef TESTDISK
311
312 #if ! defined(HASDISKSTAT)
313 #include "ERROR: don't know how to get fs info - see Makefile for defines"
314 #endif
315
316 int main(argc, argv) int argc; char **argv; {
317     struct mountinfo mi;
318     argv++;
319
320     printf("%s personality\n",
321 #ifdef USTAT
322         "ustat()"
323 #endif
324 #ifdef ULTRIXSTATFS
325         "ultrix statfs()"
326 #endif
327 #ifdef BSDSTATFS
328         "BSD statfs()"
329 #endif
330 #ifdef SVR3
331         "SVR3 4parameter statfs()"
332 #endif
333 #ifdef SVR4
334         "SVR4 statvfs()"
335 #endif
336         );
337     while(*argv) {
338         if (getdiskstats(*argv, &mi)) {
339             fprintf(stderr, "statfs on %s failed\n", *argv);
340         } else {
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);
348         }
349         argv++;
350     }
351     exit(0);
352 }
353 #endif