xref: /haiku/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /*
2  * Copyright 2003-2011, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ingo Weinhold <bonefish@cs.tu-berlin.de>
7  *		Lubos Kulic <lubos@radical.ed>
8  */
9 
10 /**	\file KPartitioningSystem.cpp
11  *
12  * 	\brief Implementation of \ref KPartitioningSystem class
13  */
14 
15 #include <fcntl.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 
19 #include <ddm_modules.h>
20 #include <KDiskDevice.h>
21 //#include <KDiskDeviceJob.h>
22 #include <KDiskDeviceManager.h>
23 #include <KDiskDeviceUtils.h>
24 #include <KPartition.h>
25 #include <KPartitioningSystem.h>
26 
27 
28 // constructor
29 KPartitioningSystem::KPartitioningSystem(const char *name)
30 	: KDiskSystem(name),
31 	  fModule(NULL)
32 {
33 }
34 
35 
36 // destructor
37 KPartitioningSystem::~KPartitioningSystem()
38 {
39 }
40 
41 
42 // Init
43 status_t
44 KPartitioningSystem::Init()
45 {
46 	status_t error = KDiskSystem::Init();
47 	if (error != B_OK)
48 		return error;
49 	error = Load();
50 	if (error != B_OK)
51 		return error;
52 	error = SetShortName(fModule->short_name);
53 	if (error == B_OK)
54 		error = SetPrettyName(fModule->pretty_name);
55 
56 	SetFlags(fModule->flags & ~(uint32)B_DISK_SYSTEM_IS_FILE_SYSTEM);
57 	Unload();
58 	return error;
59 }
60 
61 
62 // Identify
63 //! Try to identify a given partition
64 float
65 KPartitioningSystem::Identify(KPartition *partition, void **cookie)
66 {
67 	if (!partition || !cookie || !fModule || !fModule->identify_partition)
68 		return -1;
69 	int fd = -1;
70 	if (partition->Open(O_RDONLY, &fd) != B_OK)
71 		return -1;
72 	if (partition->BlockSize() == 0) {
73 		close(fd);
74 		return -1;
75 	}
76 
77 	float result = fModule->identify_partition(fd, partition->PartitionData(),
78 		cookie);
79 	close(fd);
80 	return result;
81 }
82 
83 
84 // Scan
85 //! Scan the partition
86 status_t
87 KPartitioningSystem::Scan(KPartition *partition, void *cookie)
88 {
89 	if (!partition || !fModule || !fModule->scan_partition)
90 		return B_ERROR;
91 	int fd = -1;
92 	status_t result = partition->Open(O_RDONLY, &fd);
93 	if (result != B_OK)
94 		return result;
95 	result = fModule->scan_partition(fd, partition->PartitionData(), cookie);
96 	close(fd);
97 	return result;
98 }
99 
100 
101 // FreeIdentifyCookie
102 void
103 KPartitioningSystem::FreeIdentifyCookie(KPartition *partition, void *cookie)
104 {
105 	if (!partition || !fModule || !fModule->free_identify_partition_cookie)
106 		return;
107 	fModule->free_identify_partition_cookie(partition->PartitionData(),
108 		cookie);
109 }
110 
111 
112 // FreeCookie
113 void
114 KPartitioningSystem::FreeCookie(KPartition *partition)
115 {
116 	if (!partition || !fModule || !fModule->free_partition_cookie
117 		|| partition->ParentDiskSystem() != this) {
118 		return;
119 	}
120 	fModule->free_partition_cookie(partition->PartitionData());
121 	partition->SetCookie(NULL);
122 }
123 
124 
125 // FreeContentCookie
126 void
127 KPartitioningSystem::FreeContentCookie(KPartition *partition)
128 {
129 	if (!partition || !fModule || !fModule->free_partition_content_cookie
130 		|| partition->DiskSystem() != this) {
131 		return;
132 	}
133 	fModule->free_partition_content_cookie(partition->PartitionData());
134 	partition->SetContentCookie(NULL);
135 }
136 
137 
138 // Repair
139 //! Repairs a partition
140 status_t
141 KPartitioningSystem::Repair(KPartition* partition, bool checkOnly,
142 	disk_job_id job)
143 {
144 	// to be implemented
145 	return B_ERROR;
146 }
147 
148 
149 // Resize
150 //! Resizes a partition
151 status_t
152 KPartitioningSystem::Resize(KPartition* partition, off_t size, disk_job_id job)
153 {
154 	// check parameters
155 	if (!partition || size < 0 || !fModule)
156 		return B_BAD_VALUE;
157 	if (!fModule->resize)
158 		return B_NOT_SUPPORTED;
159 
160 	// open partition device
161 	int fd = -1;
162 	status_t result = partition->Open(O_RDWR, &fd);
163 	if (result != B_OK)
164 		return result;
165 
166 	// let the module do its job
167 	result = fModule->resize(fd, partition->ID(), size, job);
168 
169 	// cleanup and return
170 	close(fd);
171 	return result;
172 }
173 
174 
175 // ResizeChild
176 //! Resizes child of a partition
177 status_t
178 KPartitioningSystem::ResizeChild(KPartition* child, off_t size, disk_job_id job)
179 {
180 	// check parameters
181 	if (!child || !child->Parent() || size < 0 || !fModule)
182 		return B_BAD_VALUE;
183 	if (!fModule->resize_child)
184 		return B_NOT_SUPPORTED;
185 
186 	// open partition device
187 	int fd = -1;
188 	status_t result = child->Parent()->Open(O_RDWR, &fd);
189 	if (result != B_OK)
190 		return result;
191 
192 	// let the module do its job
193 	result = fModule->resize_child(fd, child->ID(), size, job);
194 
195 	// cleanup and return
196 	close(fd);
197 	return result;
198 }
199 
200 
201 // Move
202 //! Moves a partition
203 status_t
204 KPartitioningSystem::Move(KPartition* partition, off_t offset, disk_job_id job)
205 {
206 	// check parameters
207 	if (!partition)
208 		return B_BAD_VALUE;
209 	if (!fModule->move)
210 		return B_NOT_SUPPORTED;
211 
212 	// open partition device
213 	int fd = -1;
214 	status_t result = partition->Open(O_RDWR, &fd);
215 	if (result != B_OK)
216 		return result;
217 
218 	// let the module do its job
219 	result = fModule->move(fd, partition->ID(), offset, job);
220 
221 	// cleanup and return
222 	close(fd);
223 	return result;
224 }
225 
226 
227 // MoveChild
228 //! Moves child of a partition
229 status_t
230 KPartitioningSystem::MoveChild(KPartition* child, off_t offset, disk_job_id job)
231 {
232 	// check parameters
233 	if (!child || !child->Parent() || !fModule)
234 		return B_BAD_VALUE;
235 	if (!fModule->move_child)
236 		return B_NOT_SUPPORTED;
237 
238 	// open partition device
239 	int fd = -1;
240 	status_t result = child->Parent()->Open(O_RDWR, &fd);
241 	if (result != B_OK)
242 		return result;
243 
244 	// let the module do its job
245 	result = fModule->move_child(fd, child->Parent()->ID(), child->ID(), offset,
246 		job);
247 
248 	// cleanup and return
249 	close(fd);
250 	return result;
251 }
252 
253 
254 // SetName
255 //! Sets name of a partition
256 status_t
257 KPartitioningSystem::SetName(KPartition* child, const char* name,
258 	disk_job_id job)
259 {
260 	// check parameters
261 	if (!child || !child->Parent() || !fModule)
262 		return B_BAD_VALUE;
263 	if (!fModule->set_name)
264 		return B_NOT_SUPPORTED;
265 
266 	// open partition device
267 	int fd = -1;
268 	status_t result = child->Parent()->Open(O_RDWR, &fd);
269 	if (result != B_OK)
270 		return result;
271 
272 	// let the module do its job
273 	result = fModule->set_name(fd, child->ID(), name, job);
274 // TODO: Change hook interface!
275 
276 	// cleanup and return
277 	close(fd);
278 	return result;
279 }
280 
281 
282 // SetContentName
283 //! Sets name of the content of a partition
284 status_t
285 KPartitioningSystem::SetContentName(KPartition* partition, const char* name,
286 	disk_job_id job)
287 {
288 	// check parameters
289 	if (!partition || !fModule)
290 		return B_BAD_VALUE;
291 	if (!fModule->set_content_name)
292 		return B_NOT_SUPPORTED;
293 
294 	// open partition device
295 	int fd = -1;
296 	status_t result = partition->Open(O_RDWR, &fd);
297 	if (result != B_OK)
298 		return result;
299 
300 	// let the module do its job
301 	result = fModule->set_content_name(fd, partition->ID(), name, job);
302 
303 	// cleanup and return
304 	close(fd);
305 	return result;
306 }
307 
308 
309 // SetType
310 //! Sets type of a partition
311 status_t
312 KPartitioningSystem::SetType(KPartition* child, const char* type,
313 	disk_job_id job)
314 {
315 	// check parameters
316 	if (!child || !child->Parent() || !type || !fModule)
317 		return B_BAD_VALUE;
318 	if (!fModule->set_type)
319 		return B_NOT_SUPPORTED;
320 
321 	// open partition device
322 	int fd = -1;
323 	status_t result = child->Parent()->Open(O_RDWR, &fd);
324 	if (result != B_OK)
325 		return result;
326 
327 	// let the module do its job
328 	result = fModule->set_type(fd, child->Parent()->ID(), type, job);
329 // TODO: Change hook interface!
330 
331 	// cleanup and return
332 	close(fd);
333 	return result;
334 }
335 
336 
337 // SetParameters
338 //! Sets parameters of a partition
339 status_t
340 KPartitioningSystem::SetParameters(KPartition* child, const char* parameters,
341 	disk_job_id job)
342 {
343 	// check parameters
344 	if (!child || !child->Parent() || !fModule)
345 		return B_BAD_VALUE;
346 	if (!fModule->set_parameters)
347 		return B_NOT_SUPPORTED;
348 
349 	// open partition device
350 	int fd = -1;
351 	status_t result = child->Parent()->Open(O_RDWR, &fd);
352 	if (result != B_OK)
353 		return result;
354 
355 	// let the module do its job
356 	result = fModule->set_parameters(fd, child->ID(), parameters, job);
357 // TODO: Change hook interface!
358 
359 	// cleanup and return
360 	close(fd);
361 	return result;
362 }
363 
364 
365 // SetContentParameters
366 //! Sets parameters of the content of a partition
367 status_t
368 KPartitioningSystem::SetContentParameters(KPartition* partition,
369 	const char* parameters, disk_job_id job)
370 {
371 	// check parameters
372 	if (!partition || !fModule)
373 		return B_BAD_VALUE;
374 	if (!fModule->set_content_parameters)
375 		return B_NOT_SUPPORTED;
376 
377 	// open partition device
378 	int fd = -1;
379 	status_t result = partition->Open(O_RDWR, &fd);
380 	if (result != B_OK)
381 		return result;
382 
383 	// let the module do its job
384 	result = fModule->set_content_parameters(fd, partition->ID(), parameters,
385 		job);
386 
387 	// cleanup and return
388 	close(fd);
389 	return result;
390 }
391 
392 
393 // Initialize
394 //! Initializes a partition with this partitioning system
395 status_t
396 KPartitioningSystem::Initialize(KPartition* partition, const char* name,
397 	const char* parameters, disk_job_id job)
398 {
399 	// check parameters
400 	if (!partition || !fModule)
401 		return B_BAD_VALUE;
402 	if (!fModule->initialize)
403 		return B_NOT_SUPPORTED;
404 
405 	// open partition device
406 	int fd = -1;
407 	status_t result = partition->Open(O_RDWR, &fd);
408 	if (result != B_OK)
409 		return result;
410 
411 	// let the module do its job
412 	result = fModule->initialize(fd, partition->ID(), name, parameters,
413 		partition->Size(), job);
414 
415 	// cleanup and return
416 	close(fd);
417 	return result;
418 }
419 
420 
421 status_t
422 KPartitioningSystem::Uninitialize(KPartition* partition, disk_job_id job)
423 {
424 	// check parameters
425 	if (partition == NULL || fModule == NULL)
426 		return B_BAD_VALUE;
427 	if (fModule->uninitialize == NULL)
428 		return B_NOT_SUPPORTED;
429 
430 	// open partition device
431 	int fd = -1;
432 	status_t result = partition->Open(O_RDWR, &fd);
433 	if (result != B_OK)
434 		return result;
435 
436 	// let the module do its job
437 	result = fModule->uninitialize(fd, partition->ID(), partition->Size(),
438 		partition->BlockSize(), job);
439 
440 	// cleanup and return
441 	close(fd);
442 	return result;
443 }
444 
445 
446 // CreateChild
447 //! Creates a child partition
448 status_t
449 KPartitioningSystem::CreateChild(KPartition* partition, off_t offset,
450 	off_t size, const char* type, const char* name, const char* parameters,
451 	disk_job_id job, KPartition** child, partition_id childID)
452 {
453 	// check parameters
454 	if (!partition || !type || !parameters || !child || !fModule)
455 		return B_BAD_VALUE;
456 	if (!fModule->create_child)
457 		return B_NOT_SUPPORTED;
458 
459 	// open partition device
460 	int fd = -1;
461 	status_t result = partition->Open(O_RDWR, &fd);
462 	if (result != B_OK)
463 		return result;
464 
465 	// let the module do its job
466 	result = fModule->create_child(fd, partition->ID(), offset, size,
467 		type, name, parameters, job, &childID);
468 
469 	// find and return the child
470 	*child = KDiskDeviceManager::Default()->FindPartition(childID);
471 
472 	// cleanup and return
473 	close(fd);
474 	return result;
475 }
476 
477 
478 // DeleteChild
479 //! Deletes a child partition
480 status_t
481 KPartitioningSystem::DeleteChild(KPartition* child, disk_job_id job)
482 {
483 	if (!child || !child->Parent())
484 		return B_BAD_VALUE;
485 	if (!fModule->delete_child)
486 		return B_NOT_SUPPORTED;
487 
488 	int fd = -1;
489 	KPartition* parent = child->Parent();
490 	status_t result = parent->Open(O_RDWR, &fd);
491 	if (result != B_OK)
492 		return result;
493 
494 	result = fModule->delete_child(fd, parent->ID(), child->ID(), job);
495 	close(fd);
496 	return result;
497 }
498 
499 
500 // LoadModule
501 status_t
502 KPartitioningSystem::LoadModule()
503 {
504 	if (fModule)		// shouldn't happen
505 		return B_OK;
506 	return get_module(Name(), (module_info**)&fModule);
507 }
508 
509 
510 // UnloadModule
511 void
512 KPartitioningSystem::UnloadModule()
513 {
514 	if (fModule) {
515 		put_module(fModule->module.name);
516 		fModule = NULL;
517 	}
518 }
519