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("%-15s ", mount); 49 if (strlen(mount) > 15) 50 printf("\n%15s ", ""); 51 } 52 } 53 54 55 void 56 PrintType(const char *fileSystem) 57 { 58 char type[10]; 59 strlcpy(type, fileSystem, sizeof(type)); 60 61 printf("%-8s", 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, "%Ld", numBlocks * blockSize); 73 else { 74 const char *units[] = {"K", "M", "G", NULL}; 75 int32 i = -1; 76 77 do { 78 blocks /= 1024.0; 79 i++; 80 } while (blocks >= 1024 && units[i + 1]); 81 82 sprintf(string, "%.1f%s", blocks, units[i]); 83 } 84 85 return string; 86 } 87 88 89 void 90 PrintBlocks(int64 blocks, int64 blockSize, bool showBlocks) 91 { 92 char temp[1024]; 93 94 if (showBlocks) 95 sprintf(temp, "%Ld", blocks * (blockSize / 1024)); 96 else 97 strcpy(temp, ByteString(blocks, blockSize)); 98 99 printf("%10s", temp); 100 } 101 102 103 void 104 PrintVerbose(dev_t device) 105 { 106 fs_info info; 107 if (fs_stat_dev(device, &info) != B_OK) { 108 fprintf(stderr, "Could not stat fs: %s\n", strerror(errno)); 109 return; 110 } 111 112 printf(" Device No.: %ld\n", info.dev); 113 PrintMountPoint(info.dev, true); 114 printf(" Volume Name: \"%s\"\n", info.volume_name); 115 printf(" File System: %s\n", info.fsh_name); 116 printf(" Device: %s\n", info.device_name); 117 118 printf(" Flags: "); 119 PrintFlag(info.flags, B_FS_HAS_QUERY, "Q", "-"); 120 PrintFlag(info.flags, B_FS_HAS_ATTR, "A", "-"); 121 PrintFlag(info.flags, B_FS_HAS_MIME, "M", "-"); 122 PrintFlag(info.flags, B_FS_IS_SHARED, "S", "-"); 123 PrintFlag(info.flags, B_FS_IS_PERSISTENT, "P", "-"); 124 PrintFlag(info.flags, B_FS_IS_REMOVABLE, "R", "-"); 125 PrintFlag(info.flags, B_FS_IS_READONLY, "-", "W"); 126 127 printf("\n I/O Size: %10s (%Ld byte)\n", ByteString(info.io_size, 1), info.io_size); 128 printf(" Block Size: %10s (%Ld byte)\n", ByteString(info.block_size, 1), info.block_size); 129 printf(" Total Blocks: %10s (%Ld blocks)\n", ByteString(info.total_blocks, info.block_size), info.total_blocks); 130 printf(" Free Blocks: %10s (%Ld blocks)\n", ByteString(info.free_blocks, info.block_size), info.free_blocks); 131 printf(" Total Nodes: %Ld\n", info.total_nodes); 132 printf(" Free Nodes: %Ld\n", info.free_nodes); 133 printf(" Root Inode: %Ld\n", info.root); 134 } 135 136 137 void 138 PrintCompact(dev_t device, bool showBlocks, bool all) 139 { 140 fs_info info; 141 if (fs_stat_dev(device, &info) != B_OK) 142 return; 143 144 if (!all && (info.flags & B_FS_IS_PERSISTENT) == 0) 145 return; 146 147 PrintMountPoint(info.dev, false); 148 PrintType(info.fsh_name); 149 PrintBlocks(info.total_blocks, info.block_size, showBlocks); 150 PrintBlocks(info.free_blocks, info.block_size, showBlocks); 151 152 printf(" "); 153 PrintFlag(info.flags, B_FS_HAS_QUERY, "Q", "-"); 154 PrintFlag(info.flags, B_FS_HAS_ATTR, "A", "-"); 155 PrintFlag(info.flags, B_FS_HAS_MIME, "M", "-"); 156 PrintFlag(info.flags, B_FS_IS_SHARED, "S", "-"); 157 PrintFlag(info.flags, B_FS_IS_PERSISTENT, "P", "-"); 158 PrintFlag(info.flags, B_FS_IS_REMOVABLE, "R", "-"); 159 PrintFlag(info.flags, B_FS_IS_READONLY, "-", "W"); 160 161 printf(" %s\n", info.device_name); 162 } 163 164 165 void 166 ShowUsage(const char *programName) 167 { 168 printf("usage: %s [--help | --blocks, -b | -all, -a] [<path-to-device>]\n" 169 " -a, --all\tinclude all file systems, also those not visible from Tracker\n" 170 " -b, --blocks\tshow device size in blocks of 1024 bytes\n" 171 "If <path-to-device> is used, detailed info for that device only will be listed.\n" 172 "Flags:\n" 173 " Q: has query\n" 174 " A: has attribute\n" 175 " M: has mime\n" 176 " S: is shared\n" 177 " P: is persistent (visible in Tracker)\n" 178 " R: is removable\n" 179 " W: is writable\n", programName); 180 exit(0); 181 } 182 183 184 int 185 main(int argc, char **argv) 186 { 187 char *programName = argv[0]; 188 if (strrchr(programName, '/')) 189 programName = strrchr(programName, '/') + 1; 190 191 bool showBlocks = false; 192 bool all = false; 193 dev_t device = -1; 194 195 while (*++argv) { 196 char *arg = *argv; 197 if (*arg == '-') { 198 while (*++arg && isalpha(*arg)) { 199 switch (arg[0]) { 200 case 'a': 201 all = true; 202 break; 203 case 'b': 204 showBlocks = true; 205 break; 206 default: 207 ShowUsage(programName); 208 } 209 } 210 if (arg[0] == '-') { 211 arg++; 212 if (!strcmp(arg, "all")) 213 all = true; 214 else if (!strcmp(arg, "blocks")) 215 showBlocks = true; 216 else 217 ShowUsage(programName); 218 } 219 } else 220 break; 221 } 222 223 // Do we already have a device? Then let's print out detailed info about that 224 225 if (argv[0] != NULL) { 226 PrintVerbose(dev_for_path(argv[0])); 227 return 0; 228 } 229 230 // If not, then just iterate over all devices and give a compact summary 231 232 printf("Mount Type Total Free Flags Device\n" 233 "--------------- -------- --------- --------- ------- --------------------------\n"); 234 235 int32 cookie = 0; 236 while ((device = next_dev(&cookie)) >= B_OK) { 237 PrintCompact(device, showBlocks, all); 238 } 239 240 return 0; 241 } 242