(adjust_blocks): Convert to a macro. The static
[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 #include <sys/types.h>
19 #include "fsusage.h"
20
21 int statfs ();
22
23 #if defined(STAT_STATFS2_BSIZE) && !defined(_IBMR2) /* 4.3BSD, SunOS 4, HP-UX, AIX PS/2.  */
24 #include <sys/vfs.h>
25 #endif
26
27 #ifdef STAT_STATFS2_FSIZE       /* 4.4BSD.  */
28 #include <sys/mount.h>
29 #endif
30
31 #ifdef STAT_STATFS2_FS_DATA     /* Ultrix.  */
32 #include <sys/param.h>
33 #include <sys/mount.h>
34 #endif
35
36 #ifdef STAT_READ                /* SVR2.  */
37 #include <sys/param.h>
38 #include <sys/filsys.h>
39 #include <fcntl.h>
40 #endif
41
42 #if defined(STAT_STATFS4) || (defined(_AIX) && defined(_IBMR2)) /* SVR3, Dynix, Irix, AIX RS6000.  */
43 #include <sys/statfs.h>
44 #endif
45
46 #if defined(_AIX) && defined(_I386) /* AIX PS/2.  */
47 #include <sys/stat.h>
48 #include <sys/dustat.h>
49 #endif
50
51 #ifdef STAT_STATVFS             /* SVR4.  */
52 #include <sys/statvfs.h>
53 int statvfs ();
54 #endif
55
56 /* Return the number of TOSIZE-byte blocks used by
57    BLOCKS FROMSIZE-byte blocks, rounding up.  */
58
59 #define adjust_blocks(blocks, fromsize, tosize)         \
60   (((fromsize) == (tosize))                             \
61    ? (blocks)   /* E.g., from 512 to 512.  */           \
62    : (((fromsize) > (tosize))                           \
63       /* E.g., from 2048 to 512.  */                    \
64       ? (blocks) * ((fromsize) / (tosize))              \
65       /* E.g., from 256 to 512.  */                     \
66       : ((blocks) + 1) / ((tosize) / (fromsize))))
67
68 /* Fill in the fields of FSP with information about space usage for
69    the filesystem on which PATH resides.
70    DISK is the device on which PATH is mounted, for space-getting
71    methods that need to know it.
72    Return 0 if successful, -1 if not. */
73
74 int
75 get_fs_usage (path, disk, fsp)
76      char *path, *disk;
77      struct fs_usage *fsp;
78 {
79 #ifdef STAT_STATFS2_FS_DATA     /* Ultrix.  */
80   struct fs_data fsd;
81
82   if (statfs (path, &fsd) != 1)
83     return -1;
84 #define convert_blocks(b) adjust_blocks ((b), 1024, 512)
85   fsp->fsu_blocks = convert_blocks (fsd.fd_req.btot);
86   fsp->fsu_bfree = convert_blocks (fsd.fd_req.bfree);
87   fsp->fsu_bavail = convert_blocks (fsd.fd_req.bfreen);
88   fsp->fsu_files = fsd.fd_req.gtot;
89   fsp->fsu_ffree = fsd.fd_req.gfree;
90 #endif
91
92 #ifdef STAT_READ                /* SVR2.  */
93 #ifndef SUPERBOFF
94 #define SUPERBOFF (SUPERB * 512)
95 #endif
96   struct filsys fsd;
97   int fd;
98
99   fd = open (disk, O_RDONLY);
100   if (fd < 0)
101     return -1;
102   lseek (fd, (long) SUPERBOFF, 0);
103   if (read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd)
104     {
105       close (fd);
106       return -1;
107     }
108   close (fd);
109 #define convert_blocks(b) adjust_blocks ((b), (fsd.s_type == Fs2b ? 1024 : 512), 512)
110   fsp->fsu_blocks = convert_blocks (fsd.s_fsize);
111   fsp->fsu_bfree = convert_blocks (fsd.s_tfree);
112   fsp->fsu_bavail = convert_blocks (fsd.s_tfree);
113   fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
114   fsp->fsu_ffree = fsd.s_tinode;
115 #endif
116
117 #ifdef STAT_STATFS2_BSIZE       /* 4.3BSD, SunOS 4, HP-UX, AIX.  */
118   struct statfs fsd;
119
120   if (statfs (path, &fsd) < 0)
121     return -1;
122 #define convert_blocks(b) adjust_blocks ((b), fsd.f_bsize, 512)
123 #endif
124
125 #ifdef STAT_STATFS2_FSIZE       /* 4.4BSD.  */
126   struct statfs fsd;
127
128   if (statfs (path, &fsd) < 0)
129     return -1;
130 #define convert_blocks(b) adjust_blocks ((b), fsd.f_fsize, 512)
131 #endif
132
133 #ifdef STAT_STATFS4             /* SVR3, Dynix, Irix.  */
134   struct statfs fsd;
135
136   if (statfs (path, &fsd, sizeof fsd, 0) < 0)
137     return -1;
138   /* Empirically, the block counts on most SVR3 and SVR3-derived
139      systems seem to always be in terms of 512-byte blocks,
140      no matter what value f_bsize has.  */
141 #define convert_blocks(b) (b)
142 #ifndef _SEQUENT_               /* _SEQUENT_ is DYNIX/ptx.  */
143 #define f_bavail f_bfree
144 #endif
145 #endif
146
147 #ifdef STAT_STATVFS             /* SVR4.  */
148   struct statvfs fsd;
149
150   if (statvfs (path, &fsd) < 0)
151     return -1;
152   /* f_frsize isn't guaranteed to be supported.  */
153 #define convert_blocks(b) \
154   adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
155 #endif
156
157 #if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ) /* !Ultrix && !SVR2.  */
158   fsp->fsu_blocks = convert_blocks (fsd.f_blocks);
159   fsp->fsu_bfree = convert_blocks (fsd.f_bfree);
160   fsp->fsu_bavail = convert_blocks (fsd.f_bavail);
161   fsp->fsu_files = fsd.f_files;
162   fsp->fsu_ffree = fsd.f_ffree;
163 #endif
164
165   return 0;
166 }
167
168 #if defined(_AIX) && defined(_I386)
169 /* AIX PS/2 does not supply statfs.  */
170
171 int
172 statfs (path, fsb)
173      char *path;
174      struct statfs *fsb;
175 {
176   struct stat stats;
177   struct dustat fsd;
178
179   if (stat (path, &stats))
180     return -1;
181   if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
182     return -1;
183   fsb->f_type   = 0;
184   fsb->f_bsize  = fsd.du_bsize;
185   fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
186   fsb->f_bfree  = fsd.du_tfree;
187   fsb->f_bavail = fsd.du_tfree;
188   fsb->f_files  = (fsd.du_isize - 2) * fsd.du_inopb;
189   fsb->f_ffree  = fsd.du_tinode;
190   fsb->f_fsid.val[0] = fsd.du_site;
191   fsb->f_fsid.val[1] = fsd.du_pckno;
192   return 0;
193 }
194 #endif /* _AIX && _I386 */