1 /* 2 * Copyright 2013, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "GPTPartitionHandle.h" 9 10 #include <new> 11 #include <stdio.h> 12 13 #include <DiskDeviceTypes.h> 14 #include <MutablePartition.h> 15 #include <PartitioningInfo.h> 16 #include <PartitionParameterEditor.h> 17 #include <Path.h> 18 #include <SupportDefs.h> 19 20 #include <AutoDeleter.h> 21 22 #include "guid.h" 23 #include "gpt_known_guids.h" 24 #include "utility.h" 25 26 27 //#define TRACE_GPT_PARTITION_HANDLE 28 #undef TRACE 29 #ifdef TRACE_GPT_PARTITION_HANDLE 30 # define TRACE(x...) printf(x) 31 #else 32 # define TRACE(x...) do {} while (false) 33 #endif 34 35 36 GPTPartitionHandle::GPTPartitionHandle(BMutablePartition* partition) 37 : 38 BPartitionHandle(partition) 39 { 40 } 41 42 43 GPTPartitionHandle::~GPTPartitionHandle() 44 { 45 } 46 47 48 status_t 49 GPTPartitionHandle::Init() 50 { 51 // TODO: how to get the path of a BMutablePartition? 52 //BPath path; 53 //status_t status = Partition()->GetPath(&path); 54 //if (status != B_OK) 55 //return status; 56 57 //fd = open(path.Path(), O_RDONLY); 58 //if (fd < 0) 59 //return errno; 60 61 //fHeader = new EFI::Header(fd, Partition()->BlockSize(), 62 //Partition()->BlockSize()); 63 //status = fHeader->InitCheck(); 64 //if (status != B_OK) 65 //return status; 66 67 //close(fd); 68 return B_OK; 69 } 70 71 72 uint32 73 GPTPartitionHandle::SupportedOperations(uint32 mask) 74 { 75 uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING 76 | B_DISK_SYSTEM_SUPPORTS_MOVING 77 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS 78 | B_DISK_SYSTEM_SUPPORTS_NAME 79 | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME 80 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING; 81 82 // creating child 83 if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) { 84 BPartitioningInfo info; 85 if (GetPartitioningInfo(&info) == B_OK 86 && info.CountPartitionableSpaces() > 1) { 87 flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; 88 } 89 } 90 91 return flags; 92 } 93 94 95 uint32 96 GPTPartitionHandle::SupportedChildOperations(const BMutablePartition* child, 97 uint32 mask) 98 { 99 return B_DISK_SYSTEM_SUPPORTS_NAME 100 | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME 101 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD 102 | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD 103 | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE 104 | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS 105 | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; 106 } 107 108 109 status_t 110 GPTPartitionHandle::GetNextSupportedType(const BMutablePartition* child, 111 int32* cookie, BString* type) 112 { 113 int32 index = *cookie; 114 TRACE("GPTPartitionHandle::GetNextSupportedType(child: %p, cookie: %" B_PRId32 ")\n", 115 child, index); 116 117 if (index >= int32(B_COUNT_OF(kTypeMap))) 118 return B_ENTRY_NOT_FOUND; 119 120 type->SetTo(kTypeMap[index].type); 121 *cookie = index + 1; 122 123 return B_OK; 124 } 125 126 127 status_t 128 GPTPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) 129 { 130 // init to the full size (minus the GPT table header and entries) 131 off_t size = Partition()->ContentSize(); 132 // TODO: use fHeader 133 size_t headerSize = Partition()->BlockSize() + 16384; 134 status_t status = info->SetTo(Partition()->BlockSize() + headerSize, 135 size - Partition()->BlockSize() - 2 * headerSize); 136 if (status != B_OK) 137 return status; 138 139 // Exclude the space of the existing partitions 140 size_t count = Partition()->CountChildren(); 141 for (size_t index = 0; index < count; index++) { 142 BMutablePartition* child = Partition()->ChildAt(index); 143 status = info->ExcludeOccupiedSpace(child->Offset(), child->Size()); 144 if (status != B_OK) 145 return status; 146 } 147 148 return B_OK; 149 } 150 151 152 status_t 153 GPTPartitionHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type, 154 BPartitionParameterEditor** editor) 155 { 156 *editor = NULL; 157 if (type == B_CREATE_PARAMETER_EDITOR || type == B_PROPERTIES_PARAMETER_EDITOR) { 158 try { 159 *editor = new BPartitionParameterEditor(); 160 } catch (std::bad_alloc&) { 161 return B_NO_MEMORY; 162 } 163 return B_OK; 164 } 165 return B_NOT_SUPPORTED; 166 } 167 168 169 status_t 170 GPTPartitionHandle::ValidateSetName(const BMutablePartition *child, BString* name) 171 { 172 // UCS-2 can use up to 2 code points per character, and GPT allows 173 // a maximum of 36 code units; 174 size_t length = name->CountChars(); 175 if (length == 0) 176 return B_OK; 177 178 size_t size = length * 2; 179 uint16 buffer[size + 1]; 180 181 do { 182 size = to_ucs2(name->String(), length, buffer, length * 2); 183 if (size <= 36) 184 return B_OK; 185 length--; 186 name->TruncateChars(length, false); 187 } while (size > 36 && length > 0); 188 189 return B_OK; 190 } 191 192 193 status_t 194 GPTPartitionHandle::SetName(BMutablePartition* child, const char* name) 195 { 196 return child->SetName(name); 197 } 198 199 200 status_t 201 GPTPartitionHandle::ValidateSetType(const BMutablePartition* child, 202 const char* type) 203 { 204 for (size_t i = 0; i < B_COUNT_OF(kTypeMap); i++) { 205 if (strcmp(type, kTypeMap[i].type) == 0) 206 return B_OK; 207 } 208 return B_BAD_VALUE; 209 } 210 211 212 status_t 213 GPTPartitionHandle::SetType(BMutablePartition* child, const char* type) 214 { 215 return child->SetType(type); 216 } 217 218 219 status_t 220 GPTPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size, 221 const char* typeString, BString* name, const char* parameters) 222 { 223 return B_OK; 224 } 225 226 227 status_t 228 GPTPartitionHandle::CreateChild(off_t offset, off_t size, 229 const char* typeString, const char* name, const char* parameters, 230 BMutablePartition** _child) 231 { 232 // create the child 233 BMutablePartition* partition = Partition(); 234 BMutablePartition* child; 235 status_t status = partition->CreateChild(partition->CountChildren(), 236 typeString, name, parameters, &child); 237 if (status != B_OK) 238 return status; 239 240 // init the child 241 child->SetOffset(offset); 242 child->SetSize(size); 243 child->SetBlockSize(partition->BlockSize()); 244 245 *_child = child; 246 return B_OK; 247 } 248 249 250 status_t 251 GPTPartitionHandle::DeleteChild(BMutablePartition* child) 252 { 253 BMutablePartition* parent = child->Parent(); 254 return parent->DeleteChild(child); 255 } 256