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 23 PrintFlag(uint32 deviceFlags, uint32 testFlag, const char *yes, const char *no) 24 { 25 printf(deviceFlags & testFlag ? yes : no); 26 } 27 28 29 void 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 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 * 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 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 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 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 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); 156 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"); 165 166 printf(" %s\n", info.device_name); 167 } 168 169 170 void 171 ShowUsage(const char *programName) 172 { 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); 186 } 187 188 189 int 190 main(int argc, char **argv) 191 { 192 char *programName = argv[0]; 193 if (strrchr(programName, '/')) 194 programName = strrchr(programName, '/') + 1; 195 196 bool showBlocks = false; 197 bool all = false; 198 dev_t device = -1; 199 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); 216 } 217 } 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); 226 } 227 } else 228 break; 229 } 230 231 // Do we already have a device? Then let's print out detailed info about that 232 233 if (argv[0] != NULL) { 234 PrintVerbose(dev_for_path(argv[0])); 235 return 0; 236 } 237 238 // If not, then just iterate over all devices and give a compact summary 239 240 printf(" Mount Type Total Free Flags Device\n" 241 "----------------- --------- --------- --------- ------- ------------------------\n"); 242 243 int32 cookie = 0; 244 while ((device = next_dev(&cookie)) >= B_OK) { 245 PrintCompact(device, showBlocks, all); 246 } 247 248 return 0; 249 } 250