10cbc783bSAxel Dörfler /*
2eac83fb3SAxel Dörfler * Copyright 2003-2017, Haiku, Inc. All Rights Reserved.
30cbc783bSAxel Dörfler * Distributed under the terms of the MIT License.
42dc6403dSIngo Weinhold *
50cbc783bSAxel Dörfler * Authors:
6285f4cf4SIngo Weinhold * Ingo Weinhold, ingo_weinhold@gmx.de
738bbc957SAxel Dörfler * Axel Dörfler, axeld@pinc-software.de
80cbc783bSAxel Dörfler */
90cbc783bSAxel Dörfler
100cbc783bSAxel Dörfler /*! \file ddm_userland_interface.cpp
110cbc783bSAxel Dörfler
120cbc783bSAxel Dörfler \brief Interface for userspace calls.
132dc6403dSIngo Weinhold */
142d690920SAxel Dörfler
1549fb53eeSAxel Dörfler #include <ddm_userland_interface.h>
1649fb53eeSAxel Dörfler
172d690920SAxel Dörfler #include <stdlib.h>
182d690920SAxel Dörfler
192d690920SAxel Dörfler #include <AutoDeleter.h>
2038bbc957SAxel Dörfler #include <fs/KPath.h>
212d690920SAxel Dörfler #include <KDiskDevice.h>
222d690920SAxel Dörfler #include <KDiskDeviceManager.h>
232d690920SAxel Dörfler #include <KDiskDeviceUtils.h>
242d690920SAxel Dörfler #include <KDiskSystem.h>
252d690920SAxel Dörfler #include <KFileDiskDevice.h>
262d690920SAxel Dörfler #include <syscall_args.h>
272d690920SAxel Dörfler
282d690920SAxel Dörfler #include "UserDataWriter.h"
292d690920SAxel Dörfler
302d690920SAxel Dörfler using namespace BPrivate::DiskDevice;
312d690920SAxel Dörfler
322d690920SAxel Dörfler // debugging
332d690920SAxel Dörfler #define ERROR(x)
342d690920SAxel Dörfler
35bf95c9aeSIngo Weinhold
367b45b55bSIngo Weinhold // TODO: Replace all instances, when it has been decided how to handle
377b45b55bSIngo Weinhold // notifications during jobs.
387b45b55bSIngo Weinhold #define DUMMY_JOB_ID 0
397b45b55bSIngo Weinhold
407b45b55bSIngo Weinhold
412d690920SAxel Dörfler /*! \brief Wrapper around user_strlcpy() that returns a status_t
422d690920SAxel Dörfler indicating appropriate success or failure.
432d690920SAxel Dörfler
442d690920SAxel Dörfler \param allowTruncation If \c true, does not return an error if
452d690920SAxel Dörfler \a from is longer than \to. If \c false, returns \c B_NAME_TOO_LONG
462d690920SAxel Dörfler if \a from is longer than \to.
472d690920SAxel Dörfler */
48d6e565c7SIngo Weinhold static status_t
ddm_strlcpy(char * to,const char * from,size_t size,bool allowTruncation=false)49d6e565c7SIngo Weinhold ddm_strlcpy(char *to, const char *from, size_t size,
50d6e565c7SIngo Weinhold bool allowTruncation = false)
51d6e565c7SIngo Weinhold {
52d6e565c7SIngo Weinhold ssize_t fromLen = user_strlcpy(to, from, size);
53d6e565c7SIngo Weinhold if (fromLen < 0)
54d6e565c7SIngo Weinhold return fromLen;
55d6e565c7SIngo Weinhold if ((size_t)fromLen >= size && !allowTruncation)
56d6e565c7SIngo Weinhold return B_NAME_TOO_LONG;
57d6e565c7SIngo Weinhold return B_OK;
582d690920SAxel Dörfler }
592d690920SAxel Dörfler
60d6e565c7SIngo Weinhold
617b45b55bSIngo Weinhold template<typename Type>
627b45b55bSIngo Weinhold static inline status_t
copy_from_user_value(Type & value,const Type * userValue)637b45b55bSIngo Weinhold copy_from_user_value(Type& value, const Type* userValue)
647b45b55bSIngo Weinhold {
65*4644c7ccSJérôme Duval if (userValue == NULL)
667b45b55bSIngo Weinhold return B_BAD_VALUE;
677b45b55bSIngo Weinhold
687b45b55bSIngo Weinhold if (!IS_USER_ADDRESS(userValue))
697b45b55bSIngo Weinhold return B_BAD_ADDRESS;
707b45b55bSIngo Weinhold
717b45b55bSIngo Weinhold return user_memcpy(&value, userValue, sizeof(Type));
727b45b55bSIngo Weinhold }
737b45b55bSIngo Weinhold
747b45b55bSIngo Weinhold
757b45b55bSIngo Weinhold template<typename Type>
767b45b55bSIngo Weinhold static inline status_t
copy_to_user_value(Type * userValue,const Type & value)777b45b55bSIngo Weinhold copy_to_user_value(Type* userValue, const Type& value)
787b45b55bSIngo Weinhold {
79*4644c7ccSJérôme Duval if (userValue == NULL)
807b45b55bSIngo Weinhold return B_BAD_VALUE;
817b45b55bSIngo Weinhold
827b45b55bSIngo Weinhold if (!IS_USER_ADDRESS(userValue))
837b45b55bSIngo Weinhold return B_BAD_ADDRESS;
847b45b55bSIngo Weinhold
857b45b55bSIngo Weinhold return user_memcpy(userValue, &value, sizeof(Type));
867b45b55bSIngo Weinhold }
877b45b55bSIngo Weinhold
887b45b55bSIngo Weinhold
897b45b55bSIngo Weinhold template<bool kAllowsNull>
907b45b55bSIngo Weinhold struct UserStringParameter {
917b45b55bSIngo Weinhold char* value;
927b45b55bSIngo Weinhold
UserStringParameterUserStringParameter937b45b55bSIngo Weinhold inline UserStringParameter()
947b45b55bSIngo Weinhold : value(NULL)
957b45b55bSIngo Weinhold {
967b45b55bSIngo Weinhold }
977b45b55bSIngo Weinhold
~UserStringParameterUserStringParameter987b45b55bSIngo Weinhold inline ~UserStringParameter()
997b45b55bSIngo Weinhold {
1007b45b55bSIngo Weinhold free(value);
1017b45b55bSIngo Weinhold }
1027b45b55bSIngo Weinhold
InitUserStringParameter1037b45b55bSIngo Weinhold inline status_t Init(const char* userValue, size_t maxSize)
1047b45b55bSIngo Weinhold {
1057b45b55bSIngo Weinhold if (userValue == NULL) {
1067b45b55bSIngo Weinhold if (!kAllowsNull)
1077b45b55bSIngo Weinhold return B_BAD_VALUE;
1087b45b55bSIngo Weinhold
1097b45b55bSIngo Weinhold return B_OK;
1107b45b55bSIngo Weinhold }
1117b45b55bSIngo Weinhold
1127b45b55bSIngo Weinhold if (!IS_USER_ADDRESS(userValue))
1137b45b55bSIngo Weinhold return B_BAD_ADDRESS;
1147b45b55bSIngo Weinhold
1157b45b55bSIngo Weinhold value = (char*)malloc(maxSize);
1167b45b55bSIngo Weinhold if (value == NULL)
1177b45b55bSIngo Weinhold return B_NO_MEMORY;
1187b45b55bSIngo Weinhold
1197b45b55bSIngo Weinhold ssize_t bytesCopied = user_strlcpy(value, userValue, maxSize);
1207b45b55bSIngo Weinhold if (bytesCopied < 0)
1217b45b55bSIngo Weinhold return bytesCopied;
1227b45b55bSIngo Weinhold
1237b45b55bSIngo Weinhold if ((size_t)bytesCopied >= maxSize)
1247b45b55bSIngo Weinhold return B_BUFFER_OVERFLOW;
1257b45b55bSIngo Weinhold
1267b45b55bSIngo Weinhold return B_OK;
1277b45b55bSIngo Weinhold }
1286cc43bfbSAxel Dörfler
operator const char*UserStringParameter1296cc43bfbSAxel Dörfler inline operator const char*()
1306cc43bfbSAxel Dörfler {
1316cc43bfbSAxel Dörfler return value;
1326cc43bfbSAxel Dörfler }
1336cc43bfbSAxel Dörfler
operator char*UserStringParameter1346cc43bfbSAxel Dörfler inline operator char*()
1356cc43bfbSAxel Dörfler {
1366cc43bfbSAxel Dörfler return value;
1376cc43bfbSAxel Dörfler }
1387b45b55bSIngo Weinhold };
1397b45b55bSIngo Weinhold
1407b45b55bSIngo Weinhold
14132788795SIngo Weinhold #if 0
142d6e565c7SIngo Weinhold static void
1432d690920SAxel Dörfler move_descendants(KPartition *partition, off_t moveBy)
1442d690920SAxel Dörfler {
1452d690920SAxel Dörfler if (!partition)
1462d690920SAxel Dörfler return;
1472d690920SAxel Dörfler partition->SetOffset(partition->Offset() + moveBy);
1482d690920SAxel Dörfler // move children
1492d690920SAxel Dörfler for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
1502d690920SAxel Dörfler move_descendants(child, moveBy);
1512d690920SAxel Dörfler }
1522d690920SAxel Dörfler
153d6e565c7SIngo Weinhold
154d6e565c7SIngo Weinhold static status_t
1552d690920SAxel Dörfler move_descendants_contents(KPartition *partition)
1562d690920SAxel Dörfler {
1572d690920SAxel Dörfler if (!partition)
1582d690920SAxel Dörfler return B_BAD_VALUE;
1592d690920SAxel Dörfler // implicit content disk system changes
1602d690920SAxel Dörfler KDiskSystem *diskSystem = partition->DiskSystem();
1612d690920SAxel Dörfler if (diskSystem || partition->AlgorithmData()) {
1622d690920SAxel Dörfler status_t error = diskSystem->ShadowPartitionChanged(partition,
163bf95c9aeSIngo Weinhold NULL, B_PARTITION_MOVE);
1642d690920SAxel Dörfler if (error != B_OK)
1652d690920SAxel Dörfler return error;
1662d690920SAxel Dörfler }
1672d690920SAxel Dörfler // move children's contents
1682d690920SAxel Dörfler for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
1692d690920SAxel Dörfler status_t error = move_descendants_contents(child);
1702d690920SAxel Dörfler if (error != B_OK)
1712d690920SAxel Dörfler return error;
1722d690920SAxel Dörfler }
1732d690920SAxel Dörfler return B_OK;
1742d690920SAxel Dörfler }
17532788795SIngo Weinhold #endif // 0
1762d690920SAxel Dörfler
177d6e565c7SIngo Weinhold
1782d690920SAxel Dörfler partition_id
_user_get_next_disk_device_id(int32 * _cookie,size_t * neededSize)1792d690920SAxel Dörfler _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize)
1802d690920SAxel Dörfler {
1812d690920SAxel Dörfler int32 cookie;
182*4644c7ccSJérôme Duval status_t error = copy_from_user_value(cookie, _cookie);
183*4644c7ccSJérôme Duval if (error != B_OK)
184*4644c7ccSJérôme Duval return error;
1852d690920SAxel Dörfler
1862d690920SAxel Dörfler partition_id id = B_ENTRY_NOT_FOUND;
1872d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
1882d690920SAxel Dörfler // get the next device
1892d690920SAxel Dörfler if (KDiskDevice *device = manager->RegisterNextDevice(&cookie)) {
1902d690920SAxel Dörfler PartitionRegistrar _(device, true);
1912d690920SAxel Dörfler id = device->ID();
192*4644c7ccSJérôme Duval if (neededSize != NULL) {
1932d690920SAxel Dörfler if (DeviceReadLocker locker = device) {
1942d690920SAxel Dörfler // get the needed size
1952d690920SAxel Dörfler UserDataWriter writer;
1968354dac7SIngo Weinhold device->WriteUserData(writer);
1976cc43bfbSAxel Dörfler status_t status = copy_to_user_value(neededSize,
1986cc43bfbSAxel Dörfler writer.AllocatedSize());
1996cc43bfbSAxel Dörfler if (status != B_OK)
2006cc43bfbSAxel Dörfler return status;
201*4644c7ccSJérôme Duval } else
2022d690920SAxel Dörfler id = B_ERROR;
2032d690920SAxel Dörfler }
2042d690920SAxel Dörfler }
205*4644c7ccSJérôme Duval
206*4644c7ccSJérôme Duval error = copy_to_user_value(_cookie, cookie);
207*4644c7ccSJérôme Duval if (error != B_OK)
208*4644c7ccSJérôme Duval return error;
2092d690920SAxel Dörfler return id;
2102d690920SAxel Dörfler }
2112d690920SAxel Dörfler
212d6e565c7SIngo Weinhold
2132d690920SAxel Dörfler partition_id
_user_find_disk_device(const char * _filename,size_t * neededSize)2142d690920SAxel Dörfler _user_find_disk_device(const char *_filename, size_t *neededSize)
2152d690920SAxel Dörfler {
2166cc43bfbSAxel Dörfler UserStringParameter<false> filename;
2176cc43bfbSAxel Dörfler status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
2186cc43bfbSAxel Dörfler if (error != B_OK)
2192d690920SAxel Dörfler return error;
2202d690920SAxel Dörfler
2212d690920SAxel Dörfler partition_id id = B_ENTRY_NOT_FOUND;
2222d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
2232d690920SAxel Dörfler // find the device
2242d690920SAxel Dörfler if (KDiskDevice *device = manager->RegisterDevice(filename)) {
2252d690920SAxel Dörfler PartitionRegistrar _(device, true);
2262d690920SAxel Dörfler id = device->ID();
227*4644c7ccSJérôme Duval if (neededSize != NULL) {
2282d690920SAxel Dörfler if (DeviceReadLocker locker = device) {
2292d690920SAxel Dörfler // get the needed size
2302d690920SAxel Dörfler UserDataWriter writer;
2318354dac7SIngo Weinhold device->WriteUserData(writer);
2326cc43bfbSAxel Dörfler error = copy_to_user_value(neededSize, writer.AllocatedSize());
2336cc43bfbSAxel Dörfler if (error != B_OK)
2346cc43bfbSAxel Dörfler return error;
2352d690920SAxel Dörfler } else
2362d690920SAxel Dörfler return B_ERROR;
2372d690920SAxel Dörfler }
2382d690920SAxel Dörfler }
2392d690920SAxel Dörfler return id;
2402d690920SAxel Dörfler }
2412d690920SAxel Dörfler
242d6e565c7SIngo Weinhold
2432d690920SAxel Dörfler partition_id
_user_find_partition(const char * _filename,size_t * neededSize)2442d690920SAxel Dörfler _user_find_partition(const char *_filename, size_t *neededSize)
2452d690920SAxel Dörfler {
2466cc43bfbSAxel Dörfler UserStringParameter<false> filename;
2476cc43bfbSAxel Dörfler status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
2486cc43bfbSAxel Dörfler if (error != B_OK)
2492d690920SAxel Dörfler return error;
2502d690920SAxel Dörfler
2512d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
2522d690920SAxel Dörfler // find the partition
253*4644c7ccSJérôme Duval KPartition *partition = manager->RegisterPartition(filename);
254*4644c7ccSJérôme Duval if (partition == NULL)
255*4644c7ccSJérôme Duval return B_ENTRY_NOT_FOUND;
2562d690920SAxel Dörfler PartitionRegistrar _(partition, true);
257*4644c7ccSJérôme Duval partition_id id = partition->ID();
258*4644c7ccSJérôme Duval if (neededSize != NULL) {
2592d690920SAxel Dörfler // get and lock the partition's device
260*4644c7ccSJérôme Duval KDiskDevice *device = manager->RegisterDevice(partition->ID(), false);
261*4644c7ccSJérôme Duval if (device == NULL)
2622d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
2632d690920SAxel Dörfler PartitionRegistrar _2(device, true);
2642d690920SAxel Dörfler if (DeviceReadLocker locker = device) {
2652d690920SAxel Dörfler // get the needed size
2662d690920SAxel Dörfler UserDataWriter writer;
2678354dac7SIngo Weinhold device->WriteUserData(writer);
2686cc43bfbSAxel Dörfler error = copy_to_user_value(neededSize, writer.AllocatedSize());
2696cc43bfbSAxel Dörfler if (error != B_OK)
2706cc43bfbSAxel Dörfler return error;
2712d690920SAxel Dörfler } else
2722d690920SAxel Dörfler return B_ERROR;
2732d690920SAxel Dörfler }
2742d690920SAxel Dörfler return id;
2752d690920SAxel Dörfler }
2762d690920SAxel Dörfler
277d6e565c7SIngo Weinhold
27838bbc957SAxel Dörfler partition_id
_user_find_file_disk_device(const char * _filename,size_t * neededSize)27938bbc957SAxel Dörfler _user_find_file_disk_device(const char *_filename, size_t *neededSize)
28038bbc957SAxel Dörfler {
28138bbc957SAxel Dörfler UserStringParameter<false> filename;
28238bbc957SAxel Dörfler status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
28338bbc957SAxel Dörfler if (error != B_OK)
28438bbc957SAxel Dörfler return error;
28538bbc957SAxel Dörfler
286eac83fb3SAxel Dörfler KPath path(filename, KPath::NORMALIZE);
28738bbc957SAxel Dörfler
28838bbc957SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
28938bbc957SAxel Dörfler // find the device
290*4644c7ccSJérôme Duval KFileDiskDevice* device = manager->RegisterFileDevice(path.Path());
291*4644c7ccSJérôme Duval if (device == NULL)
292*4644c7ccSJérôme Duval return B_ENTRY_NOT_FOUND;
29338bbc957SAxel Dörfler PartitionRegistrar _(device, true);
294*4644c7ccSJérôme Duval partition_id id = device->ID();
295*4644c7ccSJérôme Duval if (neededSize != NULL) {
29638bbc957SAxel Dörfler if (DeviceReadLocker locker = device) {
29738bbc957SAxel Dörfler // get the needed size
29838bbc957SAxel Dörfler UserDataWriter writer;
29938bbc957SAxel Dörfler device->WriteUserData(writer);
30038bbc957SAxel Dörfler error = copy_to_user_value(neededSize, writer.AllocatedSize());
30138bbc957SAxel Dörfler if (error != B_OK)
30238bbc957SAxel Dörfler return error;
30338bbc957SAxel Dörfler } else
30438bbc957SAxel Dörfler return B_ERROR;
30538bbc957SAxel Dörfler }
30638bbc957SAxel Dörfler return id;
30738bbc957SAxel Dörfler }
30838bbc957SAxel Dörfler
30938bbc957SAxel Dörfler
3102d690920SAxel Dörfler /*! \brief Writes data describing the disk device identified by ID and all
3112d690920SAxel Dörfler its partitions into the supplied buffer.
3122d690920SAxel Dörfler
3132d690920SAxel Dörfler The function passes the buffer size required to hold the data back
3142d690920SAxel Dörfler through the \a _neededSize parameter, if the device could be found at
3152d690920SAxel Dörfler least and no serious error occured. If fails with \c B_BUFFER_OVERFLOW,
3162d690920SAxel Dörfler if the supplied buffer is too small or a \c NULL buffer is supplied
3172d690920SAxel Dörfler (and \c bufferSize is 0).
3182d690920SAxel Dörfler
3192d690920SAxel Dörfler The device is identified by \a id. If \a deviceOnly is \c true, then
3202d690920SAxel Dörfler it must be the ID of a disk device, otherwise the disk device is
3212d690920SAxel Dörfler chosen, on which the partition \a id refers to resides.
3222d690920SAxel Dörfler
3232d690920SAxel Dörfler \param id The ID of an arbitrary partition on the disk device (including
3242d690920SAxel Dörfler the disk device itself), whose data shall be returned
3252d690920SAxel Dörfler (if \a deviceOnly is \c false), or the ID of the disk device
3262d690920SAxel Dörfler itself (if \a deviceOnly is true).
3272d690920SAxel Dörfler \param deviceOnly Specifies whether only IDs of disk devices (\c true),
3282d690920SAxel Dörfler or also IDs of partitions (\c false) are accepted for \a id.
3292d690920SAxel Dörfler \param buffer The buffer into which the disk device data shall be written.
3302d690920SAxel Dörfler May be \c NULL.
3312d690920SAxel Dörfler \param bufferSize The size of \a buffer.
3322d690920SAxel Dörfler \param _neededSize Pointer to a variable into which the actually needed
3332d690920SAxel Dörfler buffer size is written. May be \c NULL.
3342d690920SAxel Dörfler \return
3352d690920SAxel Dörfler - \c B_OK: Everything went fine. The device was found and, if not \c NULL,
3362d690920SAxel Dörfler in \a _neededSize the actually needed buffer size is returned. And
3372d690920SAxel Dörfler \a buffer will contain the disk device data.
3382d690920SAxel Dörfler - \c B_BAD_VALUE: \c NULL \a buffer, but not 0 \a bufferSize.
3392d690920SAxel Dörfler - \c B_BUFFER_OVERFLOW: The supplied buffer was too small. \a _neededSize,
3402d690920SAxel Dörfler if not \c NULL, will contain the required buffer size.
3412d690920SAxel Dörfler - \c B_NO_MEMORY: Insufficient memory to complete the operation.
3422d690920SAxel Dörfler - \c B_ENTRY_NOT_FOUND: \a id is no valid disk device ID (if \a deviceOnly
3432d690920SAxel Dörfler is \c true) or not even a valid partition ID (if \a deviceOnly is
3442d690920SAxel Dörfler \c false).
3452d690920SAxel Dörfler - \c B_ERROR: An unexpected error occured.
3462d690920SAxel Dörfler - another error code...
3472d690920SAxel Dörfler */
3482d690920SAxel Dörfler status_t
_user_get_disk_device_data(partition_id id,bool deviceOnly,user_disk_device_data * buffer,size_t bufferSize,size_t * _neededSize)3498354dac7SIngo Weinhold _user_get_disk_device_data(partition_id id, bool deviceOnly,
350d6e565c7SIngo Weinhold user_disk_device_data *buffer, size_t bufferSize, size_t *_neededSize)
3512d690920SAxel Dörfler {
352*4644c7ccSJérôme Duval if (buffer == NULL && bufferSize > 0)
3532d690920SAxel Dörfler return B_BAD_VALUE;
3542d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
3552d690920SAxel Dörfler // get the device
356*4644c7ccSJérôme Duval KDiskDevice *device = manager->RegisterDevice(id, deviceOnly);
357*4644c7ccSJérôme Duval if (device == NULL)
358*4644c7ccSJérôme Duval return B_ENTRY_NOT_FOUND;
359*4644c7ccSJérôme Duval
3602d690920SAxel Dörfler PartitionRegistrar _(device, true);
3612d690920SAxel Dörfler if (DeviceReadLocker locker = device) {
3622d690920SAxel Dörfler // do a dry run first to get the needed size
3632d690920SAxel Dörfler UserDataWriter writer;
3648354dac7SIngo Weinhold device->WriteUserData(writer);
3652d690920SAxel Dörfler size_t neededSize = writer.AllocatedSize();
366*4644c7ccSJérôme Duval if (_neededSize != NULL) {
3672d690920SAxel Dörfler status_t error = copy_ref_var_to_user(neededSize, _neededSize);
3682d690920SAxel Dörfler if (error != B_OK)
3692d690920SAxel Dörfler return error;
3702d690920SAxel Dörfler }
3712d690920SAxel Dörfler // if no buffer has been supplied or the buffer is too small,
3722d690920SAxel Dörfler // then we're done
373*4644c7ccSJérôme Duval if (buffer == NULL || bufferSize < neededSize)
3742d690920SAxel Dörfler return B_BUFFER_OVERFLOW;
375*4644c7ccSJérôme Duval if (!IS_USER_ADDRESS(buffer))
376*4644c7ccSJérôme Duval return B_BAD_ADDRESS;
3772d690920SAxel Dörfler // otherwise allocate a kernel buffer
3782d690920SAxel Dörfler user_disk_device_data *kernelBuffer
3792d690920SAxel Dörfler = static_cast<user_disk_device_data*>(malloc(neededSize));
380*4644c7ccSJérôme Duval if (kernelBuffer == NULL)
3812d690920SAxel Dörfler return B_NO_MEMORY;
3822d690920SAxel Dörfler MemoryDeleter deleter(kernelBuffer);
3832d690920SAxel Dörfler // write the device data into the buffer
3842d690920SAxel Dörfler writer.SetTo(kernelBuffer, bufferSize);
3858354dac7SIngo Weinhold device->WriteUserData(writer);
3862d690920SAxel Dörfler // sanity check
3872d690920SAxel Dörfler if (writer.AllocatedSize() != neededSize) {
3882d690920SAxel Dörfler ERROR(("Size of written disk device user data changed from "
3892d690920SAxel Dörfler "%lu to %lu while device was locked!\n"));
3902d690920SAxel Dörfler return B_ERROR;
3912d690920SAxel Dörfler }
3922d690920SAxel Dörfler // relocate
3932d690920SAxel Dörfler status_t error = writer.Relocate(buffer);
3942d690920SAxel Dörfler if (error != B_OK)
3952d690920SAxel Dörfler return error;
3962d690920SAxel Dörfler // copy out
3972d690920SAxel Dörfler return user_memcpy(buffer, kernelBuffer, neededSize);
3982d690920SAxel Dörfler } else
3992d690920SAxel Dörfler return B_ERROR;
4002d690920SAxel Dörfler }
4012d690920SAxel Dörfler
402d6e565c7SIngo Weinhold
4032d690920SAxel Dörfler partition_id
_user_register_file_device(const char * _filename)4042d690920SAxel Dörfler _user_register_file_device(const char *_filename)
4052d690920SAxel Dörfler {
4066cc43bfbSAxel Dörfler UserStringParameter<false> filename;
4076cc43bfbSAxel Dörfler status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
4086cc43bfbSAxel Dörfler if (error != B_OK)
4092d690920SAxel Dörfler return error;
4106cc43bfbSAxel Dörfler
411eac83fb3SAxel Dörfler KPath path(filename, KPath::NORMALIZE);
412260e077fSAxel Dörfler
4132d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
4142d690920SAxel Dörfler if (ManagerLocker locker = manager) {
415*4644c7ccSJérôme Duval KFileDiskDevice *device = manager->FindFileDevice(path.Path());
416*4644c7ccSJérôme Duval if (device != NULL)
4172d690920SAxel Dörfler return device->ID();
418260e077fSAxel Dörfler return manager->CreateFileDevice(path.Path());
4192d690920SAxel Dörfler }
4202d690920SAxel Dörfler return B_ERROR;
4212d690920SAxel Dörfler }
4222d690920SAxel Dörfler
423d6e565c7SIngo Weinhold
4242d690920SAxel Dörfler status_t
_user_unregister_file_device(partition_id deviceID,const char * _filename)4252d690920SAxel Dörfler _user_unregister_file_device(partition_id deviceID, const char *_filename)
4262d690920SAxel Dörfler {
427*4644c7ccSJérôme Duval if (deviceID < 0 && _filename == NULL)
4282d690920SAxel Dörfler return B_BAD_VALUE;
4292d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
430*4644c7ccSJérôme Duval if (deviceID >= 0)
4312d690920SAxel Dörfler return manager->DeleteFileDevice(deviceID);
432*4644c7ccSJérôme Duval
4336cc43bfbSAxel Dörfler UserStringParameter<false> filename;
4346cc43bfbSAxel Dörfler status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
4356cc43bfbSAxel Dörfler if (error != B_OK)
4362d690920SAxel Dörfler return error;
4376cc43bfbSAxel Dörfler
4382d690920SAxel Dörfler return manager->DeleteFileDevice(filename);
4392d690920SAxel Dörfler }
4402d690920SAxel Dörfler
441d6e565c7SIngo Weinhold
44238bbc957SAxel Dörfler status_t
_user_get_file_disk_device_path(partition_id id,char * buffer,size_t bufferSize)44338bbc957SAxel Dörfler _user_get_file_disk_device_path(partition_id id, char* buffer,
44438bbc957SAxel Dörfler size_t bufferSize)
44538bbc957SAxel Dörfler {
44638bbc957SAxel Dörfler if (id < 0 || buffer == NULL || bufferSize == 0)
44738bbc957SAxel Dörfler return B_BAD_VALUE;
448*4644c7ccSJérôme Duval if (!IS_USER_ADDRESS(buffer))
449*4644c7ccSJérôme Duval return B_BAD_ADDRESS;
45038bbc957SAxel Dörfler
45138bbc957SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
452*4644c7ccSJérôme Duval KDiskDevice *device = manager->RegisterDevice(id, true);
453*4644c7ccSJérôme Duval if (device != NULL) {
45438bbc957SAxel Dörfler PartitionRegistrar _(device, true);
45538bbc957SAxel Dörfler if (DeviceReadLocker locker = device) {
45638bbc957SAxel Dörfler KFileDiskDevice* fileDevice
45738bbc957SAxel Dörfler = dynamic_cast<KFileDiskDevice*>(device);
45838bbc957SAxel Dörfler if (fileDevice == NULL)
45938bbc957SAxel Dörfler return B_BAD_VALUE;
46038bbc957SAxel Dörfler
46180ea5e35SIngo Weinhold ssize_t copied = user_strlcpy(buffer, fileDevice->FilePath(),
46280ea5e35SIngo Weinhold bufferSize);
46380ea5e35SIngo Weinhold if (copied < 0)
46480ea5e35SIngo Weinhold return copied;
46580ea5e35SIngo Weinhold return (size_t)copied < bufferSize ? B_OK : B_BUFFER_OVERFLOW;
46638bbc957SAxel Dörfler }
46738bbc957SAxel Dörfler }
46838bbc957SAxel Dörfler
46938bbc957SAxel Dörfler return B_ERROR;
47038bbc957SAxel Dörfler }
47138bbc957SAxel Dörfler
47238bbc957SAxel Dörfler
4732d690920SAxel Dörfler status_t
_user_get_disk_system_info(disk_system_id id,user_disk_system_info * _info)4742d690920SAxel Dörfler _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
4752d690920SAxel Dörfler {
476*4644c7ccSJérôme Duval if (_info == NULL)
4772d690920SAxel Dörfler return B_BAD_VALUE;
4782d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
4792d690920SAxel Dörfler if (ManagerLocker locker = manager) {
480*4644c7ccSJérôme Duval KDiskSystem *diskSystem = manager->FindDiskSystem(id);
481*4644c7ccSJérôme Duval if (diskSystem != NULL) {
4822d690920SAxel Dörfler user_disk_system_info info;
4832d690920SAxel Dörfler diskSystem->GetInfo(&info);
484*4644c7ccSJérôme Duval return copy_to_user_value(_info, info);
4852d690920SAxel Dörfler }
4862d690920SAxel Dörfler }
4872d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
4882d690920SAxel Dörfler }
4892d690920SAxel Dörfler
490d6e565c7SIngo Weinhold
4912d690920SAxel Dörfler status_t
_user_get_next_disk_system_info(int32 * _cookie,user_disk_system_info * _info)4922d690920SAxel Dörfler _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
4932d690920SAxel Dörfler {
494*4644c7ccSJérôme Duval if (_info == NULL)
4952d690920SAxel Dörfler return B_BAD_VALUE;
496*4644c7ccSJérôme Duval if (!IS_USER_ADDRESS(_info))
497*4644c7ccSJérôme Duval return B_BAD_ADDRESS;
4982d690920SAxel Dörfler int32 cookie;
499*4644c7ccSJérôme Duval status_t result = copy_from_user_value(cookie, _cookie);
500*4644c7ccSJérôme Duval if (result != B_OK)
501*4644c7ccSJérôme Duval return result;
502*4644c7ccSJérôme Duval result = B_ENTRY_NOT_FOUND;
5032d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
5042d690920SAxel Dörfler if (ManagerLocker locker = manager) {
505*4644c7ccSJérôme Duval KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie);
506*4644c7ccSJérôme Duval if (diskSystem != NULL) {
5072d690920SAxel Dörfler user_disk_system_info info;
5082d690920SAxel Dörfler diskSystem->GetInfo(&info);
509*4644c7ccSJérôme Duval result = copy_to_user_value(_info, info);
5102d690920SAxel Dörfler }
5112d690920SAxel Dörfler }
512*4644c7ccSJérôme Duval status_t error = copy_to_user_value(_cookie, cookie);
513*4644c7ccSJérôme Duval if (error != B_OK)
514*4644c7ccSJérôme Duval result = error;
5152d690920SAxel Dörfler return result;
5162d690920SAxel Dörfler }
5172d690920SAxel Dörfler
518d6e565c7SIngo Weinhold
5192d690920SAxel Dörfler status_t
_user_find_disk_system(const char * _name,user_disk_system_info * _info)5202d690920SAxel Dörfler _user_find_disk_system(const char *_name, user_disk_system_info *_info)
5212d690920SAxel Dörfler {
522*4644c7ccSJérôme Duval if (_name == NULL || _info == NULL)
5232d690920SAxel Dörfler return B_BAD_VALUE;
524*4644c7ccSJérôme Duval if (!IS_USER_ADDRESS(_name) || !IS_USER_ADDRESS(_info))
525*4644c7ccSJérôme Duval return B_BAD_ADDRESS;
5262d690920SAxel Dörfler char name[B_DISK_SYSTEM_NAME_LENGTH];
5272d690920SAxel Dörfler status_t error = ddm_strlcpy(name, _name, B_DISK_SYSTEM_NAME_LENGTH);
528*4644c7ccSJérôme Duval if (error != B_OK)
5292d690920SAxel Dörfler return error;
5302d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
5312d690920SAxel Dörfler if (ManagerLocker locker = manager) {
532*4644c7ccSJérôme Duval KDiskSystem *diskSystem = manager->FindDiskSystem(name);
533*4644c7ccSJérôme Duval if (diskSystem != NULL) {
5342d690920SAxel Dörfler user_disk_system_info info;
5352d690920SAxel Dörfler diskSystem->GetInfo(&info);
536*4644c7ccSJérôme Duval return copy_to_user_value(_info, info);
5372d690920SAxel Dörfler }
5382d690920SAxel Dörfler }
5392d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
5402d690920SAxel Dörfler }
5412d690920SAxel Dörfler
542d6e565c7SIngo Weinhold
5432d690920SAxel Dörfler status_t
_user_defragment_partition(partition_id partitionID,int32 * _changeCounter)5447b45b55bSIngo Weinhold _user_defragment_partition(partition_id partitionID, int32* _changeCounter)
5452d690920SAxel Dörfler {
5467b45b55bSIngo Weinhold // copy parameters in
5477b45b55bSIngo Weinhold int32 changeCounter;
5487b45b55bSIngo Weinhold
549*4644c7ccSJérôme Duval status_t error = copy_from_user_value(changeCounter, _changeCounter);
550*4644c7ccSJérôme Duval if (error != B_OK)
5517b45b55bSIngo Weinhold return error;
5527b45b55bSIngo Weinhold
5532d690920SAxel Dörfler // get the partition
5547b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
5552d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
556*4644c7ccSJérôme Duval if (partition == NULL)
5572d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
5587b45b55bSIngo Weinhold
5592d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
5602d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
5612d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
5627b45b55bSIngo Weinhold
5637b45b55bSIngo Weinhold // check change counter
5647b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
5657b45b55bSIngo Weinhold return B_BAD_VALUE;
5667b45b55bSIngo Weinhold
5677b45b55bSIngo Weinhold // the partition must be initialized
5687b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
569*4644c7ccSJérôme Duval if (diskSystem == NULL)
5707b45b55bSIngo Weinhold return B_BAD_VALUE;
5717b45b55bSIngo Weinhold
5727b45b55bSIngo Weinhold // mark the partition busy and unlock
5737b45b55bSIngo Weinhold if (!partition->CheckAndMarkBusy(false))
5747b45b55bSIngo Weinhold return B_BUSY;
5757b45b55bSIngo Weinhold locker.Unlock();
5767b45b55bSIngo Weinhold
5777b45b55bSIngo Weinhold // defragment
5787b45b55bSIngo Weinhold error = diskSystem->Defragment(partition, DUMMY_JOB_ID);
5797b45b55bSIngo Weinhold
5807b45b55bSIngo Weinhold // re-lock and unmark busy
5817b45b55bSIngo Weinhold locker.Lock();
5827b45b55bSIngo Weinhold partition->UnmarkBusy(false);
5837b45b55bSIngo Weinhold
5842d690920SAxel Dörfler if (error != B_OK)
5852d690920SAxel Dörfler return error;
5867b45b55bSIngo Weinhold
5877b45b55bSIngo Weinhold // return change counter
588*4644c7ccSJérôme Duval return copy_to_user_value(_changeCounter, partition->ChangeCounter());
5892d690920SAxel Dörfler }
5902d690920SAxel Dörfler
591d6e565c7SIngo Weinhold
5922d690920SAxel Dörfler status_t
_user_repair_partition(partition_id partitionID,int32 * _changeCounter,bool checkOnly)5937b45b55bSIngo Weinhold _user_repair_partition(partition_id partitionID, int32* _changeCounter,
5942d690920SAxel Dörfler bool checkOnly)
5952d690920SAxel Dörfler {
5967b45b55bSIngo Weinhold // copy parameters in
5977b45b55bSIngo Weinhold int32 changeCounter;
5987b45b55bSIngo Weinhold
599*4644c7ccSJérôme Duval status_t error = copy_from_user_value(changeCounter, _changeCounter);
600*4644c7ccSJérôme Duval if (error != B_OK)
6017b45b55bSIngo Weinhold return error;
6027b45b55bSIngo Weinhold
6032d690920SAxel Dörfler // get the partition
6047b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
6052d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
606*4644c7ccSJérôme Duval if (partition == NULL)
6072d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
6087b45b55bSIngo Weinhold
6092d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
6102d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
6112d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
6127b45b55bSIngo Weinhold
6137b45b55bSIngo Weinhold // check change counter
6147b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
6157b45b55bSIngo Weinhold return B_BAD_VALUE;
6167b45b55bSIngo Weinhold
6177b45b55bSIngo Weinhold // the partition must be initialized
6187b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
619*4644c7ccSJérôme Duval if (diskSystem == NULL)
6207b45b55bSIngo Weinhold return B_BAD_VALUE;
6217b45b55bSIngo Weinhold
6227b45b55bSIngo Weinhold // mark the partition busy and unlock
6237b45b55bSIngo Weinhold if (!partition->CheckAndMarkBusy(false))
6247b45b55bSIngo Weinhold return B_BUSY;
6257b45b55bSIngo Weinhold locker.Unlock();
6267b45b55bSIngo Weinhold
6277b45b55bSIngo Weinhold // repair/check
6287b45b55bSIngo Weinhold error = diskSystem->Repair(partition, checkOnly, DUMMY_JOB_ID);
6297b45b55bSIngo Weinhold
6307b45b55bSIngo Weinhold // re-lock and unmark busy
6317b45b55bSIngo Weinhold locker.Lock();
6327b45b55bSIngo Weinhold partition->UnmarkBusy(false);
6337b45b55bSIngo Weinhold
6342d690920SAxel Dörfler if (error != B_OK)
6352d690920SAxel Dörfler return error;
6367b45b55bSIngo Weinhold
6377b45b55bSIngo Weinhold // return change counter
638*4644c7ccSJérôme Duval return copy_to_user_value(_changeCounter, partition->ChangeCounter());
6392d690920SAxel Dörfler }
6402d690920SAxel Dörfler
641d6e565c7SIngo Weinhold
6422d690920SAxel Dörfler status_t
_user_resize_partition(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,off_t size,off_t contentSize)6437b45b55bSIngo Weinhold _user_resize_partition(partition_id partitionID, int32* _changeCounter,
6447b45b55bSIngo Weinhold partition_id childID, int32* _childChangeCounter, off_t size,
645300868ceSIngo Weinhold off_t contentSize)
6462d690920SAxel Dörfler {
6477b45b55bSIngo Weinhold // copy parameters in
6487b45b55bSIngo Weinhold int32 changeCounter;
6497b45b55bSIngo Weinhold int32 childChangeCounter;
6507b45b55bSIngo Weinhold
651*4644c7ccSJérôme Duval status_t error = copy_from_user_value(changeCounter, _changeCounter);
652*4644c7ccSJérôme Duval if (error == B_OK)
653*4644c7ccSJérôme Duval error = copy_from_user_value(childChangeCounter, _childChangeCounter);
654*4644c7ccSJérôme Duval if (error != B_OK)
6557b45b55bSIngo Weinhold return error;
6567b45b55bSIngo Weinhold
6572d690920SAxel Dörfler // get the partition
6587b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
6592d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
660*4644c7ccSJérôme Duval if (partition == NULL)
6612d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
6627b45b55bSIngo Weinhold
6632d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
6642d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
6652d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
6667b45b55bSIngo Weinhold
6677b45b55bSIngo Weinhold // register child
6687b45b55bSIngo Weinhold KPartition* child = manager->RegisterPartition(childID);
669*4644c7ccSJérôme Duval if (child == NULL)
6707b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
6717b45b55bSIngo Weinhold
6727b45b55bSIngo Weinhold PartitionRegistrar registrar3(child, true);
6737b45b55bSIngo Weinhold
6747b45b55bSIngo Weinhold // check change counters
6757b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter()
6767b45b55bSIngo Weinhold || childChangeCounter != child->ChangeCounter()) {
6772d690920SAxel Dörfler return B_BAD_VALUE;
6782d690920SAxel Dörfler }
6797b45b55bSIngo Weinhold
6807b45b55bSIngo Weinhold // the partition must be initialized
6817b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
682*4644c7ccSJérôme Duval if (diskSystem == NULL)
683300868ceSIngo Weinhold return B_BAD_VALUE;
6847b45b55bSIngo Weinhold
6857b45b55bSIngo Weinhold // child must indeed be a child of partition
6867b45b55bSIngo Weinhold if (child->Parent() != partition)
6877b45b55bSIngo Weinhold return B_BAD_VALUE;
6887b45b55bSIngo Weinhold
6897b45b55bSIngo Weinhold // check sizes
6907b45b55bSIngo Weinhold if (size < 0 || contentSize < 0 || size < contentSize
6917b45b55bSIngo Weinhold || size > partition->ContentSize()) {
6927b45b55bSIngo Weinhold return B_BAD_VALUE;
6937b45b55bSIngo Weinhold }
6947b45b55bSIngo Weinhold
6957b45b55bSIngo Weinhold // mark the partitions busy and unlock
6967b45b55bSIngo Weinhold if (partition->IsBusy() || child->IsBusy())
6977b45b55bSIngo Weinhold return B_BUSY;
6987b45b55bSIngo Weinhold partition->SetBusy(true);
6997b45b55bSIngo Weinhold child->SetBusy(true);
7007b45b55bSIngo Weinhold locker.Unlock();
7017b45b55bSIngo Weinhold
7027b45b55bSIngo Weinhold // resize contents first, if shrinking
7037b45b55bSIngo Weinhold if (child->DiskSystem() && contentSize < child->ContentSize())
7047b45b55bSIngo Weinhold error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID);
7057b45b55bSIngo Weinhold
7067b45b55bSIngo Weinhold // resize the partition
7077b45b55bSIngo Weinhold if (error == B_OK && size != child->Size())
7087b45b55bSIngo Weinhold error = diskSystem->ResizeChild(child, size, DUMMY_JOB_ID);
7097b45b55bSIngo Weinhold
7107b45b55bSIngo Weinhold // resize contents last, if growing
7117b45b55bSIngo Weinhold if (error == B_OK && child->DiskSystem()
7127b45b55bSIngo Weinhold && contentSize > child->ContentSize()) {
7137b45b55bSIngo Weinhold error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID);
7147b45b55bSIngo Weinhold }
7157b45b55bSIngo Weinhold
7167b45b55bSIngo Weinhold // re-lock and unmark busy
7177b45b55bSIngo Weinhold locker.Lock();
7187b45b55bSIngo Weinhold partition->SetBusy(false);
7197b45b55bSIngo Weinhold child->SetBusy(false);
7207b45b55bSIngo Weinhold
7217b45b55bSIngo Weinhold if (error != B_OK)
7227b45b55bSIngo Weinhold return error;
7237b45b55bSIngo Weinhold
7247b45b55bSIngo Weinhold // return change counters
725*4644c7ccSJérôme Duval error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
726*4644c7ccSJérôme Duval if (error == B_OK)
727*4644c7ccSJérôme Duval error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
7287b45b55bSIngo Weinhold return error;
7297b45b55bSIngo Weinhold }
7307b45b55bSIngo Weinhold
731d6e565c7SIngo Weinhold
7322d690920SAxel Dörfler status_t
_user_move_partition(partition_id partitionID,int32 * changeCounter,partition_id childID,int32 * childChangeCounter,off_t newOffset,partition_id * descendantIDs,int32 * descendantChangeCounters,int32 descendantCount)733300868ceSIngo Weinhold _user_move_partition(partition_id partitionID, int32* changeCounter,
734300868ceSIngo Weinhold partition_id childID, int32* childChangeCounter, off_t newOffset,
735300868ceSIngo Weinhold partition_id* descendantIDs, int32* descendantChangeCounters,
736300868ceSIngo Weinhold int32 descendantCount)
7372d690920SAxel Dörfler {
738300868ceSIngo Weinhold #if 0
7392d690920SAxel Dörfler KDiskDeviceManager *manager = KDiskDeviceManager::Default();
7402d690920SAxel Dörfler // get the partition
7412d690920SAxel Dörfler KPartition *partition = manager->WriteLockPartition(partitionID);
7422d690920SAxel Dörfler if (!partition)
7432d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
7442d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
7452d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
7462d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
7472d690920SAxel Dörfler // check the new offset
7482d690920SAxel Dörfler if (newOffset == partition->Offset())
7492d690920SAxel Dörfler return B_OK;
7502d690920SAxel Dörfler off_t proposedOffset = newOffset;
7512d690920SAxel Dörfler status_t error = validate_move_partition(partition, changeCounter,
7522d690920SAxel Dörfler &proposedOffset, true);
7532d690920SAxel Dörfler if (error != B_OK)
7542d690920SAxel Dörfler return error;
7552d690920SAxel Dörfler if (proposedOffset != newOffset)
7562d690920SAxel Dörfler return B_BAD_VALUE;
7572d690920SAxel Dörfler // new offset is fine -- move the thing
7582d690920SAxel Dörfler off_t moveBy = newOffset - partition->Offset();
7592d690920SAxel Dörfler move_descendants(partition, moveBy);
7602d690920SAxel Dörfler partition->Changed(B_PARTITION_CHANGED_OFFSET);
7612d690920SAxel Dörfler // implicit partitioning system changes
7622d690920SAxel Dörfler error = partition->Parent()->DiskSystem()->ShadowPartitionChanged(
763bf95c9aeSIngo Weinhold partition->Parent(), partition, B_PARTITION_MOVE_CHILD);
7642d690920SAxel Dörfler if (error != B_OK)
7652d690920SAxel Dörfler return error;
7662d690920SAxel Dörfler // implicit descendants' content disk system changes
7672d690920SAxel Dörfler return move_descendants_contents(partition);
768300868ceSIngo Weinhold #endif
769300868ceSIngo Weinhold return B_BAD_VALUE;
7702d690920SAxel Dörfler }
7712d690920SAxel Dörfler
772d6e565c7SIngo Weinhold
7732d690920SAxel Dörfler status_t
_user_set_partition_name(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,const char * _name)7747b45b55bSIngo Weinhold _user_set_partition_name(partition_id partitionID, int32* _changeCounter,
7757b45b55bSIngo Weinhold partition_id childID, int32* _childChangeCounter, const char* _name)
7762d690920SAxel Dörfler {
7777b45b55bSIngo Weinhold // copy parameters in
7787b45b55bSIngo Weinhold UserStringParameter<false> name;
7797b45b55bSIngo Weinhold int32 changeCounter;
7807b45b55bSIngo Weinhold int32 childChangeCounter;
7817b45b55bSIngo Weinhold
782*4644c7ccSJérôme Duval status_t error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
783*4644c7ccSJérôme Duval if (error == B_OK)
784*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
785*4644c7ccSJérôme Duval if (error == B_OK)
786*4644c7ccSJérôme Duval error = copy_from_user_value(childChangeCounter, _childChangeCounter);
787*4644c7ccSJérôme Duval if (error != B_OK)
7882d690920SAxel Dörfler return error;
7897b45b55bSIngo Weinhold
7902d690920SAxel Dörfler // get the partition
7917b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
7922d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
793*4644c7ccSJérôme Duval if (partition == NULL)
7942d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
7957b45b55bSIngo Weinhold
7962d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
7972d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
7982d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
7997b45b55bSIngo Weinhold
8007b45b55bSIngo Weinhold // register child
8017b45b55bSIngo Weinhold KPartition* child = manager->RegisterPartition(childID);
802*4644c7ccSJérôme Duval if (child == NULL)
8037b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
8047b45b55bSIngo Weinhold
8057b45b55bSIngo Weinhold PartitionRegistrar registrar3(child, true);
8067b45b55bSIngo Weinhold
8077b45b55bSIngo Weinhold // check change counters
8087b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter()
8097b45b55bSIngo Weinhold || childChangeCounter != child->ChangeCounter()) {
8107b45b55bSIngo Weinhold return B_BAD_VALUE;
8117b45b55bSIngo Weinhold }
8127b45b55bSIngo Weinhold
8137b45b55bSIngo Weinhold // the partition must be initialized
8147b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
815*4644c7ccSJérôme Duval if (diskSystem == NULL)
8167b45b55bSIngo Weinhold return B_BAD_VALUE;
8177b45b55bSIngo Weinhold
8187b45b55bSIngo Weinhold // child must indeed be a child of partition
8197b45b55bSIngo Weinhold if (child->Parent() != partition)
8207b45b55bSIngo Weinhold return B_BAD_VALUE;
8217b45b55bSIngo Weinhold
8227b45b55bSIngo Weinhold // mark the partitions busy and unlock
8237b45b55bSIngo Weinhold if (partition->IsBusy() || child->IsBusy())
8247b45b55bSIngo Weinhold return B_BUSY;
8257b45b55bSIngo Weinhold partition->SetBusy(true);
8267b45b55bSIngo Weinhold child->SetBusy(true);
8277b45b55bSIngo Weinhold locker.Unlock();
8287b45b55bSIngo Weinhold
8297b45b55bSIngo Weinhold // set the child name
8307b45b55bSIngo Weinhold error = diskSystem->SetName(child, name.value, DUMMY_JOB_ID);
8317b45b55bSIngo Weinhold
8327b45b55bSIngo Weinhold // re-lock and unmark busy
8337b45b55bSIngo Weinhold locker.Lock();
8347b45b55bSIngo Weinhold partition->SetBusy(false);
8357b45b55bSIngo Weinhold child->SetBusy(false);
8367b45b55bSIngo Weinhold
8372d690920SAxel Dörfler if (error != B_OK)
8382d690920SAxel Dörfler return error;
8397b45b55bSIngo Weinhold
8407b45b55bSIngo Weinhold // return change counters
841*4644c7ccSJérôme Duval error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
842*4644c7ccSJérôme Duval if (error == B_OK)
843*4644c7ccSJérôme Duval error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
8442d690920SAxel Dörfler return error;
8457b45b55bSIngo Weinhold }
8467b45b55bSIngo Weinhold
847d6e565c7SIngo Weinhold
8482d690920SAxel Dörfler status_t
_user_set_partition_content_name(partition_id partitionID,int32 * _changeCounter,const char * _name)8497b45b55bSIngo Weinhold _user_set_partition_content_name(partition_id partitionID,
8507b45b55bSIngo Weinhold int32* _changeCounter, const char* _name)
8512d690920SAxel Dörfler {
8527b45b55bSIngo Weinhold // copy parameters in
8537b45b55bSIngo Weinhold UserStringParameter<true> name;
8547b45b55bSIngo Weinhold int32 changeCounter;
8557b45b55bSIngo Weinhold
856*4644c7ccSJérôme Duval status_t error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
857*4644c7ccSJérôme Duval if (error == B_OK)
858*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
859*4644c7ccSJérôme Duval if (error != B_OK)
8602d690920SAxel Dörfler return error;
8617b45b55bSIngo Weinhold
8622d690920SAxel Dörfler // get the partition
8637b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
8642d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
865*4644c7ccSJérôme Duval if (partition == NULL)
8662d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
8677b45b55bSIngo Weinhold
8682d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
8692d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
8702d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
8717b45b55bSIngo Weinhold
8727b45b55bSIngo Weinhold // check change counter
8737b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
8747b45b55bSIngo Weinhold return B_BAD_VALUE;
8757b45b55bSIngo Weinhold
8767b45b55bSIngo Weinhold // the partition must be initialized
8777b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
878*4644c7ccSJérôme Duval if (diskSystem == NULL)
8797b45b55bSIngo Weinhold return B_BAD_VALUE;
8807b45b55bSIngo Weinhold
8817b45b55bSIngo Weinhold // mark the partition busy and unlock
8827b45b55bSIngo Weinhold if (!partition->CheckAndMarkBusy(false))
8837b45b55bSIngo Weinhold return B_BUSY;
8847b45b55bSIngo Weinhold locker.Unlock();
8857b45b55bSIngo Weinhold
8867b45b55bSIngo Weinhold // set content parameters
8877b45b55bSIngo Weinhold error = diskSystem->SetContentName(partition, name.value, DUMMY_JOB_ID);
8887b45b55bSIngo Weinhold
8897b45b55bSIngo Weinhold // re-lock and unmark busy
8907b45b55bSIngo Weinhold locker.Lock();
8917b45b55bSIngo Weinhold partition->UnmarkBusy(false);
8927b45b55bSIngo Weinhold
8932d690920SAxel Dörfler if (error != B_OK)
8942d690920SAxel Dörfler return error;
8957b45b55bSIngo Weinhold
8967b45b55bSIngo Weinhold // return change counter
897*4644c7ccSJérôme Duval return copy_to_user_value(_changeCounter, partition->ChangeCounter());
8982d690920SAxel Dörfler }
8992d690920SAxel Dörfler
900d6e565c7SIngo Weinhold
9012d690920SAxel Dörfler status_t
_user_set_partition_type(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,const char * _type)9027b45b55bSIngo Weinhold _user_set_partition_type(partition_id partitionID, int32* _changeCounter,
9037b45b55bSIngo Weinhold partition_id childID, int32* _childChangeCounter, const char* _type)
9042d690920SAxel Dörfler {
9057b45b55bSIngo Weinhold // copy parameters in
9067b45b55bSIngo Weinhold UserStringParameter<false> type;
9077b45b55bSIngo Weinhold int32 changeCounter;
9087b45b55bSIngo Weinhold int32 childChangeCounter;
9097b45b55bSIngo Weinhold
910*4644c7ccSJérôme Duval status_t error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH);
911*4644c7ccSJérôme Duval if (error == B_OK)
912*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
913*4644c7ccSJérôme Duval if (error == B_OK)
914*4644c7ccSJérôme Duval error = copy_from_user_value(childChangeCounter, _childChangeCounter);
915*4644c7ccSJérôme Duval if (error != B_OK)
9162d690920SAxel Dörfler return error;
917*4644c7ccSJérôme Duval
9187b45b55bSIngo Weinhold
9192d690920SAxel Dörfler // get the partition
9207b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
9212d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
922*4644c7ccSJérôme Duval if (partition == NULL)
9232d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
9247b45b55bSIngo Weinhold
9252d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
9262d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
9272d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
9287b45b55bSIngo Weinhold
9297b45b55bSIngo Weinhold // register child
9307b45b55bSIngo Weinhold KPartition* child = manager->RegisterPartition(childID);
931*4644c7ccSJérôme Duval if (child == NULL)
9327b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
9337b45b55bSIngo Weinhold
9347b45b55bSIngo Weinhold PartitionRegistrar registrar3(child, true);
9357b45b55bSIngo Weinhold
9367b45b55bSIngo Weinhold // check change counters
9377b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter()
9387b45b55bSIngo Weinhold || childChangeCounter != child->ChangeCounter()) {
939300868ceSIngo Weinhold return B_BAD_VALUE;
9402d690920SAxel Dörfler }
9412d690920SAxel Dörfler
9427b45b55bSIngo Weinhold // the partition must be initialized
9437b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
944*4644c7ccSJérôme Duval if (diskSystem == NULL)
9457b45b55bSIngo Weinhold return B_BAD_VALUE;
9467b45b55bSIngo Weinhold
9477b45b55bSIngo Weinhold // child must indeed be a child of partition
9487b45b55bSIngo Weinhold if (child->Parent() != partition)
9497b45b55bSIngo Weinhold return B_BAD_VALUE;
9507b45b55bSIngo Weinhold
9517b45b55bSIngo Weinhold // mark the partition busy and unlock
9527b45b55bSIngo Weinhold if (partition->IsBusy() || child->IsBusy())
9537b45b55bSIngo Weinhold return B_BUSY;
9547b45b55bSIngo Weinhold partition->SetBusy(true);
9557b45b55bSIngo Weinhold child->SetBusy(true);
9567b45b55bSIngo Weinhold locker.Unlock();
9577b45b55bSIngo Weinhold
9587b45b55bSIngo Weinhold // set the child type
9597b45b55bSIngo Weinhold error = diskSystem->SetType(child, type.value, DUMMY_JOB_ID);
9607b45b55bSIngo Weinhold
9617b45b55bSIngo Weinhold // re-lock and unmark busy
9627b45b55bSIngo Weinhold locker.Lock();
9637b45b55bSIngo Weinhold partition->SetBusy(false);
9647b45b55bSIngo Weinhold child->SetBusy(false);
9657b45b55bSIngo Weinhold
9667b45b55bSIngo Weinhold if (error != B_OK)
9677b45b55bSIngo Weinhold return error;
9687b45b55bSIngo Weinhold
9697b45b55bSIngo Weinhold // return change counters
970*4644c7ccSJérôme Duval error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
971*4644c7ccSJérôme Duval if (error == B_OK)
972*4644c7ccSJérôme Duval error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
9737b45b55bSIngo Weinhold return error;
9747b45b55bSIngo Weinhold }
9757b45b55bSIngo Weinhold
976d6e565c7SIngo Weinhold
9772d690920SAxel Dörfler status_t
_user_set_partition_parameters(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 * _childChangeCounter,const char * _parameters)9787b45b55bSIngo Weinhold _user_set_partition_parameters(partition_id partitionID, int32* _changeCounter,
979f75b8de3SAxel Dörfler partition_id childID, int32* _childChangeCounter, const char* _parameters)
9802d690920SAxel Dörfler {
9817b45b55bSIngo Weinhold // copy parameters in
982f75b8de3SAxel Dörfler UserStringParameter<true> parameters;
9837b45b55bSIngo Weinhold int32 changeCounter;
9847b45b55bSIngo Weinhold int32 childChangeCounter;
9857b45b55bSIngo Weinhold
986*4644c7ccSJérôme Duval status_t error
987*4644c7ccSJérôme Duval = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
988*4644c7ccSJérôme Duval if (error == B_OK)
989*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
990*4644c7ccSJérôme Duval if (error == B_OK)
991*4644c7ccSJérôme Duval error = copy_from_user_value(childChangeCounter, _childChangeCounter);
992*4644c7ccSJérôme Duval if (error != B_OK)
9937b45b55bSIngo Weinhold return error;
9947b45b55bSIngo Weinhold
9952d690920SAxel Dörfler // get the partition
9967b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
9972d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
998*4644c7ccSJérôme Duval if (partition == NULL)
9997b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
10007b45b55bSIngo Weinhold
10012d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
10022d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
10032d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
10047b45b55bSIngo Weinhold
10057b45b55bSIngo Weinhold // register child
10067b45b55bSIngo Weinhold KPartition* child = manager->RegisterPartition(childID);
1007*4644c7ccSJérôme Duval if (child == NULL)
10087b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
10097b45b55bSIngo Weinhold
10107b45b55bSIngo Weinhold PartitionRegistrar registrar3(child, true);
10117b45b55bSIngo Weinhold
10127b45b55bSIngo Weinhold // check change counters
10137b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter()
10147b45b55bSIngo Weinhold || childChangeCounter != child->ChangeCounter()) {
1015300868ceSIngo Weinhold return B_BAD_VALUE;
10162d690920SAxel Dörfler }
10172d690920SAxel Dörfler
10187b45b55bSIngo Weinhold // the partition must be initialized
10197b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
1020*4644c7ccSJérôme Duval if (diskSystem == NULL)
10217b45b55bSIngo Weinhold return B_BAD_VALUE;
10227b45b55bSIngo Weinhold
10237b45b55bSIngo Weinhold // child must indeed be a child of partition
10247b45b55bSIngo Weinhold if (child->Parent() != partition)
10257b45b55bSIngo Weinhold return B_BAD_VALUE;
10267b45b55bSIngo Weinhold
10277b45b55bSIngo Weinhold // mark the partition busy and unlock
10287b45b55bSIngo Weinhold if (partition->IsBusy() || child->IsBusy())
10297b45b55bSIngo Weinhold return B_BUSY;
10307b45b55bSIngo Weinhold partition->SetBusy(true);
10317b45b55bSIngo Weinhold child->SetBusy(true);
10327b45b55bSIngo Weinhold locker.Unlock();
10337b45b55bSIngo Weinhold
10347b45b55bSIngo Weinhold // set the child parameters
10357b45b55bSIngo Weinhold error = diskSystem->SetParameters(child, parameters.value, DUMMY_JOB_ID);
10367b45b55bSIngo Weinhold
10377b45b55bSIngo Weinhold // re-lock and unmark busy
10387b45b55bSIngo Weinhold locker.Lock();
10397b45b55bSIngo Weinhold partition->SetBusy(false);
10407b45b55bSIngo Weinhold child->SetBusy(false);
10417b45b55bSIngo Weinhold
10427b45b55bSIngo Weinhold if (error != B_OK)
10437b45b55bSIngo Weinhold return error;
10447b45b55bSIngo Weinhold
10457b45b55bSIngo Weinhold // return change counters
1046*4644c7ccSJérôme Duval error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
1047*4644c7ccSJérôme Duval if (error == B_OK)
1048*4644c7ccSJérôme Duval error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
10497b45b55bSIngo Weinhold return error;
10507b45b55bSIngo Weinhold }
10517b45b55bSIngo Weinhold
1052d6e565c7SIngo Weinhold
10532d690920SAxel Dörfler status_t
_user_set_partition_content_parameters(partition_id partitionID,int32 * _changeCounter,const char * _parameters)10542d690920SAxel Dörfler _user_set_partition_content_parameters(partition_id partitionID,
1055f75b8de3SAxel Dörfler int32* _changeCounter, const char* _parameters)
10562d690920SAxel Dörfler {
10577b45b55bSIngo Weinhold // copy parameters in
1058f75b8de3SAxel Dörfler UserStringParameter<true> parameters;
10597b45b55bSIngo Weinhold int32 changeCounter;
10607b45b55bSIngo Weinhold
1061f75b8de3SAxel Dörfler status_t error
1062f75b8de3SAxel Dörfler = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
1063*4644c7ccSJérôme Duval if (error == B_OK)
1064*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
1065*4644c7ccSJérôme Duval if (error != B_OK)
10667b45b55bSIngo Weinhold return error;
10677b45b55bSIngo Weinhold
10682d690920SAxel Dörfler // get the partition
10697b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
10702d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
1071*4644c7ccSJérôme Duval if (partition == NULL)
10727b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
10737b45b55bSIngo Weinhold
10742d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
10752d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
10762d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
10777b45b55bSIngo Weinhold
10787b45b55bSIngo Weinhold // check change counter
10797b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
1080300868ceSIngo Weinhold return B_BAD_VALUE;
10817b45b55bSIngo Weinhold
10827b45b55bSIngo Weinhold // the partition must be initialized
10837b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
1084*4644c7ccSJérôme Duval if (diskSystem == NULL)
10857b45b55bSIngo Weinhold return B_BAD_VALUE;
10867b45b55bSIngo Weinhold
10877b45b55bSIngo Weinhold // mark the partition busy and unlock
10887b45b55bSIngo Weinhold if (!partition->CheckAndMarkBusy(true))
10897b45b55bSIngo Weinhold return B_BUSY;
10907b45b55bSIngo Weinhold locker.Unlock();
10917b45b55bSIngo Weinhold
10927b45b55bSIngo Weinhold // set content parameters
10937b45b55bSIngo Weinhold error = diskSystem->SetContentParameters(partition, parameters.value,
10947b45b55bSIngo Weinhold DUMMY_JOB_ID);
10957b45b55bSIngo Weinhold
10967b45b55bSIngo Weinhold // re-lock and unmark busy
10977b45b55bSIngo Weinhold locker.Lock();
10987b45b55bSIngo Weinhold partition->UnmarkBusy(true);
10997b45b55bSIngo Weinhold
11007b45b55bSIngo Weinhold if (error != B_OK)
11017b45b55bSIngo Weinhold return error;
11027b45b55bSIngo Weinhold
11037b45b55bSIngo Weinhold // return change counter
1104*4644c7ccSJérôme Duval return copy_to_user_value(_changeCounter, partition->ChangeCounter());
11052d690920SAxel Dörfler }
11062d690920SAxel Dörfler
1107d6e565c7SIngo Weinhold
11082d690920SAxel Dörfler status_t
_user_initialize_partition(partition_id partitionID,int32 * _changeCounter,const char * _diskSystemName,const char * _name,const char * _parameters)11097b45b55bSIngo Weinhold _user_initialize_partition(partition_id partitionID, int32* _changeCounter,
1110f75b8de3SAxel Dörfler const char* _diskSystemName, const char* _name, const char* _parameters)
11112d690920SAxel Dörfler {
11127b45b55bSIngo Weinhold // copy parameters in
11137b45b55bSIngo Weinhold UserStringParameter<false> diskSystemName;
11147b45b55bSIngo Weinhold UserStringParameter<true> name;
1115f75b8de3SAxel Dörfler UserStringParameter<true> parameters;
11167b45b55bSIngo Weinhold int32 changeCounter;
1117aa4d8ee6SIngo Weinhold
1118*4644c7ccSJérôme Duval status_t error
1119*4644c7ccSJérôme Duval = diskSystemName.Init(_diskSystemName, B_DISK_SYSTEM_NAME_LENGTH);
1120*4644c7ccSJérôme Duval if (error == B_OK)
1121*4644c7ccSJérôme Duval error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
1122*4644c7ccSJérôme Duval if (error == B_OK)
1123*4644c7ccSJérôme Duval error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
1124*4644c7ccSJérôme Duval if (error == B_OK)
1125*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
1126*4644c7ccSJérôme Duval if (error != B_OK)
11272d690920SAxel Dörfler return error;
1128aa4d8ee6SIngo Weinhold
11292d690920SAxel Dörfler // get the partition
1130aa4d8ee6SIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
11312d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
1132*4644c7ccSJérôme Duval if (partition == NULL)
1133aa4d8ee6SIngo Weinhold return B_ENTRY_NOT_FOUND;
1134aa4d8ee6SIngo Weinhold
11352d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
11362d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
11372d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
1138aa4d8ee6SIngo Weinhold
11397b45b55bSIngo Weinhold // check change counter
11407b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
11417b45b55bSIngo Weinhold return B_BAD_VALUE;
11427b45b55bSIngo Weinhold
11437b45b55bSIngo Weinhold // the partition must be uninitialized
1144*4644c7ccSJérôme Duval if (partition->DiskSystem() != NULL)
11457b45b55bSIngo Weinhold return B_BAD_VALUE;
11467b45b55bSIngo Weinhold
11477b45b55bSIngo Weinhold // load the new disk system
1148c9830ce0SIngo Weinhold KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName.value,
1149c9830ce0SIngo Weinhold true);
1150*4644c7ccSJérôme Duval if (diskSystem == NULL)
1151aa4d8ee6SIngo Weinhold return B_ENTRY_NOT_FOUND;
11522d690920SAxel Dörfler DiskSystemLoader loader(diskSystem, true);
1153aa4d8ee6SIngo Weinhold
11547b45b55bSIngo Weinhold // mark the partition busy and unlock
11557b45b55bSIngo Weinhold if (!partition->CheckAndMarkBusy(true))
11567b45b55bSIngo Weinhold return B_BUSY;
11577b45b55bSIngo Weinhold locker.Unlock();
1158aa4d8ee6SIngo Weinhold
11597b45b55bSIngo Weinhold // let the disk system initialize the partition
11607b45b55bSIngo Weinhold error = diskSystem->Initialize(partition, name.value, parameters.value,
11617b45b55bSIngo Weinhold DUMMY_JOB_ID);
11627b45b55bSIngo Weinhold
11637b45b55bSIngo Weinhold // re-lock and unmark busy
11647b45b55bSIngo Weinhold locker.Lock();
11657b45b55bSIngo Weinhold partition->UnmarkBusy(true);
11667b45b55bSIngo Weinhold
1167aa4d8ee6SIngo Weinhold if (error != B_OK)
1168aa4d8ee6SIngo Weinhold return error;
1169aa4d8ee6SIngo Weinhold
1170f84387d6SIngo Weinhold // Set the disk system. Re-check whether a disk system is already set on the
1171f84387d6SIngo Weinhold // partition. Some disk systems just write the on-disk structures and let
1172f84387d6SIngo Weinhold // the DDM rescan the partition, in which case the disk system will already
1173f84387d6SIngo Weinhold // be set. In very unfortunate cases the on-disk structure of the previous
1174f84387d6SIngo Weinhold // disk system has not been destroyed and the previous disk system has a
1175f84387d6SIngo Weinhold // higher priority than the new one. The old disk system will thus prevail.
1176f84387d6SIngo Weinhold // Not setting the new disk system will at least prevent that the partition
1177f84387d6SIngo Weinhold // object gets into an inconsistent state.
1178f84387d6SIngo Weinhold if (partition->DiskSystem() == NULL)
1179aa4d8ee6SIngo Weinhold partition->SetDiskSystem(diskSystem);
1180aa4d8ee6SIngo Weinhold
11817b45b55bSIngo Weinhold // return change counter
1182*4644c7ccSJérôme Duval return copy_to_user_value(_changeCounter, partition->ChangeCounter());
11832d690920SAxel Dörfler }
11842d690920SAxel Dörfler
1185d6e565c7SIngo Weinhold
11862d690920SAxel Dörfler status_t
_user_uninitialize_partition(partition_id partitionID,int32 * _changeCounter,partition_id parentID,int32 * _parentChangeCounter)11874419d699SJessica Hamilton _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter,
11884419d699SJessica Hamilton partition_id parentID, int32* _parentChangeCounter)
11892d690920SAxel Dörfler {
11907b45b55bSIngo Weinhold // copy parameters in
11917b45b55bSIngo Weinhold int32 changeCounter;
11924419d699SJessica Hamilton int32 parentChangeCounter;
11934419d699SJessica Hamilton bool haveParent = parentID >= 0;
11947b45b55bSIngo Weinhold
1195*4644c7ccSJérôme Duval status_t error = copy_from_user_value(changeCounter, _changeCounter);
1196*4644c7ccSJérôme Duval if (haveParent && error == B_OK)
1197*4644c7ccSJérôme Duval error = copy_from_user_value(parentChangeCounter, _parentChangeCounter);
1198*4644c7ccSJérôme Duval if (error != B_OK)
11994419d699SJessica Hamilton return error;
12007b45b55bSIngo Weinhold
12012d690920SAxel Dörfler // get the partition
12027b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
12032d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
1204*4644c7ccSJérôme Duval if (partition == NULL)
12052d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
12067b45b55bSIngo Weinhold
12072d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
12082d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
12092d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
12107b45b55bSIngo Weinhold
12114419d699SJessica Hamilton // register parent
12124419d699SJessica Hamilton KPartition* parent = NULL;
12134419d699SJessica Hamilton if (haveParent)
12144419d699SJessica Hamilton parent = manager->RegisterPartition(parentID);
12154419d699SJessica Hamilton
12164419d699SJessica Hamilton PartitionRegistrar registrar3(parent, true);
12174419d699SJessica Hamilton
12187b45b55bSIngo Weinhold // check change counter
12197b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
1220300868ceSIngo Weinhold return B_BAD_VALUE;
12214419d699SJessica Hamilton if (haveParent && parentChangeCounter != parent->ChangeCounter())
12224419d699SJessica Hamilton return B_BAD_VALUE;
12237b45b55bSIngo Weinhold
12247b45b55bSIngo Weinhold // the partition must be initialized
1225*4644c7ccSJérôme Duval if (partition->DiskSystem() == NULL)
12267b45b55bSIngo Weinhold return B_BAD_VALUE;
12277b45b55bSIngo Weinhold
12287b45b55bSIngo Weinhold // check busy
1229b3a5629bSIngo Weinhold if (!partition->CheckAndMarkBusy(true))
12307b45b55bSIngo Weinhold return B_BUSY;
12317b45b55bSIngo Weinhold
12324ed39e6aSAdrien Destugues if (partition->IsMounted() || partition->IsChildMounted())
1233f26118f2SAdrien Destugues return B_BAD_VALUE;
12347b45b55bSIngo Weinhold
1235285f4cf4SIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
1236285f4cf4SIngo Weinhold
1237285f4cf4SIngo Weinhold locker.Unlock();
1238285f4cf4SIngo Weinhold
1239285f4cf4SIngo Weinhold // Let the disk system uninitialize the partition. This operation is not
1240285f4cf4SIngo Weinhold // mandatory. If implemented, it will destroy the on-disk structures, so
1241285f4cf4SIngo Weinhold // that the disk system cannot accidentally identify the partition later on.
1242285f4cf4SIngo Weinhold if (diskSystem != NULL)
1243285f4cf4SIngo Weinhold diskSystem->Uninitialize(partition, DUMMY_JOB_ID);
1244285f4cf4SIngo Weinhold
1245285f4cf4SIngo Weinhold // re-lock and uninitialize the partition object
1246285f4cf4SIngo Weinhold locker.Lock();
12477b45b55bSIngo Weinhold error = partition->UninitializeContents(true);
12480cbc783bSAxel Dörfler
12490cbc783bSAxel Dörfler partition->UnmarkBusy(true);
12500cbc783bSAxel Dörfler
12517b45b55bSIngo Weinhold if (error != B_OK)
12527b45b55bSIngo Weinhold return error;
12537b45b55bSIngo Weinhold
12547b45b55bSIngo Weinhold // return change counter
12557b45b55bSIngo Weinhold error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
1256*4644c7ccSJérôme Duval if (haveParent && error == B_OK)
1257*4644c7ccSJérôme Duval error = copy_to_user_value(_parentChangeCounter, parent->ChangeCounter());
12587b45b55bSIngo Weinhold return error;
12592d690920SAxel Dörfler }
12602d690920SAxel Dörfler
1261d6e565c7SIngo Weinhold
12622d690920SAxel Dörfler status_t
_user_create_child_partition(partition_id partitionID,int32 * _changeCounter,off_t offset,off_t size,const char * _type,const char * _name,const char * _parameters,partition_id * childID,int32 * childChangeCounter)12637b45b55bSIngo Weinhold _user_create_child_partition(partition_id partitionID, int32* _changeCounter,
12647b45b55bSIngo Weinhold off_t offset, off_t size, const char* _type, const char* _name,
1265f75b8de3SAxel Dörfler const char* _parameters, partition_id* childID, int32* childChangeCounter)
12662d690920SAxel Dörfler {
12677b45b55bSIngo Weinhold // copy parameters in
12687b45b55bSIngo Weinhold UserStringParameter<false> type;
12697b45b55bSIngo Weinhold UserStringParameter<true> name;
1270f75b8de3SAxel Dörfler UserStringParameter<true> parameters;
12717b45b55bSIngo Weinhold int32 changeCounter;
12727b45b55bSIngo Weinhold
1273*4644c7ccSJérôme Duval status_t error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH);
1274*4644c7ccSJérôme Duval if (error == B_OK)
1275*4644c7ccSJérôme Duval error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
1276*4644c7ccSJérôme Duval if (error == B_OK)
1277*4644c7ccSJérôme Duval error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
1278*4644c7ccSJérôme Duval if (error == B_OK)
1279*4644c7ccSJérôme Duval error = copy_from_user_value(changeCounter, _changeCounter);
1280*4644c7ccSJérôme Duval if (error != B_OK)
12812d690920SAxel Dörfler return error;
12827b45b55bSIngo Weinhold
12832d690920SAxel Dörfler // get the partition
12847b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
12852d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
1286*4644c7ccSJérôme Duval if (partition == NULL)
12877b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
12887b45b55bSIngo Weinhold
12892d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
12902d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
12912d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
12927b45b55bSIngo Weinhold
12937b45b55bSIngo Weinhold // check change counter
12947b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter())
12957b45b55bSIngo Weinhold return B_BAD_VALUE;
12967b45b55bSIngo Weinhold
12977b45b55bSIngo Weinhold // the partition must be initialized
12987b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
1299*4644c7ccSJérôme Duval if (diskSystem == NULL)
13007b45b55bSIngo Weinhold return B_BAD_VALUE;
13017b45b55bSIngo Weinhold
13027b45b55bSIngo Weinhold // mark the partition busy and unlock
13037b45b55bSIngo Weinhold if (!partition->CheckAndMarkBusy(false))
13047b45b55bSIngo Weinhold return B_BUSY;
13057b45b55bSIngo Weinhold locker.Unlock();
13067b45b55bSIngo Weinhold
13072d690920SAxel Dörfler // create the child
13082d690920SAxel Dörfler KPartition *child = NULL;
13097b45b55bSIngo Weinhold error = diskSystem->CreateChild(partition, offset, size, type.value,
13107b45b55bSIngo Weinhold name.value, parameters.value, DUMMY_JOB_ID, &child, -1);
13117b45b55bSIngo Weinhold
13127b45b55bSIngo Weinhold // re-lock and unmark busy
13137b45b55bSIngo Weinhold locker.Lock();
13147b45b55bSIngo Weinhold partition->UnmarkBusy(false);
13157b45b55bSIngo Weinhold
13167b45b55bSIngo Weinhold if (error != B_OK)
13172d690920SAxel Dörfler return error;
13187b45b55bSIngo Weinhold
13197b45b55bSIngo Weinhold if (child == NULL)
13207b45b55bSIngo Weinhold return B_ERROR;
13217b45b55bSIngo Weinhold
13227b45b55bSIngo Weinhold child->UnmarkBusy(true);
13237b45b55bSIngo Weinhold
13247b45b55bSIngo Weinhold // return change counter and child ID
1325*4644c7ccSJérôme Duval error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
1326*4644c7ccSJérôme Duval if (error == B_OK)
1327*4644c7ccSJérôme Duval error = copy_to_user_value(childID, child->ID());
13287b45b55bSIngo Weinhold return error;
13297b45b55bSIngo Weinhold }
13307b45b55bSIngo Weinhold
1331d6e565c7SIngo Weinhold
13322d690920SAxel Dörfler status_t
_user_delete_child_partition(partition_id partitionID,int32 * _changeCounter,partition_id childID,int32 childChangeCounter)13337b45b55bSIngo Weinhold _user_delete_child_partition(partition_id partitionID, int32* _changeCounter,
1334300868ceSIngo Weinhold partition_id childID, int32 childChangeCounter)
13352d690920SAxel Dörfler {
13367b45b55bSIngo Weinhold // copy parameters in
13377b45b55bSIngo Weinhold int32 changeCounter;
13387b45b55bSIngo Weinhold
13397b45b55bSIngo Weinhold status_t error;
13407b45b55bSIngo Weinhold if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK)
13417b45b55bSIngo Weinhold return error;
13427b45b55bSIngo Weinhold
13432d690920SAxel Dörfler // get the partition
13447b45b55bSIngo Weinhold KDiskDeviceManager* manager = KDiskDeviceManager::Default();
13452d690920SAxel Dörfler KPartition* partition = manager->WriteLockPartition(partitionID);
1346*4644c7ccSJérôme Duval if (partition == NULL)
13472d690920SAxel Dörfler return B_ENTRY_NOT_FOUND;
13487b45b55bSIngo Weinhold
13492d690920SAxel Dörfler PartitionRegistrar registrar1(partition, true);
13502d690920SAxel Dörfler PartitionRegistrar registrar2(partition->Device(), true);
13512d690920SAxel Dörfler DeviceWriteLocker locker(partition->Device(), true);
13527b45b55bSIngo Weinhold
13537b45b55bSIngo Weinhold // register child
13547b45b55bSIngo Weinhold KPartition* child = manager->RegisterPartition(childID);
1355*4644c7ccSJérôme Duval if (child == NULL)
13567b45b55bSIngo Weinhold return B_ENTRY_NOT_FOUND;
13577b45b55bSIngo Weinhold
13587b45b55bSIngo Weinhold PartitionRegistrar registrar3(child, true);
13597b45b55bSIngo Weinhold
13607b45b55bSIngo Weinhold // check change counters
13617b45b55bSIngo Weinhold if (changeCounter != partition->ChangeCounter()
13627b45b55bSIngo Weinhold || childChangeCounter != child->ChangeCounter()) {
13637b45b55bSIngo Weinhold return B_BAD_VALUE;
13647b45b55bSIngo Weinhold }
13657b45b55bSIngo Weinhold
13667b45b55bSIngo Weinhold // the partition must be initialized
13677b45b55bSIngo Weinhold KDiskSystem* diskSystem = partition->DiskSystem();
1368*4644c7ccSJérôme Duval if (diskSystem == NULL)
13697b45b55bSIngo Weinhold return B_BAD_VALUE;
13707b45b55bSIngo Weinhold
13717b45b55bSIngo Weinhold // child must indeed be a child of partition
13727b45b55bSIngo Weinhold if (child->Parent() != partition)
13737b45b55bSIngo Weinhold return B_BAD_VALUE;
13747b45b55bSIngo Weinhold
13757b45b55bSIngo Weinhold // mark the partition and child busy and unlock
13767b45b55bSIngo Weinhold if (partition->IsBusy() || !child->CheckAndMarkBusy(true))
13777b45b55bSIngo Weinhold return B_BUSY;
13787b45b55bSIngo Weinhold partition->SetBusy(true);
13797b45b55bSIngo Weinhold locker.Unlock();
13807b45b55bSIngo Weinhold
13817b45b55bSIngo Weinhold // delete the child
13827b45b55bSIngo Weinhold error = diskSystem->DeleteChild(child, DUMMY_JOB_ID);
13837b45b55bSIngo Weinhold
13847b45b55bSIngo Weinhold // re-lock and unmark busy
13857b45b55bSIngo Weinhold locker.Lock();
13867b45b55bSIngo Weinhold partition->SetBusy(false);
13877b45b55bSIngo Weinhold child->UnmarkBusy(true);
13887b45b55bSIngo Weinhold
13892d690920SAxel Dörfler if (error != B_OK)
13902d690920SAxel Dörfler return error;
13917b45b55bSIngo Weinhold
13927b45b55bSIngo Weinhold // return change counter
139349fb53eeSAxel Dörfler return copy_to_user_value(_changeCounter, partition->ChangeCounter());
13942d690920SAxel Dörfler }
13953f78b216SAxel Dörfler
13963f78b216SAxel Dörfler
13973f78b216SAxel Dörfler status_t
_user_start_watching_disks(uint32 eventMask,port_id port,int32 token)13983f78b216SAxel Dörfler _user_start_watching_disks(uint32 eventMask, port_id port, int32 token)
13993f78b216SAxel Dörfler {
14003f78b216SAxel Dörfler KDiskDeviceManager* manager = KDiskDeviceManager::Default();
14013f78b216SAxel Dörfler return manager->Notifications().UpdateUserListener(eventMask, port, token);
14023f78b216SAxel Dörfler }
14033f78b216SAxel Dörfler
14043f78b216SAxel Dörfler
14053f78b216SAxel Dörfler status_t
_user_stop_watching_disks(port_id port,int32 token)14063f78b216SAxel Dörfler _user_stop_watching_disks(port_id port, int32 token)
14073f78b216SAxel Dörfler {
14083f78b216SAxel Dörfler KDiskDeviceManager* manager = KDiskDeviceManager::Default();
14093f78b216SAxel Dörfler return manager->Notifications().RemoveUserListeners(port, token);
14103f78b216SAxel Dörfler }
14113f78b216SAxel Dörfler
1412