xref: /haiku/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp (revision 300868ce276e35845db32cb8344e662de0872af9)
1 /** \file ddm_userland_interface.cpp
2  *
3  * 	\brief Interface for userspace calls.
4  */
5 
6 #include <stdlib.h>
7 
8 #include <AutoDeleter.h>
9 #include <ddm_userland_interface.h>
10 #include <KDiskDevice.h>
11 #include <KDiskDeviceJob.h>
12 #include <KDiskDeviceJobQueue.h>
13 #include <KDiskDeviceManager.h>
14 #include <KDiskDeviceUtils.h>
15 #include <KDiskSystem.h>
16 #include <KFileDiskDevice.h>
17 #include <KShadowPartition.h>
18 #include <syscall_args.h>
19 
20 #include "ddm_operation_validation.h"
21 #include "KDiskDeviceJobGenerator.h"
22 #include "UserDataWriter.h"
23 
24 using namespace BPrivate::DiskDevice;
25 
26 // debugging
27 #define ERROR(x)
28 
29 
30 // TODO: Add user address checks and check return values of user_memcpy()!
31 
32 
33 // ddm_strlcpy
34 /*! \brief Wrapper around user_strlcpy() that returns a status_t
35 	indicating appropriate success or failure.
36 
37 	\param allowTruncation If \c true, does not return an error if
38 	       \a from is longer than \to. If \c false, returns \c B_NAME_TOO_LONG
39 	       if \a from is longer than \to.
40 */
41 static status_t
42 ddm_strlcpy(char *to, const char *from, size_t size,
43 	bool allowTruncation = false)
44 {
45 	ssize_t fromLen = user_strlcpy(to, from, size);
46 	if (fromLen < 0)
47 		return fromLen;
48 	if ((size_t)fromLen >= size && !allowTruncation)
49 		return B_NAME_TOO_LONG;
50 	return B_OK;
51 }
52 
53 
54 // move_descendants
55 static void
56 move_descendants(KPartition *partition, off_t moveBy)
57 {
58 	if (!partition)
59 		return;
60 	partition->SetOffset(partition->Offset() + moveBy);
61 	// move children
62 	for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
63 		move_descendants(child, moveBy);
64 }
65 
66 
67 // move_descendants_contents
68 static status_t
69 move_descendants_contents(KPartition *partition)
70 {
71 	if (!partition)
72 		return B_BAD_VALUE;
73 	// implicit content disk system changes
74 	KDiskSystem *diskSystem = partition->DiskSystem();
75 	if (diskSystem || partition->AlgorithmData()) {
76 		status_t error = diskSystem->ShadowPartitionChanged(partition,
77 			NULL, B_PARTITION_MOVE);
78 		if (error != B_OK)
79 			return error;
80 	}
81 	// move children's contents
82 	for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
83 		status_t error = move_descendants_contents(child);
84 		if (error != B_OK)
85 			return error;
86 	}
87 	return B_OK;
88 }
89 
90 
91 // _user_get_next_disk_device_id
92 partition_id
93 _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize)
94 {
95 	if (!_cookie)
96 		return B_BAD_VALUE;
97 	int32 cookie;
98 	user_memcpy(&cookie, _cookie, sizeof(cookie));
99 
100 	partition_id id = B_ENTRY_NOT_FOUND;
101 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
102 	// get the next device
103 	if (KDiskDevice *device = manager->RegisterNextDevice(&cookie)) {
104 		PartitionRegistrar _(device, true);
105 		id = device->ID();
106 		if (neededSize) {
107 			if (DeviceReadLocker locker = device) {
108 				// get the needed size
109 				UserDataWriter writer;
110 				device->WriteUserData(writer, false);
111 				*neededSize = writer.AllocatedSize();
112 			} else {
113 				id = B_ERROR;
114 			}
115 		}
116 	}
117 	user_memcpy(_cookie, &cookie, sizeof(cookie));
118 	return id;
119 }
120 
121 
122 // _user_find_disk_device
123 partition_id
124 _user_find_disk_device(const char *_filename, size_t *neededSize)
125 {
126 	if (!_filename)
127 		return B_BAD_VALUE;
128 
129 	char filename[B_PATH_NAME_LENGTH];
130 	status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH);
131 	if (error)
132 		return error;
133 
134 	partition_id id = B_ENTRY_NOT_FOUND;
135 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
136 	// find the device
137 	if (KDiskDevice *device = manager->RegisterDevice(filename)) {
138 		PartitionRegistrar _(device, true);
139 		id = device->ID();
140 		if (neededSize) {
141 			if (DeviceReadLocker locker = device) {
142 				// get the needed size
143 				UserDataWriter writer;
144 				device->WriteUserData(writer, false);
145 				*neededSize = writer.AllocatedSize();
146 			} else
147 				return B_ERROR;
148 		}
149 	}
150 	return id;
151 }
152 
153 
154 // _user_find_partition
155 partition_id
156 _user_find_partition(const char *_filename, size_t *neededSize)
157 {
158 	if (!_filename)
159 		return B_BAD_VALUE;
160 
161 	char filename[B_PATH_NAME_LENGTH];
162 	status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH);
163 	if (error)
164 		return error;
165 
166 	partition_id id = B_ENTRY_NOT_FOUND;
167 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
168 	// find the partition
169 	if (KPartition *partition = manager->RegisterPartition(filename)) {
170 		PartitionRegistrar _(partition, true);
171 		id = partition->ID();
172 		if (neededSize) {
173 			// get and lock the partition's device
174 			KDiskDevice *device = manager->RegisterDevice(partition->ID());
175 			if (!device)
176 				return B_ENTRY_NOT_FOUND;
177 			PartitionRegistrar _2(device, true);
178 			if (DeviceReadLocker locker = device) {
179 				// get the needed size
180 				UserDataWriter writer;
181 				device->WriteUserData(writer, false);
182 				*neededSize = writer.AllocatedSize();
183 			} else
184 				return B_ERROR;
185 		}
186 	}
187 	return id;
188 }
189 
190 
191 // _user_get_disk_device_data
192 /*!	\brief Writes data describing the disk device identified by ID and all
193 		   its partitions into the supplied buffer.
194 
195 	The function passes the buffer size required to hold the data back
196 	through the \a _neededSize parameter, if the device could be found at
197 	least and no serious error occured. If fails with \c B_BUFFER_OVERFLOW,
198 	if the supplied buffer is too small or a \c NULL buffer is supplied
199 	(and \c bufferSize is 0).
200 
201 	The device is identified by \a id. If \a deviceOnly is \c true, then
202 	it must be the ID of a disk device, otherwise the disk device is
203 	chosen, on which the partition \a id refers to resides.
204 
205 	\param id The ID of an arbitrary partition on the disk device (including
206 		   the disk device itself), whose data shall be returned
207 		   (if \a deviceOnly is \c false), or the ID of the disk device
208 		   itself (if \a deviceOnly is true).
209 	\param deviceOnly Specifies whether only IDs of disk devices (\c true),
210 		   or also IDs of partitions (\c false) are accepted for \a id.
211 	\param shadow If \c true, the data of the shadow disk device is returned,
212 		   otherwise of the physical device. If there is no shadow device,
213 		   the parameter is ignored.
214 	\param buffer The buffer into which the disk device data shall be written.
215 		   May be \c NULL.
216 	\param bufferSize The size of \a buffer.
217 	\param _neededSize Pointer to a variable into which the actually needed
218 		   buffer size is written. May be \c NULL.
219 	\return
220 	- \c B_OK: Everything went fine. The device was found and, if not \c NULL,
221 	  in \a _neededSize the actually needed buffer size is returned. And
222 	  \a buffer will contain the disk device data.
223 	- \c B_BAD_VALUE: \c NULL \a buffer, but not 0 \a bufferSize.
224 	- \c B_BUFFER_OVERFLOW: The supplied buffer was too small. \a _neededSize,
225 	  if not \c NULL, will contain the required buffer size.
226 	- \c B_NO_MEMORY: Insufficient memory to complete the operation.
227 	- \c B_ENTRY_NOT_FOUND: \a id is no valid disk device ID (if \a deviceOnly
228 	  is \c true) or not even a valid partition ID (if \a deviceOnly is
229 	  \c false).
230 	- \c B_ERROR: An unexpected error occured.
231 	- another error code...
232 */
233 status_t
234 _user_get_disk_device_data(partition_id id, bool deviceOnly, bool shadow,
235 	user_disk_device_data *buffer, size_t bufferSize, size_t *_neededSize)
236 {
237 	if (!buffer && bufferSize > 0)
238 		return B_BAD_VALUE;
239 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
240 	// get the device
241 	if (KDiskDevice *device = manager->RegisterDevice(id, deviceOnly)) {
242 		PartitionRegistrar _(device, true);
243 		if (DeviceReadLocker locker = device) {
244 			// do a dry run first to get the needed size
245 			UserDataWriter writer;
246 			device->WriteUserData(writer, shadow);
247 			size_t neededSize = writer.AllocatedSize();
248 			if (_neededSize) {
249 				status_t error = copy_ref_var_to_user(neededSize, _neededSize);
250 				if (error != B_OK)
251 					return error;
252 			}
253 			// if no buffer has been supplied or the buffer is too small,
254 			// then we're done
255 			if (!buffer || bufferSize < neededSize)
256 				return B_BUFFER_OVERFLOW;
257 			// otherwise allocate a kernel buffer
258 			user_disk_device_data *kernelBuffer
259 				= static_cast<user_disk_device_data*>(malloc(neededSize));
260 			if (!kernelBuffer)
261 				return B_NO_MEMORY;
262 			MemoryDeleter deleter(kernelBuffer);
263 			// write the device data into the buffer
264 			writer.SetTo(kernelBuffer, bufferSize);
265 			device->WriteUserData(writer, shadow);
266 			// sanity check
267 			if (writer.AllocatedSize() != neededSize) {
268 				ERROR(("Size of written disk device user data changed from "
269 					   "%lu to %lu while device was locked!\n"));
270 				return B_ERROR;
271 			}
272 			// relocate
273 			status_t error = writer.Relocate(buffer);
274 			if (error != B_OK)
275 				return error;
276 			// copy out
277 			if (buffer)
278 				return user_memcpy(buffer, kernelBuffer, neededSize);
279 		} else
280 			return B_ERROR;
281 	}
282 	return B_ENTRY_NOT_FOUND;
283 }
284 
285 
286 // _user_get_partitionable_spaces
287 status_t
288 _user_get_partitionable_spaces(partition_id partitionID, int32 changeCounter,
289 	partitionable_space_data *_buffer, int32 count, int32 *_actualCount)
290 {
291 	if (count > 0 && !_buffer)
292 		return B_BAD_VALUE;
293 
294 	if (count > 0 && !IS_USER_ADDRESS(_buffer)
295 		|| _actualCount && !IS_USER_ADDRESS(_actualCount)) {
296 		return B_BAD_ADDRESS;
297 	}
298 
299 	// allocate buffer
300 	int32 bufferSize = count * sizeof(partitionable_space_data);
301 	partitionable_space_data *buffer = NULL;
302 	MemoryDeleter bufferDeleter;
303 	if (count > 0) {
304 		buffer = (partitionable_space_data*)malloc(bufferSize);
305 		if (!buffer)
306 			return B_NO_MEMORY;
307 		bufferDeleter.SetTo(buffer);
308 	}
309 
310 	status_t error = B_OK;
311 
312 	// get the partition
313 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
314 	KPartition *partition = manager->ReadLockPartition(partitionID);
315 	if (!partition)
316 		return B_ENTRY_NOT_FOUND;
317 
318 	PartitionRegistrar registrar1(partition, true);
319 	PartitionRegistrar registrar2(partition->Device(), true);
320 	DeviceReadLocker locker(partition->Device(), true);
321 
322 	if (!check_shadow_partition(partition, changeCounter))
323 		return B_BAD_VALUE;
324 
325 	// get the disk system
326 	KDiskSystem *diskSystem = partition->DiskSystem();
327 	if (!diskSystem)
328 		return B_ENTRY_NOT_FOUND;
329 
330 	// get the info
331 	int32 actualCount;
332 	error = diskSystem->GetPartitionableSpaces(partition, buffer, count,
333 		&actualCount);
334 
335 	// copy out
336 	if (_actualCount)
337 		user_memcpy(_actualCount, &actualCount, sizeof(actualCount));
338 			// copy even on error
339 
340 	if (error == B_OK && buffer)
341 		user_memcpy(_buffer, buffer, bufferSize);
342 
343 	return error;
344 }
345 
346 
347 // _user_register_file_device
348 partition_id
349 _user_register_file_device(const char *_filename)
350 {
351 	if (!_filename)
352 		return B_BAD_VALUE;
353 	char filename[B_PATH_NAME_LENGTH];
354 	status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH);
355 	if (error)
356 		return error;
357 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
358 	if (ManagerLocker locker = manager) {
359 		if (KFileDiskDevice *device = manager->FindFileDevice(filename))
360 			return device->ID();
361 		return manager->CreateFileDevice(filename);
362 	}
363 	return B_ERROR;
364 }
365 
366 
367 // _user_unregister_file_device
368 status_t
369 _user_unregister_file_device(partition_id deviceID, const char *_filename)
370 {
371 	if (deviceID < 0 && !_filename)
372 		return B_BAD_VALUE;
373 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
374 	if (deviceID >= 0) {
375 		return manager->DeleteFileDevice(deviceID);
376 	} else {
377 		char filename[B_PATH_NAME_LENGTH];
378 		status_t error = ddm_strlcpy(filename, _filename, B_PATH_NAME_LENGTH);
379 		if (error)
380 			return error;
381 		return manager->DeleteFileDevice(filename);
382 	}
383 }
384 
385 
386 // _user_get_disk_system_info
387 status_t
388 _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
389 {
390 	if (!_info)
391 		return B_BAD_VALUE;
392 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
393 	if (ManagerLocker locker = manager) {
394 		if (KDiskSystem *diskSystem = manager->FindDiskSystem(id)) {
395 			user_disk_system_info info;
396 			diskSystem->GetInfo(&info);
397 			user_memcpy(_info, &info, sizeof(info));
398 			return B_OK;
399 		}
400 	}
401 	return B_ENTRY_NOT_FOUND;
402 }
403 
404 
405 // _user_get_next_disk_system_info
406 status_t
407 _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
408 {
409 	if (!_cookie || !_info)
410 		return B_BAD_VALUE;
411 	int32 cookie;
412 	user_memcpy(&cookie, _cookie, sizeof(cookie));
413 	status_t result = B_ENTRY_NOT_FOUND;
414 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
415 	if (ManagerLocker locker = manager) {
416 		if (KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie)) {
417 			user_disk_system_info info;
418 			diskSystem->GetInfo(&info);
419 			user_memcpy(_info, &info, sizeof(info));
420 			result = B_OK;
421 		}
422 	}
423 	user_memcpy(_cookie, &cookie, sizeof(cookie));
424 	return result;
425 }
426 
427 
428 // _user_find_disk_system
429 status_t
430 _user_find_disk_system(const char *_name, user_disk_system_info *_info)
431 {
432 	if (!_name || !_info)
433 		return B_BAD_VALUE;
434 	char name[B_DISK_SYSTEM_NAME_LENGTH];
435 	status_t error = ddm_strlcpy(name, _name, B_DISK_SYSTEM_NAME_LENGTH);
436 	if (error)
437 		return error;
438 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
439 	if (ManagerLocker locker = manager) {
440 		if (KDiskSystem *diskSystem = manager->FindDiskSystem(name)) {
441 			user_disk_system_info info;
442 			diskSystem->GetInfo(&info);
443 			user_memcpy(_info, &info, sizeof(info));
444 			return B_OK;
445 		}
446 	}
447 	return B_ENTRY_NOT_FOUND;
448 }
449 
450 
451 // _user_defragment_partition
452 status_t
453 _user_defragment_partition(partition_id partitionID, int32* changeCounter)
454 {
455 #if 0
456 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
457 	// get the partition
458 	KPartition *partition = manager->WriteLockPartition(partitionID);
459 	if (!partition)
460 		return B_ENTRY_NOT_FOUND;
461 	PartitionRegistrar registrar1(partition, true);
462 	PartitionRegistrar registrar2(partition->Device(), true);
463 	DeviceWriteLocker locker(partition->Device(), true);
464 	// check whether the disk system supports defragmenting
465 	status_t error = validate_defragment_partition(partition, changeCounter);
466 	if (error != B_OK)
467 		return error;
468 	// set the defragmenting flag
469 	partition->Changed(B_PARTITION_CHANGED_DEFRAGMENTATION);
470 	return B_OK;
471 #endif
472 return B_BAD_VALUE;
473 }
474 
475 
476 // _user_repair_partition
477 status_t
478 _user_repair_partition(partition_id partitionID, int32* changeCounter,
479 	bool checkOnly)
480 {
481 #if 0
482 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
483 	// get the partition
484 	KPartition *partition = manager->WriteLockPartition(partitionID);
485 	if (!partition)
486 		return B_ENTRY_NOT_FOUND;
487 	PartitionRegistrar registrar1(partition, true);
488 	PartitionRegistrar registrar2(partition->Device(), true);
489 	DeviceWriteLocker locker(partition->Device(), true);
490 	// check whether the disk system supports defragmenting
491 	status_t error = validate_repair_partition(partition, changeCounter,
492 		checkOnly);
493 	if (error != B_OK)
494 		return error;
495 	// set the respective flag
496 	if (checkOnly)
497 		partition->Changed(B_PARTITION_CHANGED_CHECK);
498 	else
499 		partition->Changed(B_PARTITION_CHANGED_REPAIR);
500 	return B_OK;
501 #endif
502 return B_BAD_VALUE;
503 }
504 
505 
506 // _user_resize_partition
507 status_t
508 _user_resize_partition(partition_id partitionID, int32* changeCounter,
509 	partition_id childID, int32* childChangeCounter, off_t size,
510 	off_t contentSize)
511 {
512 #if 0
513 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
514 	// get the partition
515 	KPartition *partition = manager->WriteLockPartition(partitionID);
516 	if (!partition)
517 		return B_ENTRY_NOT_FOUND;
518 	PartitionRegistrar registrar1(partition, true);
519 	PartitionRegistrar registrar2(partition->Device(), true);
520 	DeviceWriteLocker locker(partition->Device(), true);
521 	// check the size
522 	if (size == partition->Size())
523 		return B_OK;
524 	off_t proposedSize = size;
525 	off_t contentSize = 0;
526 	status_t error = validate_resize_partition(partition, changeCounter,
527 		&proposedSize, &contentSize);
528 	if (error != B_OK)
529 		return error;
530 	if (proposedSize != size)
531 		return B_BAD_VALUE;
532 	// new size is fine -- resize the thing
533 	partition->SetSize(size);
534 	partition->Changed(B_PARTITION_CHANGED_SIZE);
535 	// implicit partitioning system changes
536 	error = partition->Parent()->DiskSystem()->ShadowPartitionChanged(
537 		partition->Parent(), partition, B_PARTITION_RESIZE_CHILD);
538 	if (error != B_OK)
539 		return error;
540 	// implicit content disk system changes
541 	if (partition->DiskSystem()) {
542 		error = partition->DiskSystem()->ShadowPartitionChanged(
543 			partition, NULL, B_PARTITION_RESIZE);
544 	}
545 	return error;
546 #endif
547 return B_BAD_VALUE;
548 }
549 
550 
551 // _user_move_partition
552 status_t
553 _user_move_partition(partition_id partitionID, int32* changeCounter,
554 	partition_id childID, int32* childChangeCounter, off_t newOffset,
555 	partition_id* descendantIDs, int32* descendantChangeCounters,
556 	int32 descendantCount)
557 {
558 #if 0
559 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
560 	// get the partition
561 	KPartition *partition = manager->WriteLockPartition(partitionID);
562 	if (!partition)
563 		return B_ENTRY_NOT_FOUND;
564 	PartitionRegistrar registrar1(partition, true);
565 	PartitionRegistrar registrar2(partition->Device(), true);
566 	DeviceWriteLocker locker(partition->Device(), true);
567 	// check the new offset
568 	if (newOffset == partition->Offset())
569 		return B_OK;
570 	off_t proposedOffset = newOffset;
571 	status_t error = validate_move_partition(partition, changeCounter,
572 		&proposedOffset, true);
573 	if (error != B_OK)
574 		return error;
575 	if (proposedOffset != newOffset)
576 		return B_BAD_VALUE;
577 	// new offset is fine -- move the thing
578 	off_t moveBy = newOffset - partition->Offset();
579 	move_descendants(partition, moveBy);
580 	partition->Changed(B_PARTITION_CHANGED_OFFSET);
581 	// implicit partitioning system changes
582 	error = partition->Parent()->DiskSystem()->ShadowPartitionChanged(
583 		partition->Parent(), partition, B_PARTITION_MOVE_CHILD);
584 	if (error != B_OK)
585 		return error;
586 	// implicit descendants' content disk system changes
587 	return move_descendants_contents(partition);
588 #endif
589 return B_BAD_VALUE;
590 }
591 
592 
593 // _user_set_partition_name
594 status_t
595 _user_set_partition_name(partition_id partitionID, int32* changeCounter,
596 	partition_id childID, int32* childChangeCounter, const char* name)
597 {
598 #if 0
599 	if (!_name)
600 		return B_BAD_VALUE;
601 	char name[B_DISK_DEVICE_NAME_LENGTH];
602 	status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH);
603 	if (error)
604 		return error;
605 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
606 	// get the partition
607 	KPartition *partition = manager->WriteLockPartition(partitionID);
608 	if (!partition)
609 		return B_ENTRY_NOT_FOUND;
610 	PartitionRegistrar registrar1(partition, true);
611 	PartitionRegistrar registrar2(partition->Device(), true);
612 	DeviceWriteLocker locker(partition->Device(), true);
613 	// check name
614 	char proposedName[B_DISK_DEVICE_NAME_LENGTH];
615 	strcpy(proposedName, name);
616 	error = validate_set_partition_name(partition, changeCounter, proposedName);
617 	if (error != B_OK)
618 		return error;
619 	if (strcmp(name, proposedName))
620 		return B_BAD_VALUE;
621 	// set name
622 	error = partition->SetName(name);
623 	if (error != B_OK)
624 		return error;
625 	partition->Changed(B_PARTITION_CHANGED_NAME);
626 	// implicit partitioning system changes
627 	return partition->Parent()->DiskSystem()->ShadowPartitionChanged(
628 		partition->Parent(), partition, B_PARTITION_SET_NAME);
629 #endif
630 return B_BAD_VALUE;
631 }
632 
633 
634 // _user_set_partition_content_name
635 status_t
636 _user_set_partition_content_name(partition_id partitionID, int32* changeCounter,
637 	const char* name)
638 {
639 #if 0
640 	if (!_name)
641 		return B_BAD_VALUE;
642 	char name[B_DISK_DEVICE_NAME_LENGTH];
643 	status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH);
644 	if (error)
645 		return error;
646 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
647 	// get the partition
648 	KPartition *partition = manager->WriteLockPartition(partitionID);
649 	if (!partition)
650 		return B_ENTRY_NOT_FOUND;
651 	PartitionRegistrar registrar1(partition, true);
652 	PartitionRegistrar registrar2(partition->Device(), true);
653 	DeviceWriteLocker locker(partition->Device(), true);
654 	// check name
655 	char proposedName[B_DISK_DEVICE_NAME_LENGTH];
656 	strcpy(proposedName, name);
657 	error = validate_set_partition_content_name(partition,
658 		changeCounter, proposedName);
659 	if (error != B_OK)
660 		return error;
661 	if (strcmp(name, proposedName))
662 		return B_BAD_VALUE;
663 	// set name
664 	error = partition->SetContentName(name);
665 	if (error != B_OK)
666 		return error;
667 	partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME);
668 	// implicit content disk system changes
669 	return partition->DiskSystem()->ShadowPartitionChanged(
670 		partition, NULL, B_PARTITION_SET_CONTENT_NAME);
671 #endif
672 return B_BAD_VALUE;
673 }
674 
675 
676 // _user_set_partition_type
677 status_t
678 _user_set_partition_type(partition_id partitionID, int32* changeCounter,
679 	partition_id childID, int32* childChangeCounter, const char* type)
680 {
681 #if 0
682 	if (!_type)
683 		return B_BAD_VALUE;
684 	char type[B_DISK_DEVICE_TYPE_LENGTH];
685 	status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH);
686 	if (error)
687 		return error;
688 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
689 	// get the partition
690 	KPartition *partition = manager->WriteLockPartition(partitionID);
691 	if (!partition)
692 		return B_ENTRY_NOT_FOUND;
693 	PartitionRegistrar registrar1(partition, true);
694 	PartitionRegistrar registrar2(partition->Device(), true);
695 	DeviceWriteLocker locker(partition->Device(), true);
696 	// check type
697 	error = validate_set_partition_type(partition, changeCounter, type);
698 	if (error != B_OK)
699 		return error;
700 	// set type
701 	error = partition->SetType(type);
702 	if (error != B_OK)
703 		return error;
704 	partition->Changed(B_PARTITION_CHANGED_TYPE);
705 	// implicit partitioning system changes
706 	return partition->Parent()->DiskSystem()->ShadowPartitionChanged(
707 		partition->Parent(), partition, B_PARTITION_SET_TYPE);
708 #endif
709 return B_BAD_VALUE;
710 }
711 
712 
713 // _user_set_partition_parameters
714 status_t
715 _user_set_partition_parameters(partition_id partitionID, int32* changeCounter,
716 	partition_id childID, int32* childChangeCounter, const char* parameters,
717 	size_t parametersSize)
718 {
719 #if 0
720 	if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE)
721 		return B_BAD_VALUE;
722 	char *parameters = NULL;
723 	if (_parameters) {
724 		parameters = static_cast<char*>(malloc(parametersSize));
725 		if (parameters)
726 			user_memcpy(parameters, _parameters, parametersSize);
727 		else
728 			return B_NO_MEMORY;
729 	}
730 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
731 	// get the partition
732 	KPartition *partition = manager->WriteLockPartition(partitionID);
733 	status_t error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND;
734 	if (!error) {
735 		PartitionRegistrar registrar1(partition, true);
736 		PartitionRegistrar registrar2(partition->Device(), true);
737 		DeviceWriteLocker locker(partition->Device(), true);
738 		// check parameters
739 		error = validate_set_partition_parameters(partition,
740 			changeCounter, parameters);
741 		if (!error) {
742 			// set type
743 			error = partition->SetParameters(parameters);
744 			if (!error) {
745 				partition->Changed(B_PARTITION_CHANGED_PARAMETERS);
746 				// implicit partitioning system changes
747 				error = partition->Parent()->DiskSystem()
748 					->ShadowPartitionChanged(partition->Parent(), partition,
749 						B_PARTITION_SET_PARAMETERS);
750 			}
751 		}
752 	}
753 	free(parameters);
754 	return error;
755 #endif
756 return B_BAD_VALUE;
757 }
758 
759 
760 // _user_set_partition_content_parameters
761 status_t
762 _user_set_partition_content_parameters(partition_id partitionID,
763 	int32* changeCounter, const char* parameters, size_t parametersSize)
764 {
765 #if 0
766 	if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE)
767 		return B_BAD_VALUE;
768 	char *parameters = NULL;
769 	if (_parameters) {
770 		parameters = static_cast<char*>(malloc(parametersSize));
771 		if (parameters)
772 			user_memcpy(parameters, _parameters, parametersSize);
773 		else
774 			return B_NO_MEMORY;
775 	}
776 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
777 	// get the partition
778 	KPartition *partition = manager->WriteLockPartition(partitionID);
779 	status_t error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND;
780 	if (!error) {
781 		PartitionRegistrar registrar1(partition, true);
782 		PartitionRegistrar registrar2(partition->Device(), true);
783 		DeviceWriteLocker locker(partition->Device(), true);
784 		// check parameters
785 		error = validate_set_partition_content_parameters(partition,
786 			changeCounter, parameters);
787 		if (!error) {
788 			// set name
789 			error = partition->SetContentParameters(parameters);
790 			if (!error) {
791 				partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS);
792 				// implicit content disk system changes
793 				error = partition->DiskSystem()->ShadowPartitionChanged(
794 					partition, NULL, B_PARTITION_SET_CONTENT_PARAMETERS);
795 			}
796 		}
797 	}
798 	free(partition);
799 	return error;
800 #endif
801 return B_BAD_VALUE;
802 }
803 
804 
805 // _user_initialize_partition
806 status_t
807 _user_initialize_partition(partition_id partitionID, int32* changeCounter,
808 	const char* diskSystemName, const char* name, const char* parameters,
809 	size_t parametersSize)
810 {
811 #if 0
812 	if (!_diskSystemName || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE)
813 		return B_BAD_VALUE;
814 
815 	// copy disk system name
816 	char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH];
817 	status_t error = ddm_strlcpy(diskSystemName, _diskSystemName,
818 		B_DISK_SYSTEM_NAME_LENGTH);
819 
820 	// copy name
821 	char name[B_DISK_DEVICE_NAME_LENGTH];
822 	if (!error && _name)
823 		error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH);
824 
825 	if (error)
826 		return error;
827 
828 	// copy parameters
829 	MemoryDeleter parameterDeleter;
830 	char *parameters = NULL;
831 	if (_parameters) {
832 		parameters = static_cast<char*>(malloc(parametersSize));
833 		if (!parameters)
834 			return B_NO_MEMORY;
835 		parameterDeleter.SetTo(parameters);
836 
837 		if (user_memcpy(parameters, _parameters, parametersSize) != B_OK)
838 			return B_BAD_ADDRESS;
839 	}
840 
841 	// get the partition
842 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
843 	KPartition *partition = manager->WriteLockPartition(partitionID);
844 	if (!partition)
845 		return B_ENTRY_NOT_FOUND;
846 
847 	PartitionRegistrar registrar1(partition, true);
848 	PartitionRegistrar registrar2(partition->Device(), true);
849 	DeviceWriteLocker locker(partition->Device(), true);
850 
851 	// get the disk system
852 	KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName);
853 	if (!diskSystem)
854 		return B_ENTRY_NOT_FOUND;
855 	DiskSystemLoader loader(diskSystem, true);
856 
857 	// check parameters
858 	char proposedName[B_DISK_DEVICE_NAME_LENGTH];
859 	if (_name)
860 		strcpy(proposedName, name);
861 
862 	error = validate_initialize_partition(partition, changeCounter,
863 		diskSystemName, _name ? proposedName : NULL, parameters);
864 	if (error != B_OK)
865 		return error;
866 	if (_name && strcmp(name, proposedName) != 0)
867 		return B_BAD_VALUE;
868 
869 	// unitialize the partition's contents and set the new
870 	// parameters
871 	if ((error = partition->UninitializeContents(true)) != B_OK)
872 		return error;
873 
874 	partition->SetDiskSystem(diskSystem);
875 
876 	if ((error = partition->SetContentName(_name ? name : NULL)) != B_OK)
877 		return error;
878 	partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME);
879 
880 	if ((error = partition->SetContentParameters(parameters)) != B_OK)
881 		return error;
882 	partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS);
883 
884 	partition->Changed(B_PARTITION_CHANGED_INITIALIZATION);
885 
886 	// implicit content disk system changes
887 	return partition->DiskSystem()->ShadowPartitionChanged(
888 		partition, NULL, B_PARTITION_INITIALIZE);
889 #endif
890 return B_BAD_VALUE;
891 }
892 
893 
894 // _user_uninitialize_partition
895 status_t
896 _user_uninitialize_partition(partition_id partitionID, int32* changeCounter)
897 {
898 #if 0
899 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
900 	// get the partition
901 	KPartition *partition = manager->WriteLockPartition(partitionID);
902 	if (!partition)
903 		return B_ENTRY_NOT_FOUND;
904 	PartitionRegistrar registrar1(partition, true);
905 	PartitionRegistrar registrar2(partition->Device(), true);
906 	DeviceWriteLocker locker(partition->Device(), true);
907 	// unitialize the partition's contents and set the new parameters
908 	return partition->UninitializeContents(true);
909 #endif
910 return B_BAD_VALUE;
911 }
912 
913 
914 // _user_create_child_partition
915 status_t
916 _user_create_child_partition(partition_id partitionID, int32* changeCounter,
917 	off_t offset, off_t size, const char* type, const char* name,
918 	const char* parameters, size_t parametersSize, partition_id* childID,
919 	int32* childChangeCounter)
920 
921 {
922 #if 0
923 	if (!_type || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE)
924 		return B_BAD_VALUE;
925 	char type[B_DISK_DEVICE_TYPE_LENGTH];
926 	char *parameters = NULL;
927 	status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH);
928 	if (error)
929 		return error;
930 	if (_parameters) {
931 		parameters = static_cast<char*>(malloc(parametersSize));
932 		if (parameters)
933 			user_memcpy(parameters, _parameters, parametersSize);
934 		else
935 			return B_NO_MEMORY;
936 	}
937 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
938 	// get the partition
939 	KPartition *partition = manager->WriteLockPartition(partitionID);
940 	error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND;
941 	if (!error) {
942 		PartitionRegistrar registrar1(partition, true);
943 		PartitionRegistrar registrar2(partition->Device(), true);
944 		DeviceWriteLocker locker(partition->Device(), true);
945 		// check the parameters
946 		off_t proposedOffset = offset;
947 		off_t proposedSize = size;
948 		int32 index = 0;
949 		error = validate_create_child_partition(partition, changeCounter,
950 			&proposedOffset, &proposedSize, type, parameters, &index);
951 		if (!error) {
952 			error =	(proposedOffset == offset && proposedSize == size)
953 				    ? B_OK : B_BAD_VALUE;
954 			if (!error) {
955 				// create the child
956 				KPartition *child = NULL;
957 				error = partition->CreateChild(-1, index, &child);
958 				if (!error) {
959 					partition->Changed(B_PARTITION_CHANGED_CHILDREN);
960 					if (_childID) {
961 						partition_id childID = child->ID();
962 						user_memcpy(_childID, &childID, sizeof(childID));
963 					}
964 					// set the parameters
965 					child->SetOffset(offset);
966 					child->SetSize(size);
967 					error = child->SetType(type);
968 				}
969 				if (!error) {
970 					error = child->SetParameters(parameters);
971 				}
972 				if (!error) {
973 					// implicit partitioning system changes
974 					error = partition->DiskSystem()->ShadowPartitionChanged(
975 							partition, child, B_PARTITION_CREATE_CHILD);
976 				}
977 			}
978 		}
979 	}
980 	free(parameters);
981 	return error;
982 #endif
983 return B_BAD_VALUE;
984 }
985 
986 
987 // _user_delete_child_partition
988 status_t
989 _user_delete_child_partition(partition_id partitionID, int32* changeCounter,
990 	partition_id childID, int32 childChangeCounter)
991 {
992 #if 0
993 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
994 	// get the partition
995 	KPartition *partition = manager->WriteLockPartition(partitionID);
996 	if (!partition)
997 		return B_ENTRY_NOT_FOUND;
998 	PartitionRegistrar registrar1(partition, true);
999 	PartitionRegistrar registrar2(partition->Device(), true);
1000 	DeviceWriteLocker locker(partition->Device(), true);
1001 	// check whether delete the child is OK
1002 	status_t error = validate_delete_child_partition(partition, changeCounter);
1003 	if (error != B_OK)
1004 		return error;
1005 	// delete the child
1006 	KPartition *parent = partition->Parent();
1007 	if (!parent->RemoveChild(partition))
1008 		return B_ERROR;
1009 	parent->Changed(B_PARTITION_CHANGED_CHILDREN);
1010 	return B_OK;
1011 #endif
1012 return B_BAD_VALUE;
1013 }
1014