Polyfill statfs() and fstatfs() on Windows

This commit is contained in:
Justine Tunney 2022-08-17 18:57:03 -07:00
parent f7ee9d7d99
commit c2211c9e63
16 changed files with 370 additions and 50 deletions

View file

@ -8,8 +8,10 @@
*/
#endif
#include "libc/calls/struct/statfs.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/nt/enum/statfs.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/st.h"
@ -44,41 +46,106 @@ dontinline void ShowIt(const char *path) {
"maximum length of filenames");
printf("f_flags = %#x", sf.f_flags);
if (ST_RDONLY && (sf.f_flags & ST_RDONLY)) {
printf(" ST_RDONLY");
}
if (ST_NOSUID && (sf.f_flags & ST_NOSUID)) {
printf(" ST_NOSUID");
}
if (ST_NODEV && (sf.f_flags & ST_NODEV)) {
printf(" ST_NODEV");
}
if (ST_NOEXEC && (sf.f_flags & ST_NOEXEC)) {
printf(" ST_NOEXEC");
}
if (ST_SYNCHRONOUS && (sf.f_flags & ST_SYNCHRONOUS)) {
printf(" ST_SYNCHRONOUS");
}
if (ST_MANDLOCK && (sf.f_flags & ST_MANDLOCK)) {
printf(" ST_MANDLOCK");
}
if (ST_WRITE && (sf.f_flags & ST_WRITE)) {
printf(" ST_WRITE");
}
if (ST_APPEND && (sf.f_flags & ST_APPEND)) {
printf(" ST_APPEND");
}
if (ST_IMMUTABLE && (sf.f_flags & ST_IMMUTABLE)) {
printf(" ST_IMMUTABLE");
}
if (ST_NOATIME && (sf.f_flags & ST_NOATIME)) {
printf(" ST_NOATIME");
}
if (ST_NODIRATIME && (sf.f_flags & ST_NODIRATIME)) {
printf(" ST_NODIRATIME");
}
if (ST_RELATIME && (sf.f_flags & ST_RELATIME)) {
printf(" ST_RELATIME");
if (!IsWindows()) {
if (ST_RDONLY && (sf.f_flags & ST_RDONLY)) {
printf(" ST_RDONLY");
}
if (ST_NOSUID && (sf.f_flags & ST_NOSUID)) {
printf(" ST_NOSUID");
}
if (ST_NODEV && (sf.f_flags & ST_NODEV)) {
printf(" ST_NODEV");
}
if (ST_NOEXEC && (sf.f_flags & ST_NOEXEC)) {
printf(" ST_NOEXEC");
}
if (ST_SYNCHRONOUS && (sf.f_flags & ST_SYNCHRONOUS)) {
printf(" ST_SYNCHRONOUS");
}
if (ST_MANDLOCK && (sf.f_flags & ST_MANDLOCK)) {
printf(" ST_MANDLOCK");
}
if (ST_WRITE && (sf.f_flags & ST_WRITE)) {
printf(" ST_WRITE");
}
if (ST_APPEND && (sf.f_flags & ST_APPEND)) {
printf(" ST_APPEND");
}
if (ST_IMMUTABLE && (sf.f_flags & ST_IMMUTABLE)) {
printf(" ST_IMMUTABLE");
}
if (ST_NOATIME && (sf.f_flags & ST_NOATIME)) {
printf(" ST_NOATIME");
}
if (ST_NODIRATIME && (sf.f_flags & ST_NODIRATIME)) {
printf(" ST_NODIRATIME");
}
if (ST_RELATIME && (sf.f_flags & ST_RELATIME)) {
printf(" ST_RELATIME");
}
} else {
if (sf.f_flags & kNtFileCasePreservedNames) {
printf(" CasePreservedNames");
}
if (sf.f_flags & kNtFileCaseSensitiveSearch) {
printf(" CaseSensitiveSearch");
}
if (sf.f_flags & kNtFileFileCompression) {
printf(" FileCompression");
}
if (sf.f_flags & kNtFileNamedStreams) {
printf(" NamedStreams");
}
if (sf.f_flags & kNtFilePersistentAcls) {
printf(" PersistentAcls");
}
if (sf.f_flags & kNtFileReadOnlyVolume) {
printf(" ReadOnlyVolume");
}
if (sf.f_flags & kNtFileSequentialWriteOnce) {
printf(" SequentialWriteOnce");
}
if (sf.f_flags & kNtFileSupportsEncryption) {
printf(" SupportsEncryption");
}
if (sf.f_flags & kNtFileSupportsExtendedAttributes) {
printf(" SupportsExtendedAttributes");
}
if (sf.f_flags & kNtFileSupportsHardLinks) {
printf(" SupportsHardLinks");
}
if (sf.f_flags & kNtFileSupportsObjectIds) {
printf(" SupportsObjectIds");
}
if (sf.f_flags & kNtFileSupportsOpenByFileId) {
printf(" SupportsOpenByFileId");
}
if (sf.f_flags & kNtFileSupportsReparsePoints) {
printf(" SupportsReparsePoints");
}
if (sf.f_flags & kNtFileSupportsSparseFiles) {
printf(" SupportsSparseFiles");
}
if (sf.f_flags & kNtFileSupportsTransactions) {
printf(" SupportsTransactions");
}
if (sf.f_flags & kNtFileSupportsUsnJournal) {
printf(" SupportsUsnJournal");
}
if (sf.f_flags & kNtFileUnicodeOnDisk) {
printf(" UnicodeOnDisk");
}
if (sf.f_flags & kNtFileVolumeIsCompressed) {
printf(" VolumeIsCompressed");
}
if (sf.f_flags & kNtFileVolumeQuotas) {
printf(" VolumeQuotas");
}
if (sf.f_flags & kNtFileSupportsBlockRefcounting) {
printf(" SupportsBlockRefcounting");
}
}
printf("\n");

86
libc/calls/fstatfs-nt.c Normal file
View file

@ -0,0 +1,86 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/statfs.h"
#include "libc/calls/struct/statfs.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/fsinformationclass.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/files.h"
#include "libc/nt/ntdll.h"
#include "libc/nt/struct/byhandlefileinformation.h"
#include "libc/nt/struct/filefsfullsizeinformation.h"
#include "libc/nt/struct/iostatusblock.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_fstatfs_nt(int64_t handle, struct statfs *f) {
uint64_t w;
NtStatus st;
uint32_t type;
uint32_t h, i, j;
struct NtIoStatusBlock io;
struct NtFileFsFullSizeInformation fs;
char16_t VolumeNameBuffer[261];
uint32_t VolumeSerialNumber;
uint32_t MaximumComponentLength;
uint32_t FileSystemFlags;
char16_t FileSystemNameBuffer[261];
if (!GetVolumeInformationByHandle(
handle, VolumeNameBuffer, ARRAYLEN(VolumeNameBuffer),
&VolumeSerialNumber, &MaximumComponentLength, &FileSystemFlags,
FileSystemNameBuffer, ARRAYLEN(FileSystemNameBuffer))) {
return __winerr();
}
st = NtQueryVolumeInformationFile(handle, &io, &fs, sizeof(fs),
kNtFileFsFullSizeInformation);
if (!NtSuccess(st)) {
if (st == kNtStatusDllNotFound) return enosys();
return eio();
}
for (h = j = i = 0; FileSystemNameBuffer[i]; i++) {
w = tpenc(FileSystemNameBuffer[i]);
do {
if (j + 1 < sizeof(f->f_fstypename)) {
h = ((unsigned)(w & 255) + h) * 0x9e3779b1u;
f->f_fstypename[j++] = w;
}
} while ((w >>= 8));
}
f->f_fstypename[j] = 0;
f->f_type = h;
f->f_fsid = VolumeSerialNumber;
f->f_flags = FileSystemFlags;
f->f_bsize = fs.BytesPerSector;
f->f_bsize *= fs.SectorsPerAllocationUnit;
f->f_frsize = f->f_bsize;
f->f_blocks = fs.TotalAllocationUnits;
f->f_bfree = fs.ActualAvailableAllocationUnits;
f->f_bavail = fs.CallerAvailableAllocationUnits;
f->f_files = INT64_MAX;
f->f_ffree = INT64_MAX;
f->f_namelen = 255;
f->f_owner = 0;
return 0;
}

View file

@ -17,10 +17,13 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/statfs-meta.internal.h"
#include "libc/calls/struct/statfs.internal.h"
#include "libc/dce.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/errfuns.h"
/**
* Returns information about filesystem.
@ -29,8 +32,14 @@ int fstatfs(int fd, struct statfs *sf) {
int rc;
union statfs_meta m;
CheckLargeStackAllocation(&m, sizeof(m));
if ((rc = sys_fstatfs(fd, &m)) != -1) {
statfs2cosmo(sf, &m);
if (!IsWindows()) {
if ((rc = sys_fstatfs(fd, &m)) != -1) {
statfs2cosmo(sf, &m);
}
} else if (__isfdopen(fd)) {
rc = sys_fstatfs_nt(g_fds.p[fd].handle, sf);
} else {
rc = ebadf();
}
STRACE("fstatfs(%d, [%s]) → %d% m", fd, DescribeStatfs(rc, sf));
return rc;

44
libc/calls/statfs-nt.c Normal file
View file

@ -0,0 +1,44 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/statfs.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filesharemode.h"
#include "libc/nt/runtime.h"
textwindows int sys_statfs_nt(const char *path, struct statfs *sf) {
int rc;
int64_t h;
char16_t path16[PATH_MAX];
if (__mkntpath(path, path16) == -1) return -1;
h = __fix_enotdir(
CreateFile(path16, kNtFileGenericRead,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
&kNtIsInheritable, kNtOpenExisting,
kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0),
path16);
if (h == -1) return -1;
rc = sys_fstatfs_nt(h, sf);
CloseHandle(h);
return rc;
}

View file

@ -17,10 +17,14 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/statfs-meta.internal.h"
#include "libc/calls/struct/statfs.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/at.h"
/**
* Returns information about filesystem.
@ -29,8 +33,12 @@ int statfs(const char *path, struct statfs *sf) {
int rc;
union statfs_meta m;
CheckLargeStackAllocation(&m, sizeof(m));
if ((rc = sys_statfs(path, &m)) != -1) {
statfs2cosmo(sf, &m);
if (!IsWindows()) {
if ((rc = sys_statfs(path, &m)) != -1) {
statfs2cosmo(sf, &m);
}
} else {
rc = sys_statfs_nt(path, sf);
}
STRACE("statfs(%#s, [%s]) → %d% m", path, DescribeStatfs(rc, sf));
return rc;

View file

@ -8,6 +8,8 @@ COSMOPOLITAN_C_START_
int sys_statfs(const char *, union statfs_meta *);
int sys_fstatfs(int, union statfs_meta *);
int sys_fstatfs_nt(int64_t, struct statfs *);
int sys_statfs_nt(const char *, struct statfs *);
const char *DescribeStatfs(char[300], int, const struct statfs *);
#define DescribeStatfs(rc, sf) DescribeStatfs(alloca(300), rc, sf)

29
libc/nt/enum/statfs.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_STATFS_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_STATFS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define kNtFileCasePreservedNames 0x00000002
#define kNtFileCaseSensitiveSearch 0x00000001
#define kNtFileFileCompression 0x00000010
#define kNtFileNamedStreams 0x00040000
#define kNtFilePersistentAcls 0x00000008
#define kNtFileReadOnlyVolume 0x00080000 /* ST_RDONLY */
#define kNtFileSequentialWriteOnce 0x00100000
#define kNtFileSupportsEncryption 0x00020000
#define kNtFileSupportsExtendedAttributes 0x00800000
#define kNtFileSupportsHardLinks 0x00400000
#define kNtFileSupportsObjectIds 0x00010000
#define kNtFileSupportsOpenByFileId 0x01000000
#define kNtFileSupportsReparsePoints 0x00000080
#define kNtFileSupportsSparseFiles 0x00000040
#define kNtFileSupportsTransactions 0x00200000
#define kNtFileSupportsUsnJournal 0x02000000
#define kNtFileUnicodeOnDisk 0x00000004
#define kNtFileVolumeIsCompressed 0x00008000
#define kNtFileVolumeQuotas 0x00000020
#define kNtFileSupportsBlockRefcounting 0x08000000
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_STATFS_H_ */

View file

@ -219,6 +219,15 @@ bool32 GetVolumePathName(const char16_t *lpszFileName,
char16_t *lpszVolumePathName,
uint32_t cchBufferLength);
bool32 GetVolumeInformationByHandle(int64_t hFile,
char16_t *opt_out_lpVolumeNameBuffer,
uint32_t nVolumeNameSize,
uint32_t *opt_out_lpVolumeSerialNumber,
uint32_t *opt_out_lpMaximumComponentLength,
uint32_t *opt_out_lpFileSystemFlags,
char16_t *opt_out_lpFileSystemNameBuffer,
uint32_t nFileSystemNameSize);
#if ShouldUseMsabiAttribute()
#include "libc/nt/thunk/files.inc"
#endif /* ShouldUseMsabiAttribute() */

View file

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp kernel32,__imp_GetVolumeInformationByHandleW,GetVolumeInformationByHandleW,0
.text.windows
GetVolumeInformationByHandle:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetVolumeInformationByHandleW(%rip),%rax
jmp __sysv2nt8
.endfn GetVolumeInformationByHandle,globl
.previous

View file

@ -580,7 +580,7 @@ imp 'GetVDMCurrentDirectories' GetVDMCurrentDirectories kernel32 798
imp 'GetVersion' GetVersion kernel32 0
imp 'GetVersionEx' GetVersionExW kernel32 0 1
imp 'GetVolumeInformation' GetVolumeInformationW kernel32 0
imp 'GetVolumeInformationByHandle' GetVolumeInformationByHandleW kernel32 0
imp 'GetVolumeInformationByHandle' GetVolumeInformationByHandleW kernel32 0 8
imp 'GetVolumeNameForVolumeMountPoint' GetVolumeNameForVolumeMountPointW kernel32 0
imp 'GetVolumePathName' GetVolumePathNameW kernel32 0 3
imp 'GetVolumePathNamesForVolumeName' GetVolumePathNamesForVolumeNameW kernel32 0

View file

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_FILEFSFULLSIZEINFORMATION_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_FILEFSFULLSIZEINFORMATION_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtFileFsFullSizeInformation {
int64_t TotalAllocationUnits;
int64_t CallerAvailableAllocationUnits;
int64_t ActualAvailableAllocationUnits;
uint32_t SectorsPerAllocationUnit;
uint32_t BytesPerSector;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_FILEFSFULLSIZEINFORMATION_H_ */

View file

@ -297,7 +297,6 @@ DIR *opendir(const char *name) {
} else {
res = opendir_nt(name);
}
STRACE("opendir(%#s) → %p% m", name, res);
return res;
}
@ -317,7 +316,6 @@ DIR *fdopendir(int fd) {
} else {
dir = fdopendir_nt(fd);
}
STRACE("fdopendir(%d) → %p% m", fd, dir);
return dir;
}
@ -443,7 +441,6 @@ int closedir(DIR *dir) {
} else {
rc = 0;
}
STRACE("closedir(%p) → %d% m", dir, rc);
return rc;
}
@ -454,7 +451,6 @@ long telldir(DIR *dir) {
long rc;
_lockdir(dir);
rc = dir->tell;
STRACE("telldir(%p) → %ld", dir, rc);
_unlockdir(dir);
return rc;
}
@ -472,7 +468,6 @@ int dirfd(DIR *dir) {
} else {
rc = dir->fd;
}
STRACE("dirfd(%p) → %d% m", dir, rc);
_unlockdir(dir);
return rc;
}
@ -499,7 +494,6 @@ void rewinddir(DIR *dir) {
dir->isdone = true;
}
}
STRACE("rewinddir(%p)", dir);
_unlockdir(dir);
}
@ -521,6 +515,5 @@ void seekdir(DIR *dir, long off) {
dir->buf_pos = dir->buf_end = 0;
}
dir->tell = i;
STRACE("seekdir(%p, %ld) → %ld", dir, off, i);
_unlockdir(dir);
}

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_fstatfs,0x09f04022c215a08a,globl,hidden
.scall sys_fstatfs,0x09e04022c215a08a,globl,hidden

View file

@ -1155,7 +1155,7 @@ syscon ms MS_INVALIDATE 2 2 2 4 2 0
# statfs() flags
#
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon statfs ST_RDONLY 1 1 1 1 1 0 # MNT_RDONLY on BSD
syscon statfs ST_RDONLY 1 1 1 1 1 0x00080000 # MNT_RDONLY on BSD, kNtFileReadOnlyVolume on NT
syscon statfs ST_NOSUID 2 8 8 8 8 0 # MNT_NOSUID on BSD
syscon statfs ST_NODEV 4 16 0 16 16 0 # MNT_NODEV on BSD
syscon statfs ST_NOEXEC 8 4 4 4 4 0 # MNT_NOEXEC on BSD

View file

@ -169,7 +169,7 @@ scall mknodat 0x1cc14022fffff103 globl # FreeBSD 12+
scall sys_mkfifo 0x0840840842084fff globl hidden
scall mkfifoat 0x1cb13f1f1fffffff globl
scall sys_statfs 0x09d03f22b2159089 globl hidden
scall sys_fstatfs 0x09f04022c215a08a globl hidden
scall sys_fstatfs 0x09e04022c215a08a globl hidden
scall sys_getpriority 0x064064064206408c globl hidden
scall sys_setpriority 0x060060060206008d globl hidden # modern nice()
scall mlock 0x0cb0cb0cb20cb095 globl

View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/statfs.h"
#include "libc/sysv/consts/o.h"
#include "libc/testlib/testlib.h"
char testlib_enable_tmp_setup_teardown;
struct statfs f;
TEST(statfs, testFile) {
EXPECT_SYS(0, 0, touch("foo", 0644));
EXPECT_SYS(0, 0, statfs("foo", &f));
}
TEST(statfs, testDirectory) {
EXPECT_SYS(0, 0, statfs(".", &f));
}
TEST(statfs, testFdDirectory) {
EXPECT_SYS(0, 3, open(".", O_RDONLY | O_DIRECTORY));
EXPECT_SYS(0, 0, fstatfs(3, &f));
EXPECT_SYS(0, 0, close(3));
}
TEST(statfs, testFdFile) {
EXPECT_SYS(0, 0, touch("foo", 0644));
EXPECT_SYS(0, 3, open("foo", O_RDONLY));
EXPECT_SYS(0, 0, fstatfs(3, &f));
EXPECT_SYS(0, 0, close(3));
}