diff options
Diffstat (limited to 'win32/statfs.c')
-rw-r--r-- | win32/statfs.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/win32/statfs.c b/win32/statfs.c new file mode 100644 index 000000000..9e6703849 --- /dev/null +++ b/win32/statfs.c | |||
@@ -0,0 +1,80 @@ | |||
1 | #include <sys/vfs.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 drive[4], fsname[100]; | ||
14 | |||
15 | if ( !GetDiskFreeSpaceEx(file, (PULARGE_INTEGER) &free_bytes_available, | ||
16 | (PULARGE_INTEGER) &total_number_of_bytes, | ||
17 | (PULARGE_INTEGER) &total_number_of_free_bytes) ) { | ||
18 | return -1; | ||
19 | } | ||
20 | |||
21 | if ( strlen(file) == 2 && file[1] == ':' ) { | ||
22 | /* GetVolumeInformation wants a backslash */ | ||
23 | strcat(strcpy(drive, file), "\\"); | ||
24 | file = drive; | ||
25 | } | ||
26 | |||
27 | if ( !GetVolumeInformation(file, NULL, 0, &serial, &namelen, &flags, | ||
28 | fsname, 100) ) { | ||
29 | return -1; | ||
30 | } | ||
31 | |||
32 | /* XXX I couldn't determine how to get block size. MSDN has a | ||
33 | * unhelpful hard-coded list here: | ||
34 | * http://support.microsoft.com/kb/140365 | ||
35 | * but this depends on the filesystem type, the size of the disk and | ||
36 | * the version of Windows. So this code assumes the disk is NTFS | ||
37 | * and the version of Windows is >= Win2K. | ||
38 | */ | ||
39 | if (total_number_of_bytes < UINT64_C(16) * 1024 * 1024 * 1024 * 1024) | ||
40 | buf->f_bsize = 4096; | ||
41 | else if (total_number_of_bytes < UINT64_C(32) * 1024 * 1024 * 1024 * 1024) | ||
42 | buf->f_bsize = 8192; | ||
43 | else if (total_number_of_bytes < UINT64_C(64) * 1024 * 1024 * 1024 * 1024) | ||
44 | buf->f_bsize = 16384; | ||
45 | else if (total_number_of_bytes < UINT64_C(128) * 1024 * 1024 * 1024 * 1024) | ||
46 | buf->f_bsize = 32768; | ||
47 | else | ||
48 | buf->f_bsize = 65536; | ||
49 | |||
50 | /* | ||
51 | * Valid filesystem names don't seem to be documented. The following | ||
52 | * are present in Wine. | ||
53 | */ | ||
54 | if ( strcmp(fsname, "NTFS") == 0 ) { | ||
55 | buf->f_type = 0x5346544e; | ||
56 | } | ||
57 | else if ( strcmp(fsname, "FAT") == 0 || strcmp(fsname, "FAT32") == 0 ) { | ||
58 | buf->f_type = 0x4006; | ||
59 | } | ||
60 | else if ( strcmp(fsname, "CDFS") == 0 ) { | ||
61 | buf->f_type = 0x9660; | ||
62 | } | ||
63 | else { | ||
64 | buf->f_type = 0; | ||
65 | } | ||
66 | |||
67 | /* As with stat, -1 indicates a field is not known. */ | ||
68 | buf->f_frsize = buf->f_bsize; | ||
69 | buf->f_blocks = total_number_of_bytes / buf->f_bsize; | ||
70 | buf->f_bfree = total_number_of_free_bytes / buf->f_bsize; | ||
71 | buf->f_bavail = free_bytes_available / buf->f_bsize; | ||
72 | buf->f_files = -1; | ||
73 | buf->f_ffree = -1; | ||
74 | buf->f_favail = -1; | ||
75 | buf->f_fsid = serial; | ||
76 | buf->f_flag = -1; | ||
77 | buf->f_namelen = namelen; | ||
78 | |||
79 | return 0; | ||
80 | } | ||