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
29KPartitioningSystem::KPartitioningSystem(const char *name)
30	: KDiskSystem(name),
31	  fModule(NULL)
32{
33}
34
35
36// destructor
37KPartitioningSystem::~KPartitioningSystem()
38{
39}
40
41
42// Init
43status_t
44KPartitioningSystem::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
64float
65KPartitioningSystem::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
86status_t
87KPartitioningSystem::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
102void
103KPartitioningSystem::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
113void
114KPartitioningSystem::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
126void
127KPartitioningSystem::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
140status_t
141KPartitioningSystem::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
151status_t
152KPartitioningSystem::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
177status_t
178KPartitioningSystem::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
203status_t
204KPartitioningSystem::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
229status_t
230KPartitioningSystem::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
256status_t
257KPartitioningSystem::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
284status_t
285KPartitioningSystem::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
311status_t
312KPartitioningSystem::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
339status_t
340KPartitioningSystem::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
367status_t
368KPartitioningSystem::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
395status_t
396KPartitioningSystem::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
421status_t
422KPartitioningSystem::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
448status_t
449KPartitioningSystem::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
480status_t
481KPartitioningSystem::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
501status_t
502KPartitioningSystem::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
511void
512KPartitioningSystem::UnloadModule()
513{
514	if (fModule) {
515		put_module(fModule->module.name);
516		fModule = NULL;
517	}
518}
519