partition_id
_user_find_file_disk_device(const char *_filename, size_t *neededSize)
{
	UserStringParameter<false> filename;
	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
	if (error != B_OK)
		return error;

	KPath path(filename, KPath::NORMALIZE);

	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	// find the device
	KFileDiskDevice* device = manager->RegisterFileDevice(path.Path());
	if (device == NULL)
		return B_ENTRY_NOT_FOUND;
	PartitionRegistrar _(device, true);
	partition_id id = device->ID();
	if (neededSize != NULL) {
		if (DeviceReadLocker locker = device) {
			// get the needed size
			UserDataWriter writer;
			device->WriteUserData(writer);
			error = copy_to_user_value(neededSize, writer.AllocatedSize());
			if (error != B_OK)
				return error;
		} else
			return B_ERROR;
	}
	return id;
}
status_t
_user_get_file_disk_device_path(partition_id id, char* buffer,
	size_t bufferSize)
{
	if (id < 0 || buffer == NULL || bufferSize == 0)
		return B_BAD_VALUE;
	if (!IS_USER_ADDRESS(buffer))
		return B_BAD_ADDRESS;

	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	KDiskDevice *device = manager->RegisterDevice(id, true);
	if (device != NULL) {
		PartitionRegistrar _(device, true);
		if (DeviceReadLocker locker = device) {
			KFileDiskDevice* fileDevice
				= dynamic_cast<KFileDiskDevice*>(device);
			if (fileDevice == NULL)
				return B_BAD_VALUE;

			ssize_t copied = user_strlcpy(buffer, fileDevice->FilePath(),
				bufferSize);
			if (copied < 0)
				return copied;
			return (size_t)copied < bufferSize ? B_OK : B_BUFFER_OVERFLOW;
		}
	}

	return B_ERROR;
}
partition_id
_user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize)
{
	int32 cookie;
	status_t error = copy_from_user_value(cookie, _cookie);
	if (error != B_OK)
		return error;

	partition_id id = B_ENTRY_NOT_FOUND;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	// get the next device
	if (KDiskDevice *device = manager->RegisterNextDevice(&cookie)) {
		PartitionRegistrar _(device, true);
		id = device->ID();
		if (neededSize != NULL) {
			if (DeviceReadLocker locker = device) {
				// get the needed size
				UserDataWriter writer;
				device->WriteUserData(writer);
				status_t status = copy_to_user_value(neededSize,
					writer.AllocatedSize());
				if (status != B_OK)
					return status;
			} else
				id = B_ERROR;
		}
	}

	error = copy_to_user_value(_cookie, cookie);
	if (error != B_OK)
		return error;
	return id;
}
status_t
_user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
{
	if (_info == NULL)
		return B_BAD_VALUE;
	if (!IS_USER_ADDRESS(_info))
		return B_BAD_ADDRESS;
	int32 cookie;
	status_t result = copy_from_user_value(cookie, _cookie);
	if (result != B_OK)
		return result;
	result = B_ENTRY_NOT_FOUND;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie);
		if (diskSystem != NULL) {
			user_disk_system_info info;
			diskSystem->GetInfo(&info);
			result = copy_to_user_value(_info, info);
		}
	}
	status_t error = copy_to_user_value(_cookie, cookie);
	if (error != B_OK)
		result = error;
	return result;
}
partition_id
_user_find_partition(const char *_filename, size_t *neededSize)
{
	UserStringParameter<false> filename;
	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
	if (error != B_OK)
		return error;

	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	// find the partition
	KPartition *partition = manager->RegisterPartition(filename);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;
	PartitionRegistrar _(partition, true);
	partition_id id = partition->ID();
	if (neededSize != NULL) {
		// get and lock the partition's device
		KDiskDevice *device = manager->RegisterDevice(partition->ID(), false);
		if (device == NULL)
			return B_ENTRY_NOT_FOUND;
		PartitionRegistrar _2(device, true);
		if (DeviceReadLocker locker = device) {
			// get the needed size
			UserDataWriter writer;
			device->WriteUserData(writer);
			error = copy_to_user_value(neededSize, writer.AllocatedSize());
			if (error != B_OK)
				return error;
		} else
			return B_ERROR;
	}
	return id;
}
Example #6
0
status_t
_user_set_partition_content_parameters(partition_id partitionID,
	int32* _changeCounter, const char* _parameters)
{
	// copy parameters in
	UserStringParameter<true> parameters;
	int32 changeCounter;

	status_t error
		= parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
	if (error != B_OK || (error = copy_from_user_value(changeCounter,
			_changeCounter)) != B_OK) {
		return error;
	}

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (!partition)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// check change counter
	if (changeCounter != partition->ChangeCounter())
		return B_BAD_VALUE;

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (!diskSystem)
		return B_BAD_VALUE;

	// mark the partition busy and unlock
	if (!partition->CheckAndMarkBusy(true))
		return B_BUSY;
	locker.Unlock();

	// set content parameters
	error = diskSystem->SetContentParameters(partition, parameters.value,
		DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->UnmarkBusy(true);

	if (error != B_OK)
		return error;

	// return change counter
	if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter()))
			!= B_OK) {
		return error;
	}

	return B_OK;
}
Example #7
0
status_t
_user_repair_partition(partition_id partitionID, int32* _changeCounter,
	bool checkOnly)
{
	// copy parameters in
	int32 changeCounter;

	status_t error;
	if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (!partition)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// check change counter
	if (changeCounter != partition->ChangeCounter())
		return B_BAD_VALUE;

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (!diskSystem)
		return B_BAD_VALUE;

	// mark the partition busy and unlock
	if (!partition->CheckAndMarkBusy(false))
		return B_BUSY;
	locker.Unlock();

	// repair/check
	error = diskSystem->Repair(partition, checkOnly, DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->UnmarkBusy(false);

	if (error != B_OK)
		return error;

	// return change counter
	if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter()))
			!= B_OK) {
		return error;
	}

	return B_OK;
}
/*!	\brief Writes data describing the disk device identified by ID and all
		   its partitions into the supplied buffer.

	The function passes the buffer size required to hold the data back
	through the \a _neededSize parameter, if the device could be found at
	least and no serious error occured. If fails with \c B_BUFFER_OVERFLOW,
	if the supplied buffer is too small or a \c NULL buffer is supplied
	(and \c bufferSize is 0).

	The device is identified by \a id. If \a deviceOnly is \c true, then
	it must be the ID of a disk device, otherwise the disk device is
	chosen, on which the partition \a id refers to resides.

	\param id The ID of an arbitrary partition on the disk device (including
		   the disk device itself), whose data shall be returned
		   (if \a deviceOnly is \c false), or the ID of the disk device
		   itself (if \a deviceOnly is true).
	\param deviceOnly Specifies whether only IDs of disk devices (\c true),
		   or also IDs of partitions (\c false) are accepted for \a id.
	\param buffer The buffer into which the disk device data shall be written.
		   May be \c NULL.
	\param bufferSize The size of \a buffer.
	\param _neededSize Pointer to a variable into which the actually needed
		   buffer size is written. May be \c NULL.
	\return
	- \c B_OK: Everything went fine. The device was found and, if not \c NULL,
	  in \a _neededSize the actually needed buffer size is returned. And
	  \a buffer will contain the disk device data.
	- \c B_BAD_VALUE: \c NULL \a buffer, but not 0 \a bufferSize.
	- \c B_BUFFER_OVERFLOW: The supplied buffer was too small. \a _neededSize,
	  if not \c NULL, will contain the required buffer size.
	- \c B_NO_MEMORY: Insufficient memory to complete the operation.
	- \c B_ENTRY_NOT_FOUND: \a id is no valid disk device ID (if \a deviceOnly
	  is \c true) or not even a valid partition ID (if \a deviceOnly is
	  \c false).
	- \c B_ERROR: An unexpected error occured.
	- another error code...
*/
status_t
_user_get_disk_device_data(partition_id id, bool deviceOnly,
	user_disk_device_data *buffer, size_t bufferSize, size_t *_neededSize)
{
	if (buffer == NULL && bufferSize > 0)
		return B_BAD_VALUE;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	// get the device
	KDiskDevice *device = manager->RegisterDevice(id, deviceOnly);
	if (device == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar _(device, true);
	if (DeviceReadLocker locker = device) {
		// do a dry run first to get the needed size
		UserDataWriter writer;
		device->WriteUserData(writer);
		size_t neededSize = writer.AllocatedSize();
		if (_neededSize != NULL) {
			status_t error = copy_ref_var_to_user(neededSize, _neededSize);
			if (error != B_OK)
				return error;
		}
		// if no buffer has been supplied or the buffer is too small,
		// then we're done
		if (buffer == NULL || bufferSize < neededSize)
			return B_BUFFER_OVERFLOW;
		if (!IS_USER_ADDRESS(buffer))
			return B_BAD_ADDRESS;
		// otherwise allocate a kernel buffer
		user_disk_device_data *kernelBuffer
			= static_cast<user_disk_device_data*>(malloc(neededSize));
		if (kernelBuffer == NULL)
			return B_NO_MEMORY;
		MemoryDeleter deleter(kernelBuffer);
		// write the device data into the buffer
		writer.SetTo(kernelBuffer, bufferSize);
		device->WriteUserData(writer);
		// sanity check
		if (writer.AllocatedSize() != neededSize) {
			ERROR(("Size of written disk device user data changed from "
				   "%lu to %lu while device was locked!\n"));
			return B_ERROR;
		}
		// relocate
		status_t error = writer.Relocate(buffer);
		if (error != B_OK)
			return error;
		// copy out
		return user_memcpy(buffer, kernelBuffer, neededSize);
	} else
		return B_ERROR;
}
status_t
_user_set_partition_content_name(partition_id partitionID,
	int32* _changeCounter, const char* _name)
{
	// copy parameters in
	UserStringParameter<true> name;
	int32 changeCounter;

	status_t error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
	if (error == B_OK)
		error = copy_from_user_value(changeCounter, _changeCounter);
	if (error != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// check change counter
	if (changeCounter != partition->ChangeCounter())
		return B_BAD_VALUE;

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (diskSystem == NULL)
		return B_BAD_VALUE;

	// mark the partition busy and unlock
	if (!partition->CheckAndMarkBusy(false))
		return B_BUSY;
	locker.Unlock();

	// set content parameters
	error = diskSystem->SetContentName(partition, name.value, DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->UnmarkBusy(false);

	if (error != B_OK)
		return error;

	// return change counter
	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
}
Example #10
0
status_t
_user_unregister_file_device(partition_id deviceID, const char *_filename)
{
	if (deviceID < 0 && _filename == NULL)
		return B_BAD_VALUE;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (deviceID >= 0)
		return manager->DeleteFileDevice(deviceID);

	UserStringParameter<false> filename;
	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
	if (error != B_OK)
		return error;

	return manager->DeleteFileDevice(filename);
}
Example #11
0
status_t
_user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
{
	if (_info == NULL)
		return B_BAD_VALUE;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		KDiskSystem *diskSystem = manager->FindDiskSystem(id);
		if (diskSystem != NULL) {
			user_disk_system_info info;
			diskSystem->GetInfo(&info);
			return copy_to_user_value(_info, info);
		}
	}
	return B_ENTRY_NOT_FOUND;
}
Example #12
0
status_t
_user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
{
	if (!_info)
		return B_BAD_VALUE;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		if (KDiskSystem *diskSystem = manager->FindDiskSystem(id)) {
			user_disk_system_info info;
			diskSystem->GetInfo(&info);
			user_memcpy(_info, &info, sizeof(info));
			return B_OK;
		}
	}
	return B_ENTRY_NOT_FOUND;
}
Example #13
0
partition_id
_user_register_file_device(const char *_filename)
{
	UserStringParameter<false> filename;
	status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH);
	if (error != B_OK)
		return error;

	KPath path(filename, true);

	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		if (KFileDiskDevice *device = manager->FindFileDevice(path.Path()))
			return device->ID();
		return manager->CreateFileDevice(path.Path());
	}
	return B_ERROR;
}
Example #14
0
status_t
_user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
{
	if (!_cookie || !_info)
		return B_BAD_VALUE;
	int32 cookie;
	user_memcpy(&cookie, _cookie, sizeof(cookie));
	status_t result = B_ENTRY_NOT_FOUND;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		if (KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie)) {
			user_disk_system_info info;
			diskSystem->GetInfo(&info);
			user_memcpy(_info, &info, sizeof(info));
			result = B_OK;
		}
	}
	user_memcpy(_cookie, &cookie, sizeof(cookie));
	return result;
}
Example #15
0
status_t
_user_find_disk_system(const char *_name, user_disk_system_info *_info)
{
	if (!_name || !_info)
		return B_BAD_VALUE;
	char name[B_DISK_SYSTEM_NAME_LENGTH];
	status_t error = ddm_strlcpy(name, _name, B_DISK_SYSTEM_NAME_LENGTH);
	if (error)
		return error;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		if (KDiskSystem *diskSystem = manager->FindDiskSystem(name)) {
			user_disk_system_info info;
			diskSystem->GetInfo(&info);
			user_memcpy(_info, &info, sizeof(info));
			return B_OK;
		}
	}
	return B_ENTRY_NOT_FOUND;
}
Example #16
0
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)
{
#if 0
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	// get the partition
	KPartition *partition = manager->WriteLockPartition(partitionID);
	if (!partition)
		return B_ENTRY_NOT_FOUND;
	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);
	// check the new offset
	if (newOffset == partition->Offset())
		return B_OK;
	off_t proposedOffset = newOffset;
	status_t error = validate_move_partition(partition, changeCounter,
		&proposedOffset, true);
	if (error != B_OK)
		return error;
	if (proposedOffset != newOffset)
		return B_BAD_VALUE;
	// new offset is fine -- move the thing
	off_t moveBy = newOffset - partition->Offset();
	move_descendants(partition, moveBy);
	partition->Changed(B_PARTITION_CHANGED_OFFSET);
	// implicit partitioning system changes
	error = partition->Parent()->DiskSystem()->ShadowPartitionChanged(
		partition->Parent(), partition, B_PARTITION_MOVE_CHILD);
	if (error != B_OK)
		return error;
	// implicit descendants' content disk system changes
	return move_descendants_contents(partition);
#endif
return B_BAD_VALUE;
}
Example #17
0
status_t
_user_find_disk_system(const char *_name, user_disk_system_info *_info)
{
	if (_name == NULL || _info == NULL)
		return B_BAD_VALUE;
	if (!IS_USER_ADDRESS(_name) || !IS_USER_ADDRESS(_info))
		return B_BAD_ADDRESS;
	char name[B_DISK_SYSTEM_NAME_LENGTH];
	status_t error = ddm_strlcpy(name, _name, B_DISK_SYSTEM_NAME_LENGTH);
	if (error != B_OK)
		return error;
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	if (ManagerLocker locker = manager) {
		KDiskSystem *diskSystem = manager->FindDiskSystem(name);
		if (diskSystem != NULL) {
			user_disk_system_info info;
			diskSystem->GetInfo(&info);
			return copy_to_user_value(_info, info);
		}
	}
	return B_ENTRY_NOT_FOUND;
}
Example #18
0
status_t
_user_set_partition_parameters(partition_id partitionID, int32* _changeCounter,
	partition_id childID, int32* _childChangeCounter, const char* _parameters)
{
	// copy parameters in
	UserStringParameter<true> parameters;
	int32 changeCounter;
	int32 childChangeCounter;

	status_t error
		= parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
	if (error == B_OK)
		error = copy_from_user_value(changeCounter, _changeCounter);
	if (error == B_OK)
		error = copy_from_user_value(childChangeCounter, _childChangeCounter);
	if (error != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// register child
	KPartition* child = manager->RegisterPartition(childID);
	if (child == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar3(child, true);

	// check change counters
	if (changeCounter != partition->ChangeCounter()
		|| childChangeCounter != child->ChangeCounter()) {
		return B_BAD_VALUE;
	}

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (diskSystem == NULL)
		return B_BAD_VALUE;

	// child must indeed be a child of partition
	if (child->Parent() != partition)
		return B_BAD_VALUE;

	// mark the partition busy and unlock
	if (partition->IsBusy() || child->IsBusy())
		return B_BUSY;
	partition->SetBusy(true);
	child->SetBusy(true);
	locker.Unlock();

	// set the child parameters
	error = diskSystem->SetParameters(child, parameters.value, DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->SetBusy(false);
	child->SetBusy(false);

	if (error != B_OK)
		return error;

	// return change counters
	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
	if (error == B_OK)
		error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
	return error;
}
Example #19
0
status_t
_user_uninitialize_partition(partition_id partitionID, int32* _changeCounter,
	partition_id parentID, int32* _parentChangeCounter)
{
	// copy parameters in
	int32 changeCounter;
	int32 parentChangeCounter;
	bool haveParent = parentID >= 0;

	status_t error = copy_from_user_value(changeCounter, _changeCounter);
	if (haveParent && error == B_OK)
		error = copy_from_user_value(parentChangeCounter, _parentChangeCounter);
	if (error != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// register parent
	KPartition* parent = NULL;
	if (haveParent)
		parent = manager->RegisterPartition(parentID);

	PartitionRegistrar registrar3(parent, true);

	// check change counter
	if (changeCounter != partition->ChangeCounter())
		return B_BAD_VALUE;
	if (haveParent && parentChangeCounter != parent->ChangeCounter())
		return B_BAD_VALUE;

	// the partition must be initialized
	if (partition->DiskSystem() == NULL)
		return B_BAD_VALUE;

	// check busy
	if (!partition->CheckAndMarkBusy(true))
		return B_BUSY;

	if (partition->IsMounted() || partition->IsChildMounted())
		return B_BAD_VALUE;

	KDiskSystem* diskSystem = partition->DiskSystem();

	locker.Unlock();

	// Let the disk system uninitialize the partition. This operation is not
	// mandatory. If implemented, it will destroy the on-disk structures, so
	// that the disk system cannot accidentally identify the partition later on.
	if (diskSystem != NULL)
		diskSystem->Uninitialize(partition, DUMMY_JOB_ID);

	// re-lock and uninitialize the partition object
	locker.Lock();
	error = partition->UninitializeContents(true);

	partition->UnmarkBusy(true);

	if (error != B_OK)
		return error;

	// return change counter
	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
	if (haveParent && error == B_OK)
		error = copy_to_user_value(_parentChangeCounter, parent->ChangeCounter());
	return error;
}
Example #20
0
status_t
_user_resize_partition(partition_id partitionID, int32* _changeCounter,
	partition_id childID, int32* _childChangeCounter, off_t size,
	off_t contentSize)
{
	// copy parameters in
	int32 changeCounter;
	int32 childChangeCounter;

	status_t error = copy_from_user_value(changeCounter, _changeCounter);
	if (error == B_OK)
		error = copy_from_user_value(childChangeCounter, _childChangeCounter);
	if (error != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// register child
	KPartition* child = manager->RegisterPartition(childID);
	if (child == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar3(child, true);

	// check change counters
	if (changeCounter != partition->ChangeCounter()
		|| childChangeCounter != child->ChangeCounter()) {
		return B_BAD_VALUE;
	}

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (diskSystem == NULL)
		return B_BAD_VALUE;

	// child must indeed be a child of partition
	if (child->Parent() != partition)
		return B_BAD_VALUE;

	// check sizes
	if (size < 0 || contentSize < 0 || size < contentSize
		|| size > partition->ContentSize()) {
		return B_BAD_VALUE;
	}

	// mark the partitions busy and unlock
	if (partition->IsBusy() || child->IsBusy())
		return B_BUSY;
	partition->SetBusy(true);
	child->SetBusy(true);
	locker.Unlock();

	// resize contents first, if shrinking
	if (child->DiskSystem() && contentSize < child->ContentSize())
		error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID);

	// resize the partition
	if (error == B_OK && size != child->Size())
		error = diskSystem->ResizeChild(child, size, DUMMY_JOB_ID);

	// resize contents last, if growing
	if (error == B_OK && child->DiskSystem()
		&& contentSize > child->ContentSize()) {
		error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID);
	}

	// re-lock and unmark busy
	locker.Lock();
	partition->SetBusy(false);
	child->SetBusy(false);

	if (error != B_OK)
		return error;

	// return change counters
	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
	if (error == B_OK)
		error = copy_to_user_value(_childChangeCounter, child->ChangeCounter());
	return error;
}
Example #21
0
status_t
_user_initialize_partition(partition_id partitionID, int32* _changeCounter,
	const char* _diskSystemName, const char* _name, const char* _parameters)
{
	// copy parameters in
	UserStringParameter<false> diskSystemName;
	UserStringParameter<true> name;
	UserStringParameter<true> parameters;
	int32 changeCounter;

	status_t error
		= diskSystemName.Init(_diskSystemName, B_DISK_SYSTEM_NAME_LENGTH);
	if (error == B_OK)
		error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
	if (error == B_OK)
		error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
	if (error == B_OK)
		error = copy_from_user_value(changeCounter, _changeCounter);
	if (error != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// check change counter
	if (changeCounter != partition->ChangeCounter())
		return B_BAD_VALUE;

	// the partition must be uninitialized
	if (partition->DiskSystem() != NULL)
		return B_BAD_VALUE;

	// load the new disk system
	KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName.value,
		true);
	if (diskSystem == NULL)
		return B_ENTRY_NOT_FOUND;
	DiskSystemLoader loader(diskSystem, true);

	// mark the partition busy and unlock
	if (!partition->CheckAndMarkBusy(true))
		return B_BUSY;
	locker.Unlock();

	// let the disk system initialize the partition
	error = diskSystem->Initialize(partition, name.value, parameters.value,
		DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->UnmarkBusy(true);

	if (error != B_OK)
		return error;

	// Set the disk system. Re-check whether a disk system is already set on the
	// partition. Some disk systems just write the on-disk structures and let
	// the DDM rescan the partition, in which case the disk system will already
	// be set. In very unfortunate cases the on-disk structure of the previous
	// disk system has not been destroyed and the previous disk system has a
	// higher priority than the new one. The old disk system will thus prevail.
	// Not setting the new disk system will at least prevent that the partition
	// object gets into an inconsistent state.
	if (partition->DiskSystem() == NULL)
		partition->SetDiskSystem(diskSystem);

	// return change counter
	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
}
Example #22
0
/*!	Make the boot partition (and probably others) available.
	The partitions that are a boot candidate a put into the /a partitions
	stack. If the user selected a boot device, there is will only be one
	entry in this stack; if not, the most likely is put up first.
	The boot code should then just try them one by one.
*/
static status_t
get_boot_partitions(kernel_args* args, PartitionStack& partitions)
{
	const KMessage& bootVolume = args->boot_volume;

	dprintf("get_boot_partitions(): boot volume message:\n");
	bootVolume.Dump(&dprintf);

	// create boot method
	int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT);
	dprintf("get_boot_partitions(): boot method type: %ld\n", bootMethodType);

	BootMethod* bootMethod = NULL;
	switch (bootMethodType) {
		case BOOT_METHOD_NET:
			bootMethod = new(nothrow) NetBootMethod(bootVolume, bootMethodType);
			break;

		case BOOT_METHOD_HARD_DISK:
		case BOOT_METHOD_CD:
		default:
			bootMethod = new(nothrow) DiskBootMethod(bootVolume,
				bootMethodType);
			break;
	}

	status_t status = bootMethod != NULL ? bootMethod->Init() : B_NO_MEMORY;
	if (status != B_OK)
		return status;

	KDiskDeviceManager::CreateDefault();
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();

	status = manager->InitialDeviceScan();
	if (status != B_OK) {
		dprintf("KDiskDeviceManager::InitialDeviceScan() failed: %s\n",
			strerror(status));
		return status;
	}

	if (1 /* dump devices and partitions */) {
		KDiskDevice *device;
		int32 cookie = 0;
		while ((device = manager->NextDevice(&cookie)) != NULL) {
			device->Dump(true, 0);
		}
	}

	struct BootPartitionVisitor : KPartitionVisitor {
		BootPartitionVisitor(BootMethod* bootMethod, PartitionStack &stack)
			: fPartitions(stack),
			  fBootMethod(bootMethod)
		{
		}

		virtual bool VisitPre(KPartition *partition)
		{
			if (!partition->ContainsFileSystem())
				return false;

			bool foundForSure = false;
			if (fBootMethod->IsBootPartition(partition, foundForSure))
				fPartitions.Push(partition);

			// if found for sure, we can terminate the search
			return foundForSure;
		}

		private:
			PartitionStack	&fPartitions;
			BootMethod*		fBootMethod;
	} visitor(bootMethod, partitions);

	bool strict = true;

	while (true) {
		KDiskDevice *device;
		int32 cookie = 0;
		while ((device = manager->NextDevice(&cookie)) != NULL) {
			if (!bootMethod->IsBootDevice(device, strict))
				continue;

			if (device->VisitEachDescendant(&visitor) != NULL)
				break;
		}

		if (!partitions.IsEmpty() || !strict)
			break;

		// we couldn't find any potential boot devices, try again less strict
		strict = false;
	}

	// sort partition list (e.g.. when booting from CD, CDs should come first in
	// the list)
	if (!args->boot_volume.GetBool(BOOT_VOLUME_USER_SELECTED, false))
		bootMethod->SortPartitions(partitions.Array(), partitions.CountItems());

	return B_OK;
}
Example #23
0
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)
{
	// copy parameters in
	UserStringParameter<false> type;
	UserStringParameter<true> name;
	UserStringParameter<true> parameters;
	int32 changeCounter;

	status_t error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH);
	if (error == B_OK)
		error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH);
	if (error == B_OK)
		error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE);
	if (error == B_OK)
		error = copy_from_user_value(changeCounter, _changeCounter);
	if (error != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// check change counter
	if (changeCounter != partition->ChangeCounter())
		return B_BAD_VALUE;

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (diskSystem == NULL)
		return B_BAD_VALUE;

	// mark the partition busy and unlock
	if (!partition->CheckAndMarkBusy(false))
		return B_BUSY;
	locker.Unlock();

	// create the child
	KPartition *child = NULL;
	error = diskSystem->CreateChild(partition, offset, size, type.value,
		name.value, parameters.value, DUMMY_JOB_ID, &child, -1);

	// re-lock and unmark busy
	locker.Lock();
	partition->UnmarkBusy(false);

	if (error != B_OK)
		return error;

	if (child == NULL)
		return B_ERROR;

	child->UnmarkBusy(true);

	// return change counter and child ID
	error = copy_to_user_value(_changeCounter, partition->ChangeCounter());
	if (error == B_OK)
		error = copy_to_user_value(childID, child->ID());
	return error;
}
Example #24
0
status_t
_user_stop_watching_disks(port_id port, int32 token)
{
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	return manager->Notifications().RemoveUserListeners(port, token);
}
Example #25
0
status_t
_user_start_watching_disks(uint32 eventMask, port_id port, int32 token)
{
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	return manager->Notifications().UpdateUserListener(eventMask, port, token);
}
Example #26
0
status_t
_user_delete_child_partition(partition_id partitionID, int32* _changeCounter,
	partition_id childID, int32 childChangeCounter)
{
	// copy parameters in
	int32 changeCounter;

	status_t error;
	if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK)
		return error;

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (partition == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// register child
	KPartition* child = manager->RegisterPartition(childID);
	if (child == NULL)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar3(child, true);

	// check change counters
	if (changeCounter != partition->ChangeCounter()
		|| childChangeCounter != child->ChangeCounter()) {
		return B_BAD_VALUE;
	}

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (diskSystem == NULL)
		return B_BAD_VALUE;

	// child must indeed be a child of partition
	if (child->Parent() != partition)
		return B_BAD_VALUE;

	// mark the partition and child busy and unlock
	if (partition->IsBusy() || !child->CheckAndMarkBusy(true))
		return B_BUSY;
	partition->SetBusy(true);
	locker.Unlock();

	// delete the child
	error = diskSystem->DeleteChild(child, DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->SetBusy(false);
	child->UnmarkBusy(true);

	if (error != B_OK)
		return error;

	// return change counter
	return copy_to_user_value(_changeCounter, partition->ChangeCounter());
}
Example #27
0
void
vfs_mount_boot_file_system(kernel_args* args)
{
	PartitionStack partitions;
	status_t status = get_boot_partitions(args, partitions);
	if (status < B_OK) {
		panic("get_boot_partitions failed!");
	}
	if (partitions.IsEmpty()) {
		panic("did not find any boot partitions!");
	}

	KPartition* bootPartition;
	while (partitions.Pop(&bootPartition)) {
		KPath path;
		if (bootPartition->GetPath(&path) != B_OK)
			panic("could not get boot device!\n");

		const char* fsName = NULL;
		bool readOnly = false;
		if (strcmp(bootPartition->ContentType(), "ISO9660 File System") == 0) {
			fsName = "iso9660:write_overlay:attribute_overlay";
			readOnly = true;
		} else if (bootPartition->IsReadOnly()
			&& strcmp(bootPartition->ContentType(), "Be File System") == 0) {
			fsName = "bfs:write_overlay";
			readOnly = true;
		}

		TRACE(("trying to mount boot partition: %s\n", path.Path()));
		gBootDevice = _kern_mount("/boot", path.Path(), fsName, 0, NULL, 0);
		if (gBootDevice >= B_OK) {
			gReadOnlyBootDevice = readOnly;
			break;
		}
	}

	if (gBootDevice < B_OK)
		panic("could not mount boot device!\n");

	// create link for the name of the boot device

	fs_info info;
	if (_kern_read_fs_info(gBootDevice, &info) == B_OK) {
		char path[B_FILE_NAME_LENGTH + 1];
		snprintf(path, sizeof(path), "/%s", info.volume_name);

		_kern_create_symlink(-1, path, "/boot", 0);
	}

	// Do post-boot-volume module initialization. The module code wants to know
	// whether the module images the boot loader has pre-loaded are the same as
	// on the boot volume. That is the case when booting from hard disk or CD,
	// but not via network.
	int32 bootMethodType = args->boot_volume.GetInt32(BOOT_METHOD,
		BOOT_METHOD_DEFAULT);
	bool bootingFromBootLoaderVolume = bootMethodType == BOOT_METHOD_HARD_DISK
		|| bootMethodType == BOOT_METHOD_CD;
	module_init_post_boot_device(bootingFromBootLoaderVolume);

	file_cache_init_post_boot_device();

	// search for other disk systems
	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
	manager->RescanDiskSystems();
	manager->StartMonitoring();
}
Example #28
0
status_t
_user_set_partition_name(partition_id partitionID, int32* _changeCounter,
	partition_id childID, int32* _childChangeCounter, const char* _name)
{
	// copy parameters in
	UserStringParameter<false> name;
	int32 changeCounter;
	int32 childChangeCounter;

	status_t error;
	if ((error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH)) != B_OK
		|| (error = copy_from_user_value(changeCounter, _changeCounter))
			!= B_OK
		|| (error = copy_from_user_value(childChangeCounter,
			_childChangeCounter)) != B_OK) {
		return error;
	}

	// get the partition
	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
	KPartition* partition = manager->WriteLockPartition(partitionID);
	if (!partition)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar1(partition, true);
	PartitionRegistrar registrar2(partition->Device(), true);
	DeviceWriteLocker locker(partition->Device(), true);

	// register child
	KPartition* child = manager->RegisterPartition(childID);
	if (!child)
		return B_ENTRY_NOT_FOUND;

	PartitionRegistrar registrar3(child, true);

	// check change counters
	if (changeCounter != partition->ChangeCounter()
		|| childChangeCounter != child->ChangeCounter()) {
		return B_BAD_VALUE;
	}

	// the partition must be initialized
	KDiskSystem* diskSystem = partition->DiskSystem();
	if (!diskSystem)
		return B_BAD_VALUE;

	// child must indeed be a child of partition
	if (child->Parent() != partition)
		return B_BAD_VALUE;

	// mark the partitions busy and unlock
	if (partition->IsBusy() || child->IsBusy())
		return B_BUSY;
	partition->SetBusy(true);
	child->SetBusy(true);
	locker.Unlock();

	// set the child name
	error = diskSystem->SetName(child, name.value, DUMMY_JOB_ID);

	// re-lock and unmark busy
	locker.Lock();
	partition->SetBusy(false);
	child->SetBusy(false);

	if (error != B_OK)
		return error;

	// return change counters
	if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter()))
			!= B_OK
		|| (error = copy_to_user_value(_childChangeCounter,
			child->ChangeCounter())) != B_OK) {
		return error;
	}

	return B_OK;
}