1 /* 2 * Copyright 2008 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marco Minutoli, mminutoli@gmail.com 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 #include "FsCreator.h" 11 12 #include <iostream> 13 14 #include <DiskSystem.h> 15 16 17 class UnregisterFileDevice { 18 public: 19 UnregisterFileDevice() 20 : 21 fID(-1) 22 { 23 } 24 25 ~UnregisterFileDevice() 26 { 27 if (fID >= 0) { 28 BDiskDeviceRoster roster; 29 roster.UnregisterFileDevice(fID); 30 } 31 } 32 33 void SetTo(partition_id id) 34 { 35 fID = id; 36 } 37 38 void Detach() 39 { 40 fID = -1; 41 } 42 43 private: 44 partition_id fID; 45 }; 46 47 48 extern "C" const char* __progname; 49 static const char* kProgramName = __progname; 50 51 52 FsCreator::FsCreator(const char* path, const char* type, const char* volumeName, 53 const char* fsOptions, bool quick, bool verbose) 54 : 55 fType(type), 56 fPath(path), 57 fVolumeName(volumeName), 58 fFsOptions(fsOptions), 59 fVerbose(verbose), 60 fQuick(quick) 61 { 62 } 63 64 65 bool 66 FsCreator::Run() 67 { 68 UnregisterFileDevice unregisterFileDevice; 69 70 BDiskDeviceRoster roster; 71 BPartition* partition; 72 BDiskDevice device; 73 74 status_t status = roster.GetPartitionForPath(fPath, &device, 75 &partition); 76 if (status != B_OK) { 77 if (!strncmp(fPath, "/dev", 4)) { 78 std::cerr << kProgramName << ": Failed to get disk device for path " 79 << fPath << ": " << strerror(status) << std::endl; 80 return false; 81 } 82 83 // try to register file device 84 85 partition_id id = roster.RegisterFileDevice(fPath); 86 if (id < B_OK) { 87 std::cerr << kProgramName << ": Could not register file device for " 88 "path " << fPath << ": " << strerror(status) << std::endl; 89 return false; 90 } 91 92 unregisterFileDevice.SetTo(id); 93 94 status = roster.GetPartitionWithID(id, &device, &partition); 95 if (!strncmp(fPath, "/dev", 4)) { 96 std::cerr << kProgramName << ": Cannot find registered file device " 97 "for path " << fPath << ": " << strerror(status) 98 << std::endl; 99 return false; 100 } 101 } 102 103 // check that the device is writable 104 if (partition->IsReadOnly()) { 105 std::cerr << kProgramName << ": Cannot initialize read-only device.\n"; 106 return false; 107 } 108 109 // check if the device is mounted 110 if (partition->IsMounted()) { 111 std::cerr << kProgramName << ": Cannot initialize mounted device.\n"; 112 return false; 113 } 114 115 BDiskSystem diskSystem; 116 if (roster.GetDiskSystem(&diskSystem, fType) != B_OK) { 117 std::cerr << kProgramName << ": " << fType 118 << " is an invalid or unsupported file system type.\n"; 119 return false; 120 } 121 122 // prepare the device for modifications 123 status = device.PrepareModifications(); 124 if (status != B_OK) { 125 std::cerr << kProgramName << ": A problem occurred preparing the " 126 "device for the modifications\n"; 127 return false; 128 } 129 if (fVerbose) 130 std::cout << "Preparing for modifications...\n\n"; 131 132 // validate parameters 133 BString name(fVolumeName); 134 if (partition->ValidateInitialize(diskSystem.PrettyName(), 135 &name, fFsOptions) != B_OK) { 136 std::cerr << kProgramName << ": Parameters validation failed. " 137 "Check what you wrote\n"; 138 std::cerr << status; 139 return false; 140 } 141 if (fVerbose) 142 std::cout << "Parameters Validation...\n\n"; 143 if (name != fVolumeName) { 144 std::cout << "Volume name was adjusted to " 145 << name.String() << std::endl; 146 } 147 148 // Initialize the partition 149 status = partition->Initialize(diskSystem.PrettyName(), name.String(), 150 fFsOptions); 151 if (status != B_OK) { 152 std::cerr << kProgramName << ": Initialization failed: " 153 << strerror(status) << std::endl; 154 return false; 155 } 156 157 if (!fQuick) { 158 std::cout << "\nAbout to initialize " << fPath << " with " 159 << diskSystem.PrettyName() 160 << "\nAre you sure you want to do this now?\n" 161 << "\nALL YOUR DATA in " << fPath << " will be lost forever.\n"; 162 163 BString reply; 164 do { 165 std::cout << "Continue (yes|[no])? "; 166 reply = _ReadLine(); 167 if (reply == "") 168 reply = "no"; // silence is dissence 169 } while (reply != "yes" && reply != "no"); 170 171 if (reply != "yes") 172 return true; 173 } 174 175 status = device.CommitModifications(); 176 if (status == B_OK) { 177 if (fVerbose) { 178 std::cout << "Volume " << partition->ContentName() 179 << " has been initialized successfully!\n"; 180 } 181 } else { 182 std::cout << kProgramName << ": Initialization of " 183 << partition->ContentName() << " failed: " << strerror(status) 184 << std::endl; 185 return false; 186 } 187 188 // TODO: should we keep the file device around, or unregister it 189 // after we're done? This could be an option, too (for now, we'll 190 // just keep them if everything went well). 191 unregisterFileDevice.Detach(); 192 return true; 193 } 194 195 196 inline BString 197 FsCreator::_ReadLine() 198 { 199 char line[255]; 200 201 std::cin.getline(line, sizeof(line), '\n'); 202 203 return line; 204 } 205