authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-30 01:03:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-30 01:03:38-04:00
loge14db2366160840e0c25f3a467ff984304831e4c
tree28db45a4b1230bd48325fe6ac715b42b4a0f1049
parent54987c3d8f358e4ded9113a9ee5fa04dc1372a56

run zig fmt on std/os/index.zig


1 files changed, 202 insertions(+), 126 deletions(-)

std/os/index.zig+202-126
...@@ -3,7 +3,8 @@ const builtin = @import("builtin");...@@ -3,7 +3,8 @@ const builtin = @import("builtin");
3const Os = builtin.Os;3const Os = builtin.Os;
4const is_windows = builtin.os == Os.windows;4const is_windows = builtin.os == Os.windows;
5const is_posix = switch (builtin.os) {5const is_posix = switch (builtin.os) {
6 builtin.Os.linux, builtin.Os.macosx => true,6 builtin.Os.linux,
7 builtin.Os.macosx => true,
7 else => false,8 else => false,
8};9};
9const os = this;10const os = this;
...@@ -24,9 +25,10 @@ pub const windows = @import("windows/index.zig");...@@ -24,9 +25,10 @@ pub const windows = @import("windows/index.zig");
24pub const darwin = @import("darwin.zig");25pub const darwin = @import("darwin.zig");
25pub const linux = @import("linux/index.zig");26pub const linux = @import("linux/index.zig");
26pub const zen = @import("zen.zig");27pub const zen = @import("zen.zig");
27pub const posix = switch(builtin.os) {28pub const posix = switch (builtin.os) {
28 Os.linux => linux,29 Os.linux => linux,
29 Os.macosx, Os.ios => darwin,30 Os.macosx,
31 Os.ios => darwin,
30 Os.zen => zen,32 Os.zen => zen,
31 else => @compileError("Unsupported OS"),33 else => @compileError("Unsupported OS"),
32};34};
...@@ -58,7 +60,7 @@ pub const windowsWrite = windows_util.windowsWrite;...@@ -58,7 +60,7 @@ pub const windowsWrite = windows_util.windowsWrite;
58pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;60pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
59pub const windowsOpen = windows_util.windowsOpen;61pub const windowsOpen = windows_util.windowsOpen;
60pub const windowsLoadDll = windows_util.windowsLoadDll;62pub const windowsLoadDll = windows_util.windowsLoadDll;
61pub const windowsUnloadDll = windows_util.windowsUnloadDll; 63pub const windowsUnloadDll = windows_util.windowsUnloadDll;
62pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;64pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;
6365
64pub const WindowsWaitError = windows_util.WaitError;66pub const WindowsWaitError = windows_util.WaitError;
...@@ -97,9 +99,9 @@ pub fn getRandomBytes(buf: []u8) !void {...@@ -97,9 +99,9 @@ pub fn getRandomBytes(buf: []u8) !void {
97 switch (err) {99 switch (err) {
98 posix.EINVAL => unreachable,100 posix.EINVAL => unreachable,
99 posix.EFAULT => unreachable,101 posix.EFAULT => unreachable,
100 posix.EINTR => continue,102 posix.EINTR => continue,
101 posix.ENOSYS => {103 posix.ENOSYS => {
102 const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0);104 const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0);
103 defer close(fd);105 defer close(fd);
104106
105 try posixRead(fd, buf);107 try posixRead(fd, buf);
...@@ -110,8 +112,9 @@ pub fn getRandomBytes(buf: []u8) !void {...@@ -110,8 +112,9 @@ pub fn getRandomBytes(buf: []u8) !void {
110 }112 }
111 return;113 return;
112 },114 },
113 Os.macosx, Os.ios => {115 Os.macosx,
114 const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0);116 Os.ios => {
117 const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0);
115 defer close(fd);118 defer close(fd);
116119
117 try posixRead(fd, buf);120 try posixRead(fd, buf);
...@@ -134,7 +137,20 @@ pub fn getRandomBytes(buf: []u8) !void {...@@ -134,7 +137,20 @@ pub fn getRandomBytes(buf: []u8) !void {
134 }137 }
135 },138 },
136 Os.zen => {139 Os.zen => {
137 const randomness = []u8 {42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45};140 const randomness = []u8 {
141 42,
142 1,
143 7,
144 12,
145 22,
146 17,
147 99,
148 16,
149 26,
150 87,
151 41,
152 45,
153 };
138 var i: usize = 0;154 var i: usize = 0;
139 while (i < buf.len) : (i += 1) {155 while (i < buf.len) : (i += 1) {
140 if (i > randomness.len) return error.Unknown;156 if (i > randomness.len) return error.Unknown;
...@@ -159,7 +175,9 @@ pub fn abort() noreturn {...@@ -159,7 +175,9 @@ pub fn abort() noreturn {
159 c.abort();175 c.abort();
160 }176 }
161 switch (builtin.os) {177 switch (builtin.os) {
162 Os.linux, Os.macosx, Os.ios => {178 Os.linux,
179 Os.macosx,
180 Os.ios => {
163 _ = posix.raise(posix.SIGABRT);181 _ = posix.raise(posix.SIGABRT);
164 _ = posix.raise(posix.SIGKILL);182 _ = posix.raise(posix.SIGKILL);
165 while (true) {}183 while (true) {}
...@@ -181,7 +199,9 @@ pub fn exit(status: u8) noreturn {...@@ -181,7 +199,9 @@ pub fn exit(status: u8) noreturn {
181 c.exit(status);199 c.exit(status);
182 }200 }
183 switch (builtin.os) {201 switch (builtin.os) {
184 Os.linux, Os.macosx, Os.ios => {202 Os.linux,
203 Os.macosx,
204 Os.ios => {
185 posix.exit(status);205 posix.exit(status);
186 },206 },
187 Os.windows => {207 Os.windows => {
...@@ -230,12 +250,14 @@ pub fn posixRead(fd: i32, buf: []u8) !void {...@@ -230,12 +250,14 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
230 if (err > 0) {250 if (err > 0) {
231 return switch (err) {251 return switch (err) {
232 posix.EINTR => continue,252 posix.EINTR => continue,
233 posix.EINVAL, posix.EFAULT => unreachable,253 posix.EINVAL,
254 posix.EFAULT => unreachable,
234 posix.EAGAIN => error.WouldBlock,255 posix.EAGAIN => error.WouldBlock,
235 posix.EBADF => error.FileClosed,256 posix.EBADF => error.FileClosed,
236 posix.EIO => error.InputOutput,257 posix.EIO => error.InputOutput,
237 posix.EISDIR => error.IsDir,258 posix.EISDIR => error.IsDir,
238 posix.ENOBUFS, posix.ENOMEM => error.SystemResources,259 posix.ENOBUFS,
260 posix.ENOMEM => error.SystemResources,
239 else => unexpectedErrorPosix(err),261 else => unexpectedErrorPosix(err),
240 };262 };
241 }263 }
...@@ -269,18 +291,19 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {...@@ -269,18 +291,19 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
269 const write_err = posix.getErrno(rc);291 const write_err = posix.getErrno(rc);
270 if (write_err > 0) {292 if (write_err > 0) {
271 return switch (write_err) {293 return switch (write_err) {
272 posix.EINTR => continue,294 posix.EINTR => continue,
273 posix.EINVAL, posix.EFAULT => unreachable,295 posix.EINVAL,
296 posix.EFAULT => unreachable,
274 posix.EAGAIN => PosixWriteError.WouldBlock,297 posix.EAGAIN => PosixWriteError.WouldBlock,
275 posix.EBADF => PosixWriteError.FileClosed,298 posix.EBADF => PosixWriteError.FileClosed,
276 posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,299 posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,
277 posix.EDQUOT => PosixWriteError.DiskQuota,300 posix.EDQUOT => PosixWriteError.DiskQuota,
278 posix.EFBIG => PosixWriteError.FileTooBig,301 posix.EFBIG => PosixWriteError.FileTooBig,
279 posix.EIO => PosixWriteError.InputOutput,302 posix.EIO => PosixWriteError.InputOutput,
280 posix.ENOSPC => PosixWriteError.NoSpaceLeft,303 posix.ENOSPC => PosixWriteError.NoSpaceLeft,
281 posix.EPERM => PosixWriteError.AccessDenied,304 posix.EPERM => PosixWriteError.AccessDenied,
282 posix.EPIPE => PosixWriteError.BrokenPipe,305 posix.EPIPE => PosixWriteError.BrokenPipe,
283 else => unexpectedErrorPosix(write_err),306 else => unexpectedErrorPosix(write_err),
284 };307 };
285 }308 }
286 index += rc;309 index += rc;
...@@ -326,7 +349,8 @@ pub fn posixOpenC(file_path: &const u8, flags: u32, perm: usize) !i32 {...@@ -326,7 +349,8 @@ pub fn posixOpenC(file_path: &const u8, flags: u32, perm: usize) !i32 {
326 posix.EFAULT => unreachable,349 posix.EFAULT => unreachable,
327 posix.EINVAL => unreachable,350 posix.EINVAL => unreachable,
328 posix.EACCES => return PosixOpenError.AccessDenied,351 posix.EACCES => return PosixOpenError.AccessDenied,
329 posix.EFBIG, posix.EOVERFLOW => return PosixOpenError.FileTooBig,352 posix.EFBIG,
353 posix.EOVERFLOW => return PosixOpenError.FileTooBig,
330 posix.EISDIR => return PosixOpenError.IsDir,354 posix.EISDIR => return PosixOpenError.IsDir,
331 posix.ELOOP => return PosixOpenError.SymLinkLoop,355 posix.ELOOP => return PosixOpenError.SymLinkLoop,
332 posix.EMFILE => return PosixOpenError.ProcessFdQuotaExceeded,356 posix.EMFILE => return PosixOpenError.ProcessFdQuotaExceeded,
...@@ -351,7 +375,8 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) !void {...@@ -351,7 +375,8 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) !void {
351 const err = posix.getErrno(posix.dup2(old_fd, new_fd));375 const err = posix.getErrno(posix.dup2(old_fd, new_fd));
352 if (err > 0) {376 if (err > 0) {
353 return switch (err) {377 return switch (err) {
354 posix.EBUSY, posix.EINTR => continue,378 posix.EBUSY,
379 posix.EINTR => continue,
355 posix.EMFILE => error.ProcessFdQuotaExceeded,380 posix.EMFILE => error.ProcessFdQuotaExceeded,
356 posix.EINVAL => unreachable,381 posix.EINVAL => unreachable,
357 else => unexpectedErrorPosix(err),382 else => unexpectedErrorPosix(err),
...@@ -386,7 +411,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap)...@@ -386,7 +411,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap)
386411
387pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void {412pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void {
388 for (envp_buf) |env| {413 for (envp_buf) |env| {
389 const env_buf = if (env) |ptr| ptr[0 .. cstr.len(ptr) + 1] else break;414 const env_buf = if (env) |ptr| ptr[0..cstr.len(ptr) + 1] else break;
390 allocator.free(env_buf);415 allocator.free(env_buf);
391 }416 }
392 allocator.free(envp_buf);417 allocator.free(envp_buf);
...@@ -397,9 +422,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void {...@@ -397,9 +422,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void {
397/// pointers after the args and after the environment variables.422/// pointers after the args and after the environment variables.
398/// `argv[0]` is the executable path.423/// `argv[0]` is the executable path.
399/// This function also uses the PATH environment variable to get the full path to the executable.424/// This function also uses the PATH environment variable to get the full path to the executable.
400pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap,425pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, allocator: &Allocator) !void {
401 allocator: &Allocator) !void
402{
403 const argv_buf = try allocator.alloc(?&u8, argv.len + 1);426 const argv_buf = try allocator.alloc(?&u8, argv.len + 1);
404 mem.set(?&u8, argv_buf, null);427 mem.set(?&u8, argv_buf, null);
405 defer {428 defer {
...@@ -438,7 +461,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap,...@@ -438,7 +461,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap,
438 while (it.next()) |search_path| {461 while (it.next()) |search_path| {
439 mem.copy(u8, path_buf, search_path);462 mem.copy(u8, path_buf, search_path);
440 path_buf[search_path.len] = '/';463 path_buf[search_path.len] = '/';
441 mem.copy(u8, path_buf[search_path.len + 1 ..], exe_path);464 mem.copy(u8, path_buf[search_path.len + 1..], exe_path);
442 path_buf[search_path.len + exe_path.len + 1] = 0;465 path_buf[search_path.len + exe_path.len + 1] = 0;
443 err = posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr));466 err = posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr));
444 assert(err > 0);467 assert(err > 0);
...@@ -470,10 +493,17 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {...@@ -470,10 +493,17 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {
470 assert(err > 0);493 assert(err > 0);
471 return switch (err) {494 return switch (err) {
472 posix.EFAULT => unreachable,495 posix.EFAULT => unreachable,
473 posix.E2BIG, posix.EMFILE, posix.ENAMETOOLONG, posix.ENFILE, posix.ENOMEM => error.SystemResources,496 posix.E2BIG,
474 posix.EACCES, posix.EPERM => error.AccessDenied,497 posix.EMFILE,
475 posix.EINVAL, posix.ENOEXEC => error.InvalidExe,498 posix.ENAMETOOLONG,
476 posix.EIO, posix.ELOOP => error.FileSystem,499 posix.ENFILE,
500 posix.ENOMEM => error.SystemResources,
501 posix.EACCES,
502 posix.EPERM => error.AccessDenied,
503 posix.EINVAL,
504 posix.ENOEXEC => error.InvalidExe,
505 posix.EIO,
506 posix.ELOOP => error.FileSystem,
477 posix.EISDIR => error.IsDir,507 posix.EISDIR => error.IsDir,
478 posix.ENOENT => error.FileNotFound,508 posix.ENOENT => error.FileNotFound,
479 posix.ENOTDIR => error.NotDir,509 posix.ENOTDIR => error.NotDir,
...@@ -482,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {...@@ -482,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {
482 };512 };
483}513}
484514
485pub var linux_aux_raw = []usize{0} ** 38;515pub var linux_aux_raw = []usize {0} ** 38;
486pub var posix_environ_raw: []&u8 = undefined;516pub var posix_environ_raw: []&u8 = undefined;
487517
488/// Caller must free result when done.518/// Caller must free result when done.
...@@ -496,8 +526,7 @@ pub fn getEnvMap(allocator: &Allocator) !BufMap {...@@ -496,8 +526,7 @@ pub fn getEnvMap(allocator: &Allocator) !BufMap {
496526
497 var i: usize = 0;527 var i: usize = 0;
498 while (true) {528 while (true) {
499 if (ptr[i] == 0)529 if (ptr[i] == 0) return result;
500 return result;
501530
502 const key_start = i;531 const key_start = i;
503532
...@@ -535,8 +564,7 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {...@@ -535,8 +564,7 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
535 var line_i: usize = 0;564 var line_i: usize = 0;
536 while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}565 while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
537 const this_key = ptr[0..line_i];566 const this_key = ptr[0..line_i];
538 if (!mem.eql(u8, key, this_key))567 if (!mem.eql(u8, key, this_key)) continue;
539 continue;
540568
541 var end_i: usize = line_i;569 var end_i: usize = line_i;
542 while (ptr[end_i] != 0) : (end_i += 1) {}570 while (ptr[end_i] != 0) : (end_i += 1) {}
...@@ -689,8 +717,10 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path:...@@ -689,8 +717,10 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path:
689 const err = posix.getErrno(posix.symlink(existing_buf.ptr, new_buf.ptr));717 const err = posix.getErrno(posix.symlink(existing_buf.ptr, new_buf.ptr));
690 if (err > 0) {718 if (err > 0) {
691 return switch (err) {719 return switch (err) {
692 posix.EFAULT, posix.EINVAL => unreachable,720 posix.EFAULT,
693 posix.EACCES, posix.EPERM => error.AccessDenied,721 posix.EINVAL => unreachable,
722 posix.EACCES,
723 posix.EPERM => error.AccessDenied,
694 posix.EDQUOT => error.DiskQuota,724 posix.EDQUOT => error.DiskQuota,
695 posix.EEXIST => error.PathAlreadyExists,725 posix.EEXIST => error.PathAlreadyExists,
696 posix.EIO => error.FileSystem,726 posix.EIO => error.FileSystem,
...@@ -707,9 +737,7 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path:...@@ -707,9 +737,7 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path:
707}737}
708738
709// here we replace the standard +/ with -_ so that it can be used in a file name739// here we replace the standard +/ with -_ so that it can be used in a file name
710const b64_fs_encoder = base64.Base64Encoder.init(740const b64_fs_encoder = base64.Base64Encoder.init("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", base64.standard_pad_char);
711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
712 base64.standard_pad_char);
713741
714pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void {742pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void {
715 if (symLink(allocator, existing_path, new_path)) {743 if (symLink(allocator, existing_path, new_path)) {
...@@ -728,7 +756,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path:...@@ -728,7 +756,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path:
728 tmp_path[dirname.len] = os.path.sep;756 tmp_path[dirname.len] = os.path.sep;
729 while (true) {757 while (true) {
730 try getRandomBytes(rand_buf[0..]);758 try getRandomBytes(rand_buf[0..]);
731 b64_fs_encoder.encode(tmp_path[dirname.len + 1 ..], rand_buf);759 b64_fs_encoder.encode(tmp_path[dirname.len + 1..], rand_buf);
732760
733 if (symLink(allocator, existing_path, tmp_path)) {761 if (symLink(allocator, existing_path, tmp_path)) {
734 return rename(allocator, tmp_path, new_path);762 return rename(allocator, tmp_path, new_path);
...@@ -737,7 +765,6 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path:...@@ -737,7 +765,6 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path:
737 else => return err, // TODO zig should know this set does not include PathAlreadyExists765 else => return err, // TODO zig should know this set does not include PathAlreadyExists
738 }766 }
739 }767 }
740
741}768}
742769
743pub fn deleteFile(allocator: &Allocator, file_path: []const u8) !void {770pub fn deleteFile(allocator: &Allocator, file_path: []const u8) !void {
...@@ -760,7 +787,8 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) !void {...@@ -760,7 +787,8 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) !void {
760 return switch (err) {787 return switch (err) {
761 windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,788 windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
762 windows.ERROR.ACCESS_DENIED => error.AccessDenied,789 windows.ERROR.ACCESS_DENIED => error.AccessDenied,
763 windows.ERROR.FILENAME_EXCED_RANGE, windows.ERROR.INVALID_PARAMETER => error.NameTooLong,790 windows.ERROR.FILENAME_EXCED_RANGE,
791 windows.ERROR.INVALID_PARAMETER => error.NameTooLong,
764 else => unexpectedErrorWindows(err),792 else => unexpectedErrorWindows(err),
765 };793 };
766 }794 }
...@@ -776,9 +804,11 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) !void {...@@ -776,9 +804,11 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) !void {
776 const err = posix.getErrno(posix.unlink(buf.ptr));804 const err = posix.getErrno(posix.unlink(buf.ptr));
777 if (err > 0) {805 if (err > 0) {
778 return switch (err) {806 return switch (err) {
779 posix.EACCES, posix.EPERM => error.AccessDenied,807 posix.EACCES,
808 posix.EPERM => error.AccessDenied,
780 posix.EBUSY => error.FileBusy,809 posix.EBUSY => error.FileBusy,
781 posix.EFAULT, posix.EINVAL => unreachable,810 posix.EFAULT,
811 posix.EINVAL => unreachable,
782 posix.EIO => error.FileSystem,812 posix.EIO => error.FileSystem,
783 posix.EISDIR => error.IsDir,813 posix.EISDIR => error.IsDir,
784 posix.ELOOP => error.SymLinkLoop,814 posix.ELOOP => error.SymLinkLoop,
...@@ -856,7 +886,7 @@ pub const AtomicFile = struct {...@@ -856,7 +886,7 @@ pub const AtomicFile = struct {
856886
857 while (true) {887 while (true) {
858 try getRandomBytes(rand_buf[0..]);888 try getRandomBytes(rand_buf[0..]);
859 b64_fs_encoder.encode(tmp_path[dirname.len + 1 ..], rand_buf);889 b64_fs_encoder.encode(tmp_path[dirname.len + 1..], rand_buf);
860890
861 const file = os.File.openWriteNoClobber(allocator, tmp_path, mode) catch |err| switch (err) {891 const file = os.File.openWriteNoClobber(allocator, tmp_path, mode) catch |err| switch (err) {
862 error.PathAlreadyExists => continue,892 error.PathAlreadyExists => continue,
...@@ -907,7 +937,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)...@@ -907,7 +937,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
907 new_buf[new_path.len] = 0;937 new_buf[new_path.len] = 0;
908938
909 if (is_windows) {939 if (is_windows) {
910 const flags = windows.MOVEFILE_REPLACE_EXISTING|windows.MOVEFILE_WRITE_THROUGH;940 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
911 if (windows.MoveFileExA(old_buf.ptr, new_buf.ptr, flags) == 0) {941 if (windows.MoveFileExA(old_buf.ptr, new_buf.ptr, flags) == 0) {
912 const err = windows.GetLastError();942 const err = windows.GetLastError();
913 return switch (err) {943 return switch (err) {
...@@ -918,10 +948,12 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)...@@ -918,10 +948,12 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
918 const err = posix.getErrno(posix.rename(old_buf.ptr, new_buf.ptr));948 const err = posix.getErrno(posix.rename(old_buf.ptr, new_buf.ptr));
919 if (err > 0) {949 if (err > 0) {
920 return switch (err) {950 return switch (err) {
921 posix.EACCES, posix.EPERM => error.AccessDenied,951 posix.EACCES,
952 posix.EPERM => error.AccessDenied,
922 posix.EBUSY => error.FileBusy,953 posix.EBUSY => error.FileBusy,
923 posix.EDQUOT => error.DiskQuota,954 posix.EDQUOT => error.DiskQuota,
924 posix.EFAULT, posix.EINVAL => unreachable,955 posix.EFAULT,
956 posix.EINVAL => unreachable,
925 posix.EISDIR => error.IsDir,957 posix.EISDIR => error.IsDir,
926 posix.ELOOP => error.SymLinkLoop,958 posix.ELOOP => error.SymLinkLoop,
927 posix.EMLINK => error.LinkQuotaExceeded,959 posix.EMLINK => error.LinkQuotaExceeded,
...@@ -930,7 +962,8 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)...@@ -930,7 +962,8 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
930 posix.ENOTDIR => error.NotDir,962 posix.ENOTDIR => error.NotDir,
931 posix.ENOMEM => error.SystemResources,963 posix.ENOMEM => error.SystemResources,
932 posix.ENOSPC => error.NoSpaceLeft,964 posix.ENOSPC => error.NoSpaceLeft,
933 posix.EEXIST, posix.ENOTEMPTY => error.PathAlreadyExists,965 posix.EEXIST,
966 posix.ENOTEMPTY => error.PathAlreadyExists,
934 posix.EROFS => error.ReadOnlyFileSystem,967 posix.EROFS => error.ReadOnlyFileSystem,
935 posix.EXDEV => error.RenameAcrossMountPoints,968 posix.EXDEV => error.RenameAcrossMountPoints,
936 else => unexpectedErrorPosix(err),969 else => unexpectedErrorPosix(err),
...@@ -968,7 +1001,8 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) !void {...@@ -968,7 +1001,8 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) !void {
968 const err = posix.getErrno(posix.mkdir(path_buf.ptr, 0o755));1001 const err = posix.getErrno(posix.mkdir(path_buf.ptr, 0o755));
969 if (err > 0) {1002 if (err > 0) {
970 return switch (err) {1003 return switch (err) {
971 posix.EACCES, posix.EPERM => error.AccessDenied,1004 posix.EACCES,
1005 posix.EPERM => error.AccessDenied,
972 posix.EDQUOT => error.DiskQuota,1006 posix.EDQUOT => error.DiskQuota,
973 posix.EEXIST => error.PathAlreadyExists,1007 posix.EEXIST => error.PathAlreadyExists,
974 posix.EFAULT => unreachable,1008 posix.EFAULT => unreachable,
...@@ -998,27 +1032,23 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) !void {...@@ -998,27 +1032,23 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) !void {
998 // TODO stat the file and return an error if it's not a directory1032 // TODO stat the file and return an error if it's not a directory
999 // this is important because otherwise a dangling symlink1033 // this is important because otherwise a dangling symlink
1000 // could cause an infinite loop1034 // could cause an infinite loop
1001 if (end_index == resolved_path.len)1035 if (end_index == resolved_path.len) return;
1002 return;
1003 } else if (err == error.FileNotFound) {1036 } else if (err == error.FileNotFound) {
1004 // march end_index backward until next path component1037 // march end_index backward until next path component
1005 while (true) {1038 while (true) {
1006 end_index -= 1;1039 end_index -= 1;
1007 if (os.path.isSep(resolved_path[end_index]))1040 if (os.path.isSep(resolved_path[end_index])) break;
1008 break;
1009 }1041 }
1010 continue;1042 continue;
1011 } else {1043 } else {
1012 return err;1044 return err;
1013 }1045 }
1014 };1046 };
1015 if (end_index == resolved_path.len)1047 if (end_index == resolved_path.len) return;
1016 return;
1017 // march end_index forward until next path component1048 // march end_index forward until next path component
1018 while (true) {1049 while (true) {
1019 end_index += 1;1050 end_index += 1;
1020 if (end_index == resolved_path.len or os.path.isSep(resolved_path[end_index]))1051 if (end_index == resolved_path.len or os.path.isSep(resolved_path[end_index])) break;
1021 break;
1022 }1052 }
1023 }1053 }
1024}1054}
...@@ -1035,15 +1065,18 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {...@@ -1035,15 +1065,18 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {
1035 const err = posix.getErrno(posix.rmdir(path_buf.ptr));1065 const err = posix.getErrno(posix.rmdir(path_buf.ptr));
1036 if (err > 0) {1066 if (err > 0) {
1037 return switch (err) {1067 return switch (err) {
1038 posix.EACCES, posix.EPERM => error.AccessDenied,1068 posix.EACCES,
1069 posix.EPERM => error.AccessDenied,
1039 posix.EBUSY => error.FileBusy,1070 posix.EBUSY => error.FileBusy,
1040 posix.EFAULT, posix.EINVAL => unreachable,1071 posix.EFAULT,
1072 posix.EINVAL => unreachable,
1041 posix.ELOOP => error.SymLinkLoop,1073 posix.ELOOP => error.SymLinkLoop,
1042 posix.ENAMETOOLONG => error.NameTooLong,1074 posix.ENAMETOOLONG => error.NameTooLong,
1043 posix.ENOENT => error.FileNotFound,1075 posix.ENOENT => error.FileNotFound,
1044 posix.ENOMEM => error.SystemResources,1076 posix.ENOMEM => error.SystemResources,
1045 posix.ENOTDIR => error.NotDir,1077 posix.ENOTDIR => error.NotDir,
1046 posix.EEXIST, posix.ENOTEMPTY => error.DirNotEmpty,1078 posix.EEXIST,
1079 posix.ENOTEMPTY => error.DirNotEmpty,
1047 posix.EROFS => error.ReadOnlyFileSystem,1080 posix.EROFS => error.ReadOnlyFileSystem,
1048 else => unexpectedErrorPosix(err),1081 else => unexpectedErrorPosix(err),
1049 };1082 };
...@@ -1053,7 +1086,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {...@@ -1053,7 +1086,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {
1053/// Whether ::full_path describes a symlink, file, or directory, this function1086/// Whether ::full_path describes a symlink, file, or directory, this function
1054/// removes it. If it cannot be removed because it is a non-empty directory,1087/// removes it. If it cannot be removed because it is a non-empty directory,
1055/// this function recursively removes its entries and then tries again.1088/// this function recursively removes its entries and then tries again.
1056// TODO non-recursive implementation1089/// TODO non-recursive implementation
1057const DeleteTreeError = error {1090const DeleteTreeError = error {
1058 OutOfMemory,1091 OutOfMemory,
1059 AccessDenied,1092 AccessDenied,
...@@ -1095,8 +1128,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError!...@@ -1095,8 +1128,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError!
1095 error.NotDir,1128 error.NotDir,
1096 error.FileSystem,1129 error.FileSystem,
1097 error.FileBusy,1130 error.FileBusy,
1098 error.Unexpected1131 error.Unexpected => return err,
1099 => return err,
1100 }1132 }
1101 {1133 {
1102 var dir = Dir.open(allocator, full_path) catch |err| switch (err) {1134 var dir = Dir.open(allocator, full_path) catch |err| switch (err) {
...@@ -1120,8 +1152,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError!...@@ -1120,8 +1152,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError!
1120 error.SystemResources,1152 error.SystemResources,
1121 error.NoSpaceLeft,1153 error.NoSpaceLeft,
1122 error.PathAlreadyExists,1154 error.PathAlreadyExists,
1123 error.Unexpected1155 error.Unexpected => return err,
1124 => return err,
1125 };1156 };
1126 defer dir.close();1157 defer dir.close();
11271158
...@@ -1151,7 +1182,8 @@ pub const Dir = struct {...@@ -1151,7 +1182,8 @@ pub const Dir = struct {
1151 end_index: usize,1182 end_index: usize,
11521183
1153 const darwin_seek_t = switch (builtin.os) {1184 const darwin_seek_t = switch (builtin.os) {
1154 Os.macosx, Os.ios => i64,1185 Os.macosx,
1186 Os.ios => i64,
1155 else => void,1187 else => void,
1156 };1188 };
11571189
...@@ -1175,12 +1207,14 @@ pub const Dir = struct {...@@ -1175,12 +1207,14 @@ pub const Dir = struct {
1175 pub fn open(allocator: &Allocator, dir_path: []const u8) !Dir {1207 pub fn open(allocator: &Allocator, dir_path: []const u8) !Dir {
1176 const fd = switch (builtin.os) {1208 const fd = switch (builtin.os) {
1177 Os.windows => @compileError("TODO support Dir.open for windows"),1209 Os.windows => @compileError("TODO support Dir.open for windows"),
1178 Os.linux => try posixOpen(allocator, dir_path, posix.O_RDONLY|posix.O_DIRECTORY|posix.O_CLOEXEC, 0),1210 Os.linux => try posixOpen(allocator, dir_path, posix.O_RDONLY | posix.O_DIRECTORY | posix.O_CLOEXEC, 0),
1179 Os.macosx, Os.ios => try posixOpen(allocator, dir_path, posix.O_RDONLY|posix.O_NONBLOCK|posix.O_DIRECTORY|posix.O_CLOEXEC, 0),1211 Os.macosx,
1212 Os.ios => try posixOpen(allocator, dir_path, posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC, 0),
1180 else => @compileError("Dir.open is not supported for this platform"),1213 else => @compileError("Dir.open is not supported for this platform"),
1181 };1214 };
1182 const darwin_seek_init = switch (builtin.os) {1215 const darwin_seek_init = switch (builtin.os) {
1183 Os.macosx, Os.ios => 0,1216 Os.macosx,
1217 Os.ios => 0,
1184 else => {},1218 else => {},
1185 };1219 };
1186 return Dir {1220 return Dir {
...@@ -1203,7 +1237,8 @@ pub const Dir = struct {...@@ -1203,7 +1237,8 @@ pub const Dir = struct {
1203 pub fn next(self: &Dir) !?Entry {1237 pub fn next(self: &Dir) !?Entry {
1204 switch (builtin.os) {1238 switch (builtin.os) {
1205 Os.linux => return self.nextLinux(),1239 Os.linux => return self.nextLinux(),
1206 Os.macosx, Os.ios => return self.nextDarwin(),1240 Os.macosx,
1241 Os.ios => return self.nextDarwin(),
1207 Os.windows => return self.nextWindows(),1242 Os.windows => return self.nextWindows(),
1208 else => @compileError("Dir.next not supported on " ++ @tagName(builtin.os)),1243 else => @compileError("Dir.next not supported on " ++ @tagName(builtin.os)),
1209 }1244 }
...@@ -1217,12 +1252,13 @@ pub const Dir = struct {...@@ -1217,12 +1252,13 @@ pub const Dir = struct {
1217 }1252 }
12181253
1219 while (true) {1254 while (true) {
1220 const result = posix.getdirentries64(self.fd, self.buf.ptr, self.buf.len,1255 const result = posix.getdirentries64(self.fd, self.buf.ptr, self.buf.len, &self.darwin_seek);
1221 &self.darwin_seek);
1222 const err = posix.getErrno(result);1256 const err = posix.getErrno(result);
1223 if (err > 0) {1257 if (err > 0) {
1224 switch (err) {1258 switch (err) {
1225 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,1259 posix.EBADF,
1260 posix.EFAULT,
1261 posix.ENOTDIR => unreachable,
1226 posix.EINVAL => {1262 posix.EINVAL => {
1227 self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2);1263 self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2);
1228 continue;1264 continue;
...@@ -1230,14 +1266,13 @@ pub const Dir = struct {...@@ -1230,14 +1266,13 @@ pub const Dir = struct {
1230 else => return unexpectedErrorPosix(err),1266 else => return unexpectedErrorPosix(err),
1231 }1267 }
1232 }1268 }
1233 if (result == 0)1269 if (result == 0) return null;
1234 return null;
1235 self.index = 0;1270 self.index = 0;
1236 self.end_index = result;1271 self.end_index = result;
1237 break;1272 break;
1238 }1273 }
1239 }1274 }
1240 const darwin_entry = @ptrCast(& align(1) posix.dirent, &self.buf[self.index]);1275 const darwin_entry = @ptrCast(&align(1) posix.dirent, &self.buf[self.index]);
1241 const next_index = self.index + darwin_entry.d_reclen;1276 const next_index = self.index + darwin_entry.d_reclen;
1242 self.index = next_index;1277 self.index = next_index;
12431278
...@@ -1282,7 +1317,9 @@ pub const Dir = struct {...@@ -1282,7 +1317,9 @@ pub const Dir = struct {
1282 const err = posix.getErrno(result);1317 const err = posix.getErrno(result);
1283 if (err > 0) {1318 if (err > 0) {
1284 switch (err) {1319 switch (err) {
1285 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,1320 posix.EBADF,
1321 posix.EFAULT,
1322 posix.ENOTDIR => unreachable,
1286 posix.EINVAL => {1323 posix.EINVAL => {
1287 self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2);1324 self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2);
1288 continue;1325 continue;
...@@ -1290,14 +1327,13 @@ pub const Dir = struct {...@@ -1290,14 +1327,13 @@ pub const Dir = struct {
1290 else => return unexpectedErrorPosix(err),1327 else => return unexpectedErrorPosix(err),
1291 }1328 }
1292 }1329 }
1293 if (result == 0)1330 if (result == 0) return null;
1294 return null;
1295 self.index = 0;1331 self.index = 0;
1296 self.end_index = result;1332 self.end_index = result;
1297 break;1333 break;
1298 }1334 }
1299 }1335 }
1300 const linux_entry = @ptrCast(& align(1) posix.dirent, &self.buf[self.index]);1336 const linux_entry = @ptrCast(&align(1) posix.dirent, &self.buf[self.index]);
1301 const next_index = self.index + linux_entry.d_reclen;1337 const next_index = self.index + linux_entry.d_reclen;
1302 self.index = next_index;1338 self.index = next_index;
13031339
...@@ -1366,7 +1402,8 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 {...@@ -1366,7 +1402,8 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 {
1366 if (err > 0) {1402 if (err > 0) {
1367 return switch (err) {1403 return switch (err) {
1368 posix.EACCES => error.AccessDenied,1404 posix.EACCES => error.AccessDenied,
1369 posix.EFAULT, posix.EINVAL => unreachable,1405 posix.EFAULT,
1406 posix.EINVAL => unreachable,
1370 posix.EIO => error.FileSystem,1407 posix.EIO => error.FileSystem,
1371 posix.ELOOP => error.SymLinkLoop,1408 posix.ELOOP => error.SymLinkLoop,
1372 posix.ENAMETOOLONG => error.NameTooLong,1409 posix.ENAMETOOLONG => error.NameTooLong,
...@@ -1459,8 +1496,7 @@ pub const ArgIteratorPosix = struct {...@@ -1459,8 +1496,7 @@ pub const ArgIteratorPosix = struct {
1459 }1496 }
14601497
1461 pub fn next(self: &ArgIteratorPosix) ?[]const u8 {1498 pub fn next(self: &ArgIteratorPosix) ?[]const u8 {
1462 if (self.index == self.count)1499 if (self.index == self.count) return null;
1463 return null;
14641500
1465 const s = raw[self.index];1501 const s = raw[self.index];
1466 self.index += 1;1502 self.index += 1;
...@@ -1468,8 +1504,7 @@ pub const ArgIteratorPosix = struct {...@@ -1468,8 +1504,7 @@ pub const ArgIteratorPosix = struct {
1468 }1504 }
14691505
1470 pub fn skip(self: &ArgIteratorPosix) bool {1506 pub fn skip(self: &ArgIteratorPosix) bool {
1471 if (self.index == self.count)1507 if (self.index == self.count) return false;
1472 return false;
14731508
1474 self.index += 1;1509 self.index += 1;
1475 return true;1510 return true;
...@@ -1487,7 +1522,9 @@ pub const ArgIteratorWindows = struct {...@@ -1487,7 +1522,9 @@ pub const ArgIteratorWindows = struct {
1487 quote_count: usize,1522 quote_count: usize,
1488 seen_quote_count: usize,1523 seen_quote_count: usize,
14891524
1490 pub const NextError = error{OutOfMemory};1525 pub const NextError = error {
1526 OutOfMemory,
1527 };
14911528
1492 pub fn init() ArgIteratorWindows {1529 pub fn init() ArgIteratorWindows {
1493 return initWithCmdLine(windows.GetCommandLineA());1530 return initWithCmdLine(windows.GetCommandLineA());
...@@ -1510,7 +1547,8 @@ pub const ArgIteratorWindows = struct {...@@ -1510,7 +1547,8 @@ pub const ArgIteratorWindows = struct {
1510 const byte = self.cmd_line[self.index];1547 const byte = self.cmd_line[self.index];
1511 switch (byte) {1548 switch (byte) {
1512 0 => return null,1549 0 => return null,
1513 ' ', '\t' => continue,1550 ' ',
1551 '\t' => continue,
1514 else => break,1552 else => break,
1515 }1553 }
1516 }1554 }
...@@ -1524,7 +1562,8 @@ pub const ArgIteratorWindows = struct {...@@ -1524,7 +1562,8 @@ pub const ArgIteratorWindows = struct {
1524 const byte = self.cmd_line[self.index];1562 const byte = self.cmd_line[self.index];
1525 switch (byte) {1563 switch (byte) {
1526 0 => return false,1564 0 => return false,
1527 ' ', '\t' => continue,1565 ' ',
1566 '\t' => continue,
1528 else => break,1567 else => break,
1529 }1568 }
1530 }1569 }
...@@ -1543,7 +1582,8 @@ pub const ArgIteratorWindows = struct {...@@ -1543,7 +1582,8 @@ pub const ArgIteratorWindows = struct {
1543 '\\' => {1582 '\\' => {
1544 backslash_count += 1;1583 backslash_count += 1;
1545 },1584 },
1546 ' ', '\t' => {1585 ' ',
1586 '\t' => {
1547 if (self.seen_quote_count % 2 == 0 or self.seen_quote_count == self.quote_count) {1587 if (self.seen_quote_count % 2 == 0 or self.seen_quote_count == self.quote_count) {
1548 return true;1588 return true;
1549 }1589 }
...@@ -1583,7 +1623,8 @@ pub const ArgIteratorWindows = struct {...@@ -1583,7 +1623,8 @@ pub const ArgIteratorWindows = struct {
1583 '\\' => {1623 '\\' => {
1584 backslash_count += 1;1624 backslash_count += 1;
1585 },1625 },
1586 ' ', '\t' => {1626 ' ',
1627 '\t' => {
1587 try self.emitBackslashes(&buf, backslash_count);1628 try self.emitBackslashes(&buf, backslash_count);
1588 backslash_count = 0;1629 backslash_count = 0;
1589 if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) {1630 if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) {
...@@ -1627,7 +1668,6 @@ pub const ArgIteratorWindows = struct {...@@ -1627,7 +1668,6 @@ pub const ArgIteratorWindows = struct {
1627 }1668 }
1628 }1669 }
1629 }1670 }
1630
1631};1671};
16321672
1633pub const ArgIterator = struct {1673pub const ArgIterator = struct {
...@@ -1642,7 +1682,7 @@ pub const ArgIterator = struct {...@@ -1642,7 +1682,7 @@ pub const ArgIterator = struct {
1642 }1682 }
16431683
1644 pub const NextError = ArgIteratorWindows.NextError;1684 pub const NextError = ArgIteratorWindows.NextError;
1645 1685
1646 /// You must free the returned memory when done.1686 /// You must free the returned memory when done.
1647 pub fn next(self: &ArgIterator, allocator: &Allocator) ?(NextError![]u8) {1687 pub fn next(self: &ArgIterator, allocator: &Allocator) ?(NextError![]u8) {
1648 if (builtin.os == Os.windows) {1688 if (builtin.os == Os.windows) {
...@@ -1717,15 +1757,47 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void {...@@ -1717,15 +1757,47 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void {
1717}1757}
17181758
1719test "windows arg parsing" {1759test "windows arg parsing" {
1720 testWindowsCmdLine(c"a b\tc d", [][]const u8{"a", "b", "c", "d"});1760 testWindowsCmdLine(c"a b\tc d", [][]const u8 {
1721 testWindowsCmdLine(c"\"abc\" d e", [][]const u8{"abc", "d", "e"});1761 "a",
1722 testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{"a\\\\\\b", "de fg", "h"});1762 "b",
1723 testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{"a\\\"b", "c", "d"});1763 "c",
1724 testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{"a\\\\b c", "d", "e"});1764 "d",
1725 testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{"a", "b", "c", "\"d", "f"});1765 });
17261766 testWindowsCmdLine(c"\"abc\" d e", [][]const u8 {
1727 testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"",1767 "abc",
1728 [][]const u8{".\\..\\zig-cache\\build", "bin\\zig.exe", ".\\..", ".\\..\\zig-cache", "--help"});1768 "d",
1769 "e",
1770 });
1771 testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8 {
1772 "a\\\\\\b",
1773 "de fg",
1774 "h",
1775 });
1776 testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8 {
1777 "a\\\"b",
1778 "c",
1779 "d",
1780 });
1781 testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8 {
1782 "a\\\\b c",
1783 "d",
1784 "e",
1785 });
1786 testWindowsCmdLine(c"a b\tc \"d f", [][]const u8 {
1787 "a",
1788 "b",
1789 "c",
1790 "\"d",
1791 "f",
1792 });
1793
1794 testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8 {
1795 ".\\..\\zig-cache\\build",
1796 "bin\\zig.exe",
1797 ".\\..",
1798 ".\\..\\zig-cache",
1799 "--help",
1800 });
1729}1801}
17301802
1731fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) void {1803fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) void {
...@@ -1772,7 +1844,8 @@ pub fn openSelfExe() !os.File {...@@ -1772,7 +1844,8 @@ pub fn openSelfExe() !os.File {
1772 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);1844 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1773 return os.File.openRead(&fixed_allocator.allocator, proc_file_path);1845 return os.File.openRead(&fixed_allocator.allocator, proc_file_path);
1774 },1846 },
1775 Os.macosx, Os.ios => {1847 Os.macosx,
1848 Os.ios => {
1776 var fixed_buffer_mem: [darwin.PATH_MAX * 2]u8 = undefined;1849 var fixed_buffer_mem: [darwin.PATH_MAX * 2]u8 = undefined;
1777 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);1850 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1778 const self_exe_path = try selfExePath(&fixed_allocator.allocator);1851 const self_exe_path = try selfExePath(&fixed_allocator.allocator);
...@@ -1784,8 +1857,10 @@ pub fn openSelfExe() !os.File {...@@ -1784,8 +1857,10 @@ pub fn openSelfExe() !os.File {
17841857
1785test "openSelfExe" {1858test "openSelfExe" {
1786 switch (builtin.os) {1859 switch (builtin.os) {
1787 Os.linux, Os.macosx, Os.ios => (try openSelfExe()).close(),1860 Os.linux,
1788 else => return, // Unsupported OS.1861 Os.macosx,
1862 Os.ios => (try openSelfExe()).close(),
1863 else => return, // Unsupported OS.
1789 }1864 }
1790}1865}
17911866
...@@ -1822,7 +1897,8 @@ pub fn selfExePath(allocator: &mem.Allocator) ![]u8 {...@@ -1822,7 +1897,8 @@ pub fn selfExePath(allocator: &mem.Allocator) ![]u8 {
1822 try out_path.resize(new_len);1897 try out_path.resize(new_len);
1823 }1898 }
1824 },1899 },
1825 Os.macosx, Os.ios => {1900 Os.macosx,
1901 Os.ios => {
1826 var u32_len: u32 = 0;1902 var u32_len: u32 = 0;
1827 const ret1 = c._NSGetExecutablePath(undefined, &u32_len);1903 const ret1 = c._NSGetExecutablePath(undefined, &u32_len);
1828 assert(ret1 != 0);1904 assert(ret1 != 0);
...@@ -1850,7 +1926,9 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) ![]u8 {...@@ -1850,7 +1926,9 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) ![]u8 {
1850 const dir = path.dirname(full_exe_path);1926 const dir = path.dirname(full_exe_path);
1851 return allocator.shrink(u8, full_exe_path, dir.len);1927 return allocator.shrink(u8, full_exe_path, dir.len);
1852 },1928 },
1853 Os.windows, Os.macosx, Os.ios => {1929 Os.windows,
1930 Os.macosx,
1931 Os.ios => {
1854 const self_exe_path = try selfExePath(allocator);1932 const self_exe_path = try selfExePath(allocator);
1855 errdefer allocator.free(self_exe_path);1933 errdefer allocator.free(self_exe_path);
1856 const dirname = os.path.dirname(self_exe_path);1934 const dirname = os.path.dirname(self_exe_path);
...@@ -1907,7 +1985,8 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 {...@@ -1907,7 +1985,8 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 {
1907 posix.EINVAL => return PosixSocketError.ProtocolFamilyNotAvailable,1985 posix.EINVAL => return PosixSocketError.ProtocolFamilyNotAvailable,
1908 posix.EMFILE => return PosixSocketError.ProcessFdQuotaExceeded,1986 posix.EMFILE => return PosixSocketError.ProcessFdQuotaExceeded,
1909 posix.ENFILE => return PosixSocketError.SystemFdQuotaExceeded,1987 posix.ENFILE => return PosixSocketError.SystemFdQuotaExceeded,
1910 posix.ENOBUFS, posix.ENOMEM => return PosixSocketError.SystemResources,1988 posix.ENOBUFS,
1989 posix.ENOMEM => return PosixSocketError.SystemResources,
1911 posix.EPROTONOSUPPORT => return PosixSocketError.ProtocolNotSupported,1990 posix.EPROTONOSUPPORT => return PosixSocketError.ProtocolNotSupported,
1912 else => return unexpectedErrorPosix(err),1991 else => return unexpectedErrorPosix(err),
1913 }1992 }
...@@ -1938,7 +2017,7 @@ pub const PosixBindError = error {...@@ -1938,7 +2017,7 @@ pub const PosixBindError = error {
19382017
1939 /// A nonexistent interface was requested or the requested address was not local.2018 /// A nonexistent interface was requested or the requested address was not local.
1940 AddressNotAvailable,2019 AddressNotAvailable,
1941 2020
1942 /// addr points outside the user's accessible address space.2021 /// addr points outside the user's accessible address space.
1943 PageFault,2022 PageFault,
19442023
...@@ -2027,7 +2106,7 @@ pub const PosixAcceptError = error {...@@ -2027,7 +2106,7 @@ pub const PosixAcceptError = error {
2027 FileDescriptorClosed,2106 FileDescriptorClosed,
20282107
2029 ConnectionAborted,2108 ConnectionAborted,
2030 2109
2031 /// The addr argument is not in a writable part of the user address space.2110 /// The addr argument is not in a writable part of the user address space.
2032 PageFault,2111 PageFault,
20332112
...@@ -2040,7 +2119,7 @@ pub const PosixAcceptError = error {...@@ -2040,7 +2119,7 @@ pub const PosixAcceptError = error {
20402119
2041 /// The system-wide limit on the total number of open files has been reached.2120 /// The system-wide limit on the total number of open files has been reached.
2042 SystemFdQuotaExceeded,2121 SystemFdQuotaExceeded,
2043 2122
2044 /// Not enough free memory. This often means that the memory allocation is limited2123 /// Not enough free memory. This often means that the memory allocation is limited
2045 /// by the socket buffer limits, not by the system memory.2124 /// by the socket buffer limits, not by the system memory.
2046 SystemResources,2125 SystemResources,
...@@ -2076,7 +2155,8 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError!...@@ -2076,7 +2155,8 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError!
2076 posix.EINVAL => return PosixAcceptError.InvalidSyscall,2155 posix.EINVAL => return PosixAcceptError.InvalidSyscall,
2077 posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded,2156 posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded,
2078 posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded,2157 posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded,
2079 posix.ENOBUFS, posix.ENOMEM => return PosixAcceptError.SystemResources,2158 posix.ENOBUFS,
2159 posix.ENOMEM => return PosixAcceptError.SystemResources,
2080 posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket,2160 posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket,
2081 posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported,2161 posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported,
2082 posix.EPROTO => return PosixAcceptError.ProtocolFailure,2162 posix.EPROTO => return PosixAcceptError.ProtocolFailure,
...@@ -2287,7 +2367,8 @@ pub fn posixConnectAsync(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConn...@@ -2287,7 +2367,8 @@ pub fn posixConnectAsync(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConn
2287 const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr));2367 const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr));
2288 const err = posix.getErrno(rc);2368 const err = posix.getErrno(rc);
2289 switch (err) {2369 switch (err) {
2290 0, posix.EINPROGRESS => return,2370 0,
2371 posix.EINPROGRESS => return,
2291 else => return unexpectedErrorPosix(err),2372 else => return unexpectedErrorPosix(err),
22922373
2293 posix.EACCES => return PosixConnectError.PermissionDenied,2374 posix.EACCES => return PosixConnectError.PermissionDenied,
...@@ -2351,9 +2432,9 @@ pub const Thread = struct {...@@ -2351,9 +2432,9 @@ pub const Thread = struct {
23512432
2352 pub const use_pthreads = is_posix and builtin.link_libc;2433 pub const use_pthreads = is_posix and builtin.link_libc;
2353 const Data = if (use_pthreads) struct {2434 const Data = if (use_pthreads) struct {
2354 handle: c.pthread_t,2435 handle: c.pthread_t,
2355 stack_addr: usize,2436 stack_addr: usize,
2356 stack_len: usize,2437 stack_len: usize,
2357 } else switch (builtin.os) {2438 } else switch (builtin.os) {
2358 builtin.Os.linux => struct {2439 builtin.Os.linux => struct {
2359 pid: i32,2440 pid: i32,
...@@ -2467,9 +2548,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread...@@ -2467,9 +2548,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
2467 outer_context.thread.data.alloc_start = bytes_ptr;2548 outer_context.thread.data.alloc_start = bytes_ptr;
24682549
2469 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(&c_void, &outer_context.inner);2550 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(&c_void, &outer_context.inner);
2470 outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain,2551 outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) ?? {
2471 parameter, 0, null) ??
2472 {
2473 const err = windows.GetLastError();2552 const err = windows.GetLastError();
2474 return switch (err) {2553 return switch (err) {
2475 else => os.unexpectedErrorWindows(err),2554 else => os.unexpectedErrorWindows(err),
...@@ -2500,8 +2579,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread...@@ -2500,8 +2579,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
2500 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;2579 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;
25012580
2502 const mmap_len = default_stack_size;2581 const mmap_len = default_stack_size;
2503 const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ|posix.PROT_WRITE,2582 const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
2504 posix.MAP_PRIVATE|posix.MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
2505 if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory;2583 if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory;
2506 errdefer assert(posix.munmap(stack_addr, mmap_len) == 0);2584 errdefer assert(posix.munmap(stack_addr, mmap_len) == 0);
25072585
...@@ -2547,9 +2625,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread...@@ -2547,9 +2625,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
2547 }2625 }
2548 } else if (builtin.os == builtin.Os.linux) {2626 } else if (builtin.os == builtin.Os.linux) {
2549 // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly2627 // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly
2550 const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND2628 const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED;
2551 | posix.CLONE_THREAD | posix.CLONE_SYSVSEM
2552 | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED;
2553 const newtls: usize = 0;2629 const newtls: usize = 0;
2554 const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid);2630 const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid);
2555 const err = posix.getErrno(rc);2631 const err = posix.getErrno(rc);