Add absolutepath helper for paths that may not exist

This commit is contained in:
Andrea Mazzoleni 2026-09-16 12:24:12 +02:00
parent 5d9b1aee00
commit 4320f0d6b6
3 changed files with 82 additions and 0 deletions

View file

@ -2408,6 +2408,40 @@ char* windows_realpath(const char* path, char* resolved_path)
/****************************************************************************/
/* fs */
char* absolutepath(const char* restrict path, char* restrict resolved_path)
{
if (path == 0 || path[0] == 0 || resolved_path == 0) {
errno = EINVAL;
return 0;
}
wchar_t wpath[CONV_MAX];
wchar_t wfull[CONV_MAX];
if (!u8tou16_mayfail(wpath, CONV_MAX, path, strlen(path) + 1, 0)) {
errno = EINVAL;
return 0;
}
DWORD len = GetFullPathNameW(wpath, CONV_MAX, wfull, 0);
if (len == 0) {
windows_errno(GetLastError());
return 0;
}
if (len >= CONV_MAX) {
errno = ENAMETOOLONG;
return 0;
}
if (!u16tou8_mayfail(resolved_path, CONV_MAX, wfull, len + 1, 0)) {
errno = ENAMETOOLONG;
return 0;
}
return resolved_path;
}
static BOOL GetFilePhysicalOffset(HANDLE h, uint64_t* physical)
{
STARTING_VCN_INPUT_BUFFER svib;

12
os/os.h
View file

@ -273,6 +273,18 @@ int os_validate_exec_input(const char* str);
/****************************************************************************/
/* fs */
/**
* Make a pathname absolute using the current working directory.
*
* The pathname is not required to exist and symbolic links are not resolved.
* The resolved_path buffer must be at least PATH_MAX bytes and must not overlap path.
*
* \param path Input pathname.
* \param resolved_path Destination buffer.
* \return resolved_path on success, 0 on failure with errno set.
*/
char* absolutepath(const char* restrict path, char* restrict resolved_path);
/**
* Invalid inode number.
*

View file

@ -122,6 +122,42 @@ const char* os_signal_name(int sig)
/****************************************************************************/
/* fs */
char* absolutepath(const char* restrict path, char* restrict resolved_path)
{
if (path == 0 || path[0] == 0 || resolved_path == 0) {
errno = EINVAL;
return 0;
}
size_t path_len = strlen(path);
if (path_len >= PATH_MAX) {
errno = ENAMETOOLONG;
return 0;
}
if (path[0] == '/') {
memcpy(resolved_path, path, path_len + 1);
return resolved_path;
}
if (getcwd(resolved_path, PATH_MAX) == 0)
return 0;
size_t resolved_len = strlen(resolved_path);
int separator = resolved_len != 0 && resolved_path[resolved_len - 1] != '/';
if (resolved_len + separator + path_len + 1 > PATH_MAX) {
errno = ENAMETOOLONG;
return 0;
}
if (separator)
resolved_path[resolved_len++] = '/';
memcpy(resolved_path + resolved_len, path, path_len + 1);
return resolved_path;
}
#if !HAVE_EACCESS
int eaccess(const char* pathname, int mode)
{