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