blob: a9e3615b4d261e16ee6387cc694c760a4a031e8c [file] [log] [blame] [view]
# package-directory compatibility tests
The tests in this directory are meant to compare the [pkgfs] and
[package-directory] package directory implementations against each other to
ensure compatibility where possible and note the differences where they diverge
intentionally.
[old]: https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/pkgfs/pkgfs/
[new]: https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/lib/package-directory/
Once pkgfs is deleted, these tests can be simplified and act as integration
tests of the package API surface.
## Intentional behavior differences
Because it's not practical to get the new behavior exactly identical, there will
be some behavior differences. The tests should call this out by making some
assertion logic conditional on `PackageSource::is_pkgfs()` or
`PackageSource::is_pkgdir()`. Any time this is done, it should link to a bug
blocking https://fxbug.dev/83755 or mention an entry in the following list:
### Hierarchical rights enforcement
package-directory implements hierarchical rights (because [vfs] does), and will
reject `Open()` calls which request rights which exceed the rights on the parent
connection.
[vfs]: https://cs.opensource.google/fuchsia/fuchsia/+/main:src/lib/storage/vfs/rust/
### `OPEN_RIGHT_WRITABLE` not supported
package-directory categorically rejects opening packages with
`OPEN_RIGHT_WRITABLE` in the first place, as packages are immutable.
pkgfs generally rejects `OPEN_FLAG_WRITABLE`, but accepts it when opening the
root directory of a package.
### `OPEN_FLAG_CREATE` not supported
package-directory rejects opens with `OPEN_FLAG_CREATE` as packages are
immutable and so file creation is not supported.
pkgfs mostly also rejects this flag, but happens to accept it when re-opening
the package directory for some reason.
### `OPEN_FLAG_CREATE_IF_ABSENT` without `OPEN_FLAG_CREATE`
vfs (and therefore package-directory)
[rejects opens with `OPEN_FLAG_CREATE_IF_ABSENT` but not `OPEN_FLAG_CREATE`], as
that flag doesn't makes sense on its own.
In combination with "`OPEN_FLAG_CREATE` not supported", this means that
package-directory never allows `OPEN_FLAG_CREATE_IF_ABSENT`.
pkgfs is perfectly happy to accept `OPEN_FLAG_CREATE_IF_ABSENT` on its own
(although it does not actually let one create a file).
[rejects opens with `OPEN_FLAG_CREATE_IF_ABSENT` but not `OPEN_FLAG_CREATE`]: https://cs.opensource.google/fuchsia/fuchsia/+/main:src/lib/storage/vfs/rust/src/directory/common.rs;l=111-114;drc=84109901831eb08168fe3d2c3f9bcdc1844fd564
### `OPEN_FLAG_TRUNCATE` and `OPEN_FLAG_APPEND` not supported
package-directory rejects opens with `OPEN_FLAG_TRUNCATE` or `OPEN_FLAG_APPEND`
as those are only applicable to writing files and packages are immutable.
pkgfs mostly also rejects this flag, but happens to accept it when re-opening
the package directory for some reason.
### `OPEN_FLAG_DIRECTORY` enforced
package-directory rejects opening a file with `OPEN_FLAG_DIRECTORY`.
Additionally, it interprets paths with a trailing "/" as if they had set
`OPEN_FLAG_DIRECTORY` and prevents opening files with paths that contain a
trailing "/", [as per directory.fidl][trailing slash rule].
pkgfs rejects `OPEN_FLAG_DIRECTORY` when opening content files too, but does not
reject opening files in `meta/` with `OPEN_FLAG_DIRECTORY`. Additionally, it
allows opening files via paths with a trailing "/".
### `OPEN_FLAG_NOT_DIRECTORY` enforced
package-directory rejects opening a directory with `OPEN_FLAG_NOT_DIRECTORY`.
pkgfs ignores `OPEN_FLAG_NOT_DIRECTORY` and therefore allows opening files with
the flag.
### Rights enforced for write operations
package-directory enforces hierarchical rights on write operation attempts, and
therefore returns `BAD_HANDLE` so that fdio will return [EBADF], whereas pkgfs
does not enforce rights and so just returns `NOT_SUPPORTED`.
[EBADF]: https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fdio/fdio_unistd.cc;l=99-100;drc=83f4c24fe96daa2c5535329415bd32c0ca9d90dd
### trailing slash implies `OPEN_FLAG_DIRECTORY`
package-directory allows opens of the form "subdir/" only if subdir is a
directory and not a file, [as per directory.fidl][trailing slash rule]:
> A trailing slash implies OPEN_FLAG_DIRECTORY.
pkgfs allows files to be opened via paths that contain trailing slashes.
[trailing slash rule]: https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.io/directory.fidl;l=190;drc=db4fbde2ad6f3872fe72dd5561265b88c0e0a7df
### `OPEN_FLAG_DIRECTORY` and `OPEN_FLAG_NOT_DIRECTORY` are mutually exclusive
package-directory rejects all opens with both flags set, even for meta which can
be opened both as a directory and a file.
pkgfs ignores `OPEN_FLAG_NOT_DIRECTORY` and therefore allows one to open meta as
a directory with `OPEN_FLAG_DIRECTORY | OPEN_FLAG_NOT_DIRECTORY`
### mode checked for consistency with `OPEN_FLAG{_NOT,}_DIRECTORY`
If mode and one of `OPEN_FLAG_DIRECTORY` or `OPEN_FLAG_NOT_DIRECTORY` is set,
package-directory checks them for consistency following the
[rules from fuchsia.io]:
> The mode type, if set, must always be consistent with the OPEN_FLAG_DIRECTORY
> and OPEN_FLAG_NOT_DIRECTORY flags, even if an object is not being created.
[rules from fuchsia.io]: https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/fidl/fuchsia.io/
pkgfs does not enforce any consistency between mode and these flags.
### mode is ignored other than consistency checking with `OPEN_FLAG{_NOT,}_DIRECTORY` and meta-as-file/meta-as-dir duality
package-directory ignores mode in open calls except for checking it for
consistency with `OPEN_FLAG{_NOT,}_DIRECTORY` (previous item) and its role in
determining if meta is opened as a file or directory.
pkgfs disallows `MODE_TYPE_DIRECTORY` when opening content files (but not meta
files).
### path segment rules are checked
package-directory enforces the following [rules for paths] defined in
fuchsia.io:
* Components must not be empty (i.e. "foo//bar" is invalid).
* ".." is disallowed anywhere in the path.
* "." is only allowed if the path is exactly ".", but not otherwise.
[rules for paths]: https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/fidl/fuchsia.io/
pkgfs collapses adjacent "//"s in the path, and allows extra "." segments.
Additionally, it will remove segments from paths preceding a ".." segment, so an
open of "subdir/../foo" will just result in an open of foo. (although note that
it does not allow one to escape the current directory handle this way)
### meta/ directories and files may not be opened with `OPEN_RIGHT_EXECUTABLE`
package-directory rejects opening files and directories in meta/ with
OPEN_RIGHT_EXECUTABLE, as putting executable files in meta.far is not supported.
pkgfs has the same restrictions, except it allows one to open meta/ itself (as a
file or directory) with `OPEN_RIGHT_EXECUTABLE`, even though that does not
ultimately allow for the opening of files in meta/ with `OPEN_RIGHT_EXECUTABLE`.
### `GetToken()` not supported
package-directory responds with `ZX_STATUS_NOT_SUPPORTED` for calls to
`GetToken()`, because it represents an immutable directory and tokens are only
used with mutation APIs.
pkgfs hands out tokens via `GetToken()`, but they can't subsequently be used for
any other operation.
### `GetFlags()` is supported on directories
package-directory supports `GetFlags()` on directories in addition to files.
pkgfs responds with a `ZX_ERR_NOT_SUPPORTED` status when `GetFlags()` is called
on a directory.
### creation and modification times unimplemented
When `GetAttrs()` is called, package-directory returns 0 for creation_time and
modification_time, as packages don't contain that metadata.
pkgfs also doesn't support these times, but returns a placeholder value
(18446744011573954816) instead.
### `/meta` opened as a file supports `ReadAt()`
package-directory supports `ReadAt()` on meta-as-file.
pkgfs only supports reading that file with `Read()`, not `ReadAt()`.
### `/meta` opened as a file supports `Seek()`
package-directory supports `Seek()` on meta-as-file.
pkgfs only supports reading from the beginning of that file.
### `/meta` opened as a file supports `Clone()`
package-directory supports `Clone()` on meta-as-file.
pkgfs does not support `Clone()` on meta-as-file. pkgfs will not respond to any
messages on the cloned channel and isn't even guaranteed to close its end of the
channel.
### mode protection write bit and group and other bytes not set
When `GetAttrs()` is called, package-directory always returns `0o500` for
directories and `0o400` for files (directories can be read and traversed, files
can be read, and
[zxio only uses the USR byte](https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/zxio/remote.cc;l=339;drc=e3ffcb20a4605ae4299ce5888fce6becabe2f8a9))
for the
[mode protection bits](https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.io/directory.fidl;l=97;drc=1cc9164ebb39d1c4b070e23f3808216403fcb526)
of
[NodeAttributes.mode](https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.io/node.fidl;l=91;drc=7fab2b7a07b1ab6c3d190cdf07daed196e3f4168),
whereas pkgfs returns 0o755 for directories and 0o644 for files.
### content files support `OPEN_FLAG_APPEND`
blobfs allows `OPEN_FLAG_APPEND`, but pkgfs rejects the flag before forwarding
the open.
### files under `/meta` behave like content files for `GetBuffer()`
package-directory responds to GetBuffer() calls with invalid flags on files
under meta the same way as to calls on files not under meta.
pkgfs closes the connection without responding when GetBuffer() is called with
invalid flags on files under meta.