1 /* 2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <getopt.h> 8 #include <stdio.h> 9 10 #include <DiskDevice.h> 11 #include <DiskDeviceRoster.h> 12 #include <DiskSystem.h> 13 14 15 extern "C" const char* __progname; 16 static const char* kProgramName = __progname; 17 18 19 void 20 usage(FILE* output) 21 { 22 fprintf(output, 23 "Usage: %s <options> <device|volume name>\n" 24 "\n" 25 "Options:\n" 26 " -h, --help\t\t- print this help text\n" 27 " -c, --check-only\t- do not make any changes to the file system\n" 28 "\n" 29 "Examples:\n" 30 " %s -c /Haiku\n" 31 " %s /dev/disk/ata/0/master/raw\n", 32 kProgramName, kProgramName, kProgramName); 33 } 34 35 36 int 37 main(int argc, char** argv) 38 { 39 const struct option kLongOptions[] = { 40 { "help", 0, NULL, 'h' }, 41 { "check-only", 0, NULL, 'c' }, 42 { NULL, 0, NULL, 0 } 43 }; 44 const char* kShortOptions = "hc"; 45 46 // parse argument list 47 bool checkOnly = false; 48 49 while (true) { 50 int nextOption = getopt_long(argc, argv, kShortOptions, kLongOptions, 51 NULL); 52 if (nextOption == -1) 53 break; 54 55 switch (nextOption) { 56 case 'h': // --help 57 usage(stdout); 58 return 0; 59 case 'c': // --check-only 60 checkOnly = true; 61 break; 62 default: // everything else 63 usage(stderr); 64 return 1; 65 } 66 } 67 68 // the device name should be the only non-option element 69 if (optind != argc - 1) { 70 usage(stderr); 71 return 1; 72 } 73 74 const char* path = argv[optind]; 75 //UnregisterFileDevice unregisterFileDevice; 76 77 BDiskDeviceRoster roster; 78 BPartition* partition; 79 BDiskDevice device; 80 81 status_t status = roster.GetPartitionForPath(path, &device, 82 &partition); 83 if (status != B_OK) { 84 if (strncmp(path, "/dev", 4)) { 85 // try mounted volume 86 status = roster.FindPartitionByMountPoint(path, &device, &partition) 87 ? B_OK : B_BAD_VALUE; 88 } 89 90 // TODO: try to register file device 91 92 if (status != B_OK) { 93 fprintf(stderr, "%s: Failed to get disk device for path \"%s\": " 94 "%s\n", kProgramName, path, strerror(status)); 95 return 1; 96 } 97 } 98 99 // Prepare the device for modifications 100 101 status = device.PrepareModifications(); 102 if (status != B_OK) { 103 fprintf(stderr, "%s: Could not prepare the device for modifications: " 104 "%s\n", kProgramName, strerror(status)); 105 return 1; 106 } 107 108 // Check if the partition supports repairing 109 110 bool canRepairWhileMounted; 111 bool canRepair = partition->CanRepair(checkOnly, &canRepairWhileMounted); 112 if (!canRepair && !canRepairWhileMounted) { 113 fprintf(stderr, "%s: The disk system does not support repairing.\n", 114 kProgramName); 115 return 1; 116 } 117 118 if (partition->IsMounted() && !canRepairWhileMounted) { 119 fprintf(stderr, "%s: The disk system does not support repairing a " 120 "mounted volume.\n", kProgramName); 121 return 1; 122 } 123 if (!partition->IsMounted() && !canRepair) { 124 fprintf(stderr, "%s: The disk system does not support repairing a " 125 "volume that is not mounted.\n", kProgramName); 126 return 1; 127 } 128 129 BDiskSystem diskSystem; 130 status = partition->GetDiskSystem(&diskSystem); 131 if (status != B_OK) { 132 fprintf(stderr, "%s: Failed to get disk system for partition: %s\n", 133 kProgramName, strerror(status)); 134 return 1; 135 } 136 137 // Repair the volume 138 139 status = partition->Repair(checkOnly); 140 if (status != B_OK) { 141 fprintf(stderr, "%s: Repairing failed: %s\n", kProgramName, 142 strerror(status)); 143 return 1; 144 } 145 146 status = device.CommitModifications(); 147 148 return 0; 149 } 150