xref: /haiku/src/add-ons/disk_systems/gpt/GPTPartitionHandle.cpp (revision 9918c8295480d70f55fafb98008e23109b598871)
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