-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Userland: Add the losetup utility to manage loop devices
The new utility implements an option to create a new loop device based on path of source image, as well as an option to delete an existing device.
- Loading branch information
1 parent
2c73149
commit eac9b76
Showing
2 changed files
with
88 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
## Name | ||
|
||
losetup - manage loop devices | ||
|
||
## Synopsis | ||
|
||
```**sh | ||
$ losetup [options...] [path] | ||
``` | ||
|
||
## Description | ||
|
||
losetup is a utility for managing loop devices. It can create new devices or delete | ||
existing ones. | ||
|
||
## Options | ||
|
||
* `-d`, `--delete`: Remove an existing loop device based on the `path` argument. | ||
* `-c`, `--create`: Create a new loop device based on the `path` argument. | ||
|
||
## Files | ||
|
||
* `/dev/devctl` - device control device inode, which allows creating and deleting loop devices. | ||
|
||
## Examples | ||
|
||
```sh | ||
$ losetup -c test.img | ||
Created new device at /dev/loop/0 | ||
$ losetup -d /dev/loop/0 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright (c) 2024, Liav A. <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include <AK/String.h> | ||
#include <AK/StringUtils.h> | ||
#include <AK/StringView.h> | ||
#include <LibCore/ArgsParser.h> | ||
#include <LibCore/File.h> | ||
#include <LibCore/System.h> | ||
#include <LibMain/Main.h> | ||
|
||
ErrorOr<int> serenity_main(Main::Arguments arguments) | ||
{ | ||
TRY(Core::System::pledge("stdio rpath wpath")); | ||
StringView path; | ||
bool flag_delete_device = false; | ||
bool flag_add_new_device = false; | ||
|
||
Core::ArgsParser args_parser; | ||
args_parser.set_general_help("Manage loop devices."); | ||
args_parser.add_option(flag_delete_device, "Delete a loop device", "delete", 'd'); | ||
args_parser.add_option(flag_add_new_device, "Add new device", "create", 'c'); | ||
args_parser.add_positional_argument(path, "Path", "path", Core::ArgsParser::Required::No); | ||
args_parser.parse(arguments); | ||
|
||
if (!(flag_delete_device || flag_add_new_device)) | ||
return Error::from_string_literal("No specified option was requested."); | ||
|
||
if (path.is_null()) | ||
return Error::from_string_literal("No specified path to handle."); | ||
|
||
auto devctl_device = TRY(Core::File::open("/dev/devctl"sv, Core::File::OpenMode::Read)); | ||
if (flag_delete_device) { | ||
constexpr StringView base_dev_loop_path = "/dev/loop/"sv; | ||
if (!path.starts_with(base_dev_loop_path)) | ||
return Error::from_string_literal("Invalid loop device path."); | ||
auto number = path.substring_view(base_dev_loop_path.length()); | ||
auto possible_number = number.to_number<u64>(); | ||
if (!possible_number.has_value()) | ||
return Error::from_string_literal("Invalid loop device number."); | ||
auto loop_device_index = possible_number.release_value(); | ||
TRY(Core::System::ioctl(devctl_device->fd(), DEVCTL_DESTROY_LOOP_DEVICE, &loop_device_index)); | ||
return 0; | ||
} | ||
|
||
VERIFY(flag_add_new_device); | ||
auto value = TRY(Core::System::open(path, O_RDWR)); | ||
TRY(Core::System::ioctl(devctl_device->fd(), DEVCTL_CREATE_LOOP_DEVICE, &value)); | ||
int loop_device_index = value; | ||
|
||
auto loop_device_path = TRY(String::formatted("/dev/loop/{}", loop_device_index)); | ||
outln("Created new device at {}", loop_device_path); | ||
return 0; | ||
} |