Merge branch 'stratact-no-dir-allocators'
closes #2885 closes #2886 closes #2888 closes #3249
This commit is contained in:
commit
e839250c51
@ -630,5 +630,8 @@ set_target_properties(zig PROPERTIES
|
|||||||
LINK_FLAGS ${EXE_LDFLAGS}
|
LINK_FLAGS ${EXE_LDFLAGS}
|
||||||
)
|
)
|
||||||
target_link_libraries(zig compiler "${LIBUSERLAND}")
|
target_link_libraries(zig compiler "${LIBUSERLAND}")
|
||||||
|
if(MSVC)
|
||||||
|
target_link_libraries(zig ntdll.lib)
|
||||||
|
endif()
|
||||||
add_dependencies(zig zig_build_libuserland)
|
add_dependencies(zig zig_build_libuserland)
|
||||||
install(TARGETS zig DESTINATION bin)
|
install(TARGETS zig DESTINATION bin)
|
||||||
|
@ -51,7 +51,7 @@ pub fn main() !void {
|
|||||||
var toc = try genToc(allocator, &tokenizer);
|
var toc = try genToc(allocator, &tokenizer);
|
||||||
|
|
||||||
try fs.makePath(allocator, tmp_dir_name);
|
try fs.makePath(allocator, tmp_dir_name);
|
||||||
defer fs.deleteTree(allocator, tmp_dir_name) catch {};
|
defer fs.deleteTree(tmp_dir_name) catch {};
|
||||||
|
|
||||||
try genHtml(allocator, &tokenizer, &toc, &buffered_out_stream.stream, zig_exe);
|
try genHtml(allocator, &tokenizer, &toc, &buffered_out_stream.stream, zig_exe);
|
||||||
try buffered_out_stream.flush();
|
try buffered_out_stream.flush();
|
||||||
|
@ -331,7 +331,7 @@ pub const Builder = struct {
|
|||||||
if (self.verbose) {
|
if (self.verbose) {
|
||||||
warn("rm {}\n", full_path);
|
warn("rm {}\n", full_path);
|
||||||
}
|
}
|
||||||
fs.deleteTree(self.allocator, full_path) catch {};
|
fs.deleteTree(full_path) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove empty directories
|
// TODO remove empty directories
|
||||||
@ -2687,7 +2687,7 @@ pub const RemoveDirStep = struct {
|
|||||||
const self = @fieldParentPtr(RemoveDirStep, "step", step);
|
const self = @fieldParentPtr(RemoveDirStep, "step", step);
|
||||||
|
|
||||||
const full_path = self.builder.pathFromRoot(self.dir_path);
|
const full_path = self.builder.pathFromRoot(self.dir_path);
|
||||||
fs.deleteTree(self.builder.allocator, full_path) catch |err| {
|
fs.deleteTree(full_path) catch |err| {
|
||||||
warn("Unable to remove {}: {}\n", full_path, @errorName(err));
|
warn("Unable to remove {}: {}\n", full_path, @errorName(err));
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
@ -80,6 +80,7 @@ pub extern "c" fn mmap(addr: ?*align(page_size) c_void, len: usize, prot: c_uint
|
|||||||
pub extern "c" fn munmap(addr: *align(page_size) c_void, len: usize) c_int;
|
pub extern "c" fn munmap(addr: *align(page_size) c_void, len: usize) c_int;
|
||||||
pub extern "c" fn mprotect(addr: *align(page_size) c_void, len: usize, prot: c_uint) c_int;
|
pub extern "c" fn mprotect(addr: *align(page_size) c_void, len: usize, prot: c_uint) c_int;
|
||||||
pub extern "c" fn unlink(path: [*]const u8) c_int;
|
pub extern "c" fn unlink(path: [*]const u8) c_int;
|
||||||
|
pub extern "c" fn unlinkat(dirfd: fd_t, path: [*]const u8, flags: c_uint) c_int;
|
||||||
pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
|
pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
|
||||||
pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_uint, options: c_uint) c_int;
|
pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_uint, options: c_uint) c_int;
|
||||||
pub extern "c" fn fork() c_int;
|
pub extern "c" fn fork() c_int;
|
||||||
|
@ -1312,7 +1312,7 @@ const test_tmp_dir = "std_event_fs_test";
|
|||||||
//
|
//
|
||||||
// // TODO move this into event loop too
|
// // TODO move this into event loop too
|
||||||
// try os.makePath(allocator, test_tmp_dir);
|
// try os.makePath(allocator, test_tmp_dir);
|
||||||
// defer os.deleteTree(allocator, test_tmp_dir) catch {};
|
// defer os.deleteTree(test_tmp_dir) catch {};
|
||||||
//
|
//
|
||||||
// var loop: Loop = undefined;
|
// var loop: Loop = undefined;
|
||||||
// try loop.initMultiThreaded(allocator);
|
// try loop.initMultiThreaded(allocator);
|
||||||
|
962
lib/std/fs.zig
962
lib/std/fs.zig
File diff suppressed because it is too large
Load Diff
@ -243,6 +243,7 @@ pub const File = struct {
|
|||||||
switch (rc) {
|
switch (rc) {
|
||||||
windows.STATUS.SUCCESS => {},
|
windows.STATUS.SUCCESS => {},
|
||||||
windows.STATUS.BUFFER_OVERFLOW => {},
|
windows.STATUS.BUFFER_OVERFLOW => {},
|
||||||
|
windows.STATUS.INVALID_PARAMETER => unreachable,
|
||||||
else => return windows.unexpectedStatus(rc),
|
else => return windows.unexpectedStatus(rc),
|
||||||
}
|
}
|
||||||
return Stat{
|
return Stat{
|
||||||
|
@ -136,6 +136,25 @@ pub fn isAbsolute(path: []const u8) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isAbsoluteW(path_w: [*]const u16) bool {
|
||||||
|
if (path_w[0] == '/')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (path_w[0] == '\\') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (path_w[0] == 0 or path_w[1] == 0 or path_w[2] == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (path_w[1] == ':') {
|
||||||
|
if (path_w[2] == '/')
|
||||||
|
return true;
|
||||||
|
if (path_w[2] == '\\')
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn isAbsoluteWindows(path: []const u8) bool {
|
pub fn isAbsoluteWindows(path: []const u8) bool {
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
return true;
|
return true;
|
||||||
|
@ -127,6 +127,7 @@ pub fn OutStream(comptime WriteError: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO move this to `std.fs` and add a version to `std.fs.Dir`.
|
||||||
pub fn writeFile(path: []const u8, data: []const u8) !void {
|
pub fn writeFile(path: []const u8, data: []const u8) !void {
|
||||||
var file = try File.openWrite(path);
|
var file = try File.openWrite(path);
|
||||||
defer file.close();
|
defer file.close();
|
||||||
@ -134,11 +135,13 @@ pub fn writeFile(path: []const u8, data: []const u8) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On success, caller owns returned buffer.
|
/// On success, caller owns returned buffer.
|
||||||
|
/// TODO move this to `std.fs` and add a version to `std.fs.Dir`.
|
||||||
pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
|
pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
|
||||||
return readFileAllocAligned(allocator, path, @alignOf(u8));
|
return readFileAllocAligned(allocator, path, @alignOf(u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// On success, caller owns returned buffer.
|
/// On success, caller owns returned buffer.
|
||||||
|
/// TODO move this to `std.fs` and add a version to `std.fs.Dir`.
|
||||||
pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptime A: u29) ![]align(A) u8 {
|
pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptime A: u29) ![]align(A) u8 {
|
||||||
var file = try File.openRead(path);
|
var file = try File.openRead(path);
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
149
lib/std/os.zig
149
lib/std/os.zig
@ -529,22 +529,36 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) WriteError!void
|
|||||||
|
|
||||||
pub const OpenError = error{
|
pub const OpenError = error{
|
||||||
AccessDenied,
|
AccessDenied,
|
||||||
FileTooBig,
|
|
||||||
IsDir,
|
|
||||||
SymLinkLoop,
|
SymLinkLoop,
|
||||||
ProcessFdQuotaExceeded,
|
ProcessFdQuotaExceeded,
|
||||||
NameTooLong,
|
|
||||||
SystemFdQuotaExceeded,
|
SystemFdQuotaExceeded,
|
||||||
NoDevice,
|
NoDevice,
|
||||||
FileNotFound,
|
FileNotFound,
|
||||||
|
|
||||||
|
/// The path exceeded `MAX_PATH_BYTES` bytes.
|
||||||
|
NameTooLong,
|
||||||
|
|
||||||
/// Insufficient kernel memory was available, or
|
/// Insufficient kernel memory was available, or
|
||||||
/// the named file is a FIFO and per-user hard limit on
|
/// the named file is a FIFO and per-user hard limit on
|
||||||
/// memory allocation for pipes has been reached.
|
/// memory allocation for pipes has been reached.
|
||||||
SystemResources,
|
SystemResources,
|
||||||
|
|
||||||
|
/// The file is too large to be opened. This error is unreachable
|
||||||
|
/// for 64-bit targets, as well as when opening directories.
|
||||||
|
FileTooBig,
|
||||||
|
|
||||||
|
/// The path refers to directory but the `O_DIRECTORY` flag was not provided.
|
||||||
|
IsDir,
|
||||||
|
|
||||||
|
/// A new path cannot be created because the device has no room for the new file.
|
||||||
|
/// This error is only reachable when the `O_CREAT` flag is provided.
|
||||||
NoSpaceLeft,
|
NoSpaceLeft,
|
||||||
|
|
||||||
|
/// A component used as a directory in the path was not, in fact, a directory, or
|
||||||
|
/// `O_DIRECTORY` was specified and the path was not a directory.
|
||||||
NotDir,
|
NotDir,
|
||||||
|
|
||||||
|
/// The path already exists and the `O_CREAT` and `O_EXCL` flags were provided.
|
||||||
PathAlreadyExists,
|
PathAlreadyExists,
|
||||||
DeviceBusy,
|
DeviceBusy,
|
||||||
} || UnexpectedError;
|
} || UnexpectedError;
|
||||||
@ -978,6 +992,114 @@ pub fn unlinkC(file_path: [*]const u8) UnlinkError!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const UnlinkatError = UnlinkError || error{
|
||||||
|
/// When passing `AT_REMOVEDIR`, this error occurs when the named directory is not empty.
|
||||||
|
DirNotEmpty,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Delete a file name and possibly the file it refers to, based on an open directory handle.
|
||||||
|
pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void {
|
||||||
|
if (windows.is_the_target) {
|
||||||
|
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
|
||||||
|
return unlinkatW(dirfd, &file_path_w, flags);
|
||||||
|
}
|
||||||
|
const file_path_c = try toPosixPath(file_path);
|
||||||
|
return unlinkatC(dirfd, &file_path_c, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as `unlinkat` but `file_path` is a null-terminated string.
|
||||||
|
pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatError!void {
|
||||||
|
if (windows.is_the_target) {
|
||||||
|
const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
|
||||||
|
return unlinkatW(dirfd, &file_path_w, flags);
|
||||||
|
}
|
||||||
|
switch (errno(system.unlinkat(dirfd, file_path_c, flags))) {
|
||||||
|
0 => return,
|
||||||
|
EACCES => return error.AccessDenied,
|
||||||
|
EPERM => return error.AccessDenied,
|
||||||
|
EBUSY => return error.FileBusy,
|
||||||
|
EFAULT => unreachable,
|
||||||
|
EIO => return error.FileSystem,
|
||||||
|
EISDIR => return error.IsDir,
|
||||||
|
ELOOP => return error.SymLinkLoop,
|
||||||
|
ENAMETOOLONG => return error.NameTooLong,
|
||||||
|
ENOENT => return error.FileNotFound,
|
||||||
|
ENOTDIR => return error.NotDir,
|
||||||
|
ENOMEM => return error.SystemResources,
|
||||||
|
EROFS => return error.ReadOnlyFileSystem,
|
||||||
|
ENOTEMPTY => return error.DirNotEmpty,
|
||||||
|
|
||||||
|
EINVAL => unreachable, // invalid flags, or pathname has . as last component
|
||||||
|
EBADF => unreachable, // always a race condition
|
||||||
|
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as `unlinkat` but `sub_path_w` is UTF16LE, NT prefixed. Windows only.
|
||||||
|
pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatError!void {
|
||||||
|
const w = windows;
|
||||||
|
|
||||||
|
const want_rmdir_behavior = (flags & AT_REMOVEDIR) != 0;
|
||||||
|
const create_options_flags = if (want_rmdir_behavior)
|
||||||
|
w.ULONG(w.FILE_DELETE_ON_CLOSE)
|
||||||
|
else
|
||||||
|
w.ULONG(w.FILE_DELETE_ON_CLOSE | w.FILE_NON_DIRECTORY_FILE);
|
||||||
|
|
||||||
|
const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2);
|
||||||
|
var nt_name = w.UNICODE_STRING{
|
||||||
|
.Length = path_len_bytes,
|
||||||
|
.MaximumLength = path_len_bytes,
|
||||||
|
// The Windows API makes this mutable, but it will not mutate here.
|
||||||
|
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
|
||||||
|
// Windows does not recognize this, but it does work with empty string.
|
||||||
|
nt_name.Length = 0;
|
||||||
|
}
|
||||||
|
if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
|
||||||
|
// Can't remove the parent directory with an open handle.
|
||||||
|
return error.FileBusy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var attr = w.OBJECT_ATTRIBUTES{
|
||||||
|
.Length = @sizeOf(w.OBJECT_ATTRIBUTES),
|
||||||
|
.RootDirectory = dirfd,
|
||||||
|
.Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
|
||||||
|
.ObjectName = &nt_name,
|
||||||
|
.SecurityDescriptor = null,
|
||||||
|
.SecurityQualityOfService = null,
|
||||||
|
};
|
||||||
|
var io: w.IO_STATUS_BLOCK = undefined;
|
||||||
|
var tmp_handle: w.HANDLE = undefined;
|
||||||
|
var rc = w.ntdll.NtCreateFile(
|
||||||
|
&tmp_handle,
|
||||||
|
w.SYNCHRONIZE | w.DELETE,
|
||||||
|
&attr,
|
||||||
|
&io,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE,
|
||||||
|
w.FILE_OPEN,
|
||||||
|
create_options_flags,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
if (rc == w.STATUS.SUCCESS) {
|
||||||
|
rc = w.ntdll.NtClose(tmp_handle);
|
||||||
|
}
|
||||||
|
switch (rc) {
|
||||||
|
w.STATUS.SUCCESS => return,
|
||||||
|
w.STATUS.OBJECT_NAME_INVALID => unreachable,
|
||||||
|
w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||||
|
w.STATUS.INVALID_PARAMETER => unreachable,
|
||||||
|
w.STATUS.FILE_IS_A_DIRECTORY => return error.IsDir,
|
||||||
|
else => return w.unexpectedStatus(rc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const RenameError = error{
|
const RenameError = error{
|
||||||
AccessDenied,
|
AccessDenied,
|
||||||
FileBusy,
|
FileBusy,
|
||||||
@ -1237,6 +1359,27 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn readlinkatC(dirfd: fd_t, file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
|
||||||
|
if (windows.is_the_target) {
|
||||||
|
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
|
||||||
|
@compileError("TODO implement readlink for Windows");
|
||||||
|
}
|
||||||
|
const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len);
|
||||||
|
switch (errno(rc)) {
|
||||||
|
0 => return out_buffer[0..@bitCast(usize, rc)],
|
||||||
|
EACCES => return error.AccessDenied,
|
||||||
|
EFAULT => unreachable,
|
||||||
|
EINVAL => unreachable,
|
||||||
|
EIO => return error.FileSystem,
|
||||||
|
ELOOP => return error.SymLinkLoop,
|
||||||
|
ENAMETOOLONG => return error.NameTooLong,
|
||||||
|
ENOENT => return error.FileNotFound,
|
||||||
|
ENOMEM => return error.SystemResources,
|
||||||
|
ENOTDIR => return error.NotDir,
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const SetIdError = error{
|
pub const SetIdError = error{
|
||||||
ResourceLimitReached,
|
ResourceLimitReached,
|
||||||
InvalidUserId,
|
InvalidUserId,
|
||||||
|
@ -1178,3 +1178,17 @@ pub fn S_IWHT(m: u32) bool {
|
|||||||
return m & S_IFMT == S_IFWHT;
|
return m & S_IFMT == S_IFWHT;
|
||||||
}
|
}
|
||||||
pub const HOST_NAME_MAX = 72;
|
pub const HOST_NAME_MAX = 72;
|
||||||
|
|
||||||
|
pub const AT_FDCWD = -2;
|
||||||
|
|
||||||
|
/// Use effective ids in access check
|
||||||
|
pub const AT_EACCESS = 0x0010;
|
||||||
|
|
||||||
|
/// Act on the symlink itself not the target
|
||||||
|
pub const AT_SYMLINK_NOFOLLOW = 0x0020;
|
||||||
|
|
||||||
|
/// Act on target of symlink
|
||||||
|
pub const AT_SYMLINK_FOLLOW = 0x0040;
|
||||||
|
|
||||||
|
/// Path refers to directory
|
||||||
|
pub const AT_REMOVEDIR = 0x0080;
|
||||||
|
@ -939,3 +939,23 @@ pub fn S_IWHT(m: u32) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const HOST_NAME_MAX = 255;
|
pub const HOST_NAME_MAX = 255;
|
||||||
|
|
||||||
|
/// Magic value that specify the use of the current working directory
|
||||||
|
/// to determine the target of relative file paths in the openat() and
|
||||||
|
/// similar syscalls.
|
||||||
|
pub const AT_FDCWD = -100;
|
||||||
|
|
||||||
|
/// Check access using effective user and group ID
|
||||||
|
pub const AT_EACCESS = 0x0100;
|
||||||
|
|
||||||
|
/// Do not follow symbolic links
|
||||||
|
pub const AT_SYMLINK_NOFOLLOW = 0x0200;
|
||||||
|
|
||||||
|
/// Follow symbolic link
|
||||||
|
pub const AT_SYMLINK_FOLLOW = 0x0400;
|
||||||
|
|
||||||
|
/// Remove directory instead of file
|
||||||
|
pub const AT_REMOVEDIR = 0x0800;
|
||||||
|
|
||||||
|
/// Fail if not under dirfd
|
||||||
|
pub const AT_BENEATH = 0x1000;
|
||||||
|
@ -158,3 +158,6 @@ pub const EWOULDBLOCK = 140;
|
|||||||
pub const EDQUOT = 10069;
|
pub const EDQUOT = 10069;
|
||||||
|
|
||||||
pub const F_OK = 0;
|
pub const F_OK = 0;
|
||||||
|
|
||||||
|
/// Remove directory instead of unlinking file
|
||||||
|
pub const AT_REMOVEDIR = 0x200;
|
||||||
|
@ -19,8 +19,8 @@ test "makePath, put some files in it, deleteTree" {
|
|||||||
try fs.makePath(a, "os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
|
try fs.makePath(a, "os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
|
||||||
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
|
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
|
||||||
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
|
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
|
||||||
try fs.deleteTree(a, "os_test_tmp");
|
try fs.deleteTree("os_test_tmp");
|
||||||
if (fs.Dir.open(a, "os_test_tmp")) |dir| {
|
if (fs.Dir.open("os_test_tmp")) |dir| {
|
||||||
@panic("expected error");
|
@panic("expected error");
|
||||||
} else |err| {
|
} else |err| {
|
||||||
expect(err == error.FileNotFound);
|
expect(err == error.FileNotFound);
|
||||||
@ -37,7 +37,7 @@ test "access file" {
|
|||||||
|
|
||||||
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");
|
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");
|
||||||
try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);
|
try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);
|
||||||
try fs.deleteTree(a, "os_test_tmp");
|
try fs.deleteTree("os_test_tmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testThreadIdFn(thread_id: *Thread.Id) void {
|
fn testThreadIdFn(thread_id: *Thread.Id) void {
|
||||||
|
@ -20,6 +20,8 @@ pub const shell32 = @import("windows/shell32.zig");
|
|||||||
|
|
||||||
pub usingnamespace @import("windows/bits.zig");
|
pub usingnamespace @import("windows/bits.zig");
|
||||||
|
|
||||||
|
pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize));
|
||||||
|
|
||||||
/// `builtin` is missing `subsystem` when the subsystem is automatically detected,
|
/// `builtin` is missing `subsystem` when the subsystem is automatically detected,
|
||||||
/// so Zig standard library has the subsystem detection logic here. This should generally be
|
/// so Zig standard library has the subsystem detection logic here. This should generally be
|
||||||
/// used rather than `builtin.subsystem`.
|
/// used rather than `builtin.subsystem`.
|
||||||
@ -791,6 +793,25 @@ pub fn SetFileTime(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn peb() *PEB {
|
||||||
|
switch (builtin.arch) {
|
||||||
|
.i386 => {
|
||||||
|
return asm (
|
||||||
|
\\ mov %%fs:0x18, %[ptr]
|
||||||
|
\\ mov %%ds:0x30(%[ptr]), %[ptr]
|
||||||
|
: [ptr] "=r" (-> *PEB)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
.x86_64 => {
|
||||||
|
return asm (
|
||||||
|
\\ mov %%gs:0x60, %[ptr]
|
||||||
|
: [ptr] "=r" (-> *PEB)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
else => @compileError("unsupported architecture"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A file time is a 64-bit value that represents the number of 100-nanosecond
|
/// A file time is a 64-bit value that represents the number of 100-nanosecond
|
||||||
/// intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated
|
/// intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated
|
||||||
/// Universal Time (UTC).
|
/// Universal Time (UTC).
|
||||||
@ -843,8 +864,8 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const start_index = if (mem.startsWith(u8, s, "\\\\") or !std.fs.path.isAbsolute(s)) 0 else blk: {
|
const start_index = if (mem.startsWith(u8, s, "\\?") or !std.fs.path.isAbsolute(s)) 0 else blk: {
|
||||||
const prefix = [_]u16{ '\\', '\\', '?', '\\' };
|
const prefix = [_]u16{ '\\', '?', '?', '\\' };
|
||||||
mem.copy(u16, result[0..], prefix);
|
mem.copy(u16, result[0..], prefix);
|
||||||
break :blk prefix.len;
|
break :blk prefix.len;
|
||||||
};
|
};
|
||||||
@ -878,7 +899,7 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError {
|
|||||||
/// and you get an unexpected status.
|
/// and you get an unexpected status.
|
||||||
pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
|
pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
|
||||||
if (std.os.unexpected_error_tracing) {
|
if (std.os.unexpected_error_tracing) {
|
||||||
std.debug.warn("error.Unexpected NTSTATUS={}\n", status);
|
std.debug.warn("error.Unexpected NTSTATUS=0x{x}\n", status);
|
||||||
std.debug.dumpCurrentStackTrace(null);
|
std.debug.dumpCurrentStackTrace(null);
|
||||||
}
|
}
|
||||||
return error.Unexpected;
|
return error.Unexpected;
|
||||||
|
@ -300,6 +300,44 @@ pub const FILE_SHARE_DELETE = 0x00000004;
|
|||||||
pub const FILE_SHARE_READ = 0x00000001;
|
pub const FILE_SHARE_READ = 0x00000001;
|
||||||
pub const FILE_SHARE_WRITE = 0x00000002;
|
pub const FILE_SHARE_WRITE = 0x00000002;
|
||||||
|
|
||||||
|
pub const DELETE = 0x00010000;
|
||||||
|
pub const READ_CONTROL = 0x00020000;
|
||||||
|
pub const WRITE_DAC = 0x00040000;
|
||||||
|
pub const WRITE_OWNER = 0x00080000;
|
||||||
|
pub const SYNCHRONIZE = 0x00100000;
|
||||||
|
pub const STANDARD_RIGHTS_REQUIRED = 0x000f0000;
|
||||||
|
|
||||||
|
// disposition for NtCreateFile
|
||||||
|
pub const FILE_SUPERSEDE = 0;
|
||||||
|
pub const FILE_OPEN = 1;
|
||||||
|
pub const FILE_CREATE = 2;
|
||||||
|
pub const FILE_OPEN_IF = 3;
|
||||||
|
pub const FILE_OVERWRITE = 4;
|
||||||
|
pub const FILE_OVERWRITE_IF = 5;
|
||||||
|
pub const FILE_MAXIMUM_DISPOSITION = 5;
|
||||||
|
|
||||||
|
// flags for NtCreateFile and NtOpenFile
|
||||||
|
pub const FILE_DIRECTORY_FILE = 0x00000001;
|
||||||
|
pub const FILE_WRITE_THROUGH = 0x00000002;
|
||||||
|
pub const FILE_SEQUENTIAL_ONLY = 0x00000004;
|
||||||
|
pub const FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008;
|
||||||
|
pub const FILE_SYNCHRONOUS_IO_ALERT = 0x00000010;
|
||||||
|
pub const FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020;
|
||||||
|
pub const FILE_NON_DIRECTORY_FILE = 0x00000040;
|
||||||
|
pub const FILE_CREATE_TREE_CONNECTION = 0x00000080;
|
||||||
|
pub const FILE_COMPLETE_IF_OPLOCKED = 0x00000100;
|
||||||
|
pub const FILE_NO_EA_KNOWLEDGE = 0x00000200;
|
||||||
|
pub const FILE_OPEN_FOR_RECOVERY = 0x00000400;
|
||||||
|
pub const FILE_RANDOM_ACCESS = 0x00000800;
|
||||||
|
pub const FILE_DELETE_ON_CLOSE = 0x00001000;
|
||||||
|
pub const FILE_OPEN_BY_FILE_ID = 0x00002000;
|
||||||
|
pub const FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000;
|
||||||
|
pub const FILE_NO_COMPRESSION = 0x00008000;
|
||||||
|
pub const FILE_RESERVE_OPFILTER = 0x00100000;
|
||||||
|
pub const FILE_TRANSACTED_MODE = 0x00200000;
|
||||||
|
pub const FILE_OPEN_OFFLINE_FILE = 0x00400000;
|
||||||
|
pub const FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000;
|
||||||
|
|
||||||
pub const CREATE_ALWAYS = 2;
|
pub const CREATE_ALWAYS = 2;
|
||||||
pub const CREATE_NEW = 1;
|
pub const CREATE_NEW = 1;
|
||||||
pub const OPEN_ALWAYS = 4;
|
pub const OPEN_ALWAYS = 4;
|
||||||
@ -720,15 +758,119 @@ pub const VECTORED_EXCEPTION_HANDLER = stdcallcc fn (ExceptionInfo: *EXCEPTION_P
|
|||||||
|
|
||||||
pub const OBJECT_ATTRIBUTES = extern struct {
|
pub const OBJECT_ATTRIBUTES = extern struct {
|
||||||
Length: ULONG,
|
Length: ULONG,
|
||||||
RootDirectory: HANDLE,
|
RootDirectory: ?HANDLE,
|
||||||
ObjectName: *UNICODE_STRING,
|
ObjectName: *UNICODE_STRING,
|
||||||
Attributes: ULONG,
|
Attributes: ULONG,
|
||||||
SecurityDescriptor: ?*c_void,
|
SecurityDescriptor: ?*c_void,
|
||||||
SecurityQualityOfService: ?*c_void,
|
SecurityQualityOfService: ?*c_void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const OBJ_INHERIT = 0x00000002;
|
||||||
|
pub const OBJ_PERMANENT = 0x00000010;
|
||||||
|
pub const OBJ_EXCLUSIVE = 0x00000020;
|
||||||
|
pub const OBJ_CASE_INSENSITIVE = 0x00000040;
|
||||||
|
pub const OBJ_OPENIF = 0x00000080;
|
||||||
|
pub const OBJ_OPENLINK = 0x00000100;
|
||||||
|
pub const OBJ_KERNEL_HANDLE = 0x00000200;
|
||||||
|
pub const OBJ_VALID_ATTRIBUTES = 0x000003F2;
|
||||||
|
|
||||||
pub const UNICODE_STRING = extern struct {
|
pub const UNICODE_STRING = extern struct {
|
||||||
Length: USHORT,
|
Length: c_ushort,
|
||||||
MaximumLength: USHORT,
|
MaximumLength: c_ushort,
|
||||||
Buffer: [*]WCHAR,
|
Buffer: [*]WCHAR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const PEB = extern struct {
|
||||||
|
Reserved1: [2]BYTE,
|
||||||
|
BeingDebugged: BYTE,
|
||||||
|
Reserved2: [1]BYTE,
|
||||||
|
Reserved3: [2]PVOID,
|
||||||
|
Ldr: *PEB_LDR_DATA,
|
||||||
|
ProcessParameters: *RTL_USER_PROCESS_PARAMETERS,
|
||||||
|
Reserved4: [3]PVOID,
|
||||||
|
AtlThunkSListPtr: PVOID,
|
||||||
|
Reserved5: PVOID,
|
||||||
|
Reserved6: ULONG,
|
||||||
|
Reserved7: PVOID,
|
||||||
|
Reserved8: ULONG,
|
||||||
|
AtlThunkSListPtr32: ULONG,
|
||||||
|
Reserved9: [45]PVOID,
|
||||||
|
Reserved10: [96]BYTE,
|
||||||
|
PostProcessInitRoutine: PPS_POST_PROCESS_INIT_ROUTINE,
|
||||||
|
Reserved11: [128]BYTE,
|
||||||
|
Reserved12: [1]PVOID,
|
||||||
|
SessionId: ULONG,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PEB_LDR_DATA = extern struct {
|
||||||
|
Reserved1: [8]BYTE,
|
||||||
|
Reserved2: [3]PVOID,
|
||||||
|
InMemoryOrderModuleList: LIST_ENTRY,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RTL_USER_PROCESS_PARAMETERS = extern struct {
|
||||||
|
AllocationSize: ULONG,
|
||||||
|
Size: ULONG,
|
||||||
|
Flags: ULONG,
|
||||||
|
DebugFlags: ULONG,
|
||||||
|
ConsoleHandle: HANDLE,
|
||||||
|
ConsoleFlags: ULONG,
|
||||||
|
hStdInput: HANDLE,
|
||||||
|
hStdOutput: HANDLE,
|
||||||
|
hStdError: HANDLE,
|
||||||
|
CurrentDirectory: CURDIR,
|
||||||
|
DllPath: UNICODE_STRING,
|
||||||
|
ImagePathName: UNICODE_STRING,
|
||||||
|
CommandLine: UNICODE_STRING,
|
||||||
|
Environment: [*]WCHAR,
|
||||||
|
dwX: ULONG,
|
||||||
|
dwY: ULONG,
|
||||||
|
dwXSize: ULONG,
|
||||||
|
dwYSize: ULONG,
|
||||||
|
dwXCountChars: ULONG,
|
||||||
|
dwYCountChars: ULONG,
|
||||||
|
dwFillAttribute: ULONG,
|
||||||
|
dwFlags: ULONG,
|
||||||
|
dwShowWindow: ULONG,
|
||||||
|
WindowTitle: UNICODE_STRING,
|
||||||
|
Desktop: UNICODE_STRING,
|
||||||
|
ShellInfo: UNICODE_STRING,
|
||||||
|
RuntimeInfo: UNICODE_STRING,
|
||||||
|
DLCurrentDirectory: [0x20]RTL_DRIVE_LETTER_CURDIR,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RTL_DRIVE_LETTER_CURDIR = extern struct {
|
||||||
|
Flags: c_ushort,
|
||||||
|
Length: c_ushort,
|
||||||
|
TimeStamp: ULONG,
|
||||||
|
DosPath: UNICODE_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PPS_POST_PROCESS_INIT_ROUTINE = ?extern fn () void;
|
||||||
|
|
||||||
|
pub const FILE_BOTH_DIR_INFORMATION = extern struct {
|
||||||
|
NextEntryOffset: ULONG,
|
||||||
|
FileIndex: ULONG,
|
||||||
|
CreationTime: LARGE_INTEGER,
|
||||||
|
LastAccessTime: LARGE_INTEGER,
|
||||||
|
LastWriteTime: LARGE_INTEGER,
|
||||||
|
ChangeTime: LARGE_INTEGER,
|
||||||
|
EndOfFile: LARGE_INTEGER,
|
||||||
|
AllocationSize: LARGE_INTEGER,
|
||||||
|
FileAttributes: ULONG,
|
||||||
|
FileNameLength: ULONG,
|
||||||
|
EaSize: ULONG,
|
||||||
|
ShortNameLength: CHAR,
|
||||||
|
ShortName: [12]WCHAR,
|
||||||
|
FileName: [1]WCHAR,
|
||||||
|
};
|
||||||
|
pub const FILE_BOTH_DIRECTORY_INFORMATION = FILE_BOTH_DIR_INFORMATION;
|
||||||
|
|
||||||
|
pub const IO_APC_ROUTINE = extern fn (PVOID, *IO_STATUS_BLOCK, ULONG) void;
|
||||||
|
|
||||||
|
pub const CURDIR = extern struct {
|
||||||
|
DosPath: UNICODE_STRING,
|
||||||
|
Handle: HANDLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DUPLICATE_SAME_ACCESS = 2;
|
@ -47,6 +47,8 @@ pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_
|
|||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;
|
pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;
|
||||||
|
|
||||||
|
pub extern "kernel32" stdcallcc fn DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
|
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
|
pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
|
||||||
|
@ -13,12 +13,33 @@ pub extern "NtDll" stdcallcc fn NtCreateFile(
|
|||||||
DesiredAccess: ACCESS_MASK,
|
DesiredAccess: ACCESS_MASK,
|
||||||
ObjectAttributes: *OBJECT_ATTRIBUTES,
|
ObjectAttributes: *OBJECT_ATTRIBUTES,
|
||||||
IoStatusBlock: *IO_STATUS_BLOCK,
|
IoStatusBlock: *IO_STATUS_BLOCK,
|
||||||
AllocationSize: *LARGE_INTEGER,
|
AllocationSize: ?*LARGE_INTEGER,
|
||||||
FileAttributes: ULONG,
|
FileAttributes: ULONG,
|
||||||
ShareAccess: ULONG,
|
ShareAccess: ULONG,
|
||||||
CreateDisposition: ULONG,
|
CreateDisposition: ULONG,
|
||||||
CreateOptions: ULONG,
|
CreateOptions: ULONG,
|
||||||
EaBuffer: *c_void,
|
EaBuffer: ?*c_void,
|
||||||
EaLength: ULONG,
|
EaLength: ULONG,
|
||||||
) NTSTATUS;
|
) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtClose(Handle: HANDLE) NTSTATUS;
|
pub extern "NtDll" stdcallcc fn NtClose(Handle: HANDLE) NTSTATUS;
|
||||||
|
pub extern "NtDll" stdcallcc fn RtlDosPathNameToNtPathName_U(
|
||||||
|
DosPathName: [*]const u16,
|
||||||
|
NtPathName: *UNICODE_STRING,
|
||||||
|
NtFileNamePart: ?*?[*]const u16,
|
||||||
|
DirectoryInfo: ?*CURDIR,
|
||||||
|
) BOOL;
|
||||||
|
pub extern "NtDll" stdcallcc fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) void;
|
||||||
|
|
||||||
|
pub extern "NtDll" stdcallcc fn NtQueryDirectoryFile(
|
||||||
|
FileHandle: HANDLE,
|
||||||
|
Event: ?HANDLE,
|
||||||
|
ApcRoutine: ?IO_APC_ROUTINE,
|
||||||
|
ApcContext: ?*c_void,
|
||||||
|
IoStatusBlock: *IO_STATUS_BLOCK,
|
||||||
|
FileInformation: *c_void,
|
||||||
|
Length: ULONG,
|
||||||
|
FileInformationClass: FILE_INFORMATION_CLASS,
|
||||||
|
ReturnSingleEntry: BOOLEAN,
|
||||||
|
FileName: ?*UNICODE_STRING,
|
||||||
|
RestartScan: BOOLEAN,
|
||||||
|
) NTSTATUS;
|
||||||
|
@ -3,3 +3,11 @@ pub const SUCCESS = 0x00000000;
|
|||||||
|
|
||||||
/// The data was too large to fit into the specified buffer.
|
/// The data was too large to fit into the specified buffer.
|
||||||
pub const BUFFER_OVERFLOW = 0x80000005;
|
pub const BUFFER_OVERFLOW = 0x80000005;
|
||||||
|
|
||||||
|
pub const INVALID_PARAMETER = 0xC000000D;
|
||||||
|
pub const ACCESS_DENIED = 0xC0000022;
|
||||||
|
pub const OBJECT_NAME_INVALID = 0xC0000033;
|
||||||
|
pub const OBJECT_NAME_NOT_FOUND = 0xC0000034;
|
||||||
|
pub const OBJECT_PATH_NOT_FOUND = 0xC000003A;
|
||||||
|
pub const OBJECT_PATH_SYNTAX_BAD = 0xC000003B;
|
||||||
|
pub const FILE_IS_A_DIRECTORY = 0xC00000BA;
|
||||||
|
@ -16,14 +16,17 @@ pub fn main() anyerror!void {
|
|||||||
var test_node = root_node.start(test_fn.name, null);
|
var test_node = root_node.start(test_fn.name, null);
|
||||||
test_node.activate();
|
test_node.activate();
|
||||||
progress.refresh();
|
progress.refresh();
|
||||||
|
if (progress.terminal == null) std.debug.warn("{}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
|
||||||
if (test_fn.func()) |_| {
|
if (test_fn.func()) |_| {
|
||||||
ok_count += 1;
|
ok_count += 1;
|
||||||
test_node.end();
|
test_node.end();
|
||||||
|
if (progress.terminal == null) std.debug.warn("OK\n");
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.SkipZigTest => {
|
error.SkipZigTest => {
|
||||||
skip_count += 1;
|
skip_count += 1;
|
||||||
test_node.end();
|
test_node.end();
|
||||||
progress.log("{}...SKIP\n", test_fn.name);
|
progress.log("{}...SKIP\n", test_fn.name);
|
||||||
|
if (progress.terminal == null) std.debug.warn("SKIP\n");
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
progress.log("");
|
progress.log("");
|
||||||
@ -32,7 +35,9 @@ pub fn main() anyerror!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
root_node.end();
|
root_node.end();
|
||||||
if (ok_count != test_fn_list.len) {
|
if (ok_count == test_fn_list.len) {
|
||||||
|
std.debug.warn("All tests passed.\n");
|
||||||
|
} else {
|
||||||
std.debug.warn("{} passed; {} skipped.\n", ok_count, skip_count);
|
std.debug.warn("{} passed; {} skipped.\n", ok_count, skip_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,7 +747,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
|
|||||||
)) catch |err| switch (err) {
|
)) catch |err| switch (err) {
|
||||||
error.IsDir, error.AccessDenied => {
|
error.IsDir, error.AccessDenied => {
|
||||||
// TODO make event based (and dir.next())
|
// TODO make event based (and dir.next())
|
||||||
var dir = try fs.Dir.open(fmt.loop.allocator, file_path);
|
var dir = try fs.Dir.open(file_path);
|
||||||
defer dir.close();
|
defer dir.close();
|
||||||
|
|
||||||
var group = event.Group(FmtError!void).init(fmt.loop);
|
var group = event.Group(FmtError!void).init(fmt.loop);
|
||||||
|
@ -283,11 +283,13 @@ fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void
|
|||||||
const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
|
const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
|
||||||
error.IsDir, error.AccessDenied => {
|
error.IsDir, error.AccessDenied => {
|
||||||
// TODO make event based (and dir.next())
|
// TODO make event based (and dir.next())
|
||||||
var dir = try fs.Dir.open(fmt.allocator, file_path);
|
var dir = try fs.Dir.open(file_path);
|
||||||
defer dir.close();
|
defer dir.close();
|
||||||
|
|
||||||
while (try dir.next()) |entry| {
|
var dir_it = dir.iterate();
|
||||||
if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
|
|
||||||
|
while (try dir_it.next()) |entry| {
|
||||||
|
if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
|
||||||
const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
|
const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
|
||||||
try fmtPath(fmt, full_path, check_mode);
|
try fmtPath(fmt, full_path, check_mode);
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,11 @@ pub const TestContext = struct {
|
|||||||
errdefer allocator.free(self.zig_lib_dir);
|
errdefer allocator.free(self.zig_lib_dir);
|
||||||
|
|
||||||
try std.fs.makePath(allocator, tmp_dir_name);
|
try std.fs.makePath(allocator, tmp_dir_name);
|
||||||
errdefer std.fs.deleteTree(allocator, tmp_dir_name) catch {};
|
errdefer std.fs.deleteTree(tmp_dir_name) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *TestContext) void {
|
fn deinit(self: *TestContext) void {
|
||||||
std.fs.deleteTree(allocator, tmp_dir_name) catch {};
|
std.fs.deleteTree(tmp_dir_name) catch {};
|
||||||
allocator.free(self.zig_lib_dir);
|
allocator.free(self.zig_lib_dir);
|
||||||
self.zig_compiler.deinit();
|
self.zig_compiler.deinit();
|
||||||
self.loop.deinit();
|
self.loop.deinit();
|
||||||
|
@ -37,7 +37,7 @@ pub fn main() !void {
|
|||||||
testMissingOutputPath,
|
testMissingOutputPath,
|
||||||
};
|
};
|
||||||
for (test_fns) |testFn| {
|
for (test_fns) |testFn| {
|
||||||
try fs.deleteTree(a, dir_path);
|
try fs.deleteTree(dir_path);
|
||||||
try fs.makeDir(dir_path);
|
try fs.makeDir(dir_path);
|
||||||
try testFn(zig_exe, dir_path);
|
try testFn(zig_exe, dir_path);
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult {
|
|||||||
fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
|
fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
|
||||||
_ = try exec(dir_path, [_][]const u8{ zig_exe, "init-lib" });
|
_ = try exec(dir_path, [_][]const u8{ zig_exe, "init-lib" });
|
||||||
const test_result = try exec(dir_path, [_][]const u8{ zig_exe, "build", "test" });
|
const test_result = try exec(dir_path, [_][]const u8{ zig_exe, "build", "test" });
|
||||||
testing.expect(std.mem.eql(u8, test_result.stderr, ""));
|
testing.expect(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
|
fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
|
||||||
|
@ -340,7 +340,7 @@ pub fn main() !void {
|
|||||||
try dir_stack.append(target_include_dir);
|
try dir_stack.append(target_include_dir);
|
||||||
|
|
||||||
while (dir_stack.popOrNull()) |full_dir_name| {
|
while (dir_stack.popOrNull()) |full_dir_name| {
|
||||||
var dir = std.fs.Dir.open(allocator, full_dir_name) catch |err| switch (err) {
|
var dir = std.fs.Dir.open(full_dir_name) catch |err| switch (err) {
|
||||||
error.FileNotFound => continue :search,
|
error.FileNotFound => continue :search,
|
||||||
error.AccessDenied => continue :search,
|
error.AccessDenied => continue :search,
|
||||||
else => return err,
|
else => return err,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user