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