remove trailing blanks
[coreutils.git] / lib / fsusage.c
blobd9d5234bd98214d4cc7b4d96c341131a260af7b2
1 /* fsusage.c -- return space usage of mounted filesystems
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
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.
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.
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 Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 #if HAVE_CONFIG_H
19 # include <config.h>
20 #endif
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include "fsusage.h"
26 int statfs ();
28 #if HAVE_SYS_PARAM_H
29 # include <sys/param.h>
30 #endif
32 #if HAVE_SYS_MOUNT_H
33 # include <sys/mount.h>
34 #endif
36 #if HAVE_SYS_VFS_H
37 # include <sys/vfs.h>
38 #endif
40 #if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */
41 # include <sys/fs/s5param.h>
42 #endif
44 #if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY)
45 # include <sys/filsys.h> /* SVR2 */
46 #endif
48 #if HAVE_FCNTL_H
49 # include <fcntl.h>
50 #endif
52 #if HAVE_SYS_STATFS_H
53 # include <sys/statfs.h>
54 #endif
56 #if HAVE_DUSTAT_H /* AIX PS/2 */
57 # include <sys/dustat.h>
58 #endif
60 #if HAVE_SYS_STATVFS_H /* SVR4 */
61 # include <sys/statvfs.h>
62 int statvfs ();
63 #endif
65 int safe_read ();
67 /* Return the number of TOSIZE-byte blocks used by
68 BLOCKS FROMSIZE-byte blocks, rounding away from zero.
69 TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
71 static long
72 adjust_blocks (blocks, fromsize, tosize)
73 long blocks;
74 int fromsize, tosize;
76 if (tosize <= 0)
77 abort ();
78 if (fromsize <= 0)
79 return -1;
81 if (fromsize == tosize) /* e.g., from 512 to 512 */
82 return blocks;
83 else if (fromsize > tosize) /* e.g., from 2048 to 512 */
84 return blocks * (fromsize / tosize);
85 else /* e.g., from 256 to 512 */
86 return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
89 /* Fill in the fields of FSP with information about space usage for
90 the filesystem on which PATH resides.
91 DISK is the device on which PATH is mounted, for space-getting
92 methods that need to know it.
93 Return 0 if successful, -1 if not. */
95 int
96 get_fs_usage (path, disk, fsp)
97 const char *path;
98 const char *disk;
99 struct fs_usage *fsp;
101 #ifdef STAT_STATFS3_OSF1
102 # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512)
104 struct statfs fsd;
106 if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
107 return -1;
109 #endif /* STAT_STATFS3_OSF1 */
111 #ifdef STAT_STATFS2_FS_DATA /* Ultrix */
112 # define CONVERT_BLOCKS(B) adjust_blocks ((B), 1024, 512)
114 struct fs_data fsd;
116 if (statfs (path, &fsd) != 1)
117 return -1;
118 fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot);
119 fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree);
120 fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen);
121 fsp->fsu_files = fsd.fd_req.gtot;
122 fsp->fsu_ffree = fsd.fd_req.gfree;
124 #endif /* STAT_STATFS2_FS_DATA */
126 #ifdef STAT_READ_FILSYS /* SVR2 */
127 # ifndef SUPERBOFF
128 # define SUPERBOFF (SUPERB * 512)
129 # endif
130 # define CONVERT_BLOCKS(B) \
131 adjust_blocks ((B), (fsd.s_type == Fs2b ? 1024 : 512), 512)
133 struct filsys fsd;
134 int fd;
136 fd = open (disk, O_RDONLY);
137 if (fd < 0)
138 return -1;
139 lseek (fd, (long) SUPERBOFF, 0);
140 if (safe_read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd)
142 close (fd);
143 return -1;
145 close (fd);
146 fsp->fsu_blocks = CONVERT_BLOCKS (fsd.s_fsize);
147 fsp->fsu_bfree = CONVERT_BLOCKS (fsd.s_tfree);
148 fsp->fsu_bavail = CONVERT_BLOCKS (fsd.s_tfree);
149 fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
150 fsp->fsu_ffree = fsd.s_tinode;
152 #endif /* STAT_READ_FILSYS */
154 #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */
155 # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512)
157 struct statfs fsd;
159 if (statfs (path, &fsd) < 0)
160 return -1;
162 # ifdef STATFS_TRUNCATES_BLOCK_COUNTS
164 /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
165 struct statfs are truncated to 2GB. These conditions detect that
166 truncation, presumably without botching the 4.1.1 case, in which
167 the values are not truncated. The correct counts are stored in
168 undocumented spare fields. */
169 if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0)
171 fsd.f_blocks = fsd.f_spare[0];
172 fsd.f_bfree = fsd.f_spare[1];
173 fsd.f_bavail = fsd.f_spare[2];
175 # endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
177 #endif /* STAT_STATFS2_BSIZE */
179 #ifdef STAT_STATFS2_FSIZE /* 4.4BSD */
180 # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512)
182 struct statfs fsd;
184 if (statfs (path, &fsd) < 0)
185 return -1;
187 #endif /* STAT_STATFS2_FSIZE */
189 #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */
190 # if _AIX || defined(_CRAY)
191 # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512)
192 # ifdef _CRAY
193 # define f_bavail f_bfree
194 # endif
195 # else
196 # define CONVERT_BLOCKS(B) (B)
197 # ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */
198 # ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
199 # define f_bavail f_bfree
200 # endif
201 # endif
202 # endif
204 struct statfs fsd;
206 if (statfs (path, &fsd, sizeof fsd, 0) < 0)
207 return -1;
208 /* Empirically, the block counts on most SVR3 and SVR3-derived
209 systems seem to always be in terms of 512-byte blocks,
210 no matter what value f_bsize has. */
212 #endif /* STAT_STATFS4 */
214 #ifdef STAT_STATVFS /* SVR4 */
215 # define CONVERT_BLOCKS(B) \
216 adjust_blocks ((B), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
218 struct statvfs fsd;
220 if (statvfs (path, &fsd) < 0)
221 return -1;
222 /* f_frsize isn't guaranteed to be supported. */
224 #endif /* STAT_STATVFS */
226 #if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS)
227 /* !Ultrix && !SVR2 */
229 fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks);
230 fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree);
231 fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail);
232 fsp->fsu_files = fsd.f_files;
233 fsp->fsu_ffree = fsd.f_ffree;
235 #endif /* not STAT_STATFS2_FS_DATA && not STAT_READ_FILSYS */
237 return 0;
240 #if defined(_AIX) && defined(_I386)
241 /* AIX PS/2 does not supply statfs. */
244 statfs (path, fsb)
245 char *path;
246 struct statfs *fsb;
248 struct stat stats;
249 struct dustat fsd;
251 if (stat (path, &stats))
252 return -1;
253 if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
254 return -1;
255 fsb->f_type = 0;
256 fsb->f_bsize = fsd.du_bsize;
257 fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
258 fsb->f_bfree = fsd.du_tfree;
259 fsb->f_bavail = fsd.du_tfree;
260 fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
261 fsb->f_ffree = fsd.du_tinode;
262 fsb->f_fsid.val[0] = fsd.du_site;
263 fsb->f_fsid.val[1] = fsd.du_pckno;
264 return 0;
267 #endif /* _AIX && _I386 */