os: cleanup; ci: fix a segfault in the tcc32 job when calling pref.vexe_path() -> os.real_path(os.executable())

pull/12550/head
Delyan Angelov 2021-11-22 10:32:10 +02:00
parent e77a11001e
commit fe48380e85
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 93 additions and 84 deletions

View File

@ -620,54 +620,49 @@ pub fn on_segfault(f voidptr) {
// process. // process.
[manualfree] [manualfree]
pub fn executable() string { pub fn executable() string {
$if linux { size := max_path_bufffer_size()
mut xresult := vcalloc_noscan(max_path_len) mut result := unsafe { vcalloc_noscan(size) }
defer {
unsafe { free(xresult) }
}
count := C.readlink(c'/proc/self/exe', &char(xresult), max_path_len)
if count < 0 {
eprintln('os.executable() failed at reading /proc/self/exe to get exe path')
return executable_fallback()
}
res := unsafe { tos_clone(xresult) }
return res
}
$if windows {
max := 512
size := max * 2 // max_path_len * sizeof(wchar_t)
mut result := unsafe { &u16(vcalloc_noscan(size)) }
defer { defer {
unsafe { free(result) } unsafe { free(result) }
} }
len := C.GetModuleFileName(0, result, max) $if windows {
pu16_result := unsafe { &u16(result) }
len := C.GetModuleFileName(0, pu16_result, 512)
// determine if the file is a windows symlink // determine if the file is a windows symlink
attrs := C.GetFileAttributesW(result) attrs := C.GetFileAttributesW(pu16_result)
is_set := attrs & 0x400 // FILE_ATTRIBUTE_REPARSE_POINT is_set := attrs & 0x400 // FILE_ATTRIBUTE_REPARSE_POINT
if is_set != 0 { // it's a windows symlink if is_set != 0 { // it's a windows symlink
// gets handle with GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 // gets handle with GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
file := C.CreateFile(result, 0x80000000, 1, 0, 3, 0x80, 0) file := C.CreateFile(pu16_result, 0x80000000, 1, 0, 3, 0x80, 0)
if file != voidptr(-1) { if file != voidptr(-1) {
final_path := unsafe { &u16(vcalloc_noscan(size)) } defer {
C.CloseHandle(file)
}
final_path := unsafe { vcalloc_noscan(size) }
defer {
unsafe { free(final_path) }
}
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
final_len := C.GetFinalPathNameByHandleW(file, final_path, size, 0) final_len := C.GetFinalPathNameByHandleW(file, unsafe { &u16(final_path) },
size, 0)
if final_len < size { if final_len < size {
ret := unsafe { string_from_wide2(final_path, final_len) } ret := unsafe { string_from_wide2(&u16(final_path), final_len) }
defer {
unsafe { ret.free() }
}
// remove '\\?\' from beginning (see link above) // remove '\\?\' from beginning (see link above)
return ret[4..] ret_slice := ret[4..]
res := ret_slice.clone()
return res
} else { } else {
eprintln('os.executable() saw that the executable file path was too long') eprintln('os.executable() saw that the executable file path was too long')
} }
} }
C.CloseHandle(file)
} }
return unsafe { string_from_wide2(result, len) } res := unsafe { string_from_wide2(pu16_result, len) }
return res
} }
$if macos { $if macos {
mut result := vcalloc_noscan(max_path_len)
defer {
unsafe { free(result) }
}
pid := C.getpid() pid := C.getpid()
ret := proc_pidpath(pid, result, max_path_len) ret := proc_pidpath(pid, result, max_path_len)
if ret <= 0 { if ret <= 0 {
@ -678,28 +673,12 @@ pub fn executable() string {
return res return res
} }
$if freebsd { $if freebsd {
mut result := vcalloc_noscan(max_path_len)
defer {
unsafe { free(result) }
}
mib := [1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1] mib := [1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1]
size := max_path_len
unsafe { C.sysctl(mib.data, 4, result, &size, 0, 0) } unsafe { C.sysctl(mib.data, 4, result, &size, 0, 0) }
res := unsafe { tos_clone(result) } res := unsafe { tos_clone(result) }
return res return res
} }
// "Sadly there is no way to get the full path of the executed file in OpenBSD."
$if openbsd {
}
$if solaris {
}
$if haiku {
}
$if netbsd { $if netbsd {
mut result := vcalloc_noscan(max_path_len)
defer {
unsafe { free(result) }
}
count := C.readlink(c'/proc/curproc/exe', &char(result), max_path_len) count := C.readlink(c'/proc/curproc/exe', &char(result), max_path_len)
if count < 0 { if count < 0 {
eprintln('os.executable() failed at reading /proc/curproc/exe to get exe path') eprintln('os.executable() failed at reading /proc/curproc/exe to get exe path')
@ -709,10 +688,6 @@ pub fn executable() string {
return res return res
} }
$if dragonfly { $if dragonfly {
mut result := vcalloc_noscan(max_path_len)
defer {
unsafe { free(result) }
}
count := C.readlink(c'/proc/curproc/file', &char(result), max_path_len) count := C.readlink(c'/proc/curproc/file', &char(result), max_path_len)
if count < 0 { if count < 0 {
eprintln('os.executable() failed at reading /proc/curproc/file to get exe path') eprintln('os.executable() failed at reading /proc/curproc/file to get exe path')
@ -721,6 +696,22 @@ pub fn executable() string {
res := unsafe { tos_clone(result) } res := unsafe { tos_clone(result) }
return res return res
} }
$if linux {
count := C.readlink(c'/proc/self/exe', &char(result), max_path_len)
if count < 0 {
eprintln('os.executable() failed at reading /proc/self/exe to get exe path')
return executable_fallback()
}
res := unsafe { tos_clone(result) }
return res
}
// "Sadly there is no way to get the full path of the executed file in OpenBSD."
$if openbsd {
}
$if solaris {
}
$if haiku {
}
return executable_fallback() return executable_fallback()
} }
@ -770,30 +761,33 @@ pub fn chdir(path string) ? {
} }
} }
fn max_path_bufffer_size() int {
mut size := max_path_len
$if windows {
size *= 2
}
return size
}
// getwd returns the absolute path of the current directory. // getwd returns the absolute path of the current directory.
[manualfree] [manualfree]
pub fn getwd() string { pub fn getwd() string {
$if windows {
max := 512 // max_path_len * sizeof(wchar_t)
unsafe { unsafe {
buf := &u16(vcalloc_noscan(max * 2)) buf := vcalloc_noscan(max_path_bufffer_size())
if C._wgetcwd(buf, max) == 0 { defer {
free(buf) free(buf)
}
$if windows {
if C._wgetcwd(&u16(buf), max_path_len) == 0 {
return '' return ''
} }
res := string_from_wide(buf) res := string_from_wide(&u16(buf))
free(buf)
return res return res
}
} $else { } $else {
buf := vcalloc_noscan(max_path_len)
unsafe {
if C.getcwd(&char(buf), max_path_len) == 0 { if C.getcwd(&char(buf), max_path_len) == 0 {
free(buf)
return '' return ''
} }
res := tos_clone(buf) res := tos_clone(buf)
free(buf)
return res return res
} }
} }
@ -806,49 +800,53 @@ pub fn getwd() string {
// NB: this particular rabbit hole is *deep* ... // NB: this particular rabbit hole is *deep* ...
[manualfree] [manualfree]
pub fn real_path(fpath string) string { pub fn real_path(fpath string) string {
size := max_path_bufffer_size()
mut fullpath := unsafe { vcalloc_noscan(size) }
defer {
unsafe { free(fullpath) }
}
mut res := '' mut res := ''
$if windows { $if windows {
size := max_path_len * 2 pu16_fullpath := unsafe { &u16(fullpath) }
// gets handle with GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 // gets handle with GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
// use C.CreateFile(fpath.to_wide(), 0x80000000, 1, 0, 3, 0x80, 0) instead of get_file_handle // use C.CreateFile(fpath.to_wide(), 0x80000000, 1, 0, 3, 0x80, 0) instead of get_file_handle
// try to open the file to get symbolic link path // try to open the file to get symbolic link path
file := C.CreateFile(fpath.to_wide(), 0x80000000, 1, 0, 3, 0x80, 0) fpath_wide := fpath.to_wide()
defer {
unsafe { free(voidptr(fpath_wide)) }
}
file := C.CreateFile(fpath_wide, 0x80000000, 1, 0, 3, 0x80, 0)
if file != voidptr(-1) { if file != voidptr(-1) {
mut fullpath := unsafe { &u16(vcalloc_noscan(size)) } defer {
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
final_len := C.GetFinalPathNameByHandleW(file, fullpath, size, 0)
C.CloseHandle(file) C.CloseHandle(file)
}
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
final_len := C.GetFinalPathNameByHandleW(file, pu16_fullpath, size, 0)
if final_len < size { if final_len < size {
rt := unsafe { string_from_wide2(fullpath, final_len) } rt := unsafe { string_from_wide2(pu16_fullpath, final_len) }
unsafe { free(fullpath) } srt := rt[4..]
unsafe { res.free() } unsafe { res.free() }
res = rt[4..] res = srt.clone()
} else { } else {
eprintln('os.real_path() saw that the file path was too long') eprintln('os.real_path() saw that the file path was too long')
unsafe { res.free() } unsafe { res.free() }
unsafe { free(fullpath) }
return fpath.clone() return fpath.clone()
} }
} else { } else {
// if it is not a file C.CreateFile doesn't gets a file handle, use GetFullPath instead // if it is not a file C.CreateFile doesn't gets a file handle, use GetFullPath instead
mut fullpath := unsafe { &u16(vcalloc_noscan(max_path_len * 2)) } ret := C.GetFullPathName(fpath_wide, max_path_len, pu16_fullpath, 0)
// TODO: check errors if path len is not enough
ret := C.GetFullPathName(fpath.to_wide(), max_path_len, fullpath, 0)
if ret == 0 { if ret == 0 {
// TODO: check errors if path len is not enough
unsafe { res.free() } unsafe { res.free() }
unsafe { free(fullpath) }
return fpath.clone() return fpath.clone()
} }
unsafe { res.free() } unsafe { res.free() }
res = unsafe { string_from_wide(fullpath) } res = unsafe { string_from_wide(pu16_fullpath) }
unsafe { free(fullpath) }
} }
} $else { } $else {
mut fullpath := vcalloc_noscan(max_path_len)
ret := &char(C.realpath(&char(fpath.str), &char(fullpath))) ret := &char(C.realpath(&char(fpath.str), &char(fullpath)))
if ret == 0 { if ret == 0 {
unsafe { res.free() } unsafe { res.free() }
unsafe { free(fullpath) }
return fpath.clone() return fpath.clone()
} }
// NB: fullpath is much larger (usually ~4KB), than what C.realpath will // NB: fullpath is much larger (usually ~4KB), than what C.realpath will
@ -857,7 +855,6 @@ pub fn real_path(fpath string) string {
// 4KB fullpath buffer. // 4KB fullpath buffer.
unsafe { res.free() } unsafe { res.free() }
res = unsafe { tos_clone(fullpath) } res = unsafe { tos_clone(fullpath) }
unsafe { free(fullpath) }
} }
unsafe { normalize_drive_letter(res) } unsafe { normalize_drive_letter(res) }
return res return res

View File

@ -216,7 +216,19 @@ pub fn vexe_path() string {
if vexe != '' { if vexe != '' {
return vexe return vexe
} }
real_vexe_path := os.real_path(os.executable()) myexe := os.executable()
mut real_vexe_path := myexe
for {
$if tinyc {
$if x32 {
// TODO: investigate why exactly tcc32 segfaults on os.real_path here,
// and remove this cludge.
break
}
}
real_vexe_path = os.real_path(real_vexe_path)
break
}
os.setenv('VEXE', real_vexe_path, true) os.setenv('VEXE', real_vexe_path, true)
return real_vexe_path return real_vexe_path
} }