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
usage(FILE * output)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
main(int argc,char ** argv)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