vfs: check userland buffers before reading them.
[haiku.git] / src / bin / checkfs.cpp
blob9c63de655db26457401817379001b1f7bc02edd3
1 /*
2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <getopt.h>
8 #include <stdio.h>
10 #include <DiskDevice.h>
11 #include <DiskDeviceRoster.h>
12 #include <DiskSystem.h>
15 extern "C" const char* __progname;
16 static const char* kProgramName = __progname;
19 void
20 usage(FILE* output)
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);
32 int
33 main(int argc, char** argv)
35 const struct option kLongOptions[] = {
36 { "help", 0, NULL, 'h' },
37 { "check-only", 0, NULL, 'c' },
38 { NULL, 0, NULL, 0 }
40 const char* kShortOptions = "hc";
42 // parse argument list
43 bool checkOnly = false;
45 while (true) {
46 int nextOption = getopt_long(argc, argv, kShortOptions, kLongOptions,
47 NULL);
48 if (nextOption == -1)
49 break;
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;
64 // the device name should be the only non-option element
65 if (optind != argc - 1) {
66 usage(stderr);
67 return 1;
70 const char* path = argv[optind];
71 //UnregisterFileDevice unregisterFileDevice;
73 BDiskDeviceRoster roster;
74 BPartition* partition;
75 BDiskDevice device;
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;
86 // TODO: try to register file device
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;
95 // Prepare the device for modifications
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;
104 // Check if the partition supports repairing
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;
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;
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;
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;
133 // Repair the volume
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;
142 status = device.CommitModifications();
144 return 0;