int fstatvfs64 (int fd, struct statvfs64 *buf) { /* `struct statvfs64' is in fact identical to `struct statfs64' so we can simply call fstatfs64. */ return __fstatfs64 (fd, (struct statfs64 *)buf); }
/* Return information about the filesystem on which FD resides. */ int __fstatvfs64 (int fd, struct statvfs64 *buf) { struct statfs64 fsbuf; int res = __fstatfs64 (fd, &fsbuf); #ifndef __ASSUME_STATFS64 if (res < 0 && errno == ENOSYS) { struct statvfs buf32; res = fstatvfs (fd, &buf32); if (res == 0) { buf->f_bsize = buf32.f_bsize; buf->f_frsize = buf32.f_frsize; buf->f_blocks = buf32.f_blocks; buf->f_bfree = buf32.f_bfree; buf->f_bavail = buf32.f_bavail; buf->f_files = buf32.f_files; buf->f_ffree = buf32.f_ffree; buf->f_favail = buf32.f_favail; buf->f_fsid = buf32.f_fsid; buf->f_flag = buf32.f_flag; buf->f_namemax = buf32.f_namemax; memcpy (buf->__f_spare, buf32.__f_spare, sizeof (buf32.__f_spare)); } } #endif if (res == 0) { /* Convert the result. */ struct stat64 st; __internal_statvfs64 (NULL, buf, &fsbuf, fstat64 (fd, &st) == -1 ? NULL : &st); } return res; }
int __posix_fallocate64_l64 (int fd, __off64_t offset, __off64_t len) { struct stat64 st; if (offset < 0 || len < 0) return EINVAL; /* Perform overflow check. The outer cast relies on a GCC extension. */ if ((__off64_t) ((uint64_t) offset + (uint64_t) len) < 0) return EFBIG; /* pwrite64 below will not do the right thing in O_APPEND mode. */ { int flags = __fcntl (fd, F_GETFL, 0); if (flags < 0 || (flags & O_APPEND) != 0) return EBADF; } /* We have to make sure that this is really a regular file. */ if (__fxstat64 (_STAT_VER, fd, &st) != 0) return EBADF; if (S_ISFIFO (st.st_mode)) return ESPIPE; if (! S_ISREG (st.st_mode)) return ENODEV; if (len == 0) { /* This is racy, but there is no good way to satisfy a zero-length allocation request. */ if (st.st_size < offset) { int ret = __ftruncate64 (fd, offset); if (ret != 0) ret = errno; return ret; } return 0; } /* Minimize data transfer for network file systems, by issuing single-byte write requests spaced by the file system block size. (Most local file systems have fallocate support, so this fallback code is not used there.) */ unsigned increment; { struct statfs64 f; if (__fstatfs64 (fd, &f) != 0) return errno; if (f.f_bsize == 0) increment = 512; else if (f.f_bsize < 4096) increment = f.f_bsize; else /* NFS clients do not propagate the block size of the underlying storage and may report a much larger value which would still leave holes after the loop below, so we cap the increment at 4096. */ increment = 4096; } /* Write a null byte to every block. This is racy; we currently lack a better option. Compare-and-swap against a file mapping might address local races, but requires interposition of a signal handler to catch SIGBUS. */ for (offset += (len - 1) % increment; len > 0; offset += increment) { len -= increment; if (offset < st.st_size) { unsigned char c; ssize_t rsize = __libc_pread64 (fd, &c, 1, offset); if (rsize < 0) return errno; /* If there is a non-zero byte, the block must have been allocated already. */ else if (rsize == 1 && c != 0) continue; } if (__libc_pwrite64 (fd, "", 1, offset) != 1) return errno; } return 0; }
int fstatfs(int fd, struct statfs* stat) { return __fstatfs64(fd, sizeof(struct statfs), stat); }