btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / bin / df.cpp
blobcb281a37596a381a1f8af384389d82095de1d0fd
1 // df - for Haiku
2 //
3 // authors, in order of contribution:
4 // jonas.sundstrom@kirilla.com
5 // axeld@pinc-software.de
6 //
9 #include <Volume.h>
10 #include <Directory.h>
11 #include <Path.h>
13 #include <fs_info.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <errno.h>
22 void
23 PrintFlag(uint32 deviceFlags, uint32 testFlag, const char *yes, const char *no)
25 printf(deviceFlags & testFlag ? yes : no);
29 void
30 PrintMountPoint(dev_t device, bool verbose)
32 char mount[B_PATH_NAME_LENGTH];
33 mount[0] = '\0';
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));
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 ", "");
55 void
56 PrintType(const char *fileSystem)
58 char type[16];
59 strlcpy(type, fileSystem, sizeof(type));
61 printf("%-9s", type);
65 const char *
66 ByteString(int64 numBlocks, int64 blockSize)
68 double blocks = 1. * numBlocks * blockSize;
69 static char string[64];
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;
78 do {
79 blocks /= 1024.0;
80 i++;
81 } while (blocks >= 1024 && units[i + 1]);
83 sprintf(string, "%.1f %s", blocks, units[i]);
86 return string;
90 void
91 PrintBlocks(int64 blocks, int64 blockSize, bool showBlocks)
93 char temp[1024];
95 if (showBlocks)
96 sprintf(temp, "%" B_PRId64, blocks * (blockSize / 1024));
97 else
98 strcpy(temp, ByteString(blocks, blockSize));
100 printf("%10s", temp);
104 void
105 PrintVerbose(dev_t device)
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;
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);
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");
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);
142 void
143 PrintCompact(dev_t device, bool showBlocks, bool all)
145 fs_info info;
146 if (fs_stat_dev(device, &info) != B_OK)
147 return;
149 if (!all && (info.flags & B_FS_IS_PERSISTENT) == 0)
150 return;
152 PrintMountPoint(info.dev, false);
153 PrintType(info.fsh_name);
154 PrintBlocks(info.total_blocks, info.block_size, showBlocks);
155 PrintBlocks(info.free_blocks, info.block_size, showBlocks);
157 printf(" ");
158 PrintFlag(info.flags, B_FS_HAS_QUERY, "Q", "-");
159 PrintFlag(info.flags, B_FS_HAS_ATTR, "A", "-");
160 PrintFlag(info.flags, B_FS_HAS_MIME, "M", "-");
161 PrintFlag(info.flags, B_FS_IS_SHARED, "S", "-");
162 PrintFlag(info.flags, B_FS_IS_PERSISTENT, "P", "-");
163 PrintFlag(info.flags, B_FS_IS_REMOVABLE, "R", "-");
164 PrintFlag(info.flags, B_FS_IS_READONLY, "-", "W");
166 printf(" %s\n", info.device_name);
170 void
171 ShowUsage(const char *programName)
173 printf("usage: %s [--help | --blocks, -b | -all, -a] [<path-to-device>]\n"
174 " -a, --all\tinclude all file systems, also those not visible from Tracker\n"
175 " -b, --blocks\tshow device size in blocks of 1024 bytes\n"
176 "If <path-to-device> is used, detailed info for that device only will be listed.\n"
177 "Flags:\n"
178 " Q: has query\n"
179 " A: has attribute\n"
180 " M: has mime\n"
181 " S: is shared\n"
182 " P: is persistent (visible in Tracker)\n"
183 " R: is removable\n"
184 " W: is writable\n", programName);
185 exit(0);
190 main(int argc, char **argv)
192 char *programName = argv[0];
193 if (strrchr(programName, '/'))
194 programName = strrchr(programName, '/') + 1;
196 bool showBlocks = false;
197 bool all = false;
198 dev_t device = -1;
200 while (*++argv) {
201 char *arg = *argv;
202 if (*arg == '-') {
203 while (*++arg && isalpha(*arg)) {
204 switch (arg[0]) {
205 case 'a':
206 all = true;
207 break;
208 case 'b':
209 showBlocks = true;
210 break;
211 case 'h':
212 // human readable units in Unix df
213 break;
214 default:
215 ShowUsage(programName);
218 if (arg[0] == '-') {
219 arg++;
220 if (!strcmp(arg, "all"))
221 all = true;
222 else if (!strcmp(arg, "blocks"))
223 showBlocks = true;
224 else
225 ShowUsage(programName);
227 } else
228 break;
231 // Do we already have a device? Then let's print out detailed info about that
233 if (argv[0] != NULL) {
234 PrintVerbose(dev_for_path(argv[0]));
235 return 0;
238 // If not, then just iterate over all devices and give a compact summary
240 printf(" Mount Type Total Free Flags Device\n"
241 "----------------- --------- --------- --------- ------- ------------------------\n");
243 int32 cookie = 0;
244 while ((device = next_dev(&cookie)) >= B_OK) {
245 PrintCompact(device, showBlocks, all);
248 return 0;