os: fix using Win32-API with TCC32 (#10496)

pull/10536/head
Bastian Buck 2021-06-21 13:14:58 +02:00 committed by GitHub
parent 45c6b6493b
commit 1e9e717111
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 20 deletions

View File

@ -779,16 +779,35 @@ pub fn getwd() string {
pub fn real_path(fpath string) string {
mut res := ''
$if windows {
// GetFullPathName doesn't work with symbolic links,
// so if it is not a file, get full path
mut fullpath := unsafe { &u16(vcalloc_noscan(max_path_len * 2)) }
// TODO: check errors if path len is not enough
ret := C.GetFullPathName(fpath.to_wide(), max_path_len, fullpath, 0)
if ret == 0 {
unsafe { free(fullpath) }
return fpath.clone()
size := max_path_len * 2
// 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
// try to open the file to get symbolic link path
file := C.CreateFile(fpath.to_wide(), 0x80000000, 1, 0, 3, 0x80, 0)
if file != voidptr(-1) {
mut fullpath := unsafe { &u16(vcalloc_noscan(size)) }
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
final_len := C.GetFinalPathNameByHandleW(file, fullpath, size, 0)
C.CloseHandle(file)
if final_len < size {
rt := unsafe { string_from_wide2(fullpath, final_len) }
res = rt[4..]
} else {
unsafe { free(fullpath) }
eprintln('os.real_path() saw that the file path was too long')
return fpath.clone()
}
} else {
// 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)) }
// TODO: check errors if path len is not enough
ret := C.GetFullPathName(fpath.to_wide(), max_path_len, fullpath, 0)
if ret == 0 {
unsafe { free(fullpath) }
return fpath.clone()
}
res = unsafe { string_from_wide(fullpath) }
}
res = unsafe { string_from_wide(fullpath) }
} $else {
mut fullpath := vcalloc_noscan(max_path_len)
ret := &char(C.realpath(&char(fpath.str), &char(fullpath)))

View File

@ -342,6 +342,20 @@ fn test_realpath_does_not_absolutize_non_existing_relative_paths() {
}
}
fn test_realpath_absolutepath_symlink() {
file_name := 'tolink_file.txt'
symlink_name := 'symlink.txt'
mut f := os.create(file_name) or { panic(err) }
f.close()
assert os.symlink(file_name, symlink_name) or { panic(err) }
rpath := os.real_path(symlink_name)
println(rpath)
assert os.is_abs_path(rpath)
assert rpath.ends_with(file_name)
os.rm(symlink_name) or {}
os.rm(file_name) or {}
}
fn test_tmpdir() {
t := os.temp_dir()
assert t.len > 0

View File

@ -9,8 +9,7 @@ import strings
fn C.CreateSymbolicLinkW(&u16, &u16, u32) int
// See https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createhardlinkw
// TCC gets builder error
// fn C.CreateHardLinkW(&u16, &u16, C.SECURITY_ATTRIBUTES) int
fn C.CreateHardLinkW(&u16, &u16, C.SECURITY_ATTRIBUTES) int
fn C._getpid() int
@ -321,7 +320,7 @@ pub fn execute(cmd string) Result {
pub fn symlink(origin string, target string) ?bool {
// this is a temporary fix for TCC32 due to runtime error
// TODO: patch TCC32
// TODO: find the cause why TCC32 for Windows does not work without the compiletime option
$if x64 || x32 {
mut flags := 0
if is_dir(origin) {
@ -344,8 +343,6 @@ pub fn symlink(origin string, target string) ?bool {
}
pub fn link(origin string, target string) ?bool {
/*
// TODO: TCC gets builder error
res := C.CreateHardLinkW(target.to_wide(), origin.to_wide(), C.NULL)
// 1 = success, != 1 failure => https://stackoverflow.com/questions/33010440/createsymboliclink-on-windows-10
if res != 1 {
@ -355,12 +352,6 @@ pub fn link(origin string, target string) ?bool {
return error('C.CreateHardLinkW reported success, but link still does not exist')
}
return true
*/
res := execute('fsutil hardlink create $target $origin')
if res.exit_code != 0 {
return error(res.output)
}
return true
}
pub fn (mut f File) close() {