diff --git a/Cargo.toml b/Cargo.toml index f36617e..b90e848 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ resolver = "2" members = [ "components/*", ] +exclude = [ + "components/wit", +] [workspace.dependencies] chrono = { git = "https://github.com/chronotope/chrono.git", branch = "0.5.x" } diff --git a/Makefile b/Makefile index da95bbc..f31a554 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ SHELL := /bin/bash export RUST_BACKTRACE ?= 1 export WASMTIME_BACKTRACE_DETAILS ?= 1 -COMPONENTS = $(shell ls -1 components) +COMPONENTS = $(sort $(notdir $(patsubst %/,%,$(dir $(wildcard components/*/Cargo.toml))))) .PHONY: all all: components @@ -14,20 +14,24 @@ clean: rm -rf lib/*.wasm rm -rf lib/*.wasm.md +.PHONY: test +test: + @echo "TODO add tests" + .PHONY: components -components: $(foreach component,$(COMPONENTS),lib/$(component).wasm $(foreach component,$(COMPONENTS),lib/$(component).debug.wasm)) +components: lib/interface.wasm $(foreach component,$(COMPONENTS),lib/$(component).wasm lib/$(component).debug.wasm) define BUILD_COMPONENT .PHONY: components/$1 components/$1: lib/$1.wasm lib/$1.debug.wasm -lib/$1.wasm: Cargo.toml Cargo.lock wit/deps $(shell find components/$1 -type f) +lib/$1.wasm: Cargo.toml Cargo.lock components/wit/deps $(shell find components/$1 -type f) cargo build -p $1 --target wasm32-unknown-unknown --release wasm-tools component new target/wasm32-unknown-unknown/release/$(subst -,_,$1).wasm -o lib/$1.wasm cp components/$1/README.md lib/$1.wasm.md -lib/$1.debug.wasm: Cargo.toml Cargo.lock wit/deps $(shell find components/$1 -type f) +lib/$1.debug.wasm: Cargo.toml Cargo.lock components/wit/deps $(shell find components/$1 -type f) cargo build -p $1 --target wasm32-unknown-unknown wasm-tools component new target/wasm32-unknown-unknown/debug/$(subst -,_,$1).wasm -o lib/$1.debug.wasm cp components/$1/README.md lib/$1.debug.wasm.md @@ -36,15 +40,21 @@ endef $(foreach component,$(COMPONENTS),$(eval $(call BUILD_COMPONENT,$(component)))) +lib/interface.wasm: wit/deps README.md + wkg build -o lib/interface.wasm + cp README.md lib/interface.wasm.md .PHONY: wit -wit: wit/deps +wit: wit/deps components/wit/deps wit/deps: wkg.toml $(shell find wit -type f -name "*.wit" -not -path "deps") - wkg wit fetch + wkg fetch + +components/wit/deps: wit/deps components/wkg.toml $(shell find components/wit -type f -name "*.wit" -not -path "deps") + ( cd components && wkg fetch ) -.PHONY: publish -publish: $(shell find lib -type f -name "*.wasm" -maxdepth 1 | sed -e 's:^lib/:publish-:g') +.PHONY: publish ## Publish each component in the lib directory +publish: $(shell find lib -maxdepth 1 -type f -name "*.wasm" | sed -e 's:^lib/:publish-:g') .PHONY: publish-% publish-%: @@ -55,25 +65,28 @@ ifndef REPOSITORY $(error REPOSITORY is undefined) endif @$(eval FILE := $(@:publish-%=%)) - @$(eval COMPONENT := $(FILE:%.wasm=%)) + @$(eval COMPONENT := $(if $(filter %.debug.wasm,$(FILE)),$(FILE:%.debug.wasm=%),$(FILE:%.wasm=%))) + @$(eval TITLE := $(if $(filter %.debug.wasm,$(FILE)),$(COMPONENT) (debug),$(COMPONENT))) @$(eval DESCRIPTION := $(shell head -n 3 "lib/${FILE}.md" | tail -n 1)) @$(eval REVISION := $(shell git rev-parse HEAD)$(shell git diff --quiet HEAD && echo "+dirty")) - @$(eval TAG := $(patsubst v%,%,$(subst +,_,$(VERSION)))) + @$(eval COMPONENT_VERSION := $(if $(filter %.debug.wasm,$(FILE)),${VERSION}+debug,${VERSION})) + @$(eval TAG := $(patsubst v%,%,$(subst +,_,$(COMPONENT_VERSION)))) + @$(eval IMAGE := $(if $(filter interface.wasm,$(FILE)),${REPOSITORY}:${TAG},${REPOSITORY}/${COMPONENT}:${TAG})) - @echo "::group::${FILE} -> ${REPOSITORY}/${COMPONENT}:${TAG}" + @echo "::group::${FILE} -> ${IMAGE}" @DIGEST=$$( \ wkg oci push \ - --annotation "org.opencontainers.image.title=${COMPONENT}" \ + --annotation "org.opencontainers.image.title=${TITLE}" \ --annotation "org.opencontainers.image.description=${DESCRIPTION}" \ - --annotation "org.opencontainers.image.version=${VERSION}" \ + --annotation "org.opencontainers.image.version=${COMPONENT_VERSION}" \ --annotation "org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}.git" \ --annotation "org.opencontainers.image.revision=${REVISION}" \ --annotation "org.opencontainers.image.licenses=Apache-2.0" \ - "${REPOSITORY}/${COMPONENT}:${TAG}" \ + "${IMAGE}" \ "lib/${FILE}" \ 2>&1 \ | tee /dev/stderr \ | grep -o 'sha256:[a-f0-9]\{64\}' \ ) ; \ - cosign sign --yes "${REPOSITORY}/${COMPONENT}:${TAG}@$${DIGEST}" + cosign sign --yes "${IMAGE}@$${DIGEST}" @echo "::endgroup::" diff --git a/components/chroot/src/lib.rs b/components/chroot/src/lib.rs index bc0b8ab..4d19753 100644 --- a/components/chroot/src/lib.rs +++ b/components/chroot/src/lib.rs @@ -296,7 +296,7 @@ impl GuestDescriptor for FilesystemChrootDescriptor { } wit_bindgen::generate!({ - path: "../../wit", + path: "../wit", world: "filesystem", merge_structurally_equal_types: true, generate_all diff --git a/components/readonly/src/lib.rs b/components/readonly/src/lib.rs index 0a81bfa..6ee90b9 100644 --- a/components/readonly/src/lib.rs +++ b/components/readonly/src/lib.rs @@ -234,7 +234,7 @@ impl exports::wasi::filesystem::types::GuestDescriptor for ReadOnlyDescriptor { } wit_bindgen::generate!({ - path: "../../wit", + path: "../wit", world: "filesystem", merge_structurally_equal_types: true, generate_all diff --git a/components/tracing/src/lib.rs b/components/tracing/src/lib.rs index 56d4aef..4dc2b85 100644 --- a/components/tracing/src/lib.rs +++ b/components/tracing/src/lib.rs @@ -576,7 +576,7 @@ impl Display for types::Instant { } wit_bindgen::generate!({ - path: "../../wit", + path: "../wit", world: "filesystem", merge_structurally_equal_types: true, generate_all diff --git a/components/wit/deps/componentized-filesystem-0.3.0-dev/package.wit b/components/wit/deps/componentized-filesystem-0.3.0-dev/package.wit new file mode 100644 index 0000000..51d830e --- /dev/null +++ b/components/wit/deps/componentized-filesystem-0.3.0-dev/package.wit @@ -0,0 +1,8 @@ +package componentized:filesystem@0.3.0-dev; + +world imports { + import wasi:clocks/types@0.3.0; + import wasi:clocks/system-clock@0.3.0; + import wasi:filesystem/types@0.3.0; + import wasi:filesystem/preopens@0.3.0; +} diff --git a/components/wit/deps/wasi-clocks-0.3.0/package.wit b/components/wit/deps/wasi-clocks-0.3.0/package.wit new file mode 100644 index 0000000..2594e02 --- /dev/null +++ b/components/wit/deps/wasi-clocks-0.3.0/package.wit @@ -0,0 +1,19 @@ +package wasi:clocks@0.3.0; + +interface types { + type duration = u64; +} + +interface system-clock { + use types.{duration}; + + record instant { + seconds: s64, + nanoseconds: u32, + } + + now: func() -> instant; + + get-resolution: func() -> duration; +} + diff --git a/wit/deps/wasi-config-0.2.0-rc.1/package.wit b/components/wit/deps/wasi-config-0.2.0-rc.1/package.wit similarity index 100% rename from wit/deps/wasi-config-0.2.0-rc.1/package.wit rename to components/wit/deps/wasi-config-0.2.0-rc.1/package.wit diff --git a/components/wit/deps/wasi-filesystem-0.3.0/package.wit b/components/wit/deps/wasi-filesystem-0.3.0/package.wit new file mode 100644 index 0000000..e4a778f --- /dev/null +++ b/components/wit/deps/wasi-filesystem-0.3.0/package.wit @@ -0,0 +1,575 @@ +package wasi:filesystem@0.3.0; + +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// Though this package presents a portable interface modelled on POSIX, it +/// prioritizes compatibility over portability: allowing users to access their +/// files on their machine is more important than exposing a single semantics +/// across all platforms. Notably, depending on the underlying operating system +/// and file system: +/// * Paths may be case-folded or not. +/// * Deleting (unlinking) a file may fail if there are other file descriptors +/// open. +/// * Durability and atomicity of changes to underlying files when there are +/// concurrent writers. +/// +/// Users that need well-defined, portable semantics should use a key-value +/// store or a database instead. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +@since(version = 0.3.0) +interface types { + @since(version = 0.3.0) + use wasi:clocks/system-clock@0.3.0.{instant}; + + /// File size or length of a region within a file. + @since(version = 0.3.0) + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + @since(version = 0.3.0) + variant descriptor-type { + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + /// The type of the descriptor or file is different from any of the + /// other types specified. + other(option), + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + @since(version = 0.3.0) + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrity + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// Flags determining the method of how paths are resolved. + @since(version = 0.3.0) + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + @since(version = 0.3.0) + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Number of hard links to an inode. + @since(version = 0.3.0) + type link-count = u64; + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + @since(version = 0.3.0) + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// When setting a timestamp, this gives the value to set it to. + @since(version = 0.3.0) + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(instant), + } + + /// A directory entry. + @since(version = 0.3.0) + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + @since(version = 0.3.0) + variant error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + /// A catch-all for errors not captured by the existing variants. + /// Implementations can use this to extend the error type without + /// breaking existing code. + other(option), + } + + /// File or memory access pattern advisory information. + @since(version = 0.3.0) + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + @since(version = 0.3.0) + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + @since(version = 0.3.0) + resource descriptor { + /// Return a stream for reading from a file. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// This function returns a `stream` which provides the data received from the + /// file, and a `future` providing additional error information in case an + /// error is encountered. + /// + /// If no error is encountered, `stream.read` on the `stream` will return + /// `read-status::closed` with no `error-context` and the future resolves to + /// the value `ok`. If an error is encountered, `stream.read` on the + /// `stream` returns `read-status::closed` with an `error-context` and the future + /// resolves to `err` with an `error-code`. + /// + /// Note: This is similar to `pread` in POSIX. + @since(version = 0.3.0) + read-via-stream: func(offset: filesize) -> tuple, future>>; + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// This function returns once either full contents of the stream are + /// written or an error is encountered. + /// + /// Note: This is similar to `pwrite` in POSIX. + @since(version = 0.3.0) + write-via-stream: func(data: stream, offset: filesize) -> future>; + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// This function returns once either full contents of the stream are + /// written or an error is encountered. + /// + /// Note: This is similar to `write` with `O_APPEND` in POSIX. + @since(version = 0.3.0) + append-via-stream: func(data: stream) -> future>; + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + @since(version = 0.3.0) + advise: async func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>; + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + @since(version = 0.3.0) + sync-data: async func() -> result<_, error-code>; + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.3.0) + get-flags: async func() -> result; + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.3.0) + get-type: async func() -> result; + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + @since(version = 0.3.0) + set-size: async func(size: filesize) -> result<_, error-code>; + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + @since(version = 0.3.0) + set-times: async func(data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + /// + /// This function returns a future, which will resolve to an error code if + /// reading full contents of the directory fails. + @since(version = 0.3.0) + read-directory: func() -> tuple, future>>; + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + @since(version = 0.3.0) + sync: async func() -> result<_, error-code>; + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + @since(version = 0.3.0) + create-directory-at: async func(path: string) -> result<_, error-code>; + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + @since(version = 0.3.0) + stat: async func() -> result; + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + @since(version = 0.3.0) + stat-at: async func(path-flags: path-flags, path: string) -> result; + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + @since(version = 0.3.0) + set-times-at: async func(path-flags: path-flags, path: string, data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + /// Create a hard link. + /// + /// Fails with `error-code::no-entry` if the old path does not exist, + /// with `error-code::exist` if the new path already exists, and + /// `error-code::not-permitted` if the old path is not a file. + /// + /// Note: This is similar to `linkat` in POSIX. + @since(version = 0.3.0) + link-at: async func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + /// Open a file or directory. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + @since(version = 0.3.0) + open-at: async func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: descriptor-flags) -> result; + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + @since(version = 0.3.0) + readlink-at: async func(path: string) -> result; + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + @since(version = 0.3.0) + remove-directory-at: async func(path: string) -> result<_, error-code>; + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + @since(version = 0.3.0) + rename-at: async func(old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + @since(version = 0.3.0) + symlink-at: async func(old-path: string, new-path: string) -> result<_, error-code>; + /// Unlink a filesystem object that is not a directory. + /// + /// This is similar to `unlinkat(fd, path, 0)` in POSIX. + /// + /// Error returns are as specified by POSIX. + /// + /// If the filesystem object is a directory, `error-code::access` or + /// `error-code::is-directory` may be returned instead of the + /// POSIX-specified `error-code::not-permitted`. + @since(version = 0.3.0) + unlink-file-at: async func(path: string) -> result<_, error-code>; + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + @since(version = 0.3.0) + is-same-object: async func(other: borrow) -> bool; + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encouraged to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + @since(version = 0.3.0) + metadata-hash: async func() -> result; + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + @since(version = 0.3.0) + metadata-hash-at: async func(path-flags: path-flags, path: string) -> result; + } +} + +@since(version = 0.3.0) +interface preopens { + @since(version = 0.3.0) + use types.{descriptor}; + + /// Return the set of preopened directories, and their paths. + @since(version = 0.3.0) + get-directories: func() -> list>; +} + +@since(version = 0.3.0) +world imports { + @since(version = 0.3.0) + import wasi:clocks/types@0.3.0; + @since(version = 0.3.0) + import wasi:clocks/system-clock@0.3.0; + @since(version = 0.3.0) + import types; + @since(version = 0.3.0) + import preopens; +} diff --git a/wit/deps/wasi-logging-0.1.0-draft/package.wit b/components/wit/deps/wasi-logging-0.1.0-draft/package.wit similarity index 100% rename from wit/deps/wasi-logging-0.1.0-draft/package.wit rename to components/wit/deps/wasi-logging-0.1.0-draft/package.wit diff --git a/components/wit/worlds.wit b/components/wit/worlds.wit new file mode 100644 index 0000000..e85c334 --- /dev/null +++ b/components/wit/worlds.wit @@ -0,0 +1,10 @@ +package componentized:filesystem-components; + +world filesystem { + import wasi:config/store@0.2.0-rc.1; + import wasi:logging/logging@0.1.0-draft; + import wasi:filesystem/preopens@0.3.0; + export wasi:filesystem/preopens@0.3.0; + import wasi:filesystem/types@0.3.0; + export wasi:filesystem/types@0.3.0; +} diff --git a/components/wkg.lock b/components/wkg.lock new file mode 100644 index 0000000..d82b52c --- /dev/null +++ b/components/wkg.lock @@ -0,0 +1,30 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:config" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0-rc.1" +version = "0.2.0-rc.1" +digest = "sha256:1b7f1b0fd07bb4cede16c6a6ec8852815dfb924639a78735fc7bdffdc164485d" + +[[packages]] +name = "wasi:filesystem" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.3.0" +version = "0.3.0" +digest = "sha256:42921410cddcdce2e009fd65c9a763bfb3fb61e2c0a64ff71647cc4405470378" + +[[packages]] +name = "wasi:logging" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.1.0-draft" +version = "0.1.0-draft" +digest = "sha256:09621a45b12b0a9cddc798517f778aac0e5ae4bd234077b3d70758d6cf625580" diff --git a/components/wkg.toml b/components/wkg.toml new file mode 100644 index 0000000..f165f21 --- /dev/null +++ b/components/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"componentized:filesystem" = { path = "../wit" } diff --git a/wit/worlds.wit b/wit/worlds.wit index d527e48..b4f47f1 100644 --- a/wit/worlds.wit +++ b/wit/worlds.wit @@ -1,10 +1,6 @@ -package componentized:filesystem; +package componentized:filesystem@0.3.0-dev; -world filesystem { - import wasi:config/store@0.2.0-rc.1; - import wasi:logging/logging@0.1.0-draft; +world imports { import wasi:filesystem/preopens@0.3.0; - export wasi:filesystem/preopens@0.3.0; import wasi:filesystem/types@0.3.0; - export wasi:filesystem/types@0.3.0; } diff --git a/wkg.lock b/wkg.lock index d82b52c..a35e14e 100644 --- a/wkg.lock +++ b/wkg.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 1 -[[packages]] -name = "wasi:config" -registry = "wasi.dev" - -[[packages.versions]] -requirement = "=0.2.0-rc.1" -version = "0.2.0-rc.1" -digest = "sha256:1b7f1b0fd07bb4cede16c6a6ec8852815dfb924639a78735fc7bdffdc164485d" - [[packages]] name = "wasi:filesystem" registry = "wasi.dev" @@ -19,12 +10,3 @@ registry = "wasi.dev" requirement = "=0.3.0" version = "0.3.0" digest = "sha256:42921410cddcdce2e009fd65c9a763bfb3fb61e2c0a64ff71647cc4405470378" - -[[packages]] -name = "wasi:logging" -registry = "wasi.dev" - -[[packages.versions]] -requirement = "=0.1.0-draft" -version = "0.1.0-draft" -digest = "sha256:09621a45b12b0a9cddc798517f778aac0e5ae4bd234077b3d70758d6cf625580"