xref: /haiku/src/bin/checkfs.cpp (revision 4f2fd49bdc6078128b1391191e4edac647044c3d)
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