GNU file utilities
[gnulib.git] / lib / fsusage.c
1 /* fsusage.c -- return space usage of mounted filesystems
2    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17
18 #ifdef HAVE_CONFIG_H
19 #if defined (CONFIG_BROKETS)
20 /* We use <config.h> instead of "config.h" so that a compilation
21    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
22    (which it would do because it found this file in $srcdir).  */
23 #include <config.h>
24 #else
25 #include "config.h"
26 #endif
27 #endif
28
29 #include <sys/types.h>
30 #include "fsusage.h"
31
32 int statfs ();
33
34 #if defined (STAT_STATFS3_OSF1) /* DEC Alpha running OSF/1 */
35 #  include <sys/mount.h>
36 #endif
37
38 #if defined(STAT_STATFS2_BSIZE) && !defined(_IBMR2) /* 4.3BSD, SunOS 4, HP-UX, AIX PS/2.  */
39 #include <sys/vfs.h>
40 #endif
41
42 #ifdef STAT_STATFS2_FSIZE       /* 4.4BSD.  */
43 #include <sys/mount.h>
44 #endif
45
46 #ifdef STAT_STATFS2_FS_DATA     /* Ultrix.  */
47 #include <sys/param.h>
48 #include <sys/mount.h>
49 #endif
50
51 #ifdef STAT_READ                /* SVR2.  */
52 #include <sys/param.h>
53 #include <sys/filsys.h>
54 #include <fcntl.h>
55 #endif
56
57 #if defined(STAT_STATFS4) || (defined(_AIX) && defined(_IBMR2)) /* SVR3, Dynix, Irix, AIX RS6000.  */
58 #include <sys/statfs.h>
59 #endif
60
61 #if defined(_AIX) && defined(_I386) /* AIX PS/2.  */
62 #include <sys/stat.h>
63 #include <sys/dustat.h>
64 #endif
65
66 #ifdef STAT_STATVFS             /* SVR4.  */
67 #include <sys/statvfs.h>
68 int statvfs ();
69 #endif
70
71 /* Return the number of TOSIZE-byte blocks used by
72    BLOCKS FROMSIZE-byte blocks, rounding away from zero.  */
73
74 static long
75 adjust_blocks (blocks, fromsize, tosize)
76      long blocks;
77      int fromsize, tosize;
78 {
79   if (fromsize == tosize)       /* E.g., from 512 to 512.  */
80     return blocks;
81   else if (fromsize > tosize)   /* E.g., from 2048 to 512.  */
82     return blocks * (fromsize / tosize);
83   else                          /* E.g., from 256 to 512.  */
84     return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
85 }
86
87 /* Fill in the fields of FSP with information about space usage for
88    the filesystem on which PATH resides.
89    DISK is the device on which PATH is mounted, for space-getting
90    methods that need to know it.
91    Return 0 if successful, -1 if not. */
92
93 int
94 get_fs_usage (path, disk, fsp)
95      char *path, *disk;
96      struct fs_usage *fsp;
97 {
98 #if defined (STAT_STATFS3_OSF1)
99   struct statfs fsd;
100
101   if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
102     return (-1);
103 #define convert_blocks(b) adjust_blocks ((b),fsd.f_fsize, 512)
104 #endif /* STAT_STATFS3_OSF1 */
105
106 #ifdef STAT_STATFS2_FS_DATA     /* Ultrix.  */
107   struct fs_data fsd;
108
109   if (statfs (path, &fsd) != 1)
110     return -1;
111 #define convert_blocks(b) adjust_blocks ((b), 1024, 512)
112   fsp->fsu_blocks = convert_blocks (fsd.fd_req.btot);
113   fsp->fsu_bfree = convert_blocks (fsd.fd_req.bfree);
114   fsp->fsu_bavail = convert_blocks (fsd.fd_req.bfreen);
115   fsp->fsu_files = fsd.fd_req.gtot;
116   fsp->fsu_ffree = fsd.fd_req.gfree;
117 #endif
118
119 #ifdef STAT_READ                /* SVR2.  */
120 #ifndef SUPERBOFF
121 #define SUPERBOFF (SUPERB * 512)
122 #endif
123   struct filsys fsd;
124   int fd;
125
126   fd = open (disk, O_RDONLY);
127   if (fd < 0)
128     return -1;
129   lseek (fd, (long) SUPERBOFF, 0);
130   if (read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd)
131     {
132       close (fd);
133       return -1;
134     }
135   close (fd);
136 #define convert_blocks(b) adjust_blocks ((b), (fsd.s_type == Fs2b ? 1024 : 512), 512)
137   fsp->fsu_blocks = convert_blocks (fsd.s_fsize);
138   fsp->fsu_bfree = convert_blocks (fsd.s_tfree);
139   fsp->fsu_bavail = convert_blocks (fsd.s_tfree);
140   fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
141   fsp->fsu_ffree = fsd.s_tinode;
142 #endif
143
144 #ifdef STAT_STATFS2_BSIZE       /* 4.3BSD, SunOS 4, HP-UX, AIX.  */
145   struct statfs fsd;
146
147   if (statfs (path, &fsd) < 0)
148     return -1;
149 #define convert_blocks(b) adjust_blocks ((b), fsd.f_bsize, 512)
150 #endif
151
152 #ifdef STAT_STATFS2_FSIZE       /* 4.4BSD.  */
153   struct statfs fsd;
154
155   if (statfs (path, &fsd) < 0)
156     return -1;
157 #define convert_blocks(b) adjust_blocks ((b), fsd.f_fsize, 512)
158 #endif
159
160 #ifdef STAT_STATFS4             /* SVR3, Dynix, Irix.  */
161   struct statfs fsd;
162
163   if (statfs (path, &fsd, sizeof fsd, 0) < 0)
164     return -1;
165   /* Empirically, the block counts on most SVR3 and SVR3-derived
166      systems seem to always be in terms of 512-byte blocks,
167      no matter what value f_bsize has.  */
168 #define convert_blocks(b) (b)
169 #ifndef _SEQUENT_               /* _SEQUENT_ is DYNIX/ptx.  */
170 #ifndef DOLPHIN                 /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
171 #define f_bavail f_bfree
172 #endif
173 #endif
174 #endif
175
176 #ifdef STAT_STATVFS             /* SVR4.  */
177   struct statvfs fsd;
178
179   if (statvfs (path, &fsd) < 0)
180     return -1;
181   /* f_frsize isn't guaranteed to be supported.  */
182 #define convert_blocks(b) \
183   adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
184 #endif
185
186 #if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ) /* !Ultrix && !SVR2.  */
187   fsp->fsu_blocks = convert_blocks (fsd.f_blocks);
188   fsp->fsu_bfree = convert_blocks (fsd.f_bfree);
189   fsp->fsu_bavail = convert_blocks (fsd.f_bavail);
190   fsp->fsu_files = fsd.f_files;
191   fsp->fsu_ffree = fsd.f_ffree;
192 #endif
193
194   return 0;
195 }
196
197 #if defined(_AIX) && defined(_I386)
198 /* AIX PS/2 does not supply statfs.  */
199
200 int
201 statfs (path, fsb)
202      char *path;
203      struct statfs *fsb;
204 {
205   struct stat stats;
206   struct dustat fsd;
207
208   if (stat (path, &stats))
209     return -1;
210   if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
211     return -1;
212   fsb->f_type   = 0;
213   fsb->f_bsize  = fsd.du_bsize;
214   fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
215   fsb->f_bfree  = fsd.du_tfree;
216   fsb->f_bavail = fsd.du_tfree;
217   fsb->f_files  = (fsd.du_isize - 2) * fsd.du_inopb;
218   fsb->f_ffree  = fsd.du_tinode;
219   fsb->f_fsid.val[0] = fsd.du_site;
220   fsb->f_fsid.val[1] = fsd.du_pckno;
221   return 0;
222 }
223 #endif /* _AIX && _I386 */