mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 09:18:31 +00:00
Improve system call documentation
This change also introduces partial faccessat() support for zipos and makes some slight breaking changes in errno results. close() is fixed to use `EBADF` rather than `EINVAL` and we're now using `ENOTSUP` not `EOPNOTSUPP` to indicate that zipos doesn't support a system call yet
This commit is contained in:
parent
0b5f84dd20
commit
ad97775370
18 changed files with 273 additions and 67 deletions
|
@ -36,17 +36,113 @@
|
|||
/**
|
||||
* Opens file.
|
||||
*
|
||||
* @param dirfd is normally AT_FDCWD but if it's an open directory and
|
||||
* file is a relative path, then file is opened relative to dirfd
|
||||
* @param file is a UTF-8 string, preferably relative w/ forward slashes
|
||||
* @param flags should be O_RDONLY, O_WRONLY, or O_RDWR, and can be or'd
|
||||
* with O_CREAT, O_TRUNC, O_APPEND, O_EXCL, O_CLOEXEC, O_TMPFILE
|
||||
* @param mode is an octal user/group/other permission signifier, that's
|
||||
* ignored if O_CREAT or O_TMPFILE weren't passed
|
||||
* @return number needing close(), or -1 w/ errno
|
||||
* @asyncsignalsafe (zip files may have issues)
|
||||
* @vforksafe (raises error if zip file)
|
||||
* Here's an example of how a file can be created:
|
||||
*
|
||||
* int fd = openat(AT_FDCWD, "hi.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
||||
* write(fd, "hello\n", 6);
|
||||
* close(fd);
|
||||
*
|
||||
* Here's an example of how that file could read back into memory:
|
||||
*
|
||||
* char data[513] = {0};
|
||||
* int fd = openat(AT_FDCWD, "hi.txt", O_RDONLY);
|
||||
* read(fd, data, 512);
|
||||
* close(fd);
|
||||
* assert(!strcmp(data, "hello\n"));
|
||||
*
|
||||
* If your main() source file has this statement:
|
||||
*
|
||||
* STATIC_YOINK("zip_uri_support");
|
||||
*
|
||||
* Then you can read zip assets by adding a `"/zip/..."` prefix to `file`, e.g.
|
||||
*
|
||||
* // run `zip program.com hi.txt` beforehand
|
||||
* openat(AT_FDCWD, "/zip/hi.txt", O_RDONLY);
|
||||
*
|
||||
* @param dirfd is normally `AT_FDCWD` but if it's an open directory and
|
||||
* `file` names a relative path then it's opened relative to `dirfd`
|
||||
* @param file is a UTF-8 string naming filesystem entity, e.g. `foo/bar.txt`,
|
||||
* which on Windows is bludgeoned into a WIN32 path automatically, e.g.
|
||||
* - `foo/bar.txt` becomes `foo\bar.txt`
|
||||
* - `/tmp/...` becomes whatever GetTempPath() is
|
||||
* - `\\...` or `//...` is passed through to WIN32 unchanged
|
||||
* - `/c/foo` or `\c\foo` becomes `\\?\c:\foo`
|
||||
* - `c:/foo` or `c:\foo` becomes `\\?\c:\foo`
|
||||
* - `/D` becomes `\\?\D:\`
|
||||
* @param flags must have one of the following under the `O_ACCMODE` bits:
|
||||
* - `O_RDONLY` to open `file` for reading only
|
||||
* - `O_WRONLY` to open `file` for writing
|
||||
* - `O_RDWR` to open `file` for reading and writing
|
||||
* The following may optionally be bitwise or'd into `flags`:
|
||||
* - `O_CREAT` create file if it doesn't exist
|
||||
* - `O_TRUNC` automatic `ftruncate(fd,0)` if exists
|
||||
* - `O_CLOEXEC` automatic close() upon execve()
|
||||
* - `O_EXCL` exclusive access (see below)
|
||||
* - `O_APPEND` open file for appending only
|
||||
* - `O_EXEC` open file for execution only; see fexecve()
|
||||
* - `O_NOCTTY` prevents `file` possibly becoming controlling terminal
|
||||
* - `O_NONBLOCK` asks read/write to fail with `EAGAIN` rather than block
|
||||
* - `O_DIRECT` it's complicated (not supported on Apple and OpenBSD)
|
||||
* - `O_DIRECTORY` useful for stat'ing (hint on UNIX but required on NT)
|
||||
* - `O_NOFOLLOW` fail if it's a symlink (zero on Windows)
|
||||
* - `O_DSYNC` it's complicated (zero on non-Linux/Apple)
|
||||
* - `O_RSYNC` it's complicated (zero on non-Linux/Apple)
|
||||
* - `O_VERIFY` it's complicated (zero on non-FreeBSD)
|
||||
* - `O_SHLOCK` it's complicated (zero on non-BSD)
|
||||
* - `O_EXLOCK` it's complicated (zero on non-BSD)
|
||||
* - `O_PATH` open only for metadata (Linux 2.6.39+ otherwise zero)
|
||||
* - `O_NOATIME` don't record access time (zero on non-Linux)
|
||||
* - `O_RANDOM` hint random access intent (zero on non-Windows)
|
||||
* - `O_SEQUENTIAL` hint sequential access intent (zero on non-Windows)
|
||||
* - `O_COMPRESSED` ask fs to abstract compression (zero on non-Windows)
|
||||
* - `O_INDEXED` turns on that slow performance (zero on non-Windows)
|
||||
* - `O_TMPFILE` should not be used; use tmpfd() or tmpfile() instead
|
||||
* There are three regular combinations for the above flags:
|
||||
* - `O_RDONLY`: Opens existing file for reading. If it doesn't
|
||||
* exist then nil is returned and errno will be `ENOENT` (or in
|
||||
* some other cases `ENOTDIR`).
|
||||
* - `O_WRONLY|O_CREAT|O_TRUNC`: Creates file. If it already
|
||||
* exists, then the existing copy is destroyed and the opened
|
||||
* file will start off with a length of zero. This is the
|
||||
* behavior of the traditional creat() system call.
|
||||
* - `O_WRONLY|O_CREAT|O_EXCL`: Create file only if doesn't exist
|
||||
* already. If it does exist then `nil` is returned along with
|
||||
* `errno` set to `EEXIST`.
|
||||
* @param mode is an octal user/group/other permission signifier that's
|
||||
* ignored if `O_CREAT` isn't passed in `flags`; when creating files
|
||||
* you'll usually want `mode` to be `0644` which enables global read
|
||||
* and only permits the owner to write; or when creating executables
|
||||
* you'll usually want `mode` to be `0755` which is the same, except
|
||||
* the executable bit is set thrice too
|
||||
* @return file descriptor (which needs to be close()'d), or -1 w/ errno
|
||||
* @raise EPERM if pledge() is in play w/o appropriate rpath/wpath/cpath
|
||||
* @raise EACCES if unveil() is in play and didn't unveil your `file` path
|
||||
* @raise EACCES if we don't have permission to search a component of `file`
|
||||
* @raise EACCES if file exists but requested `flags & O_ACCMODE` was denied
|
||||
* @raise EACCES if file doesn't exist and parent dir lacks write permissions
|
||||
* @raise EACCES if `O_TRUNC` was specified in `flags` but writing was denied
|
||||
* @raise ENOTSUP if `file` is on zip file system and `dirfd` isn't `AT_FDCWD`
|
||||
* @raise ENOTDIR if a directory component in `file` exists as non-directory
|
||||
* @raise ENOTDIR if `file` is relative and `dirfd` isn't an open directory
|
||||
* @raise EROFS when writing is requested w/ `file` on read-only filesystem
|
||||
* @raise ENAMETOOLONG if symlink-resolved `file` length exceeds `PATH_MAX`
|
||||
* @raise ENAMETOOLONG if component in `file` exists longer than `NAME_MAX`
|
||||
* @raise ENOTSUP if `file` is on zip file system and process is vfork()'d
|
||||
* @raise ENOSPC if file system is full when `file` would be `O_CREAT`ed
|
||||
* @raise EINTR if we needed to block and a signal was delivered instead
|
||||
* @raise ENOENT if `file` doesn't exist when `O_CREAT` isn't in `flags`
|
||||
* @raise ENOENT if `file` points to a string that's empty
|
||||
* @raise ENOMEM if insufficient memory was available
|
||||
* @raise EMFILE if `RLIMIT_NOFILE` has been reached
|
||||
* @raise EOPNOTSUPP if `file` names a named socket
|
||||
* @raise ETXTBSY if writing is requested on `file` that's being executed
|
||||
* @raise ELOOP if `flags` had `O_NOFOLLOW` and `file` is a symbolic link
|
||||
* @raise ELOOP if a loop was detected resolving components of `file`
|
||||
* @raise EISDIR if writing is requested and `file` names a directory
|
||||
* @asyncsignalsafe
|
||||
* @restartable
|
||||
* @threadsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int openat(int dirfd, const char *file, int flags, ...) {
|
||||
int rc;
|
||||
|
@ -63,7 +159,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
if (!__vforked && dirfd == AT_FDCWD) {
|
||||
rc = _weaken(__zipos_open)(&zipname, flags, mode);
|
||||
} else {
|
||||
rc = eopnotsupp(); /* TODO */
|
||||
rc = enotsup(); /* TODO */
|
||||
}
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_openat(dirfd, file, flags, mode);
|
||||
|
@ -73,7 +169,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
rc = sys_open_nt(dirfd, file, flags, mode);
|
||||
}
|
||||
} else {
|
||||
rc = eopnotsupp(); /* TODO */
|
||||
rc = enotsup(); /* TODO */
|
||||
}
|
||||
} else {
|
||||
rc = efault();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue