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