1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
|
## `libpathrs` Binding-Agnostic Test Binary API ##
In order to allow us to test the full functionality of the `libpathrs` bindings
in a uniform way, we need have some kind of binary-agnostic API that the tests
can use so we can test the same functionality for all bindings easily.
This is accomplished by implementing a test binary for each binding that
implements a fairly simple CLI interface that tests can be written against.
The basic usage of the tool looks like this:
```
pathrs-cmd <operation> <operation args...>
```
The following operations are all part of the API used by our tests in
[`e2e-tests/tests`](../tests). Any change in this API should result in changes
in the test suite.
#### Error Output ####
Each section below describes the `pathrs-cmd` output in successful cases, but
if an operation fails the output will be consistent:
```
ERRNO <errno code> (<errno string>)
ERROR-DESCRIPTION <error message>
```
Note that `<errno string>` can have different formatting based on the language,
so tests should only ever test against the numerical `<errno code>`. Tests
against `<error message>` are acceptable but should be used carefully as such
tests could be brittle.
### `Root` Operations ###
All of the following operations are subcommands of the `root` subcommand.
#### `resolve` ####
```
pathrs-cmd root --root <root>
resolve [--[no-]follow] [--reopen=<oflags>] <subpath>
```
Calls `Root::resolve` (or `Root::resolve_nofollow`) with the given `subpath`
argument.
* `--no-follow` indicates to use `Root::resolve_nofollow` (i.e., do not follow
trailing symlinks) rather than `Root::resolve`. The default is `--follow`.
* `--reopen` indicates that we should re-open the handle with the given set of
`O_*` flags.
##### Output #####
```
HANDLE-PATH <full path of resolved handle>
FILE-PATH <full path of reopened file from handle>
```
**TODO**: We currently do not do an I/O for the re-opened file.
#### `open` ####
```
pathrs-cmd root --root <root>
open [--[no-]follow] [--oflags=<oflags=O_RDONLY>] <subpath>
```
Calls `Root::open_subpath` with the given `subpath` argument.
* `--oflags` is the set of `O_*` flags to use when opening the subpath.
* `--no-follow` is equivalent to `--oflags O_NOFOLLOW`. The default is
`--follow`.
<!--
* `--no-follow` is generally equivalent to `--oflags O_NOFOLLOW` but some
bindings might switch between using `Root::open` and `Root::open_follow`
directly based on this flag instead. In general, bindings that have a
distinction should treat `--[no-]follow` as calling different APIs, while
`--oflags` should only affect the set of `O_*` flags passed.
-->
##### Output #####
```
FILE-PATH <full path of opened file>
```
**TODO**: We currently do not do an I/O for the opened file.
#### `mkfile` ####
```
pathrs-cmd root --root <root>
mkfile [--oflags=<oflags=O_RDONLY>] [--mode <mode=0o644>] <subpath>
```
Calls `Root::create_file` with the given `subpath` argument. This is
effectively a safe `O_CREAT|O_EXCL|O_NOFOLLOW`.
* `--oflags` is the set of `O_*` flags to use when creating the file.
(`O_CREAT` is not required and is actually an invalid argument.)
* `--mode` is the mode of the created file (umask still applies).
##### Output #####
```
FILE-PATH <full path of opened file>
```
**TODO**: We currently do not do an I/O for the newly-created file.
#### `mkdir` ####
```
pathrs-cmd root --root <root>
mkdir [--mode <mode=0o755>] <subpath>
```
Calls `pathrs_inroot_mkdir` (`Root::create(InodeType::Directory)`) with the
given `subpath` argument.
* `--mode` is the mode of the created directory (umask still applies).
#### `mkdir-all` ####
```
pathrs-cmd root --root <root>
mkdir-all [--mode <mode=0o755>] <subpath>
```
Calls `Root::mkdir_all` with the given `subpath` argument.
* `--mode` is the mode of the created directories (umask still applies).
Existing directories do not have their modes changed.
##### Output #####
```
HANDLE-PATH <full path of deepest created directory>
```
#### `mknod` ####
```
pathrs-cmd root --root <root>
mknod [--mode <mode=0o644>] <subpath> <type> [<major=0> <minor=0>]
```
Calls `Root::create` with various inode types with the given `subpath`
argument, loosely effectively equivalent to `mknod(1)`.
* `--mode` is the mode of the created inode (umask still applies).
* `type` is the inode type to create, and must be one of the following values:
- `f`: regular **f**ile
- `d`: **d**irectory
- `b`: **b**lock device (`major:minor`)
- `c` (or `u`): **c**character device (`major:minor`)
- `p`: named **p**ipe (aka FIFO)
* `major` and `minor` only have effect for `b` and `c`/`u` but `pathrs-cmd`
will pass the device value to all calls if they are specified.
#### `hardlink` ####
```
pathrs-cmd root --root <root> hardlink <target> <linkname>
```
Calls `Root::create(InodeType::Hardlink)` with the given `subpath` argument.
Both `target` and `linkname` are resolved inside the root.
* `target` is an existing path that will be the target of the new hardlink.
* `linkname` is the path to where the new hardlink will be placed.
Note that the argument order is the same as `ln(1)`!
#### `symlink` ####
```
pathrs-cmd root --root <root> symlink <target> <linkname>
```
Calls `Root::create(InodeType::Symlink)` with the given `subpath` argument.
* `target` is an arbitrary string that will be the content of the symlink.
* `linkname` is the path to where the new symlink will be placed.
Note that the argument order is the same as `ln(1)`!
#### `readlink` ####
```
pathrs-cmd root --root <root> readlink <subpath>
```
Calls `Root::readlink` with the given `subpath` argument.
##### Output #####
```
LINK-TARGET <link target>
```
#### `rmdir` ####
```
pathrs-cmd root --root <root> rmdir <subpath>
```
Calls `Root::remove_dir` with the given `subpath` argument. (`subpath` needs to
be an empty directory.)
#### `unlink` ####
```
pathrs-cmd root --root <root> unlink <subpath>
```
Calls `Root::remove_file` with the given `subpath` argument. (`subpath` needs
to be a non-directory.)
#### `remove-all` ####
```
pathrs-cmd root --root <root> remove-all <subpath>
```
Calls `Root::remove_all` with the given `subpath` argument.
#### `rename` ####
```
pathrs-cmd root --root <root>
rename [--whiteout] [--exchange] [--[no-]clobber]
<source> <destination>
```
Calls `Root::rename` with the given `source` and `destination` arguments.
* `--whiteout` indicates that the `RENAME_WHITEOUT` flag should be set.
* `--exchange` indicates that the `RENAME_EXCHANGE` flag should be set.
* `--no-clobber` indicates the the `RENAME_NOREPLACE` flag should be set.
Some of these flag combinations are not permitted by Linux, however
`pathrs-cmd` allows any combination to be provided and for libpathrs to return
an error if appropriate.
### `ProcfsHandle` Operations ###
All of the following operations are subcommands of the `procfs` subcommand. All
procfs commands take the following arguments:
* `--unmasked` indicates whether to use `ProcfsHandleBuilder::unmasked()` when
configuring the `ProcfsHandle`. At the moment there isn't really a way to
determine that this is not a no-op in our tests, but we may expand this
capability in the future (such as by looking at `mnt_id` after successive
calls).
* `--base` indicates what `ProcfsBase` to use, and must be one of the
following values:
- `root`: `ProcfsBase::ProcRoot`
- `self`: `ProcfsBase::ProcSelf`
- `thread-self`: `ProcfsBase::ProcThreadSelf`
- `pid=$n`: `ProcfsBase::ProcPid($n)` (`$n` is an integer)
The default is `--base root`.
**TODO**: We should probably expose `ProcfsHandleRef::try_from_fd`.
#### `open` ####
```
pathrs-cmd procfs [--unmasked] [--base <base>]
open [--[no-]follow] [--oflags <oflags=O_RDONLY>] <subpath>`
```
Calls `ProcfsHandle::open` (or `ProcfsHandle::open_follow`) with the given
`subpath` argument.
* `--oflags` is the set of `O_*` flags to use when opening the subpath.
* `--no-follow` is generally equivalent to `--oflags O_NOFOLLOW` but some
bindings might switch between using `ProcfsHandle::open` and
`ProcfsHandle::open_follow` directly based on this flag instead. In general,
bindings that have a distinction should treat `--[no-]follow` as calling
different APIs, while `--oflags` should only affect the set of `O_*` flags
passed. (libpathrs treats both equivalently, but for test purposes we keep
this distinction to make sure that libpathrs bindings also treat these
equivalently.) The default is `--follow`.
##### Output #####
```
FILE-PATH <full path of opened file>
```
**TODO**: We currently do not do an I/O for the opened file.
#### `readlink` ####
```
pathrs-cmd procfs [--unmasked] [--base <base>]
readlink <subpath>`
```
Calls `ProcfsHandle::readlink` with the given `subpath` argument.
##### Output #####
```
LINK-TARGET <link target>
```
|