xref: /haiku/src/bin/resizefs.cpp (revision 8c78892580f132d10e624aef96f835df8d94bf19)
1 /*
2  * Copyright 2012, Andreas Henriksson, sausageboy@gmail.com.
3  * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <stdio.h>
9 
10 #include <DiskDevice.h>
11 #include <DiskDeviceRoster.h>
12 #include <DiskSystem.h>
13 #include <StringForSize.h>
14 
15 
16 extern "C" const char* __progname;
17 static const char* kProgramName = __progname;
18 
19 
20 int
21 main(int argc, char** argv)
22 {
23 	if (argc != 3) {
24 		fprintf(stderr, "Usage: %s <device> <size>\n"
25 			"Resize volume on <device> to new size <size> (in bytes, suffixes "
26 			"'k', 'm', 'g', 't' are interpreted as KiB, Mib, GiB, TiB).\n",
27 			kProgramName);
28 		return 1;
29 	}
30 
31 	int64 size = parse_size(argv[2]);
32 	if (size <= 0) {
33 		fprintf(stderr, "%s: The new size \"%s\" is not a number\n",
34 			kProgramName, argv[2]);
35 		return 1;
36 	}
37 
38 	BDiskDeviceRoster roster;
39 	BPartition* partition;
40 	BDiskDevice device;
41 
42 	status_t status = roster.GetPartitionForPath(argv[1], &device,
43 		&partition);
44 	if (status != B_OK) {
45 		if (strncmp(argv[1], "/dev", 4)) {
46 			// try mounted volume
47 			status = roster.FindPartitionByMountPoint(argv[1], &device,
48 				&partition) ? B_OK : B_BAD_VALUE;
49 		}
50 
51 		// TODO: try to register file device
52 
53 		if (status != B_OK) {
54 			fprintf(stderr, "%s: Failed to get disk device for path \"%s\": "
55 				"%s\n", kProgramName, argv[1], strerror(status));
56 			return 1;
57 		}
58 	}
59 
60 	// Prepare the device for modifications
61 
62 	status = device.PrepareModifications();
63 	if (status != B_OK) {
64 		fprintf(stderr, "%s: Could not prepare the device for modifications: "
65 			"%s\n", kProgramName, strerror(status));
66 		return false;
67 	}
68 
69 	// Check if the partition supports resizing
70 
71 	bool canResizeWhileMounted;
72 	bool canResize = partition->CanResize(NULL, &canResizeWhileMounted);
73 
74 	if (!canResize && !canResizeWhileMounted) {
75 		fprintf(stderr, "%s: The disk system does not support resizing.\n",
76 			kProgramName);
77 		return 1;
78 	}
79 
80 	if (partition->IsMounted() && !canResizeWhileMounted) {
81 		fprintf(stderr, "%s: The disk system does not support resizing a "
82 			"mounted volume.\n", kProgramName);
83 		return 1;
84 	}
85 	if (!partition->IsMounted() && !canResize) {
86 		fprintf(stderr, "%s: The disk system does not support resizing a "
87 			"volume that is not mounted.\n", kProgramName);
88 		return 1;
89 	}
90 
91 	// Validate the requested size
92 
93 	off_t validatedSize = size;
94 	status = partition->ValidateResize(&validatedSize);
95 	if (status != B_OK) {
96 		fprintf(stderr, "%s: Failed to validate the size: %s\n", kProgramName,
97 			strerror(status));
98 		return 1;
99 	}
100 
101 	if (validatedSize != size) {
102 		printf("The requested size (%" B_PRId64 " bytes) was not accepted.\n"
103 			"Resize to %" B_PRId64 " bytes instead? (y/N): ", size,
104 			(int64)validatedSize);
105 
106 		int c = getchar();
107 		if (c != 'y')
108 			return 0;
109 	}
110 
111 	// Resize the volume
112 
113 	status = partition->Resize(validatedSize);
114 	if (status != B_OK) {
115 		fprintf(stderr, "%s: Resizing failed: %s\n", kProgramName,
116 			strerror(status));
117 		return 1;
118 	}
119 
120 	status = device.CommitModifications();
121 	if (status != B_OK) {
122 		fprintf(stderr, "%s: Failed to commit modifications: %s\n",
123 			kProgramName, strerror(status));
124 		return 1;
125 	}
126 
127 	return 0;
128 }
129