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 - print this help text\n" 27 " -c, --check-only - do not make any changes to the file system\n", 28 kProgramName); 29 } 30 31 32 int 33 main(int argc, char** argv) 34 { 35 const struct option kLongOptions[] = { 36 { "help", 0, NULL, 'h' }, 37 { "check-only", 0, NULL, 'c' }, 38 { NULL, 0, NULL, 0 } 39 }; 40 const char* kShortOptions = "hc"; 41 42 // parse argument list 43 bool checkOnly = false; 44 45 while (true) { 46 int nextOption = getopt_long(argc, argv, kShortOptions, kLongOptions, 47 NULL); 48 if (nextOption == -1) 49 break; 50 51 switch (nextOption) { 52 case 'h': // --help 53 usage(stdout); 54 return 0; 55 case 'c': // --check-only 56 checkOnly = true; 57 break; 58 default: // everything else 59 usage(stderr); 60 return 1; 61 } 62 } 63 64 // the device name should be the only non-option element 65 if (optind != argc - 1) { 66 usage(stderr); 67 return 1; 68 } 69 70 const char* path = argv[optind]; 71 //UnregisterFileDevice unregisterFileDevice; 72 73 BDiskDeviceRoster roster; 74 BPartition* partition; 75 BDiskDevice device; 76 77 status_t status = roster.GetPartitionForPath(path, &device, 78 &partition); 79 if (status != B_OK) { 80 if (strncmp(path, "/dev", 4)) { 81 // try mounted volume 82 status = roster.FindPartitionByMountPoint(path, &device, &partition) 83 ? B_OK : B_BAD_VALUE; 84 } 85 86 // TODO: try to register file device 87 88 if (status != B_OK) { 89 fprintf(stderr, "%s: Failed to get disk device for path \"%s\": " 90 "%s\n", kProgramName, path, strerror(status)); 91 return 1; 92 } 93 } 94 95 // Prepare the device for modifications 96 97 status = device.PrepareModifications(); 98 if (status != B_OK) { 99 fprintf(stderr, "%s: Could not prepare the device for modifications: " 100 "%s\n", kProgramName, strerror(status)); 101 return false; 102 } 103 104 // Check if the partition supports repairing 105 106 bool canRepairWhileMounted; 107 bool canRepair = partition->CanRepair(checkOnly, &canRepairWhileMounted); 108 if (!canRepair && !canRepairWhileMounted) { 109 fprintf(stderr, "%s: The disk system does not support repairing.\n", 110 kProgramName); 111 return 1; 112 } 113 114 if (partition->IsMounted() && !canRepairWhileMounted) { 115 fprintf(stderr, "%s: The disk system does not support repairing a " 116 "mounted volume.\n", kProgramName); 117 return 1; 118 } 119 if (!partition->IsMounted() && !canRepair) { 120 fprintf(stderr, "%s: The disk system does not support repairing a " 121 "volume that is not mounted.\n", kProgramName); 122 return 1; 123 } 124 125 BDiskSystem diskSystem; 126 status = partition->GetDiskSystem(&diskSystem); 127 if (status != B_OK) { 128 fprintf(stderr, "%s: Failed to get disk system for partition: %s\n", 129 kProgramName, strerror(status)); 130 return 1; 131 } 132 133 // Repair the volume 134 135 status = partition->Repair(checkOnly); 136 if (status != B_OK) { 137 fprintf(stderr, "%s: Repairing failed: %s\n", kProgramName, 138 strerror(status)); 139 return 1; 140 } 141 142 status = device.CommitModifications(); 143 144 return 0; 145 } 146