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 case -1: // done with options 59 break; 60 default: // everything else 61 usage(stderr); 62 return 1; 63 } 64 } 65 66 // the device name should be the only non-option element 67 if (optind != argc - 1) { 68 usage(stderr); 69 return 1; 70 } 71 72 const char* path = argv[optind]; 73 //UnregisterFileDevice unregisterFileDevice; 74 75 BDiskDeviceRoster roster; 76 BPartition* partition; 77 BDiskDevice device; 78 79 status_t status = roster.GetPartitionForPath(path, &device, 80 &partition); 81 if (status != B_OK) { 82 if (strncmp(path, "/dev", 4)) { 83 // try mounted volume 84 status = roster.FindPartitionByMountPoint(path, &device, &partition) 85 ? B_OK : B_BAD_VALUE; 86 } 87 88 // TODO: try to register file device 89 90 if (status != B_OK) { 91 fprintf(stderr, "%s: Failed to get disk device for path \"%s\": " 92 "%s\n", kProgramName, path, strerror(status)); 93 return 1; 94 } 95 } 96 97 // Prepare the device for modifications 98 99 status = device.PrepareModifications(); 100 if (status != B_OK) { 101 fprintf(stderr, "%s: Could not prepare the device for modifications: " 102 "%s\n", kProgramName, strerror(status)); 103 return false; 104 } 105 106 // Check if the partition supports repairing 107 108 bool canRepairWhileMounted; 109 bool canRepair = partition->CanRepair(checkOnly, &canRepairWhileMounted); 110 if (!canRepair && !canRepairWhileMounted) { 111 fprintf(stderr, "%s: The disk system does not support repairing.\n", 112 kProgramName); 113 return 1; 114 } 115 116 if (partition->IsMounted() && !canRepairWhileMounted) { 117 fprintf(stderr, "%s: The disk system does not support repairing a " 118 "mounted volume.\n", kProgramName); 119 return 1; 120 } 121 if (!partition->IsMounted() && !canRepair) { 122 fprintf(stderr, "%s: The disk system does not support repairing a " 123 "volume that is not mounted.\n", kProgramName); 124 return 1; 125 } 126 127 BDiskSystem diskSystem; 128 status = partition->GetDiskSystem(&diskSystem); 129 if (status != B_OK) { 130 fprintf(stderr, "%s: Failed to get disk system for partition: %s\n", 131 kProgramName, strerror(status)); 132 return 1; 133 } 134 135 // Repair the volume 136 137 status = partition->Repair(checkOnly); 138 if (status != B_OK) { 139 fprintf(stderr, "%s: Repairing failed: %s\n", kProgramName, 140 strerror(status)); 141 return 1; 142 } 143 144 status = device.CommitModifications(); 145 146 return 0; 147 } 148