1 /* 2 * Copyright 2008-2009 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 BString contentName = partition->ContentName(); 176 // CommitModifications() will invalidate our partition object 177 178 status = device.CommitModifications(); 179 if (status == B_OK) { 180 if (fVerbose) { 181 std::cout << "Volume \"" << contentName.String() 182 << "\" has been initialized successfully!" << std::endl; 183 } 184 } else { 185 std::cout << kProgramName << ": Initialization of \"" 186 << contentName.String() << "\" failed: " << strerror(status) 187 << std::endl; 188 return false; 189 } 190 191 // TODO: should we keep the file device around, or unregister it 192 // after we're done? This could be an option, too (for now, we'll 193 // just keep them if everything went well). 194 unregisterFileDevice.Detach(); 195 return true; 196 } 197 198 199 inline BString 200 FsCreator::_ReadLine() 201 { 202 char line[255]; 203 204 std::cin.getline(line, sizeof(line), '\n'); 205 206 return line; 207 } 208