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	float result = fModule->identify_partition(fd, partition->PartitionData(),
73		cookie);
74	close(fd);
75	return result;
76}
77
78
79// Scan
80//! Scan the partition
81status_t
82KPartitioningSystem::Scan(KPartition *partition, void *cookie)
83{
84	if (!partition || !fModule || !fModule->scan_partition)
85		return B_ERROR;
86	int fd = -1;
87	status_t result = partition->Open(O_RDONLY, &fd);
88	if (result != B_OK)
89		return result;
90	result = fModule->scan_partition(fd, partition->PartitionData(), cookie);
91	close(fd);
92	return result;
93}
94
95
96// FreeIdentifyCookie
97void
98KPartitioningSystem::FreeIdentifyCookie(KPartition *partition, void *cookie)
99{
100	if (!partition || !fModule || !fModule->free_identify_partition_cookie)
101		return;
102	fModule->free_identify_partition_cookie(partition->PartitionData(),
103		cookie);
104}
105
106
107// FreeCookie
108void
109KPartitioningSystem::FreeCookie(KPartition *partition)
110{
111	if (!partition || !fModule || !fModule->free_partition_cookie
112		|| partition->ParentDiskSystem() != this) {
113		return;
114	}
115	fModule->free_partition_cookie(partition->PartitionData());
116	partition->SetCookie(NULL);
117}
118
119
120// FreeContentCookie
121void
122KPartitioningSystem::FreeContentCookie(KPartition *partition)
123{
124	if (!partition || !fModule || !fModule->free_partition_content_cookie
125		|| partition->DiskSystem() != this) {
126		return;
127	}
128	fModule->free_partition_content_cookie(partition->PartitionData());
129	partition->SetContentCookie(NULL);
130}
131
132
133// Repair
134//! Repairs a partition
135status_t
136KPartitioningSystem::Repair(KPartition* partition, bool checkOnly,
137	disk_job_id job)
138{
139	// to be implemented
140	return B_ERROR;
141}
142
143
144// Resize
145//! Resizes a partition
146status_t
147KPartitioningSystem::Resize(KPartition* partition, off_t size, disk_job_id job)
148{
149	// check parameters
150	if (!partition || size < 0 || !fModule)
151		return B_BAD_VALUE;
152	if (!fModule->resize)
153		return B_NOT_SUPPORTED;
154
155	// open partition device
156	int fd = -1;
157	status_t result = partition->Open(O_RDWR, &fd);
158	if (result != B_OK)
159		return result;
160
161	// let the module do its job
162	result = fModule->resize(fd, partition->ID(), size, job);
163
164	// cleanup and return
165	close(fd);
166	return result;
167}
168
169
170// ResizeChild
171//! Resizes child of a partition
172status_t
173KPartitioningSystem::ResizeChild(KPartition* child, off_t size, disk_job_id job)
174{
175	// check parameters
176	if (!child || !child->Parent() || size < 0 || !fModule)
177		return B_BAD_VALUE;
178	if (!fModule->resize_child)
179		return B_NOT_SUPPORTED;
180
181	// open partition device
182	int fd = -1;
183	status_t result = child->Parent()->Open(O_RDWR, &fd);
184	if (result != B_OK)
185		return result;
186
187	// let the module do its job
188	result = fModule->resize_child(fd, child->ID(), size, job);
189
190	// cleanup and return
191	close(fd);
192	return result;
193}
194
195
196// Move
197//! Moves a partition
198status_t
199KPartitioningSystem::Move(KPartition* partition, off_t offset, disk_job_id job)
200{
201	// check parameters
202	if (!partition)
203		return B_BAD_VALUE;
204	if (!fModule->move)
205		return B_NOT_SUPPORTED;
206
207	// open partition device
208	int fd = -1;
209	status_t result = partition->Open(O_RDWR, &fd);
210	if (result != B_OK)
211		return result;
212
213	// let the module do its job
214	result = fModule->move(fd, partition->ID(), offset, job);
215
216	// cleanup and return
217	close(fd);
218	return result;
219}
220
221
222// MoveChild
223//! Moves child of a partition
224status_t
225KPartitioningSystem::MoveChild(KPartition* child, off_t offset, disk_job_id job)
226{
227	// check parameters
228	if (!child || !child->Parent() || !fModule)
229		return B_BAD_VALUE;
230	if (!fModule->move_child)
231		return B_NOT_SUPPORTED;
232
233	// open partition device
234	int fd = -1;
235	status_t result = child->Parent()->Open(O_RDWR, &fd);
236	if (result != B_OK)
237		return result;
238
239	// let the module do its job
240	result = fModule->move_child(fd, child->Parent()->ID(), child->ID(), offset,
241		job);
242
243	// cleanup and return
244	close(fd);
245	return result;
246}
247
248
249// SetName
250//! Sets name of a partition
251status_t
252KPartitioningSystem::SetName(KPartition* child, const char* name,
253	disk_job_id job)
254{
255	// check parameters
256	if (!child || !child->Parent() || !fModule)
257		return B_BAD_VALUE;
258	if (!fModule->set_name)
259		return B_NOT_SUPPORTED;
260
261	// open partition device
262	int fd = -1;
263	status_t result = child->Parent()->Open(O_RDWR, &fd);
264	if (result != B_OK)
265		return result;
266
267	// let the module do its job
268	result = fModule->set_name(fd, child->ID(), name, job);
269// TODO: Change hook interface!
270
271	// cleanup and return
272	close(fd);
273	return result;
274}
275
276
277// SetContentName
278//! Sets name of the content of a partition
279status_t
280KPartitioningSystem::SetContentName(KPartition* partition, const char* name,
281	disk_job_id job)
282{
283	// check parameters
284	if (!partition || !fModule)
285		return B_BAD_VALUE;
286	if (!fModule->set_content_name)
287		return B_NOT_SUPPORTED;
288
289	// open partition device
290	int fd = -1;
291	status_t result = partition->Open(O_RDWR, &fd);
292	if (result != B_OK)
293		return result;
294
295	// let the module do its job
296	result = fModule->set_content_name(fd, partition->ID(), name, job);
297
298	// cleanup and return
299	close(fd);
300	return result;
301}
302
303
304// SetType
305//! Sets type of a partition
306status_t
307KPartitioningSystem::SetType(KPartition* child, const char* type,
308	disk_job_id job)
309{
310	// check parameters
311	if (!child || !child->Parent() || !type || !fModule)
312		return B_BAD_VALUE;
313	if (!fModule->set_type)
314		return B_NOT_SUPPORTED;
315
316	// open partition device
317	int fd = -1;
318	status_t result = child->Parent()->Open(O_RDWR, &fd);
319	if (result != B_OK)
320		return result;
321
322	// let the module do its job
323	result = fModule->set_type(fd, child->Parent()->ID(), type, job);
324// TODO: Change hook interface!
325
326	// cleanup and return
327	close(fd);
328	return result;
329}
330
331
332// SetParameters
333//! Sets parameters of a partition
334status_t
335KPartitioningSystem::SetParameters(KPartition* child, const char* parameters,
336	disk_job_id job)
337{
338	// check parameters
339	if (!child || !child->Parent() || !fModule)
340		return B_BAD_VALUE;
341	if (!fModule->set_parameters)
342		return B_NOT_SUPPORTED;
343
344	// open partition device
345	int fd = -1;
346	status_t result = child->Parent()->Open(O_RDWR, &fd);
347	if (result != B_OK)
348		return result;
349
350	// let the module do its job
351	result = fModule->set_parameters(fd, child->ID(), parameters, job);
352// TODO: Change hook interface!
353
354	// cleanup and return
355	close(fd);
356	return result;
357}
358
359
360// SetContentParameters
361//! Sets parameters of the content of a partition
362status_t
363KPartitioningSystem::SetContentParameters(KPartition* partition,
364	const char* parameters, disk_job_id job)
365{
366	// check parameters
367	if (!partition || !fModule)
368		return B_BAD_VALUE;
369	if (!fModule->set_content_parameters)
370		return B_NOT_SUPPORTED;
371
372	// open partition device
373	int fd = -1;
374	status_t result = partition->Open(O_RDWR, &fd);
375	if (result != B_OK)
376		return result;
377
378	// let the module do its job
379	result = fModule->set_content_parameters(fd, partition->ID(), parameters,
380		job);
381
382	// cleanup and return
383	close(fd);
384	return result;
385}
386
387
388// Initialize
389//! Initializes a partition with this partitioning system
390status_t
391KPartitioningSystem::Initialize(KPartition* partition, const char* name,
392	const char* parameters, disk_job_id job)
393{
394	// check parameters
395	if (!partition || !fModule)
396		return B_BAD_VALUE;
397	if (!fModule->initialize)
398		return B_NOT_SUPPORTED;
399
400	// open partition device
401	int fd = -1;
402	status_t result = partition->Open(O_RDWR, &fd);
403	if (result != B_OK)
404		return result;
405
406	// let the module do its job
407	result = fModule->initialize(fd, partition->ID(), name, parameters,
408		partition->Size(), job);
409
410	// cleanup and return
411	close(fd);
412	return result;
413}
414
415
416status_t
417KPartitioningSystem::Uninitialize(KPartition* partition, disk_job_id job)
418{
419	// check parameters
420	if (partition == NULL || fModule == NULL)
421		return B_BAD_VALUE;
422	if (fModule->uninitialize == NULL)
423		return B_NOT_SUPPORTED;
424
425	// open partition device
426	int fd = -1;
427	status_t result = partition->Open(O_RDWR, &fd);
428	if (result != B_OK)
429		return result;
430
431	// let the module do its job
432	result = fModule->uninitialize(fd, partition->ID(), partition->Size(),
433		partition->BlockSize(), job);
434
435	// cleanup and return
436	close(fd);
437	return result;
438}
439
440
441// CreateChild
442//! Creates a child partition
443status_t
444KPartitioningSystem::CreateChild(KPartition* partition, off_t offset,
445	off_t size, const char* type, const char* name, const char* parameters,
446	disk_job_id job, KPartition** child, partition_id childID)
447{
448	// check parameters
449	if (!partition || !type || !parameters || !child || !fModule)
450		return B_BAD_VALUE;
451	if (!fModule->create_child)
452		return B_NOT_SUPPORTED;
453
454	// open partition device
455	int fd = -1;
456	status_t result = partition->Open(O_RDWR, &fd);
457	if (result != B_OK)
458		return result;
459
460	// let the module do its job
461	result = fModule->create_child(fd, partition->ID(), offset, size,
462		type, name, parameters, job, &childID);
463
464	// find and return the child
465	*child = KDiskDeviceManager::Default()->FindPartition(childID);
466
467	// cleanup and return
468	close(fd);
469	return result;
470}
471
472
473// DeleteChild
474//! Deletes a child partition
475status_t
476KPartitioningSystem::DeleteChild(KPartition* child, disk_job_id job)
477{
478	if (!child || !child->Parent())
479		return B_BAD_VALUE;
480	if (!fModule->delete_child)
481		return B_NOT_SUPPORTED;
482
483	int fd = -1;
484	KPartition* parent = child->Parent();
485	status_t result = parent->Open(O_RDWR, &fd);
486	if (result != B_OK)
487		return result;
488
489	result = fModule->delete_child(fd, parent->ID(), child->ID(), job);
490	close(fd);
491	return result;
492}
493
494
495// LoadModule
496status_t
497KPartitioningSystem::LoadModule()
498{
499	if (fModule)		// shouldn't happen
500		return B_OK;
501	return get_module(Name(), (module_info**)&fModule);
502}
503
504
505// UnloadModule
506void
507KPartitioningSystem::UnloadModule()
508{
509	if (fModule) {
510		put_module(fModule->module.name);
511		fModule = NULL;
512	}
513}
514