authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-10-02 17:51:52-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-03 21:31:08-04:00
logcbdd8250566b84730a00c8ff10de8f7d557b0ae1
treea3f7123d6e7e6a99d0d0f6479c85d4d22423cd4f
parent26546af1b892925e1cfeb06564c7296e85abc840

stage1: delete unused os code


2 files changed, 21 insertions(+), 1104 deletions(-)

src/stage1/os.cpp+21-1052
......@@ -94,105 +94,6 @@ static clock_serv_t macos_monotonic_clock;
9494extern char **environ;
9595#endif
9696
97#if defined(ZIG_OS_POSIX)
98static void populate_termination(Termination *term, int status) {
99 if (WIFEXITED(status)) {
100 term->how = TerminationIdClean;
101 term->code = WEXITSTATUS(status);
102 } else if (WIFSIGNALED(status)) {
103 term->how = TerminationIdSignaled;
104 term->code = WTERMSIG(status);
105 } else if (WIFSTOPPED(status)) {
106 term->how = TerminationIdStopped;
107 term->code = WSTOPSIG(status);
108 } else {
109 term->how = TerminationIdUnknown;
110 term->code = status;
111 }
112}
113
114static void os_spawn_process_posix(ZigList<const char *> &args, Termination *term) {
115 const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1);
116 for (size_t i = 0; i < args.length; i += 1) {
117 argv[i] = args.at(i);
118 }
119 argv[args.length] = nullptr;
120
121 pid_t pid;
122 int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast<char *const*>(argv), environ);
123 if (rc != 0) {
124 zig_panic("unable to spawn %s: %s", args.at(0), strerror(rc));
125 }
126
127 int status;
128 waitpid(pid, &status, 0);
129 populate_termination(term, status);
130}
131#endif
132
133#if defined(ZIG_OS_WINDOWS)
134
135static void os_windows_create_command_line(Buf *command_line, ZigList<const char *> &args) {
136 buf_resize(command_line, 0);
137 const char *prefix = "\"";
138 for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) {
139 const char *arg = args.at(arg_i);
140 buf_append_str(command_line, prefix);
141 prefix = " \"";
142 size_t arg_len = strlen(arg);
143 for (size_t c_i = 0; c_i < arg_len; c_i += 1) {
144 if (arg[c_i] == '\"') {
145 zig_panic("TODO");
146 }
147 buf_append_char(command_line, arg[c_i]);
148 }
149 buf_append_char(command_line, '\"');
150 }
151}
152
153static void os_spawn_process_windows(ZigList<const char *> &args, Termination *term) {
154 Buf command_line = BUF_INIT;
155 os_windows_create_command_line(&command_line, args);
156
157 PROCESS_INFORMATION piProcInfo = {0};
158 STARTUPINFOW siStartInfo = {0};
159 siStartInfo.cb = sizeof(STARTUPINFOW);
160
161 Slice<uint8_t> exe_slice = str(args.at(0));
162 auto exe_utf16_slice = Slice<WCHAR>::alloc(exe_slice.len + 1);
163 exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0;
164
165 auto command_line_utf16 = Slice<WCHAR>::alloc(buf_len(&command_line) + 1);
166 command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0;
167
168 BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr,
169 &siStartInfo, &piProcInfo);
170
171 if (!success) {
172 zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line));
173 }
174
175 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
176
177 DWORD exit_code;
178 if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
179 zig_panic("GetExitCodeProcess failed");
180 }
181 term->how = TerminationIdClean;
182 term->code = exit_code;
183}
184#endif
185
186void os_spawn_process(ZigList<const char *> &args, Termination *term) {
187#if defined(ZIG_OS_WINDOWS)
188 os_spawn_process_windows(args, term);
189#elif defined(ZIG_OS_POSIX)
190 os_spawn_process_posix(args, term);
191#else
192#error "missing os_spawn_process implementation"
193#endif
194}
195
19697void os_path_dirname(Buf *full_path, Buf *out_dirname) {
19798 return os_path_split(full_path, out_dirname, nullptr);
19899}
......@@ -280,71 +181,27 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
280181 buf_append_buf(out_full_path, basename);
281182}
282183
283Error os_path_real(Buf *rel_path, Buf *out_abs_path) {
284#if defined(ZIG_OS_WINDOWS)
285 PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path));
286 PathSpace out_abs_path_space;
287
288 if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) {
289 zig_panic("_wfullpath failed");
290 }
291 utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]);
292 return ErrorNone;
293#elif defined(ZIG_OS_POSIX)
294 buf_resize(out_abs_path, PATH_MAX + 1);
295 char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path));
296 if (!result) {
297 int err = errno;
298 if (err == EACCES) {
299 return ErrorAccess;
300 } else if (err == ENOENT) {
301 return ErrorFileNotFound;
302 } else if (err == ENOMEM) {
303 return ErrorNoMem;
304 } else {
305 return ErrorFileSystem;
306 }
307 }
308 buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));
309 return ErrorNone;
310#else
311#error "missing os_path_real implementation"
312#endif
313}
314
315#if defined(ZIG_OS_WINDOWS)
316// Ported from std/os/path.zig
317static bool isAbsoluteWindows(Slice<uint8_t> path) {
318 if (path.ptr[0] == '/')
319 return true;
320
321 if (path.ptr[0] == '\\') {
322 return true;
323 }
324 if (path.len < 3) {
325 return false;
326 }
327 if (path.ptr[1] == ':') {
328 if (path.ptr[2] == '/')
329 return true;
330 if (path.ptr[2] == '\\')
331 return true;
332 }
333 return false;
334}
335#endif
336
337bool os_path_is_absolute(Buf *path) {
338#if defined(ZIG_OS_WINDOWS)
339 return isAbsoluteWindows(buf_to_slice(path));
340#elif defined(ZIG_OS_POSIX)
341 return buf_ptr(path)[0] == '/';
342#else
343#error "missing os_path_is_absolute implementation"
344#endif
345}
346184
347#if defined(ZIG_OS_WINDOWS)
185#if defined(ZIG_OS_WINDOWS)
186// Ported from std/os/path.zig
187static bool isAbsoluteWindows(Slice<uint8_t> path) {
188 if (path.ptr[0] == '/')
189 return true;
190
191 if (path.ptr[0] == '\\') {
192 return true;
193 }
194 if (path.len < 3) {
195 return false;
196 }
197 if (path.ptr[1] == ':') {
198 if (path.ptr[2] == '/')
199 return true;
200 if (path.ptr[2] == '\\')
201 return true;
202 }
203 return false;
204}
348205
349206enum WindowsPathKind {
350207 WindowsPathKindNone,
......@@ -687,7 +544,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
687544 size_t max_size = 0;
688545 for (size_t i = 0; i < paths_len; i += 1) {
689546 Buf *p = paths_ptr[i];
690 if (os_path_is_absolute(p)) {
547 if (buf_ptr(p)[0] == '/') {
691548 first_index = i;
692549 have_abs = true;
693550 max_size = 0;
......@@ -786,256 +643,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {
786643 zig_unreachable();
787644}
788645
789Error os_file_exists(Buf *full_path, bool *result) {
790#if defined(ZIG_OS_WINDOWS)
791 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
792 *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES;
793 return ErrorNone;
794#else
795 *result = access(buf_ptr(full_path), F_OK) != -1;
796 return ErrorNone;
797#endif
798}
799
800#if defined(ZIG_OS_POSIX)
801static Error os_exec_process_posix(ZigList<const char *> &args,
802 Termination *term, Buf *out_stderr, Buf *out_stdout)
803{
804 int stdin_pipe[2];
805 int stdout_pipe[2];
806 int stderr_pipe[2];
807 int err_pipe[2];
808
809 int err;
810 if ((err = pipe(stdin_pipe)))
811 zig_panic("pipe failed");
812 if ((err = pipe(stdout_pipe)))
813 zig_panic("pipe failed");
814 if ((err = pipe(stderr_pipe)))
815 zig_panic("pipe failed");
816 if ((err = pipe(err_pipe)))
817 zig_panic("pipe failed");
818
819 pid_t pid = fork();
820 if (pid == -1)
821 zig_panic("fork failed: %s", strerror(errno));
822 if (pid == 0) {
823 // child
824 if (dup2(stdin_pipe[0], STDIN_FILENO) == -1)
825 zig_panic("dup2 failed");
826
827 if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1)
828 zig_panic("dup2 failed");
829
830 if (dup2(stderr_pipe[1], STDERR_FILENO) == -1)
831 zig_panic("dup2 failed");
832
833 const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1);
834 argv[args.length] = nullptr;
835 for (size_t i = 0; i < args.length; i += 1) {
836 argv[i] = args.at(i);
837 }
838 execvp(argv[0], const_cast<char * const *>(argv));
839 Error report_err = ErrorUnexpected;
840 if (errno == ENOENT) {
841 report_err = ErrorFileNotFound;
842 }
843 if (write(err_pipe[1], &report_err, sizeof(Error)) == -1) {
844 zig_panic("write failed");
845 }
846 exit(1);
847 } else {
848 // parent
849 close(stdin_pipe[0]);
850 close(stdin_pipe[1]);
851 close(stdout_pipe[1]);
852 close(stderr_pipe[1]);
853
854 int status;
855 waitpid(pid, &status, 0);
856 populate_termination(term, status);
857
858 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
859 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
860 Error err1 = os_fetch_file(stdout_f, out_stdout);
861 Error err2 = os_fetch_file(stderr_f, out_stderr);
862
863 fclose(stdout_f);
864 fclose(stderr_f);
865
866 if (err1) return err1;
867 if (err2) return err2;
868
869 Error child_err = ErrorNone;
870 if (write(err_pipe[1], &child_err, sizeof(Error)) == -1) {
871 zig_panic("write failed");
872 }
873 close(err_pipe[1]);
874 if (read(err_pipe[0], &child_err, sizeof(Error)) == -1) {
875 zig_panic("write failed");
876 }
877 close(err_pipe[0]);
878 return child_err;
879 }
880}
881#endif
882
883#if defined(ZIG_OS_WINDOWS)
884
885//static void win32_panic(const char *str) {
886// DWORD err = GetLastError();
887// LPSTR messageBuffer = nullptr;
888// FormatMessageA(
889// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
890// NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
891// zig_panic(str, messageBuffer);
892// LocalFree(messageBuffer);
893//}
894
895static Error os_exec_process_windows(ZigList<const char *> &args,
896 Termination *term, Buf *out_stderr, Buf *out_stdout)
897{
898 Buf command_line = BUF_INIT;
899 os_windows_create_command_line(&command_line, args);
900
901 HANDLE g_hChildStd_IN_Rd = NULL;
902 HANDLE g_hChildStd_IN_Wr = NULL;
903 HANDLE g_hChildStd_OUT_Rd = NULL;
904 HANDLE g_hChildStd_OUT_Wr = NULL;
905 HANDLE g_hChildStd_ERR_Rd = NULL;
906 HANDLE g_hChildStd_ERR_Wr = NULL;
907
908 SECURITY_ATTRIBUTES saAttr;
909 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
910 saAttr.bInheritHandle = TRUE;
911 saAttr.lpSecurityDescriptor = NULL;
912
913 if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) {
914 zig_panic("StdoutRd CreatePipe");
915 }
916
917 if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) {
918 zig_panic("Stdout SetHandleInformation");
919 }
920
921 if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) {
922 zig_panic("stderr CreatePipe");
923 }
924
925 if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) {
926 zig_panic("stderr SetHandleInformation");
927 }
928
929 if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) {
930 zig_panic("Stdin CreatePipe");
931 }
932
933 if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) {
934 zig_panic("Stdin SetHandleInformation");
935 }
936
937
938 PROCESS_INFORMATION piProcInfo = {0};
939 STARTUPINFO siStartInfo = {0};
940 siStartInfo.cb = sizeof(STARTUPINFO);
941 siStartInfo.hStdError = g_hChildStd_ERR_Wr;
942 siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
943 siStartInfo.hStdInput = g_hChildStd_IN_Rd;
944 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
945
946 const char *exe = args.at(0);
947 BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
948 &siStartInfo, &piProcInfo);
949
950 if (!success) {
951 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
952 CloseHandle(piProcInfo.hProcess);
953 CloseHandle(piProcInfo.hThread);
954 return ErrorFileNotFound;
955 }
956 zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line));
957 }
958
959 if (!CloseHandle(g_hChildStd_IN_Wr)) {
960 zig_panic("stdinwr closehandle");
961 }
962
963 CloseHandle(g_hChildStd_IN_Rd);
964 CloseHandle(g_hChildStd_ERR_Wr);
965 CloseHandle(g_hChildStd_OUT_Wr);
966
967 static const size_t BUF_SIZE = 4 * 1024;
968 {
969 DWORD dwRead;
970 char chBuf[BUF_SIZE];
971
972 buf_resize(out_stdout, 0);
973 for (;;) {
974 success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
975 if (!success || dwRead == 0) break;
976
977 buf_append_mem(out_stdout, chBuf, dwRead);
978 }
979 CloseHandle(g_hChildStd_OUT_Rd);
980 }
981 {
982 DWORD dwRead;
983 char chBuf[BUF_SIZE];
984
985 buf_resize(out_stderr, 0);
986 for (;;) {
987 success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
988 if (!success || dwRead == 0) break;
989
990 buf_append_mem(out_stderr, chBuf, dwRead);
991 }
992 CloseHandle(g_hChildStd_ERR_Rd);
993 }
994
995 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
996
997 DWORD exit_code;
998 if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
999 zig_panic("GetExitCodeProcess failed");
1000 }
1001 term->how = TerminationIdClean;
1002 term->code = exit_code;
1003
1004 CloseHandle(piProcInfo.hProcess);
1005 CloseHandle(piProcInfo.hThread);
1006
1007 return ErrorNone;
1008}
1009#endif
1010
1011Error os_execv(const char *exe, const char **argv) {
1012#if defined(ZIG_OS_WINDOWS)
1013 return ErrorUnsupportedOperatingSystem;
1014#else
1015 execv(exe, (char *const *)argv);
1016 switch (errno) {
1017 case ENOMEM:
1018 return ErrorSystemResources;
1019 case EIO:
1020 return ErrorFileSystem;
1021 default:
1022 return ErrorUnexpected;
1023 }
1024#endif
1025}
1026
1027Error os_exec_process(ZigList<const char *> &args,
1028 Termination *term, Buf *out_stderr, Buf *out_stdout)
1029{
1030#if defined(ZIG_OS_WINDOWS)
1031 return os_exec_process_windows(args, term, out_stderr, out_stdout);
1032#elif defined(ZIG_OS_POSIX)
1033 return os_exec_process_posix(args, term, out_stderr, out_stdout);
1034#else
1035#error "missing os_exec_process implementation"
1036#endif
1037}
1038
1039646Error os_write_file(Buf *full_path, Buf *contents) {
1040647#if defined(ZIG_OS_WINDOWS)
1041648 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
......@@ -1074,35 +681,6 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
1074681 }
1075682}
1076683
1077Error os_dump_file(Buf *src_path, FILE *dest_file) {
1078 Error err;
1079
1080#if defined(ZIG_OS_WINDOWS)
1081 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
1082 FILE *src_f = _wfopen(&path_space.data.items[0], L"rb");
1083#else
1084 FILE *src_f = fopen(buf_ptr(src_path), "rb");
1085#endif
1086 if (!src_f) {
1087 int err = errno;
1088 if (err == ENOENT) {
1089 return ErrorFileNotFound;
1090 } else if (err == EACCES || err == EPERM) {
1091 return ErrorAccess;
1092 } else {
1093 return ErrorFileSystem;
1094 }
1095 }
1096 copy_open_files(src_f, dest_file);
1097 if ((err = copy_open_files(src_f, dest_file))) {
1098 fclose(src_f);
1099 return err;
1100 }
1101
1102 fclose(src_f);
1103 return ErrorNone;
1104}
1105
1106684#if defined(ZIG_OS_WINDOWS)
1107685static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
1108686 mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
......@@ -1116,88 +694,6 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) {
1116694}
1117695#endif
1118696
1119static Error set_file_times(OsFile file, OsTimeStamp ts) {
1120#if defined(ZIG_OS_WINDOWS)
1121 FILETIME ft = windows_os_timestamp_to_filetime(ts);
1122 if (SetFileTime(file, nullptr, &ft, &ft) == 0) {
1123 return ErrorUnexpected;
1124 }
1125 return ErrorNone;
1126#else
1127 struct timespec times[2] = {
1128 { (time_t)ts.sec, (long)ts.nsec },
1129 { (time_t)ts.sec, (long)ts.nsec },
1130 };
1131 if (futimens(file, times) == -1) {
1132 switch (errno) {
1133 case EBADF:
1134 zig_panic("futimens EBADF");
1135 default:
1136 return ErrorUnexpected;
1137 }
1138 }
1139 return ErrorNone;
1140#endif
1141}
1142
1143Error os_update_file(Buf *src_path, Buf *dst_path) {
1144 Error err;
1145
1146 OsFile src_file;
1147 OsFileAttr src_attr;
1148 if ((err = os_file_open_r(src_path, &src_file, &src_attr))) {
1149 return err;
1150 }
1151
1152 OsFile dst_file;
1153 OsFileAttr dst_attr;
1154 if ((err = os_file_open_w(dst_path, &dst_file, &dst_attr, src_attr.mode))) {
1155 os_file_close(&src_file);
1156 return err;
1157 }
1158
1159 if (src_attr.size == dst_attr.size &&
1160 src_attr.mode == dst_attr.mode &&
1161 src_attr.mtime.sec == dst_attr.mtime.sec &&
1162 src_attr.mtime.nsec == dst_attr.mtime.nsec)
1163 {
1164 os_file_close(&src_file);
1165 os_file_close(&dst_file);
1166 return ErrorNone;
1167 }
1168#if defined(ZIG_OS_WINDOWS)
1169 if (SetEndOfFile(dst_file) == 0) {
1170 return ErrorUnexpected;
1171 }
1172#else
1173 if (ftruncate(dst_file, 0) == -1) {
1174 return ErrorUnexpected;
1175 }
1176#endif
1177#if defined(ZIG_OS_WINDOWS)
1178 FILE *src_libc_file = _fdopen(_open_osfhandle((intptr_t)src_file, _O_RDONLY), "rb");
1179 FILE *dst_libc_file = _fdopen(_open_osfhandle((intptr_t)dst_file, 0), "wb");
1180#else
1181 FILE *src_libc_file = fdopen(src_file, "rb");
1182 FILE *dst_libc_file = fdopen(dst_file, "wb");
1183#endif
1184 assert(src_libc_file);
1185 assert(dst_libc_file);
1186
1187 if ((err = copy_open_files(src_libc_file, dst_libc_file))) {
1188 fclose(src_libc_file);
1189 fclose(dst_libc_file);
1190 return err;
1191 }
1192 if (fflush(dst_libc_file) == -1) {
1193 return ErrorUnexpected;
1194 }
1195 err = set_file_times(dst_file, src_attr.mtime);
1196 fclose(src_libc_file);
1197 fclose(dst_libc_file);
1198 return err;
1199}
1200
1201697Error os_copy_file(Buf *src_path, Buf *dest_path) {
1202698#if defined(ZIG_OS_WINDOWS)
1203699 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
......@@ -1358,14 +854,6 @@ bool os_stderr_tty(void) {
1358854#endif
1359855}
1360856
1361Error os_delete_file(Buf *path) {
1362 if (remove(buf_ptr(path))) {
1363 return ErrorFileSystem;
1364 } else {
1365 return ErrorNone;
1366 }
1367}
1368
1369857Error os_rename(Buf *src_path, Buf *dest_path) {
1370858 if (buf_eql_buf(src_path, dest_path)) {
1371859 return ErrorNone;
......@@ -1384,30 +872,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) {
1384872 return ErrorNone;
1385873}
1386874
1387OsTimeStamp os_timestamp_calendar(void) {
1388 OsTimeStamp result;
1389#if defined(ZIG_OS_WINDOWS)
1390 FILETIME ft;
1391 GetSystemTimeAsFileTime(&ft);
1392 windows_filetime_to_os_timestamp(&ft, &result);
1393#elif defined(__MACH__)
1394 mach_timespec_t mts;
1395
1396 kern_return_t err = clock_get_time(macos_calendar_clock, &mts);
1397 assert(!err);
1398
1399 result.sec = mts.tv_sec;
1400 result.nsec = mts.tv_nsec;
1401#else
1402 struct timespec tms;
1403 clock_gettime(CLOCK_REALTIME, &tms);
1404
1405 result.sec = tms.tv_sec;
1406 result.nsec = tms.tv_nsec;
1407#endif
1408 return result;
1409}
1410
1411875OsTimeStamp os_timestamp_monotonic(void) {
1412876 OsTimeStamp result;
1413877#if defined(ZIG_OS_WINDOWS)
......@@ -1501,49 +965,8 @@ Error os_make_dir(Buf *path) {
1501965#endif
1502966}
1503967
1504static void init_rand() {
1505#if defined(ZIG_OS_WINDOWS)
1506 char bytes[sizeof(unsigned)];
1507 unsigned seed;
1508 RtlGenRandom(bytes, sizeof(unsigned));
1509 memcpy(&seed, bytes, sizeof(unsigned));
1510 srand(seed);
1511#elif defined(ZIG_OS_LINUX)
1512 unsigned char *ptr_random = (unsigned char*)getauxval(AT_RANDOM);
1513 unsigned seed;
1514 memcpy(&seed, ptr_random, sizeof(seed));
1515 srand(seed);
1516#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
1517 unsigned seed;
1518 size_t len = sizeof(seed);
1519 int mib[2] = { CTL_KERN, KERN_ARND };
1520 if (sysctl(mib, 2, &seed, &len, NULL, 0) != 0) {
1521 zig_panic("unable to query random data from sysctl");
1522 }
1523 srand(seed);
1524#else
1525 int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
1526 if (fd == -1) {
1527 zig_panic("unable to open /dev/urandom");
1528 }
1529 char bytes[sizeof(unsigned)];
1530 ssize_t amt_read;
1531 while ((amt_read = read(fd, bytes, sizeof(unsigned))) == -1) {
1532 if (errno == EINTR) continue;
1533 zig_panic("unable to read /dev/urandom");
1534 }
1535 if (amt_read != sizeof(unsigned)) {
1536 zig_panic("unable to read enough bytes from /dev/urandom");
1537 }
1538 close(fd);
1539 unsigned seed;
1540 memcpy(&seed, bytes, sizeof(unsigned));
1541 srand(seed);
1542#endif
1543}
1544968
1545969int os_init(void) {
1546 init_rand();
1547970#if defined(ZIG_OS_WINDOWS)
1548971 _setmode(fileno(stdout), _O_BINARY);
1549972 _setmode(fileno(stderr), _O_BINARY);
......@@ -1580,71 +1003,6 @@ int os_init(void) {
15801003 return 0;
15811004}
15821005
1583Error os_self_exe_path(Buf *out_path) {
1584#if defined(ZIG_OS_WINDOWS)
1585 PathSpace path_space;
1586 DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE);
1587 if (copied_amt <= 0) {
1588 return ErrorFileNotFound;
1589 }
1590 utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]);
1591 return ErrorNone;
1592
1593#elif defined(ZIG_OS_DARWIN)
1594 // How long is the executable's path?
1595 uint32_t u32_len = 0;
1596 int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
1597 assert(ret1 != 0);
1598
1599 Buf *tmp = buf_alloc_fixed(u32_len);
1600
1601 // Fill the executable path.
1602 int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len);
1603 assert(ret2 == 0);
1604
1605 // According to libuv project, PATH_MAX*2 works around a libc bug where
1606 // the resolved path is sometimes bigger than PATH_MAX.
1607 buf_resize(out_path, PATH_MAX*2);
1608 char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
1609 if (!real_path) {
1610 buf_init_from_buf(out_path, tmp);
1611 return ErrorNone;
1612 }
1613
1614 // Resize out_path for the correct length.
1615 buf_resize(out_path, strlen(buf_ptr(out_path)));
1616
1617 return ErrorNone;
1618#elif defined(ZIG_OS_LINUX)
1619 buf_resize(out_path, PATH_MAX);
1620 ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
1621 if (amt == -1) {
1622 return ErrorUnexpected;
1623 }
1624 buf_resize(out_path, amt);
1625 return ErrorNone;
1626#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_DRAGONFLY)
1627 buf_resize(out_path, PATH_MAX);
1628 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
1629 size_t cb = PATH_MAX;
1630 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
1631 return ErrorUnexpected;
1632 }
1633 buf_resize(out_path, cb - 1);
1634 return ErrorNone;
1635#elif defined(ZIG_OS_NETBSD)
1636 buf_resize(out_path, PATH_MAX);
1637 int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
1638 size_t cb = PATH_MAX;
1639 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
1640 return ErrorUnexpected;
1641 }
1642 buf_resize(out_path, cb - 1);
1643 return ErrorNone;
1644#endif
1645 return ErrorFileNotFound;
1646}
1647
16481006#define VT_RED "\x1b[31;1m"
16491007#define VT_GREEN "\x1b[32;1m"
16501008#define VT_CYAN "\x1b[36;1m"
......@@ -1954,392 +1312,3 @@ PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
19541312 return path_space;
19551313}
19561314#endif
1957
1958// Ported from std.os.getAppDataDir
1959Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1960#if defined(ZIG_OS_WINDOWS)
1961 WCHAR *dir_path_ptr;
1962 switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
1963 case S_OK:
1964 // defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr));
1965 utf16le_ptr_to_utf8(out_path, dir_path_ptr);
1966 CoTaskMemFree(dir_path_ptr);
1967 buf_appendf(out_path, "\\%s", appname);
1968 return ErrorNone;
1969 case E_OUTOFMEMORY:
1970 return ErrorNoMem;
1971 default:
1972 return ErrorUnexpected;
1973 }
1974 zig_unreachable();
1975#elif defined(ZIG_OS_DARWIN)
1976 const char *home_dir = getenv("HOME");
1977 if (home_dir == nullptr) {
1978 // TODO use /etc/passwd
1979 return ErrorFileNotFound;
1980 }
1981 buf_resize(out_path, 0);
1982 buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
1983 return ErrorNone;
1984#elif defined(ZIG_OS_POSIX)
1985 const char *cache_dir = getenv("XDG_CACHE_HOME");
1986 if (cache_dir == nullptr) {
1987 cache_dir = getenv("HOME");
1988 if (cache_dir == nullptr) {
1989 // TODO use /etc/passwd
1990 return ErrorFileNotFound;
1991 }
1992 if (cache_dir[0] == 0) {
1993 return ErrorFileNotFound;
1994 }
1995 buf_init_from_str(out_path, cache_dir);
1996 if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
1997 buf_append_char(out_path, '/');
1998 }
1999 buf_appendf(out_path, ".cache/%s", appname);
2000 } else {
2001 if (cache_dir[0] == 0) {
2002 return ErrorFileNotFound;
2003 }
2004 buf_init_from_str(out_path, cache_dir);
2005 if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
2006 buf_append_char(out_path, '/');
2007 }
2008 buf_appendf(out_path, "%s", appname);
2009 }
2010 return ErrorNone;
2011#endif
2012}
2013
2014#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
2015static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
2016 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
2017 if (info->dlpi_name[0] == '/') {
2018 libs->append(buf_create_from_str(info->dlpi_name));
2019 }
2020 return 0;
2021}
2022#endif
2023
2024Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
2025#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
2026 paths.resize(0);
2027 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
2028 return ErrorNone;
2029#elif defined(ZIG_OS_DARWIN)
2030 paths.resize(0);
2031 uint32_t img_count = _dyld_image_count();
2032 for (uint32_t i = 0; i != img_count; i += 1) {
2033 const char *name = _dyld_get_image_name(i);
2034 paths.append(buf_create_from_str(name));
2035 }
2036 return ErrorNone;
2037#elif defined(ZIG_OS_WINDOWS)
2038 // zig is built statically on windows, so we can return an empty list
2039 paths.resize(0);
2040 return ErrorNone;
2041#else
2042#error unimplemented
2043#endif
2044}
2045
2046Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {
2047#if defined(ZIG_OS_WINDOWS)
2048 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
2049 HANDLE result = CreateFileW(&path_space.data.items[0],
2050 need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,
2051 need_write ? 0 : FILE_SHARE_READ,
2052 nullptr,
2053 need_write ? OPEN_ALWAYS : OPEN_EXISTING,
2054 FILE_ATTRIBUTE_NORMAL, nullptr);
2055
2056 if (result == INVALID_HANDLE_VALUE) {
2057 DWORD err = GetLastError();
2058 switch (err) {
2059 case ERROR_SHARING_VIOLATION:
2060 return ErrorSharingViolation;
2061 case ERROR_ALREADY_EXISTS:
2062 return ErrorPathAlreadyExists;
2063 case ERROR_FILE_EXISTS:
2064 return ErrorPathAlreadyExists;
2065 case ERROR_FILE_NOT_FOUND:
2066 return ErrorFileNotFound;
2067 case ERROR_PATH_NOT_FOUND:
2068 return ErrorFileNotFound;
2069 case ERROR_ACCESS_DENIED:
2070 return ErrorAccess;
2071 case ERROR_PIPE_BUSY:
2072 return ErrorPipeBusy;
2073 default:
2074 return ErrorUnexpected;
2075 }
2076 }
2077 *out_file = result;
2078
2079 if (attr != nullptr) {
2080 BY_HANDLE_FILE_INFORMATION file_info;
2081 if (!GetFileInformationByHandle(result, &file_info)) {
2082 CloseHandle(result);
2083 return ErrorUnexpected;
2084 }
2085 windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime);
2086 attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow;
2087 attr->mode = 0;
2088 attr->size = (((uint64_t)file_info.nFileSizeHigh) << 32) | file_info.nFileSizeLow;
2089 }
2090
2091 return ErrorNone;
2092#else
2093 for (;;) {
2094 int fd = open(buf_ptr(full_path),
2095 need_write ? (O_RDWR|O_CLOEXEC|O_CREAT) : (O_RDONLY|O_CLOEXEC), mode);
2096 if (fd == -1) {
2097 switch (errno) {
2098 case EINTR:
2099 continue;
2100 case EINVAL:
2101 zig_unreachable();
2102 case EFAULT:
2103 zig_unreachable();
2104 case EACCES:
2105 case EPERM:
2106 return ErrorAccess;
2107 case EISDIR:
2108 return ErrorIsDir;
2109 case ENOENT:
2110 return ErrorFileNotFound;
2111 default:
2112 return ErrorFileSystem;
2113 }
2114 }
2115 struct stat statbuf;
2116 if (fstat(fd, &statbuf) == -1) {
2117 close(fd);
2118 return ErrorFileSystem;
2119 }
2120 if (S_ISDIR(statbuf.st_mode)) {
2121 close(fd);
2122 return ErrorIsDir;
2123 }
2124 *out_file = fd;
2125
2126 if (attr != nullptr) {
2127 attr->inode = statbuf.st_ino;
2128#if defined(ZIG_OS_DARWIN)
2129 attr->mtime.sec = statbuf.st_mtimespec.tv_sec;
2130 attr->mtime.nsec = statbuf.st_mtimespec.tv_nsec;
2131#else
2132 attr->mtime.sec = statbuf.st_mtim.tv_sec;
2133 attr->mtime.nsec = statbuf.st_mtim.tv_nsec;
2134#endif
2135 attr->mode = statbuf.st_mode;
2136 attr->size = statbuf.st_size;
2137 }
2138 return ErrorNone;
2139 }
2140#endif
2141}
2142
2143Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
2144 return os_file_open_rw(full_path, out_file, attr, false, 0);
2145}
2146
2147Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode) {
2148 return os_file_open_rw(full_path, out_file, attr, true, mode);
2149}
2150
2151Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
2152#if defined(ZIG_OS_WINDOWS)
2153 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
2154 for (;;) {
2155 HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE,
2156 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
2157
2158 if (result == INVALID_HANDLE_VALUE) {
2159 DWORD err = GetLastError();
2160 switch (err) {
2161 case ERROR_SHARING_VIOLATION:
2162 // TODO wait for the lock instead of sleeping
2163 Sleep(10);
2164 continue;
2165 case ERROR_ALREADY_EXISTS:
2166 return ErrorPathAlreadyExists;
2167 case ERROR_FILE_EXISTS:
2168 return ErrorPathAlreadyExists;
2169 case ERROR_FILE_NOT_FOUND:
2170 return ErrorFileNotFound;
2171 case ERROR_PATH_NOT_FOUND:
2172 return ErrorFileNotFound;
2173 case ERROR_ACCESS_DENIED:
2174 return ErrorAccess;
2175 case ERROR_PIPE_BUSY:
2176 return ErrorPipeBusy;
2177 default:
2178 return ErrorUnexpected;
2179 }
2180 }
2181 *out_file = result;
2182 return ErrorNone;
2183 }
2184#else
2185 int fd;
2186 for (;;) {
2187 fd = open(buf_ptr(full_path), O_RDWR|O_CLOEXEC|O_CREAT, 0666);
2188 if (fd == -1) {
2189 switch (errno) {
2190 case EINTR:
2191 continue;
2192 case EINVAL:
2193 zig_unreachable();
2194 case EFAULT:
2195 zig_unreachable();
2196 case EACCES:
2197 case EPERM:
2198 return ErrorAccess;
2199 case EISDIR:
2200 return ErrorIsDir;
2201 case ENOENT:
2202 return ErrorFileNotFound;
2203 case ENOTDIR:
2204 return ErrorNotDir;
2205 default:
2206 return ErrorFileSystem;
2207 }
2208 }
2209 break;
2210 }
2211 for (;;) {
2212 struct flock lock;
2213 lock.l_type = F_WRLCK;
2214 lock.l_whence = SEEK_SET;
2215 lock.l_start = 0;
2216 lock.l_len = 0;
2217 if (fcntl(fd, F_SETLKW, &lock) == -1) {
2218 switch (errno) {
2219 case EINTR:
2220 continue;
2221 case EBADF:
2222 zig_unreachable();
2223 case EFAULT:
2224 zig_unreachable();
2225 case EINVAL:
2226 zig_unreachable();
2227 default:
2228 close(fd);
2229 return ErrorFileSystem;
2230 }
2231 }
2232 break;
2233 }
2234 *out_file = fd;
2235 return ErrorNone;
2236#endif
2237}
2238
2239Error os_file_read(OsFile file, void *ptr, size_t *len) {
2240#if defined(ZIG_OS_WINDOWS)
2241 DWORD amt_read;
2242 if (ReadFile(file, ptr, *len, &amt_read, nullptr) == 0)
2243 return ErrorUnexpected;
2244 *len = amt_read;
2245 return ErrorNone;
2246#else
2247 for (;;) {
2248 ssize_t rc = read(file, ptr, *len);
2249 if (rc == -1) {
2250 switch (errno) {
2251 case EINTR:
2252 continue;
2253 case EBADF:
2254 zig_unreachable();
2255 case EFAULT:
2256 zig_unreachable();
2257 case EISDIR:
2258 return ErrorIsDir;
2259 default:
2260 return ErrorFileSystem;
2261 }
2262 }
2263 *len = rc;
2264 return ErrorNone;
2265 }
2266#endif
2267}
2268
2269Error os_file_read_all(OsFile file, Buf *contents) {
2270 Error err;
2271 size_t index = 0;
2272 for (;;) {
2273 size_t amt = buf_len(contents) - index;
2274
2275 if (amt < 4096) {
2276 buf_resize(contents, buf_len(contents) + (4096 - amt));
2277 amt = buf_len(contents) - index;
2278 }
2279
2280 if ((err = os_file_read(file, buf_ptr(contents) + index, &amt)))
2281 return err;
2282
2283 if (amt == 0) {
2284 buf_resize(contents, index);
2285 return ErrorNone;
2286 }
2287
2288 index += amt;
2289 }
2290}
2291
2292Error os_file_overwrite(OsFile file, Buf *contents) {
2293#if defined(ZIG_OS_WINDOWS)
2294 if (SetFilePointer(file, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
2295 return ErrorFileSystem;
2296 if (!SetEndOfFile(file))
2297 return ErrorFileSystem;
2298 DWORD bytes_written;
2299 if (!WriteFile(file, buf_ptr(contents), buf_len(contents), &bytes_written, nullptr))
2300 return ErrorFileSystem;
2301 return ErrorNone;
2302#else
2303 if (lseek(file, 0, SEEK_SET) == -1)
2304 return ErrorUnexpectedSeekFailure;
2305 if (ftruncate(file, 0) == -1)
2306 return ErrorUnexpectedFileTruncationFailure;
2307 for (;;) {
2308 if (write(file, buf_ptr(contents), buf_len(contents)) == -1) {
2309 switch (errno) {
2310 case EINTR:
2311 continue;
2312 case EINVAL:
2313 zig_unreachable();
2314 case EBADF:
2315 zig_unreachable();
2316 case EFAULT:
2317 zig_unreachable();
2318 case EDQUOT:
2319 return ErrorDiskQuota;
2320 case ENOSPC:
2321 return ErrorDiskSpace;
2322 case EFBIG:
2323 return ErrorFileTooBig;
2324 case EIO:
2325 return ErrorFileSystem;
2326 case EPERM:
2327 return ErrorAccess;
2328 default:
2329 return ErrorUnexpectedWriteFailure;
2330 }
2331 }
2332 return ErrorNone;
2333 }
2334#endif
2335}
2336
2337void os_file_close(OsFile *file) {
2338#if defined(ZIG_OS_WINDOWS)
2339 CloseHandle(*file);
2340 *file = NULL;
2341#else
2342 close(*file);
2343 *file = -1;
2344#endif
2345}
src/stage1/os.hpp-52
......@@ -70,66 +70,25 @@ enum TermColor {
7070 TermColorReset,
7171};
7272
73enum TerminationId {
74 TerminationIdClean,
75 TerminationIdSignaled,
76 TerminationIdStopped,
77 TerminationIdUnknown,
78};
79
80struct Termination {
81 TerminationId how;
82 int code;
83};
84
85#if defined(ZIG_OS_WINDOWS)
86#define OsFile void *
87#else
88#define OsFile int
89#endif
90
9173struct OsTimeStamp {
9274 int64_t sec;
9375 int64_t nsec;
9476};
9577
96struct OsFileAttr {
97 OsTimeStamp mtime;
98 uint64_t size;
99 uint64_t inode;
100 uint32_t mode;
101};
102
10378int os_init(void);
10479
105void os_spawn_process(ZigList<const char *> &args, Termination *term);
106Error os_exec_process(ZigList<const char *> &args,
107 Termination *term, Buf *out_stderr, Buf *out_stdout);
108Error os_execv(const char *exe, const char **argv);
109
11080void os_path_dirname(Buf *full_path, Buf *out_dirname);
11181void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
11282void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
11383void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
114Error os_path_real(Buf *rel_path, Buf *out_abs_path);
11584Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
11685bool os_path_is_absolute(Buf *path);
11786
11887Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
11988Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
12089
121Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr);
122Error ATTRIBUTE_MUST_USE os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode);
123Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
124Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
125Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
126Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
127void os_file_close(OsFile *file);
128
12990Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
13091Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
131Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
132Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file);
13392
13493Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
13594Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
......@@ -139,22 +98,11 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
13998bool os_stderr_tty(void);
14099void os_stderr_set_color(TermColor color);
141100
142Error os_delete_file(Buf *path);
143
144Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);
145
146101Error os_rename(Buf *src_path, Buf *dest_path);
147102OsTimeStamp os_timestamp_monotonic(void);
148OsTimeStamp os_timestamp_calendar(void);
149103
150104bool os_is_sep(uint8_t c);
151105
152Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
153
154Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
155
156Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
157
158106const size_t PATH_MAX_WIDE = 32767;
159107
160108struct PathSpace {