@@ -153,18 +153,18 @@ pub fn truncate(path string, len u64) ! {
153153 C.open (& char (path.str), o_wronly | o_trunc, 0 )
154154 }
155155 if fp < 0 {
156- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
156+ return error_posix ( )
157157 }
158158 defer {
159159 C.close (fp)
160160 }
161161 $if windows {
162162 if C._chsize_s (fp, len) != 0 {
163- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
163+ return error_posix ( )
164164 }
165165 } $else {
166166 if C.ftruncate (fp, len) != 0 {
167- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
167+ return error_posix ( )
168168 }
169169 }
170170}
@@ -263,8 +263,7 @@ pub fn cp(src string, dst string) ! {
263263 w_src := src.replace ('/' , '\\ ' )
264264 w_dst := dst.replace ('/' , '\\ ' )
265265 if C.CopyFile (w_src.to_wide (), w_dst.to_wide (), false ) == 0 {
266- result := C.GetLastError ()
267- return error_with_code ('failed to copy ${src} to ${dst} ' , int (result))
266+ return error_win32 (msg: 'failed to copy ${src} to ${dst} ' )
268267 }
269268 } $else {
270269 fp_from := C.open (& char (src.str), C.O_RDONLY, 0 )
@@ -320,7 +319,7 @@ pub fn vfopen(path string, mode string) !&C.FILE {
320319 fp = C.fopen (& char (path.str), & char (mode.str))
321320 }
322321 if isnil (fp) {
323- return error ( 'failed to open file "${path} "' )
322+ return error_posix (msg: 'failed to open file "${path} "' )
324323 } else {
325324 return fp
326325 }
@@ -515,7 +514,7 @@ pub fn rm(path string) ! {
515514 rc = C.remove (& char (path.str))
516515 }
517516 if rc == - 1 {
518- return error ( 'Failed to remove "${path} ": ' + posix_get_error_msg (C.errno))
517+ return error_posix (msg: 'Failed to remove "${path} ": ' + posix_get_error_msg (C.errno))
519518 }
520519 // C.unlink(path.cstr())
521520}
@@ -526,12 +525,14 @@ pub fn rmdir(path string) ! {
526525 rc := C.RemoveDirectory (path.to_wide ())
527526 if ! rc {
528527 // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya - 0 == false, is failure
529- return error ('Failed to remove "${path} ": ' + posix_get_error_msg (C.errno))
528+ return error_win32 (
529+ msg: 'Failed to remove "${path} ": ' + get_error_msg (int (C.GetLastError ()))
530+ )
530531 }
531532 } $else {
532533 rc := C.rmdir (& char (path.str))
533534 if rc == - 1 {
534- return error ( posix_get_error_msg (C.errno) )
535+ return error_posix ( )
535536 }
536537 }
537538}
@@ -868,7 +869,7 @@ fn kind_of_existing_path(path string) PathKind {
868869pub fn chdir (path string ) ! {
869870 ret := $if windows { C._wchdir (path.to_wide ()) } $else { C.chdir (& char (path.str)) }
870871 if ret == - 1 {
871- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
872+ return error_posix ( )
872873 }
873874}
874875
@@ -1021,7 +1022,7 @@ pub fn flush() {
10211022// Octals like `0o600` can be used.
10221023pub fn chmod (path string , mode int ) ! {
10231024 if C.chmod (& char (path.str), mode) != 0 {
1024- return error_with_code ( 'chmod failed: ' + posix_get_error_msg (C.errno), C.errno )
1025+ return error_posix (msg: 'chmod failed: ' + posix_get_error_msg (C.errno))
10251026 }
10261027}
10271028
@@ -1031,7 +1032,7 @@ pub fn chown(path string, owner int, group int) ! {
10311032 return error ('os.chown() not implemented for Windows' )
10321033 } $else {
10331034 if C.chown (& char (path.str), owner, group) != 0 {
1034- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
1035+ return error_posix ( )
10351036 }
10361037 }
10371038}
@@ -1053,7 +1054,7 @@ pub fn open_append(path string) !File {
10531054 }
10541055 }
10551056 if isnil (file.cfile) {
1056- return error ( 'failed to create(append) file "${path} "' )
1057+ return error_posix (msg: 'failed to create(append) file "${path} "' )
10571058 }
10581059 file.is_opened = true
10591060 return file
@@ -1078,7 +1079,7 @@ pub fn execvp(cmdpath string, cmdargs []string) ! {
10781079 res = C.execvp (& char (cmdpath.str), cargs.data)
10791080 }
10801081 if res == - 1 {
1081- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
1082+ return error_posix ( )
10821083 }
10831084
10841085 // just in case C._execvp returned ... that happens on windows ...
@@ -1112,7 +1113,7 @@ pub fn execve(cmdpath string, cmdargs []string, envs []string) ! {
11121113 // Note: normally execve does not return at all.
11131114 // If it returns, then something went wrong...
11141115 if res == - 1 {
1115- return error_with_code ( posix_get_error_msg (C.errno), C.errno )
1116+ return error_posix ( )
11161117 }
11171118}
11181119
@@ -1155,3 +1156,36 @@ pub fn last_error() IError {
11551156 return error_with_code (msg, code)
11561157 }
11571158}
1159+
1160+ // Magic constant because zero is used explicitly at times
1161+ const error_code_not_set = 0x7EFEFEFE
1162+
1163+ @[params]
1164+ struct SystemError {
1165+ msg string
1166+ code int = os.error_code_not_set
1167+ }
1168+
1169+ // Return a POSIX error:
1170+ // Code defaults to last error (from C.errno)
1171+ // Message defaults to POSIX error message for the error code
1172+ @[inline]
1173+ pub fn error_posix (e SystemError) IError {
1174+ code := if e.code == os.error_code_not_set { C.errno } else { e.code }
1175+ message := if e.msg == '' { posix_get_error_msg (code) } else { e.msg }
1176+ return error_with_code (message, code)
1177+ }
1178+
1179+ // Return a Win32 API error:
1180+ // Code defaults to last error (calling C.GetLastError())
1181+ // Message defaults to Win 32 API error message for the error code
1182+ @[inline]
1183+ pub fn error_win32 (e SystemError) IError {
1184+ $if windows {
1185+ code := if e.code == os.error_code_not_set { int (C.GetLastError ()) } else { e.code }
1186+ message := if e.msg == '' { get_error_msg (code) } else { e.msg }
1187+ return error_with_code (message, code)
1188+ } $else {
1189+ panic ('Win32 API not available on this platform.' )
1190+ }
1191+ }
0 commit comments