os: cleanup; ci: fix a segfault in the tcc32 job when calling pref.vexe_path() -> os.real_path(os.executable())
parent
e77a11001e
commit
fe48380e85
155
vlib/os/os.c.v
155
vlib/os/os.c.v
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue