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, "%" B_PRId64, 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, "%" B_PRId64, 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.: %" B_PRIdDEV "\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 (%" B_PRIdOFF " byte)\n", 128 ByteString(info.io_size, 1), info.io_size); 129 printf(" Block Size: %10s (%" B_PRIdOFF " byte)\n", 130 ByteString(info.block_size, 1), info.block_size); 131 printf(" Total Blocks: %10s (%" B_PRIdOFF " blocks)\n", 132 ByteString(info.total_blocks, info.block_size), info.total_blocks); 133 printf(" Free Blocks: %10s (%" B_PRIdOFF " blocks)\n", 134 ByteString(info.free_blocks, info.block_size), info.free_blocks); 135 printf(" Total Nodes: %" B_PRIdOFF "\n", info.total_nodes); 136 printf(" Free Nodes: %" B_PRIdOFF "\n", info.free_nodes); 137 printf(" Root Inode: %" B_PRIdINO "\n", info.root); 138 } 139 140 141 void 142 PrintCompact(dev_t device, bool showBlocks, bool all) 143 { 144 fs_info info; 145 if (fs_stat_dev(device, &info) != B_OK) 146 return; 147 148 if (!all && (info.flags & B_FS_IS_PERSISTENT) == 0) 149 return; 150 151 PrintMountPoint(info.dev, false); 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(" %s\n", info.device_name); 166 } 167 168 169 void 170 ShowUsage(const char *programName) 171 { 172 printf("usage: %s [--help | --blocks, -b | -all, -a] [<path-to-device>]\n" 173 " -a, --all\tinclude all file systems, also those not visible from Tracker\n" 174 " -b, --blocks\tshow device size in blocks of 1024 bytes\n" 175 "If <path-to-device> is used, detailed info for that device only will be listed.\n" 176 "Flags:\n" 177 " Q: has query\n" 178 " A: has attribute\n" 179 " M: has mime\n" 180 " S: is shared\n" 181 " P: is persistent (visible in Tracker)\n" 182 " R: is removable\n" 183 " W: is writable\n", programName); 184 exit(0); 185 } 186 187 188 int 189 main(int argc, char **argv) 190 { 191 char *programName = argv[0]; 192 if (strrchr(programName, '/')) 193 programName = strrchr(programName, '/') + 1; 194 195 bool showBlocks = false; 196 bool all = false; 197 dev_t device = -1; 198 199 while (*++argv) { 200 char *arg = *argv; 201 if (*arg == '-') { 202 while (*++arg && isalpha(*arg)) { 203 switch (arg[0]) { 204 case 'a': 205 all = true; 206 break; 207 case 'b': 208 showBlocks = true; 209 break; 210 case 'h': 211 // human readable units in Unix df 212 break; 213 default: 214 ShowUsage(programName); 215 } 216 } 217 if (arg[0] == '-') { 218 arg++; 219 if (!strcmp(arg, "all")) 220 all = true; 221 else if (!strcmp(arg, "blocks")) 222 showBlocks = true; 223 else 224 ShowUsage(programName); 225 } 226 } else 227 break; 228 } 229 230 // Do we already have a device? Then let's print out detailed info about that 231 232 if (argv[0] != NULL) { 233 PrintVerbose(dev_for_path(argv[0])); 234 return 0; 235 } 236 237 // If not, then just iterate over all devices and give a compact summary 238 239 printf("Mount Type Total Free Flags Device\n" 240 "--------------- -------- --------- --------- ------- --------------------------\n"); 241 242 int32 cookie = 0; 243 while ((device = next_dev(&cookie)) >= B_OK) { 244 PrintCompact(device, showBlocks, all); 245 } 246 247 return 0; 248 } 249