Files
c3c/lib/std/io/os/temp_directory.c3
Manu Linares f254c27966 std/io/os/temp_directory.c3: fix INVALID_PATH in Win32 native_temp_directory (#2762)
* std/io/os/temp_directory.c3: fix INVALID_PATH in Windows native_temp_directory

- Use the actual length from GetTempPathW for Windows temp path slice
- We can remove the workaround in the test_suite_runner for WIN32 and
create all directories in %temp% now

* Updated releasenotes.

---------

Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
2026-01-15 21:23:30 +01:00

137 lines
5.1 KiB
Plaintext

module std::io::os;
enum NativeSystemDir
{
DESKTOP,
DOCUMENTS,
VIDEOS,
MUSIC,
DOWNLOADS,
PICTURES,
TEMPLATES,
PUBLIC_SHARE,
SAVED_GAMES,
SCREENSHOTS
}
module std::io::os @if(env::LIBC);
import std::io, std::os;
fn String? win32_get_known_folder_temp(Win32_REFKNOWNFOLDERID rfid) @private @if(env::WIN32)
{
Win32_PWSTR path;
Win32_HRESULT res = win32::shGetKnownFolderPath(rfid, 0x00008000 /* KF_FLAG_CREATE */, null, &path);
if (res) return io::PATH_COULD_NOT_BE_FOUND?;
return string::from_wstring(tmem, (WString)path);
}
fn Path? native_home_directory(Allocator allocator) => @pool()
{
$switch env::OS_TYPE:
$case IOS:
$case MACOS:
$case TVOS:
$case WATCHOS:
$case FREEBSD:
$case KFREEBSD:
$case LINUX:
$case NETBSD:
$case OPENBSD:
$case HAIKU:
return path::new(allocator, env::tget_var("HOME")) ?? io::PATH_COULD_NOT_BE_FOUND?;
$case WIN32:
return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_PROFILE));
$default:
return io::PATH_COULD_NOT_BE_FOUND?;
$endswitch
}
fn Path? native_user_directory(Allocator allocator, NativeSystemDir dir) => @pool()
{
$switch env::OS_TYPE:
$case FREEBSD:
$case KFREEBSD:
$case LINUX:
$case NETBSD:
$case OPENBSD:
$case HAIKU:
switch (dir)
{
case DESKTOP: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "DESKTOP"));
case DOWNLOADS: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "DOWNLOAD"));
case DOCUMENTS: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "DOCUMENTS"));
case MUSIC: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "MUSIC"));
case VIDEOS: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "VIDEOS"));
case PICTURES: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "PICTURES"));
case PUBLIC_SHARE: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "PUBLICSHARE"));
case TEMPLATES: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "TEMPLATES"));
case SAVED_GAMES:
case SCREENSHOTS: nextcase;
default: return io::PATH_COULD_NOT_BE_FOUND?;
}
$case IOS:
$case MACOS:
$case WATCHOS:
$case TVOS:
switch (dir)
{
case DESKTOP: return path::new(allocator, darwin::find_first_directory_temp(DESKTOP, USER));
case DOWNLOADS: return path::new(allocator, darwin::find_first_directory_temp(DOWNLOADS, USER));
case DOCUMENTS: return path::new(allocator, darwin::find_first_directory_temp(DOCUMENT, USER));
case MUSIC: return path::new(allocator, darwin::find_first_directory_temp(MUSIC, USER));
case VIDEOS: return path::new(allocator, darwin::find_first_directory_temp(MOVIES, USER));
case PICTURES: return path::new(allocator, darwin::find_first_directory_temp(PICTURES, USER));
case PUBLIC_SHARE: return path::new(allocator, darwin::find_first_directory_temp(SHARED_PUBLIC, USER));
case SAVED_GAMES:
case SCREENSHOTS:
case TEMPLATES: nextcase;
default: return io::PATH_COULD_NOT_BE_FOUND?;
}
$case WIN32:
switch (dir)
{
case DOWNLOADS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_DOWNLOADS));
case DOCUMENTS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_DOCUMENTS));
case DESKTOP: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_DESKTOP));
case MUSIC: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_MUSIC));
case VIDEOS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_VIDEOS));
case PICTURES: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_PICTURES));
case SAVED_GAMES: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_SAVED_GAMES));
case SCREENSHOTS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_SCREENSHOTS));
case TEMPLATES: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_TEMPLATES));
case PUBLIC_SHARE: nextcase;
default: return io::PATH_COULD_NOT_BE_FOUND?;
}
$default:
return io::PATH_COULD_NOT_BE_FOUND?;
$endswitch
}
fn Path? native_temp_directory(Allocator allocator) @if(!env::WIN32)
{
foreach (String env : { "TMPDIR", "TMP", "TEMP", "TEMPDIR" })
{
String tmpdir = env::tget_var(env) ?? "";
if (tmpdir) return path::new(allocator, tmpdir);
}
return path::new(allocator, "/tmp");
}
fn Path? native_temp_directory(Allocator allocator) @if(env::WIN32) => @pool()
{
Win32_DWORD len = win32::getTempPathW(0, null);
if (!len) return io::GENERAL_ERROR?;
Char16[] buff = mem::talloc_array(Char16, len);
Win32_DWORD res = win32::getTempPathW(len, buff);
if (!res) return io::GENERAL_ERROR?;
return path::new(allocator, string::tfrom_utf16(buff[:res]));
}
module std::io::os @if(env::NO_LIBC);
import std::io::path;
macro Path? native_home_directory(Allocator allocator) => io::PATH_COULD_NOT_BE_FOUND?;
macro Path? native_temp_directory(Allocator allocator) => io::PATH_COULD_NOT_BE_FOUND?;
fn Path? native_user_directory(Allocator allocator, NativeSystemDir dir) => io::PATH_COULD_NOT_BE_FOUND?;