-
Notifications
You must be signed in to change notification settings - Fork 47
add mount utility #504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rodolfo-gatti
wants to merge
6
commits into
uutils:main
Choose a base branch
from
rodolfo-gatti:feat/mount
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
add mount utility #504
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
247f688
mount: add mount utility
rodolfo-gatti 312c200
Compile the mount crate on non-Linux platforms by cfg-gating
rodolfo-gatti de95d96
Gate the remaining Linux/Unix-only mount helpers so the workspace
rodolfo-gatti b0dc27b
Move the Linux-specific mount pieces behind Linux-only
rodolfo-gatti 83c04a8
Move escape_octal to mtab module
rodolfo-gatti 4f93b62
Add missing license headers
rodolfo-gatti File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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
This file contains hidden or 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,17 @@ | ||
| [package] | ||
| name = "uu_mount" | ||
| version = "0.0.1" | ||
| edition = "2021" | ||
|
|
||
| [lib] | ||
| path = "src/mount.rs" | ||
|
|
||
| [[bin]] | ||
| name = "mount" | ||
| path = "src/main.rs" | ||
|
|
||
| [dependencies] | ||
| clap = { workspace = true } | ||
| libc = { workspace = true } | ||
| thiserror = { workspace = true } | ||
| uucore = { workspace = true } |
This file contains hidden or 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,109 @@ | ||
| # mount | ||
|
|
||
| ``` | ||
| mount [options] | ||
| mount [options] <source> <directory> | ||
| mount [options] <source> | <directory> | ||
| mount [options] --source <source> [--target <directory>] | ||
| mount [options] [--source <source>] --target <directory> | ||
| mount [options] --make-{shared,slave,private,unbindable} <mountpoint> | ||
| mount [options] --make-{rshared,rslave,rprivate,runbindable} <mountpoint> | ||
| ``` | ||
|
|
||
| Mount a filesystem, or show all currently mounted filesystems. | ||
|
|
||
| When called without arguments, or with `-t` but no source and target, mount | ||
| prints all currently mounted filesystems (read from `/proc/mounts` on Linux). | ||
| The `-t` option filters the listing to entries of the given type. `-l` requests | ||
| labels in listing output when they can be discovered from `/dev/disk/by-label`. | ||
|
|
||
| When called with a source device and a target directory, mount attaches the | ||
| filesystem found on the source to the target directory. | ||
|
|
||
| When called with a single positional argument, mount resolves that argument via | ||
| `/etc/fstab`. The argument may be either a source specifier or a mount point. | ||
| `--source` and `--target` can be used to disambiguate that lookup. | ||
|
|
||
| When called with `--make-*`, mount applies mount-propagation changes to the | ||
| specified mountpoint. If a normal mount is also requested in the same command, | ||
| the propagation changes are applied after the mount succeeds. | ||
|
|
||
| ## Supported contract | ||
|
|
||
| This implementation currently targets **Linux** and is intended to provide a | ||
| strong baseline `mount` with the core operational semantics in place: | ||
|
|
||
| - no-argument listing from `/proc/mounts` | ||
| - direct mounts plus `--bind`, `--rbind`, and `--move` | ||
| - `--all` with already-mounted skipping, `-t` filtering, `-O` filtering, and | ||
| optional `--fork` | ||
| - `/etc/fstab`-driven single-argument resolution, including alternate files via | ||
| `-T` | ||
| - label/UUID/PARTLABEL/PARTUUID resolution | ||
| - merged `fstab` + CLI `-o` options for fstab-derived mounts | ||
| - optional mountpoint creation via `-m` | ||
| - propagation changes via `--make-*` | ||
|
|
||
| This command is **not yet a full upstream-compatible replacement** for every | ||
| advanced `mount(8)` feature. The supported behavior is intentionally explicit so | ||
| reviewers can evaluate the current contract clearly. | ||
|
|
||
| ## Options | ||
|
|
||
| - `-a`, `--all` — mount all filesystems listed in `/etc/fstab` (respects `noauto` | ||
| and `-t` / `-O` filters) | ||
| - `-B`, `--bind` — bind-mount a subtree at another location (`MS_BIND`) | ||
| - `-R`, `--rbind` — recursively bind-mount a subtree (`MS_BIND | MS_REC`) | ||
| - `-M`, `--move` — atomically move a mounted subtree to a new location | ||
| (`MS_MOVE`) | ||
| - `--make-shared` — mark a subtree as shared | ||
| - `--make-slave` — mark a subtree as slave | ||
| - `--make-private` — mark a subtree as private | ||
| - `--make-unbindable` — mark a subtree as unbindable | ||
| - `--make-rshared` — recursively mark a whole subtree as shared | ||
| - `--make-rslave` — recursively mark a whole subtree as slave | ||
| - `--make-rprivate` — recursively mark a whole subtree as private | ||
| - `--make-runbindable` — recursively mark a whole subtree as unbindable | ||
| - `-f`, `--fake` — dry run; parse arguments and resolve devices but skip the | ||
| actual `mount(2)` syscall | ||
| - `-F`, `--fork` — with `--all`, mount matching filesystems in separate worker | ||
| processes | ||
| - `-T`, `--fstab PATH` — use an alternate fstab file instead of `/etc/fstab` | ||
| - `-l`, `--show-labels` — show filesystem labels in listing output when | ||
| available | ||
| - `-m`, `--mkdir` — create the target mountpoint if it does not already exist | ||
| - `-n`, `--no-mtab` — do not write an entry to `/etc/mtab` | ||
| - `-o`, `--options LIST` — comma-separated list of mount options (e.g. | ||
| `ro,noatime,uid=1000`); for `/etc/fstab`-resolved mounts, CLI options are | ||
| appended after `fstab` options so later values win | ||
| - `-O`, `--test-opts LIST` — with `--all`, limit mounts to fstab entries whose | ||
| option field matches `LIST` | ||
| - `-r`, `--read-only` — mount read-only (same as `-o ro`) | ||
| - `-w`, `--read-write` — mount read-write, overriding a `ro` option from fstab | ||
| - `-t`, `--types LIST` — filesystem type filter; prefix a type with `no` to | ||
| exclude it (e.g. `-t noext4`) | ||
| - `-v`, `--verbose` — print a diagnostic line for each mount operation | ||
| - `-L`, `--label LABEL` — mount the device with the given filesystem label | ||
| - `-U`, `--uuid UUID` — mount the device with the given filesystem UUID | ||
| - `--partlabel LABEL` — mount the partition with the given partition label | ||
| (`PARTLABEL=`) | ||
| - `--partuuid UUID` — mount the partition with the given partition UUID | ||
| (`PARTUUID=`) | ||
| - `--source SOURCE` — explicitly specify the source side of the mount or the | ||
| single-argument fstab lookup key | ||
| - `--target DIRECTORY` — explicitly specify the target side of the mount or the | ||
| single-argument fstab lookup key | ||
|
|
||
| ## Notes | ||
|
|
||
| - `--make-*` propagation operations are not combined with `--all`. | ||
| - Propagation changes do not read `/etc/fstab`; provide the target mountpoint | ||
| explicitly when using them directly. | ||
|
|
||
| ## Deferred features | ||
|
|
||
| Notable items that remain outside the current supported contract include: | ||
|
|
||
| - alternate `--options-mode` handling beyond the current append-style merge | ||
| - helper-specific behaviors outside this in-process Linux implementation | ||
| - additional advanced `mount(8)` compatibility options not yet implemented |
This file contains hidden or 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,66 @@ | ||
| // This file is part of the uutils util-linux package. | ||
| // | ||
| // For the full copyright and license information, please view the LICENSE | ||
| // file that was distributed with this source code. | ||
|
|
||
| use thiserror::Error; | ||
| use uucore::error::UError; | ||
|
|
||
| pub const EXIT_MOUNT_FAILED: i32 = 32; | ||
|
|
||
| #[derive(Error, Debug)] | ||
| pub enum MountError { | ||
| #[error("cannot open /proc/mounts: {0}")] | ||
| ProcMounts(std::io::Error), | ||
|
|
||
| #[error("cannot read {0}: {1}")] | ||
| FstabRead(String, std::io::Error), | ||
|
|
||
| #[error("I/O error: {0}")] | ||
| Fstab(#[from] std::io::Error), | ||
|
|
||
| #[error("cannot find device with label {0:?}")] | ||
| LabelNotFound(String), | ||
|
|
||
| #[error("cannot find device with UUID {0:?}")] | ||
| UuidNotFound(String), | ||
|
|
||
| #[error("cannot find mount entry for {0:?} in fstab")] | ||
| FstabEntryNotFound(String), | ||
|
|
||
| #[error("no mount point specified and none found in fstab for {0}")] | ||
| NoMountPoint(String), | ||
|
|
||
| #[error("cannot create mount point {0}: {1}")] | ||
| CreateMountPoint(String, std::io::Error), | ||
|
|
||
| #[error("cannot fork mount worker: {0}")] | ||
| Fork(std::io::Error), | ||
|
|
||
| #[error("cannot wait for mount worker: {0}")] | ||
| Wait(std::io::Error), | ||
|
|
||
| #[error("invalid source path: {0}")] | ||
| InvalidSource(std::ffi::NulError), | ||
|
|
||
| #[error("invalid target path: {0}")] | ||
| InvalidTarget(std::ffi::NulError), | ||
|
|
||
| #[error("invalid filesystem type: {0}")] | ||
| InvalidFSType(std::ffi::NulError), | ||
|
|
||
| #[error("invalid mount options: {0}")] | ||
| InvalidOptions(std::ffi::NulError), | ||
|
|
||
| #[error("mount: {1} on {2}: {0}")] | ||
| MountFailed(std::io::Error, String, String), | ||
| } | ||
|
|
||
| impl UError for MountError { | ||
| fn code(&self) -> i32 { | ||
| match self { | ||
| MountError::MountFailed(_, _, _) => EXIT_MOUNT_FAILED, | ||
| _ => 1, | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or 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,32 @@ | ||
| // This file is part of the uutils util-linux package. | ||
| // | ||
| // For the full copyright and license information, please view the LICENSE | ||
| // file that was distributed with this source code. | ||
|
|
||
| /// Expand octal escape sequences of the form `\NNN` used in mount-table style | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| /// files to encode whitespace and other special characters. | ||
| pub(crate) fn unescape_octal(s: &str) -> String { | ||
| let mut result: Vec<u8> = Vec::with_capacity(s.len()); | ||
| let bytes = s.as_bytes(); | ||
| let mut i = 0; | ||
| while i < bytes.len() { | ||
| if bytes[i] == b'\\' && i + 3 < bytes.len() { | ||
| let (a, b, c) = (bytes[i + 1], bytes[i + 2], bytes[i + 3]); | ||
| if a.is_ascii_digit() | ||
| && a < b'8' | ||
| && b.is_ascii_digit() | ||
| && b < b'8' | ||
| && c.is_ascii_digit() | ||
| && c < b'8' | ||
| { | ||
| let value = (a - b'0') * 64 + (b - b'0') * 8 + (c - b'0'); | ||
| result.push(value); | ||
| i += 4; | ||
| continue; | ||
| } | ||
| } | ||
| result.push(bytes[i]); | ||
| i += 1; | ||
| } | ||
| String::from_utf8_lossy(&result).into_owned() | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add the license header