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