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