|
|
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.