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