1 // df - for Haiku
2 //
3 // authors, in order of contribution:
4 // jonas.sundstrom@kirilla.com
5 // axeld@pinc-software.de
6 //
7
8
9 #include <Volume.h>
10 #include <Directory.h>
11 #include <Path.h>
12
13 #include <fs_info.h>
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <errno.h>
20
21
22 void
PrintFlag(uint32 deviceFlags,uint32 testFlag,char yes,char no)23 PrintFlag(uint32 deviceFlags, uint32 testFlag, char yes, char no)
24 {
25 printf("%c", deviceFlags & testFlag ? yes : no);
26 }
27
28
29 void
PrintMountPoint(dev_t device,bool verbose)30 PrintMountPoint(dev_t device, bool verbose)
31 {
32 char mount[B_PATH_NAME_LENGTH];
33 mount[0] = '\0';
34
35 BVolume volume(device);
36 BDirectory root;
37 if (volume.GetRootDirectory(&root) == B_OK) {
38 BPath path(&root, NULL);
39 if (path.InitCheck() == B_OK)
40 strlcpy(mount, path.Path(), sizeof(mount));
41 else
42 strlcpy(mount, "?", sizeof(mount));
43 }
44
45 if (verbose)
46 printf(" Mounted at: %s\n", mount);
47 else {
48 printf("%-17s ", mount);
49 if (strlen(mount) > 17)
50 printf("\n%17s ", "");
51 }
52 }
53
54
55 void
PrintType(const char * fileSystem)56 PrintType(const char *fileSystem)
57 {
58 char type[16];
59 strlcpy(type, fileSystem, sizeof(type));
60
61 printf("%-9s", type);
62 }
63
64
65 const char *
ByteString(int64 numBlocks,int64 blockSize)66 ByteString(int64 numBlocks, int64 blockSize)
67 {
68 double blocks = 1. * numBlocks * blockSize;
69 static char string[64];
70
71 if (blocks < 1024)
72 sprintf(string, "%" B_PRId64, numBlocks * blockSize);
73 else {
74 const char *units[] = {"KiB", "MiB", "GiB", "TiB", "PiB", "EiB",
75 "ZiB", "YiB", NULL};
76 int32 i = -1;
77
78 do {
79 blocks /= 1024.0;
80 i++;
81 } while (blocks >= 1024 && units[i + 1]);
82
83 sprintf(string, "%.1f %s", blocks, units[i]);
84 }
85
86 return string;
87 }
88
89
90 void
PrintBlocks(int64 blocks,int64 blockSize,bool showBlocks)91 PrintBlocks(int64 blocks, int64 blockSize, bool showBlocks)
92 {
93 char temp[1024];
94
95 if (showBlocks)
96 sprintf(temp, "%" B_PRId64, blocks * (blockSize / 1024));
97 else
98 strcpy(temp, ByteString(blocks, blockSize));
99
100 printf("%10s", temp);
101 }
102
103
104 void
PrintVerbose(dev_t device)105 PrintVerbose(dev_t device)
106 {
107 fs_info info;
108 if (fs_stat_dev(device, &info) != B_OK) {
109 fprintf(stderr, "Could not stat fs: %s\n", strerror(errno));
110 return;
111 }
112
113 printf(" Device No.: %" B_PRIdDEV "\n", info.dev);
114 PrintMountPoint(info.dev, true);
115 printf(" Volume Name: \"%s\"\n", info.volume_name);
116 printf(" File System: %s\n", info.fsh_name);
117 printf(" Device: %s\n", info.device_name);
118
119 printf(" Flags: ");
120 PrintFlag(info.flags, B_FS_HAS_QUERY, 'Q', '-');
121 PrintFlag(info.flags, B_FS_HAS_ATTR, 'A', '-');
122 PrintFlag(info.flags, B_FS_HAS_MIME, 'M', '-');
123 PrintFlag(info.flags, B_FS_IS_SHARED, 'S', '-');
124 PrintFlag(info.flags, B_FS_IS_PERSISTENT, 'P', '-');
125 PrintFlag(info.flags, B_FS_IS_REMOVABLE, 'R', '-');
126 PrintFlag(info.flags, B_FS_IS_READONLY, '-', 'W');
127
128 printf("\n I/O Size: %10s (%" B_PRIdOFF " byte)\n",
129 ByteString(info.io_size, 1), info.io_size);
130 printf(" Block Size: %10s (%" B_PRIdOFF " byte)\n",
131 ByteString(info.block_size, 1), info.block_size);
132 printf(" Total Blocks: %10s (%" B_PRIdOFF " blocks)\n",
133 ByteString(info.total_blocks, info.block_size), info.total_blocks);
134 printf(" Free Blocks: %10s (%" B_PRIdOFF " blocks)\n",
135 ByteString(info.free_blocks, info.block_size), info.free_blocks);
136 printf(" Total Nodes: %" B_PRIdOFF "\n", info.total_nodes);
137 printf(" Free Nodes: %" B_PRIdOFF "\n", info.free_nodes);
138 printf(" Root Inode: %" B_PRIdINO "\n", info.root);
139 }
140
141
142 void
PrintCompact(dev_t device,bool showBlocks,bool all)143 PrintCompact(dev_t device, bool showBlocks, bool all)
144 {
145 fs_info info;
146 if (fs_stat_dev(device, &info) != B_OK)
147 return;
148
149 if (!all && (info.flags & B_FS_IS_PERSISTENT) == 0)
150 return;
151
152 PrintType(info.fsh_name);
153 PrintBlocks(info.total_blocks, info.block_size, showBlocks);
154 PrintBlocks(info.free_blocks, info.block_size, showBlocks);
155
156 printf(" ");
157 PrintFlag(info.flags, B_FS_HAS_QUERY, 'Q', '-');
158 PrintFlag(info.flags, B_FS_HAS_ATTR, 'A', '-');
159 PrintFlag(info.flags, B_FS_HAS_MIME, 'M', '-');
160 PrintFlag(info.flags, B_FS_IS_SHARED, 'S', '-');
161 PrintFlag(info.flags, B_FS_IS_PERSISTENT, 'P', '-');
162 PrintFlag(info.flags, B_FS_IS_REMOVABLE, 'R', '-');
163 PrintFlag(info.flags, B_FS_IS_READONLY, '-', 'W');
164
165 printf(" %24s ", info.device_name);
166 PrintMountPoint(info.dev, false);
167 printf("\n");
168 }
169
170
171 void
ShowUsage(const char * programName)172 ShowUsage(const char *programName)
173 {
174 printf("usage: %s [--help | --blocks, -b | -all, -a] [<path-to-device>]\n"
175 " -a, --all\tinclude all file systems, also those not visible from Tracker\n"
176 " -b, --blocks\tshow device size in blocks of 1024 bytes\n"
177 "If <path-to-device> is used, detailed info for that device only will be listed.\n"
178 "Flags:\n"
179 " Q: has query\n"
180 " A: has attribute\n"
181 " M: has mime\n"
182 " S: is shared\n"
183 " P: is persistent (visible in Tracker)\n"
184 " R: is removable\n"
185 " W: is writable\n", programName);
186 exit(0);
187 }
188
189
190 int
main(int argc,char ** argv)191 main(int argc, char **argv)
192 {
193 char *programName = argv[0];
194 if (strrchr(programName, '/'))
195 programName = strrchr(programName, '/') + 1;
196
197 bool showBlocks = false;
198 bool all = false;
199 dev_t device = -1;
200
201 while (*++argv) {
202 char *arg = *argv;
203 if (*arg == '-') {
204 while (*++arg && isalpha(*arg)) {
205 switch (arg[0]) {
206 case 'a':
207 all = true;
208 break;
209 case 'b':
210 showBlocks = true;
211 break;
212 case 'h':
213 // human readable units in Unix df
214 break;
215 default:
216 ShowUsage(programName);
217 }
218 }
219 if (arg[0] == '-') {
220 arg++;
221 if (!strcmp(arg, "all"))
222 all = true;
223 else if (!strcmp(arg, "blocks"))
224 showBlocks = true;
225 else
226 ShowUsage(programName);
227 }
228 } else
229 break;
230 }
231
232 // Do we already have a device? Then let's print out detailed info about that
233
234 if (argv[0] != NULL) {
235 PrintVerbose(dev_for_path(argv[0]));
236 return 0;
237 }
238
239 // If not, then just iterate over all devices and give a compact summary
240
241 printf(" Type Total Free Flags Device Mounted on\n"
242 "--------- --------- --------- ------- ------------------------ -----------------\n");
243
244 int32 cookie = 0;
245 while ((device = next_dev(&cookie)) >= B_OK) {
246 PrintCompact(device, showBlocks, all);
247 }
248
249 return 0;
250 }
251