Skip to content

Commit

Permalink
Add support for reading Windows symlinks
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasMertes committed Nov 22, 2023
1 parent a2b5deb commit 4bff51f
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 14 deletions.
7 changes: 3 additions & 4 deletions src/chkccomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5904,13 +5904,12 @@ static void determineStatFunctions (FILE *versionFile)
int has_struct_stati64 = 0;

/* determineStatFunctions */
#if !defined os_lstat || !defined os_stat
fputs("#define DEFINE_WSTATI64_EXT\n", versionFile);
#endif
#ifndef os_lstat
fputs("#define os_lstat wstati64Ext\n", versionFile);
fputs("#define DEFINE_LSTATI64_EXT\n", versionFile);
fputs("#define os_lstat lstati64Ext\n", versionFile);
#endif
#ifndef os_stat
fputs("#define DEFINE_WSTATI64_EXT\n", versionFile);
fputs("#define os_stat wstati64Ext\n", versionFile);
#endif
#ifndef os_stat_struct
Expand Down
3 changes: 3 additions & 0 deletions src/cmd_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ int wsetenv (const const_os_striType name, const const_os_striType value,
#ifdef DEFINE_WUNSETENV
int wunsetenv (const const_os_striType name);
#endif
#ifdef OS_STRI_WCHAR
striType winReadLink (const const_striType filePath, errInfoType *err_info);
#endif
striType cmdGetGroup (const const_striType filePath);
striType cmdGetOwner (const const_striType filePath);
void cmdSetGroup (const const_striType filePath, const const_striType group);
Expand Down
14 changes: 14 additions & 0 deletions src/cmd_rtl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3368,9 +3368,16 @@ striType cmdReadLink (const const_striType filePath)
if (unlikely(destination == NULL)) {
raise_error(err_info);
} /* if */
#else
#ifdef OS_STRI_WCHAR
destination = winReadLink(filePath, &err_info);
if (unlikely(destination == NULL)) {
raise_error(err_info);
} /* if */
#else
raise_error(FILE_ERROR);
destination = NULL;
#endif
#endif
logFunction(printf("cmdReadLink --> \"%s\"\n",
striAsUnquotedCStri(destination)););
Expand Down Expand Up @@ -3411,9 +3418,16 @@ striType cmdReadLinkAbsolute (const const_striType filePath)
if (unlikely(destination == NULL)) {
raise_error(err_info);
} /* if */
#else
#ifdef OS_STRI_WCHAR
destination = winReadLink(filePath, &err_info);
if (unlikely(destination == NULL)) {
raise_error(err_info);
} /* if */
#else
raise_error(FILE_ERROR);
destination = NULL;
#endif
#endif
logFunction(printf("cmdReadLinkAbsolute --> \"%s\"\n",
striAsUnquotedCStri(destination)););
Expand Down
70 changes: 70 additions & 0 deletions src/cmd_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,76 @@ static PSID getSidFromName (const const_striType name, errInfoType *err_info)



striType winReadLink (const const_striType filePath, errInfoType *err_info)

{
os_striType os_filePath;
int path_info;
HANDLE fileHandle;
os_charType buffer[PATH_MAX];
os_striType bufferPtr;
DWORD bufferSize;
DWORD linkSize;
striType destination = NULL;

/* winReadLink */
logFunction(printf("winReadLink(\"%s\", %d)\n",
striAsUnquotedCStri(filePath), *err_info););
os_filePath = cp_to_os_path(filePath, &path_info, err_info);
if (unlikely(os_filePath == NULL)) {
logError(printf("winReadLink: cp_to_os_path(\"%s\", *, *) failed:\n"
"path_info=%d, err_info=%d\n",
striAsUnquotedCStri(filePath), path_info, *err_info););
} else {
fileHandle = CreateFileW(os_filePath, 0, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (unlikely(fileHandle == INVALID_HANDLE_VALUE)) {
logError(printf("winReadLink: OpenFileW(\"%ls\", *, OF_READ) failed\n"
os_filePath););
*err_info = FILE_ERROR;
} else {
bufferSize = (DWORD) (sizeof(buffer) / sizeof(os_charType));
linkSize = GetFinalPathNameByHandleW(fileHandle, buffer,
bufferSize, FILE_NAME_OPENED);
if (unlikely(linkSize == 0)) {
logError(printf("winReadLink: GetFinalPathNameByHandle failed\n"););
*err_info = FILE_ERROR;
} else if (linkSize <= bufferSize - NULL_TERMINATION_LEN) {
destination = cp_from_os_path(buffer, err_info);
} else {
do {
bufferSize = linkSize;
if (unlikely(!os_stri_alloc(bufferPtr, (memSizeType) bufferSize))) {
*err_info = MEMORY_ERROR;
} else {
linkSize = GetFinalPathNameByHandleW(fileHandle, bufferPtr,
bufferSize, FILE_NAME_OPENED);
if (unlikely(linkSize == 0)) {
logError(printf("winReadLink: GetFinalPathNameByHandle failed\n"););
*err_info = FILE_ERROR;
} else if (linkSize <= bufferSize - NULL_TERMINATION_LEN) {
destination = cp_from_os_path(buffer, err_info);
} else if (linkSize <= bufferSize) {
logError(printf("winReadLink: GetFinalPathNameByHandle loop\n"););
*err_info = FILE_ERROR;
} /* if */
os_stri_free(bufferPtr);
} /* if */
} while (destination == NULL && *err_info == OKAY_NO_ERROR);
} /* if */
CloseHandle(fileHandle);
} /* if */
os_stri_free(os_filePath);
} /* if */
logFunction(printf("winReadLink(\"%s\", %d) --> ",
striAsUnquotedCStri(filePath), *err_info);
printf("\"%s\"\n", striAsUnquotedCStri(destination)););
return destination;
} /* winReadLink */



striType cmdGetGroup (const const_striType filePath)

{
Expand Down
11 changes: 7 additions & 4 deletions src/stat_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@
#endif


#ifndef S_IFLNK
#define S_IFLNK 0120000 /* Symbolic link */
#endif

#ifndef S_ISLNK
#ifdef S_IFLNK
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#else
#define S_ISLNK(mode) FALSE
#endif
#endif

#ifndef S_ISSOCK
Expand Down Expand Up @@ -213,6 +213,9 @@ struct stati64Ext {
#ifdef DEFINE_WSTATI64_EXT
int wstati64Ext (const wchar_t *path, os_stat_struct *statBuf);
#endif
#ifdef DEFINE_LSTATI64_EXT
int lstati64Ext (const wchar_t *path, os_stat_struct *statBuf);
#endif
#ifdef DEFINE_FSTATI64_EXT
int fstati64Ext (int fd, os_fstat_struct *statBuf);
#endif
56 changes: 50 additions & 6 deletions src/stat_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,7 @@ int wstati64Ext (const wchar_t *path, os_stat_struct *statBuf)
int result = 0;

/* wstati64Ext */
logFunction(printf("wstati64Ext(\"%ls\", *)", path);
fflush(stdout););
logFunction(printf("wstati64Ext(\"%ls\", *)\n", path););
if (likely(GetFileAttributesExW(path, GetFileExInfoStandard, &fileInfo) != 0)) {
/* The function os_stat_orig() fails with ENOENT, if the path is */
/* longer than MAX_PATH. So GetFileAttributesExW(), which works with */
Expand Down Expand Up @@ -272,13 +271,59 @@ int wstati64Ext (const wchar_t *path, os_stat_struct *statBuf)
result = -1;
#endif
} /* if */
logFunctionResult(printf("%d\n", result););
logFunction(printf("wstati64Ext --> %d\n", result););
return result;
} /* wstati64Ext */
#endif



#ifdef DEFINE_LSTATI64_EXT
int lstati64Ext (const wchar_t *path, os_stat_struct *statBuf)

{
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
HANDLE fileHandle;
int result;

/* lstati64Ext */
logFunction(printf("lstati64Ext(\"%ls\", *)\n", path););
result = wstati64Ext(path, statBuf);
if (result == 0) {
if (likely(GetFileAttributesExW(path, GetFileExInfoStandard, &fileInfo) != 0)) {
/* printf("dwFileAttributes: " FMT_X32 "\n", fileInfo.dwFileAttributes); */
if ((fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
statBuf->st_mode = S_IFLNK | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH |
S_IXUSR | S_IXGRP | S_IXOTH;
fileHandle = CreateFileW(path, 0, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (unlikely(fileHandle == INVALID_HANDLE_VALUE)) {
statBuf->st_size = 0;
} else {
/* Compute the length of the symbolic link. */
/* Surrogate pairs are not considered. */
/* A link with surrogate pairs will have */
/* fewer UTF-32 characters. */
statBuf->st_size = (int64Type)
GetFinalPathNameByHandleW(fileHandle, NULL, 0, FILE_NAME_OPENED);
statBuf->st_size -= NULL_TERMINATION_LEN;
#if USE_EXTENDED_LENGTH_PATH
statBuf->st_size -= PREFIX_LEN;
#endif
CloseHandle(fileHandle);
} /* if */
} /* if */
} /* if */
} /* if */
logFunction(printf("lstati64Ext --> %d\n", result););
return result;
} /* lstati64Ext */
#endif



#ifdef DEFINE_FSTATI64_EXT
int fstati64Ext (int fd, os_fstat_struct *statBuf)

Expand All @@ -295,8 +340,7 @@ int fstati64Ext (int fd, os_fstat_struct *statBuf)
int result;

/* fstati64Ext */
logFunction(printf("fstati64Ext(%d, *)", fd);
fflush(stdout););
logFunction(printf("fstati64Ext(%d, *)\n", fd););
fileHandle = (HANDLE) _get_osfhandle(fd);
#ifdef os_fstat_orig
result = os_fstat_orig(fd, &tmp);
Expand Down Expand Up @@ -348,7 +392,7 @@ int fstati64Ext (int fd, os_fstat_struct *statBuf)
errno = ENOENT;
result = -1;
} /* if */
logFunctionResult(printf("%d\n", result););
logFunction(printf("fstati64Ext --> %d\n", result););
return result;
} /* fstati64Ext */
#endif

0 comments on commit 4bff51f

Please sign in to comment.