diff options
Diffstat (limited to '')
-rw-r--r-- | win32/statfs.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/win32/statfs.c b/win32/statfs.c new file mode 100644 index 000000000..97b3ce679 --- /dev/null +++ b/win32/statfs.c | |||
@@ -0,0 +1,70 @@ | |||
1 | #include <sys/statfs.h> | ||
2 | #include "libbb.h" | ||
3 | |||
4 | /* | ||
5 | * Code from libguestfs (with addition of GetVolumeInformation call) | ||
6 | */ | ||
7 | int statfs(const char *file, struct statfs *buf) | ||
8 | { | ||
9 | ULONGLONG free_bytes_available; /* for user - similar to bavail */ | ||
10 | ULONGLONG total_number_of_bytes; | ||
11 | ULONGLONG total_number_of_free_bytes; /* for everyone - bfree */ | ||
12 | DWORD serial, namelen, flags; | ||
13 | char fsname[100]; | ||
14 | struct mntent *mnt; | ||
15 | /* Valid filesystem names don't seem to be documented. The following | ||
16 | * are present in Wine (dlls/kernel32/volume.c). */ | ||
17 | #define FS_NAMES "NTFS\0FAT\0FAT32\0CDFS\0UDF\0" | ||
18 | int fstypes[] = {0, 0x5346544e, 0x4006, 0x4006, 0x9660, 0x15013346}; | ||
19 | |||
20 | if ( (mnt=find_mount_point(file, 0)) == NULL ) { | ||
21 | return -1; | ||
22 | } | ||
23 | |||
24 | file = mnt->mnt_dir; | ||
25 | if ( !GetDiskFreeSpaceEx(file, (PULARGE_INTEGER) &free_bytes_available, | ||
26 | (PULARGE_INTEGER) &total_number_of_bytes, | ||
27 | (PULARGE_INTEGER) &total_number_of_free_bytes) ) { | ||
28 | errno = err_win_to_posix(); | ||
29 | return -1; | ||
30 | } | ||
31 | |||
32 | if ( !GetVolumeInformation(file, NULL, 0, &serial, &namelen, &flags, | ||
33 | fsname, 100) ) { | ||
34 | errno = err_win_to_posix(); | ||
35 | return -1; | ||
36 | } | ||
37 | |||
38 | memset(buf, 0, sizeof(*buf)); | ||
39 | |||
40 | /* XXX I couldn't determine how to get block size. MSDN has a | ||
41 | * unhelpful hard-coded list here: | ||
42 | * http://support.microsoft.com/kb/140365 | ||
43 | * but this depends on the filesystem type, the size of the disk and | ||
44 | * the version of Windows. So this code assumes the disk is NTFS | ||
45 | * and the version of Windows is >= Win2K. | ||
46 | */ | ||
47 | if (total_number_of_bytes < UINT64_C(16) * 1024 * 1024 * 1024 * 1024) | ||
48 | buf->f_bsize = 4096; | ||
49 | else if (total_number_of_bytes < UINT64_C(32) * 1024 * 1024 * 1024 * 1024) | ||
50 | buf->f_bsize = 8192; | ||
51 | else if (total_number_of_bytes < UINT64_C(64) * 1024 * 1024 * 1024 * 1024) | ||
52 | buf->f_bsize = 16384; | ||
53 | else if (total_number_of_bytes < UINT64_C(128) * 1024 * 1024 * 1024 * 1024) | ||
54 | buf->f_bsize = 32768; | ||
55 | else | ||
56 | buf->f_bsize = 65536; | ||
57 | |||
58 | buf->f_type = fstypes[index_in_strings(FS_NAMES, fsname)+1]; | ||
59 | buf->f_frsize = buf->f_bsize; | ||
60 | buf->f_blocks = total_number_of_bytes / buf->f_bsize; | ||
61 | buf->f_bfree = total_number_of_free_bytes / buf->f_bsize; | ||
62 | buf->f_bavail = free_bytes_available / buf->f_bsize; | ||
63 | //buf->f_files = 0; | ||
64 | //buf->f_ffree = 0; | ||
65 | buf->f_fsid = serial; | ||
66 | //buf->f_flag = 0; | ||
67 | buf->f_namelen = namelen; | ||
68 | |||
69 | return 0; | ||
70 | } | ||