|
|
1.1 root 1: /* fsusage.c -- return space usage of mounted filesystems
2: Copyright (C) 1991, 1992, 1996 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 Foundation,
16: Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17:
18: #include "sysconfig.h"
19:
20: #include <sys/types.h>
21:
22: #ifdef HAVE_SYS_STAT_H
23: #include <sys/stat.h>
24: #endif
25:
26: #include "fsusage.h"
27:
28: /* Return the number of TOSIZE-byte blocks used by
29: BLOCKS FROMSIZE-byte blocks, rounding away from zero.
30: TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
31:
32: static long
33: adjust_blocks (blocks, fromsize, tosize)
34: long blocks;
35: int fromsize, tosize;
36: {
37: if (tosize <= 0)
38: abort ();
39: if (fromsize <= 0)
40: return -1;
41:
42: if (fromsize == tosize) /* e.g., from 512 to 512 */
43: return blocks;
44: else if (fromsize > tosize) /* e.g., from 2048 to 512 */
45: return blocks * (fromsize / tosize);
46: else /* e.g., from 256 to 512 */
47: return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
48: }
49:
50: #ifdef _WIN32
51:
52: #include <windows.h>
53:
54: int
55: get_fs_usage (path, disk, fsp)
56: const char *path;
57: const char *disk;
58: struct fs_usage *fsp;
59: {
60: char buf1[1024];
61: char buf2[1024];
62: DWORD SectorsPerCluster;
63: DWORD BytesPerSector;
64: DWORD NumberOfFreeClusters;
65: DWORD TotalNumberOfClusters;
66:
67: fname_atow (path, buf1, sizeof buf1);
68:
69: GetFullPathName (buf1, sizeof buf2, buf2, NULL);
70:
71: buf2[3] = 0;
72:
73: if (!GetDiskFreeSpace (buf2, &SectorsPerCluster, &BytesPerSector,
74: &NumberOfFreeClusters, &TotalNumberOfClusters))
75: {
76: /* lasterror = GetLastError ();*/
77: return -1;
78: }
79:
80: BytesPerSector *= SectorsPerCluster;
81: fsp->fsu_blocks = adjust_blocks (TotalNumberOfClusters, BytesPerSector, 512);
82: fsp->fsu_bavail = adjust_blocks (NumberOfFreeClusters, BytesPerSector, 512);
83:
84: return 0;
85: }
86:
87: #else /* ! _WIN32 */
88:
89: int statfs ();
90:
91: #if HAVE_UNISTD_H
92: # include <unistd.h>
93: #endif
94:
95: #if HAVE_SYS_PARAM_H
96: # include <sys/param.h>
97: #endif
98:
99: #if HAVE_SYS_MOUNT_H
100: # include <sys/mount.h>
101: #endif
102:
103: #if HAVE_SYS_VFS_H
104: # include <sys/vfs.h>
105: #endif
106:
107: #if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */
108: # include <sys/fs/s5param.h>
109: #endif
110:
111: #if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY)
112: # include <sys/filsys.h> /* SVR2 */
113: #endif
114:
115: #if HAVE_FCNTL_H
116: # include <fcntl.h>
117: #endif
118:
119: #if HAVE_SYS_STATFS_H
120: # include <sys/statfs.h>
121: #endif
122:
123: #if HAVE_DUSTAT_H /* AIX PS/2 */
124: # include <sys/dustat.h>
125: #endif
126:
127: #if HAVE_SYS_STATVFS_H /* SVR4 */
128: # include <sys/statvfs.h>
129: int statvfs ();
130: #endif
131:
132: /* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
133: Return the actual number of bytes read, zero for EOF, or negative
134: for an error. */
135:
136: int
137: safe_read (desc, ptr, len)
138: int desc;
139: char *ptr;
140: int len;
141: {
142: int n_chars;
143:
144: if (len <= 0)
145: return len;
146:
147: #ifdef EINTR
148: do
149: {
150: n_chars = read (desc, ptr, len);
151: }
152: while (n_chars < 0 && errno == EINTR);
153: #else
154: n_chars = read (desc, ptr, len);
155: #endif
156:
157: return n_chars;
158: }
159:
160: /* Fill in the fields of FSP with information about space usage for
161: the filesystem on which PATH resides.
162: DISK is the device on which PATH is mounted, for space-getting
163: methods that need to know it.
164: Return 0 if successful, -1 if not. When returning -1, ensure that
165: ERRNO is either a system error value, or zero if DISK is NULL
166: on a system that requires a non-NULL value. */
167: int
168: get_fs_usage (path, disk, fsp)
169: const char *path;
170: const char *disk;
171: struct fs_usage *fsp;
172: {
173: #ifdef STAT_STATFS3_OSF1
174: # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512)
175:
176: struct statfs fsd;
177:
178: if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
179: return -1;
180:
181: #endif /* STAT_STATFS3_OSF1 */
182:
183: #ifdef STAT_STATFS2_FS_DATA /* Ultrix */
184: # define CONVERT_BLOCKS(B) adjust_blocks ((B), 1024, 512)
185:
186: struct fs_data fsd;
187:
188: if (statfs (path, &fsd) != 1)
189: return -1;
190: fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot);
191: fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree);
192: fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen);
193: fsp->fsu_files = fsd.fd_req.gtot;
194: fsp->fsu_ffree = fsd.fd_req.gfree;
195:
196: #endif /* STAT_STATFS2_FS_DATA */
197:
198: #ifdef STAT_READ_FILSYS /* SVR2 */
199: # ifndef SUPERBOFF
200: # define SUPERBOFF (SUPERB * 512)
201: # endif
202: # define CONVERT_BLOCKS(B) \
203: adjust_blocks ((B), (fsd.s_type == Fs2b ? 1024 : 512), 512)
204:
205: struct filsys fsd;
206: int fd;
207:
208: if (! disk)
209: {
210: errno = 0;
211: return -1;
212: }
213:
214: fd = open (disk, O_RDONLY);
215: if (fd < 0)
216: return -1;
217: lseek (fd, (long) SUPERBOFF, 0);
218: if (safe_read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd)
219: {
220: close (fd);
221: return -1;
222: }
223: close (fd);
224: fsp->fsu_blocks = CONVERT_BLOCKS (fsd.s_fsize);
225: fsp->fsu_bfree = CONVERT_BLOCKS (fsd.s_tfree);
226: fsp->fsu_bavail = CONVERT_BLOCKS (fsd.s_tfree);
227: fsp->fsu_files = (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1);
228: fsp->fsu_ffree = fsd.s_tinode;
229:
230: #endif /* STAT_READ_FILSYS */
231:
232: #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */
233: # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512)
234:
235: struct statfs fsd;
236:
237: if (statfs (path, &fsd) < 0)
238: return -1;
239:
240: # ifdef STATFS_TRUNCATES_BLOCK_COUNTS
241:
242: /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
243: struct statfs are truncated to 2GB. These conditions detect that
244: truncation, presumably without botching the 4.1.1 case, in which
245: the values are not truncated. The correct counts are stored in
246: undocumented spare fields. */
247: if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0)
248: {
249: fsd.f_blocks = fsd.f_spare[0];
250: fsd.f_bfree = fsd.f_spare[1];
251: fsd.f_bavail = fsd.f_spare[2];
252: }
253: # endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
254:
255: #endif /* STAT_STATFS2_BSIZE */
256:
257: #ifdef STAT_STATFS2_FSIZE /* 4.4BSD */
258: # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_fsize, 512)
259:
260: struct statfs fsd;
261:
262: if (statfs (path, &fsd) < 0)
263: return -1;
264:
265: #endif /* STAT_STATFS2_FSIZE */
266:
267: #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */
268: # if _AIX || defined(_CRAY)
269: # define CONVERT_BLOCKS(B) adjust_blocks ((B), fsd.f_bsize, 512)
270: # ifdef _CRAY
271: # define f_bavail f_bfree
272: # endif
273: # else
274: # define CONVERT_BLOCKS(B) (B)
275: # ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */
276: # ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
277: # define f_bavail f_bfree
278: # endif
279: # endif
280: # endif
281:
282: struct statfs fsd;
283:
284: if (statfs (path, &fsd, sizeof fsd, 0) < 0)
285: return -1;
286: /* Empirically, the block counts on most SVR3 and SVR3-derived
287: systems seem to always be in terms of 512-byte blocks,
288: no matter what value f_bsize has. */
289:
290: #endif /* STAT_STATFS4 */
291:
292: #ifdef STAT_STATVFS /* SVR4 */
293: # define CONVERT_BLOCKS(B) \
294: adjust_blocks ((B), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
295:
296: struct statvfs fsd;
297:
298: if (statvfs (path, &fsd) < 0)
299: return -1;
300: /* f_frsize isn't guaranteed to be supported. */
301:
302: #endif /* STAT_STATVFS */
303:
304: #if !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS)
305: /* !Ultrix && !SVR2 */
306:
307: fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks);
308: fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree);
309: fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail);
310: fsp->fsu_files = fsd.f_files;
311: fsp->fsu_ffree = fsd.f_ffree;
312:
313: #endif /* not STAT_STATFS2_FS_DATA && not STAT_READ_FILSYS */
314:
315: return 0;
316: }
317:
318: #if defined(_AIX) && defined(_I386)
319: /* AIX PS/2 does not supply statfs. */
320:
321: int
322: statfs (path, fsb)
323: char *path;
324: struct statfs *fsb;
325: {
326: struct stat stats;
327: struct dustat fsd;
328:
329: if (stat (path, &stats))
330: return -1;
331: if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
332: return -1;
333: fsb->f_type = 0;
334: fsb->f_bsize = fsd.du_bsize;
335: fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
336: fsb->f_bfree = fsd.du_tfree;
337: fsb->f_bavail = fsd.du_tfree;
338: fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
339: fsb->f_ffree = fsd.du_tinode;
340: fsb->f_fsid.val[0] = fsd.du_site;
341: fsb->f_fsid.val[1] = fsd.du_pckno;
342: return 0;
343: }
344:
345: #endif /* _AIX && _I386 */
346:
347: #endif /* ! _WIN32 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.