Commit graph

388 commits

Author SHA1 Message Date
Ryan Liptak
c6ff1a7160 Windows: Fix iterator name buffer size not handling all possible file name components
Each u16 within a file name component can be encoded as up to 3 UTF-8 bytes, so we need to use MAX_NAME_BYTES to account for all possible UTF-8 encoded names.

Fixes #8268
2022-10-29 14:30:44 -07:00
Ryan Liptak
33fdc43714 std.fs: Add MAX_NAME_BYTES
Also add some NAME_MAX or equivalent definitions where necessary
2022-10-29 14:30:43 -07:00
Motiejus Jakštys
fd10baf748 os.copy_file_range: save a syscall for most operations
Currenty copy_file_range always uses at least two syscalls:

1. As many as it needs to do the initial copy (always 1 during my
   testing)
2. The last one is always when offset is the size of the file.

The second syscall is used to detect the terminating condition. However,
because we do a stat for other reasons, we know the size of the file,
and we can skip the syscall.

Sparse files: since copy_file_range expands holes of sparse files, I
conclude that this layer was not intended to work with sparse files. In
other words, this commit does not make it worse for sparse file society.

Test program
------------

    const std = @import("std");

    pub fn main() !void {
        const arg1 = std.mem.span(std.os.argv[1]);
        const arg2 = std.mem.span(std.os.argv[2]);
        try std.fs.cwd().copyFile(arg1, std.fs.cwd(), arg2, .{});
    }

Test output (current master)
----------------------------

Observe two `copy_file_range` syscalls: one with 209 bytes, one with
zero:

    $ zig build-exe cp.zig
    $ strace ./cp ./cp.zig ./cp2.zig |& grep copy_file_range
    copy_file_range(3, [0], 5, [0], 4294967295, 0) = 209
    copy_file_range(3, [209], 5, [209], 4294967295, 0) = 0
    $

Test output (this diff)
-----------------------

Observe a single `copy_file_range` syscall with 209 bytes:

    $ /code/zig/build/zig build-exe cp.zig
    $ strace ./cp ./cp.zig ./cp2.zig |& grep copy_file_range
    copy_file_range(3, [0], 5, [0], 4294967295, 0) = 209
    $
2022-10-18 12:57:21 -04:00
xEgoist
ae39e7867d Added os check for std.fs.setAsCwd() to work with windows
Due to the unavailability of fchdir in Windows, a call for setting the
CWD needs to either call chdir with the path string or call
SetCurrentDirectory.
Either way, since we are dealing with a Handle in Windows, a call for
GetFinalPathNameByHandle is necessary for getting the file path first.
2022-10-15 11:05:15 -04:00
Ryan Liptak
c8da03a0e1 Fix compile error in Dir.deleteTreeMinStackSize and add test
Follow up to #13073
2022-10-14 14:48:23 -04:00
Ryan Liptak
1468eb12f3 std.fs.deleteTree: Unify how the initial sub_path is treated between deleteTree/deleteTreeMinStackSize 2022-10-05 20:08:53 -07:00
Ryan Liptak
063c5f43e9 fs.Dir.deleteTree: Fix FileBusy errors on Windows
Windows requires the directory handle to be closed before attempting to delete the directory, so now we do that and then re-open it if we need to retry (from getting DirNotEmpty when trying to delete).
2022-10-05 19:58:36 -07:00
Ryan Liptak
db0829c15a fs.Dir.deleteTree: Fix some handling of NotDir error in deleteFile calls
We don't control sub_path so it may contain directory components; therefore, NotDir is a potential error when acting on sub_path.
2022-10-05 19:51:43 -07:00
Ryan Liptak
34f180901e fs: deleteTreeFallback -> deleteTreeMinStackSize and make it pub 2022-10-05 16:15:25 -07:00
Ryan Liptak
39f192d54e fs: Reduce IterableDir.Iterator buf size to 1024
This was sized large so that `getdents` (and other platforms' equivalents) could provide large amounts of entries per syscall, but some benchmarking seems to indicate that the larger 8192 sizing doesn't actually lead to performance gains outside of edge cases like extremely large amounts of entries within a single directory (e.g. 25,000 files in one directory), and even then the gains are minimal ('./walk-8192 dir-with-tons-of-entries' ran 1.02 ± 0.34 times faster than './walk-1024 dir-with-tons-of-entries').

Note: Sizes 1024 and 2048 had similar performance characteristics, so the smaller of the two was chosen.
2022-10-05 16:05:02 -07:00
Ryan Liptak
274d19575e fs: Optimize Dir.deleteTree for non-deeply-nested directories
`deleteTree` now uses a stack-allocated stack for the first 16 nested directories, and then falls back to the previous implementation (which only keeps 1 directory open at a time) when it runs out of room in its stack. This allows the function to perform as well as a recursive implementation for most use-cases without needing allocation or introducing the possibility of stack overflow.
2022-10-05 03:27:25 -07:00
Ryan Liptak
e9889cd25f fs: Add IterableDir.Iterator.reset 2022-10-05 03:26:13 -07:00
Ryan Liptak
8cec8f6ddd fs.Dir.deleteTree: Reduce the number of failing deleteFile calls
There are two parts to this:

1. The deleteFile call on the sub_path has been moved outside the loop, since if the first call fails with `IsDir` then it's very likely that all the subsequent calls will do the same. Instead, if the `openIterableDir` call ever hits `NotDir` after the `deleteFile` hit `IsDir`, then we assume that the tree was deleted at some point and can consider the deleteTree a success.

2. Inside the `dir_it.next()` loop, we look at entry.kind and only try doing the relevant (deleteFile/openIterableDir) operation, but always fall back to the other if we get the relevant error (NotDir/IsDir).
2022-10-05 03:26:13 -07:00
Ryan Liptak
5059384b57 Introduce IterableDir.iterateAssumeFirstIteration
This allows for avoiding an unnecessary lseek (or equivalent) call in places where it can be known that the fd has not had its cursor modified yet.
2022-10-05 02:20:13 -07:00
Ryan Liptak
764cf4e53f std.fs: Fix WalkerEntry.dir not always being the containing dir
Before this commit, the modified test would fail with `FileNotFound` because the `entry.dir` would be for the entry itself rather than the containing dir of the entry. That is, if you were walking a tree of `a/b`, then (previously) the entry for `b` would incorrectly have an `entry.dir` for `b` rather than `a`.
2022-08-15 11:25:51 +03:00
Ryan Liptak
e7b6a18331 std.fs: Split Iterator.next on Linux and WASI to allow for handling platform-specific errors
Follow up to #12226, implements the compromise detailed in https://github.com/ziglang/zig/issues/12211#issuecomment-1196011590
2022-08-01 19:38:05 +03:00
Ryan Liptak
75e5b38410
std.fs: End iteration on Linux/WASI during Iterator.next when hitting ENOENT
`getdents` on Linux can return `ENOENT` if the directory referred to by the fd is deleted during iteration. Returning null when this happens makes sense because:

- `ENOENT` is specific to the Linux implementation of `getdents`
- On other platforms like FreeBSD, `getdents` returns `0` in this scenario, which is functionally equivalent to the `.NOENT => return null` handling on Linux
- In all the usage sites of `Iterator.next` throughout the standard library, translating `ENOENT` returned from `next` as null was the best way to handle it, so the use-case for handling the exact `ENOENT` scenario specifically may not exist to a relevant extent

Previously, ENOENT being returned would trigger `os.unexpectedErrno`.

Closes #12211
2022-07-25 16:14:25 +03:00
Ryan Liptak
4624c81899 std.fs: Fix Walker closing the initial directory when not fully iterated
This is a fix for a regression caused by 61c5d8f8f1

Closes #12209
2022-07-24 12:00:14 -07:00
Veikka Tuominen
0e26c61499 std.fs: remove accidental comptime block 2022-07-17 11:54:13 +03:00
Veikka Tuominen
fcaeca5b0a std.fs: add Iterable versions of openDirAbsolute*
Follow up to 262f4c7b3a
2022-07-17 11:52:30 +03:00
Veikka Tuominen
262f4c7b3a std.fs: remove OpenDirOptions.iterate 2022-07-15 14:39:21 +03:00
Veikka Tuominen
2b67f56c35 std.fs: split Dir into IterableDir
Also adds safety check for attempting to iterate directory not opened with `iterate = true`.
2022-07-15 13:04:21 +03:00
Veikka Tuominen
61c5d8f8f1 std.fs: fix incorrect passing of pointer to temporary 2022-06-06 13:11:50 -07:00
Ali Chraghi
0e6285c8fc math: make cast return optional instead of an error 2022-05-27 16:43:33 -04:00
Cody Tapscott
bb9cd6db1c stage2: Move WASI/Zig-specific selfExePath to introspect.zig 2022-04-18 23:06:49 -07:00
Cody Tapscott
3a63fa6b7f stage2: Add 'zig.wasm' fallback for binary name 2022-04-18 10:20:20 -07:00
Cody Tapscott
922d8378e7 stage2: Add limited WASI support for selfExePath and globalCacheDir
This change adds support for locating the Zig executable and the library
and global cache directories, based on looking in the fixed "/zig" and
"/cache" directories.

Since our argv[0] on WASI is just the basename (any absolute/relative
path information is deleted by the runtime), there's very limited
introspection we can do on WASI, so we rely on these fixed directories.
These can be provided on the command-line using `--mapdir`, as follows:

```
wasmtime --mapdir=/cwd::. --mapdir=/cache::"$HOME/.cache/zig" --mapdir=/zig::./zig-out/ ./zig-out/bin/zig.wasm
```
2022-04-18 10:19:34 -07:00
Evan Haas
618398b7d3 std.fs: prevent possible integer overflow in Dir.makePath
The call to `makeDir` for the top-level component of `sub_path`
can return `error.FileNotFound` if the directory represented by
`self` has been deleted.

Fixes #11397
2022-04-15 11:19:23 +03:00
Yorhel
a3030221c3 std.fs: Handle EINVAL from linux.getdents64
Fixes #11178
2022-03-27 11:24:31 +03:00
Cody Tapscott
58f961f4cb stdlib: Add emulated CWD to std.os for WASI targets
This adds a special CWD file descriptor, AT.FDCWD (-2), to refer to the
current working directory. The `*at(...)` functions look for this and
resolve relative paths against the stored CWD. Absolute paths are
dynamically matched against the stored Preopens.

"os.initPreopensWasi()" must be called before std.os functions will
resolve relative or absolute paths correctly. This is asserted at
runtime.

Support has been added for: `open`, `rename`, `mkdir`, `rmdir`, `chdir`,
`fchdir`, `link`, `symlink`, `unlink`, `readlink`, `fstatat`, `access`,
and `faccessat`.

This also includes limited support for `getcwd()` and `realpath()`.
These return an error if the CWD does not correspond to a Preopen with
an absolute path. They also do not currently expand symlinks.
2022-03-03 14:31:49 -07:00
Anthony Carrico
078aa5f7b2 Adds Linux support for POSIX file locking with fcntl
On Linux, locking fails with EAGAIN (vs. EACCES on other systems).
This commit also adds FcntlErrors for EDEADLK and ENOLCK.
2022-02-15 13:22:50 +02:00
ominitay
11b4cc589c
std.fs: Implement cross-platform metadata API
Implements a cross-platform metadata API, aiming to reduce unnecessary Unix-dependence of the `std.fs` api. Presently, all OSes beside Windows are treated as Unix; this is likely the best way to treat things by default, instead of explicitly listing each Unix-like OS.

Platform-specific operations are not provided by `File.Metadata`, and instead are to be accessed from `File.Metadata.inner`.

Adds:

- File.setPermissions() : Sets permission of a file according to a `Permissions` struct (not available on WASI)

- File.Permissions : A cross-platform representation of file permissions
  - Permissions.readOnly() : Returns whether the file is read-only
  - Permissions.setReadOnly() : Sets whether the file is read-only
  - Permissions.unixSet() : Sets permissions for a class (UNIX-only)
  - Permissions.unixGet() : Checks a permission for a class (UNIX-only)
  - Permissions.unixNew() : Returns a new Permissions struct to represent the passed mode (UNIX-only)

- File.Metadata : A cross-platform representation of file metadata
  - Metadata.size() : Returns the size of a file
  - Metadata.permissions() : Returns a `Permissions` struct, representing permissions on the file
  - Metadata.kind() : Returns the `Kind` of the file
  - Metadata.accessed() : Returns the time the file was last accessed
  - Metadata.modified() : Returns the time the file was last modified
  - Metadata.created() : Returns the time the file was created (this is an optional, as the underlying filesystem, or OS may not support this)

Methods of `File.Metadata` are also available for the below, so I won't repeat myself
The below may be used for platform-specific functionality

- File.MetadataUnix : The internal implementation of `File.Metadata` on Unices

- File.MetadataLinux : The internal implementation of `File.Metadata` on Linux

- File.MetadataWindows : The implementation of `File.Metadata` on Windows
2022-02-13 20:56:06 +00:00
Jakub Konka
dd7309bde4
Merge pull request #10404 from ominitay/iterator
std: Fix using `fs.Dir.Iterator` twice
2022-01-30 14:25:50 +01:00
Meghan
5e60ee4127
std: define static error set for fs.Dir.copyFile 2022-01-29 20:48:36 +02:00
Sage Hane
e288148f60
fs: Use OpenMode enum instead of read/write flags. 2022-01-29 15:52:08 +02:00
ominitay
dc11fe4047
std: Fix using fs.Dir.Iterator twice
This fixes the use of multiple `Iterator`s in a row on a directory.
Previously, on many platforms, using an `Iterator` on an
already-iterated directory would give no entries.

Fixing this involved seeking to the beginning of the directory on the
first call of `next()`.
2022-01-28 16:12:05 +00:00
Andrew Kelley
d3f87f8ac0 std.fs.rename: fix Windows implementation
The semantics of this function are that it moves both files and
directories. Previously we had this `is_dir` boolean field of
`std.os.windows.OpenFile` which required the API user to choose: are we
opening a file or directory? And the other kind would either cause
error.IsDir or error.NotDir. But that is not a limitation of the Windows
file system API; it was self-imposed.

On Windows, rename is implemented internally with `NtCreateFile` so we
need to allow it to open either files or directories. This is now done
by `std.os.windows.OpenFile` accepting enum{file_only,dir_only,any}
instead of a boolean.
2022-01-02 16:58:05 -08:00
Andrew Kelley
274555be21 stage2: improve handling of the generated file builtin.zig
All Zig code is eligible to `@import("builtin")` which is mapped to a
generated file, build.zig, based on the target and other settings.

Zig invocations which share the same target settings will generate the
same builtin.zig file and thus the path to builtin.zig is in a shared
cache folder, and different projects can sometimes use the same file.

Before this commit, this led to race conditions where multiple
invocations of `zig` would race to write this file. If one process
wanted to *read* the file while the other process *wrote* the file, the
reading process could observe a truncated or partially written
builtin.zig file.

This commit makes the following improvements:
 - limitations:
   - avoid clobbering the inode, mtime in the hot path
   - avoid creating a partially written file
   - builtin.zig needs to be on disk for debug info / stack trace purposes
   - don't mark the task as complete until the file is finished being populated
     (possibly by an external process)
 - strategy:
   - create the `@import("builtin")` `Module.File` during the AstGen
     work, based on generating the contents in memory rather than
     loading from disk.
   - write builtin.zig in a separate task that doesn't have
     to complete until the end of the AstGen work queue so that it
     can be done in parallel with everything else.
   - when writing the file, first stat the file path. If it exists, we are done.
   - otherwise, write the file to a temp file in the same directory and atomically
     rename it into place (clobbering the inode, mtime in the cold path).
 - summary:
   - all limitations respected
   - hot path: one stat() syscall that happens in a worker thread

This required adding a missing function to the standard library:
`std.fs.Dir.statFile`. In this commit, it does open() and then fstat()
which is two syscalls. It should be improved in a future commit to only
make one.

Fixes #9439.
2021-12-06 23:30:18 -08:00
Andrew Kelley
a3d9cd1c1d std.os: handle ETXTBSY from open() 2021-12-06 16:29:39 -07:00
Lee Cannon
85de022c56
allocgate: std Allocator interface refactor 2021-11-30 23:32:47 +00:00
Andrew Kelley
902df103c6 std lib API deprecations for the upcoming 0.9.0 release
See #3811
2021-11-30 00:13:07 -07:00
Andrew Kelley
36c8adf589
Merge pull request #10073 from hoanga/haiku-support-build2
more haiku support
2021-11-24 18:42:30 -08:00
Ominitay
796687f156 Add chmod and chown 2021-11-15 20:04:55 -05:00
Al Hoang
426f54026b updates for haiku stdc
* add team_info, area_info
* update signature for get_next_image_info
* add error checks for haiku system calls
* update and cleanup of haiku constants
2021-11-15 00:29:26 -06:00
Andrew Kelley
6115cf2240 migrate from std.Target.current to @import("builtin").target
closes #9388
closes #9321
2021-10-04 23:48:55 -07:00
Stephen Gregoratto
87fd502fb6 Initial bringup of the Solaris/Illumos port 2021-09-24 14:06:16 -04:00
Andrew Kelley
5a4cc24c0e std: dirent is not part of posix 2021-09-01 17:54:07 -07:00
Andrew Kelley
f8dd4b13d6 std.os reorg: more fixes caught by CI 2021-09-01 17:54:07 -07:00
Andrew Kelley
057f0fec33 std.os fixes to get the test suite passing again 2021-09-01 17:54:07 -07:00
Andrew Kelley
cca57042df std: fix regressions from this branch
Also move some usingnamespace test cases from compare_output to
behavior.
2021-09-01 17:54:07 -07:00