diff --git a/src/libpsl-native/src/CMakeLists.txt b/src/libpsl-native/src/CMakeLists.txt index 22e8f5dd85..5d4c432b40 100644 --- a/src/libpsl-native/src/CMakeLists.txt +++ b/src/libpsl-native/src/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(psl-native SHARED getstat.cpp + getlstat.cpp getpwuid.cpp getuserfrompid.cpp getfileowner.cpp diff --git a/src/libpsl-native/src/getlstat.cpp b/src/libpsl-native/src/getlstat.cpp new file mode 100644 index 0000000000..d2fcb69697 --- /dev/null +++ b/src/libpsl-native/src/getlstat.cpp @@ -0,0 +1,95 @@ +//! @file getlstat.cpp +//! @author Andrew Schwartzmeyer +//! @brief returns the lstat of a file + +#include +#include +#include +#include +#include +#include +#include "getlstat.h" + +//! @brief GetLStat returns the lstat of a file. This simply delegates to the +//! lstat() system call and maps errno to the expected values for GetLastError. +//! +//! GetLstat +//! +//! @param[in] path +//! @parblock +//! A pointer to the buffer that contains the file name +//! +//! char* is marshaled as an LPStr, which on Linux is UTF-8. +//! @endparblock +//! +//! @param[in] lstat +//! @parblock +//! A pointer to the buffer in which to place the lstat information +//! @endparblock +//! +//! @exception errno Passes these errors via errno to GetLastError: +//! - ERROR_INVALID_PARAMETER: parameter is not valid +//! - ERROR_FILE_NOT_FOUND: file does not exist +//! - ERROR_ACCESS_DENIED: access is denied +//! - ERROR_INVALID_ADDRESS: attempt to access invalid address +//! - ERROR_STOPPED_ON_SYMLINK: too many symbolic links +//! - ERROR_GEN_FAILURE: I/O error occurred +//! - ERROR_INVALID_NAME: file provided is not a symbolic link +//! - ERROR_INVALID_FUNCTION: incorrect function +//! - ERROR_BAD_PATH_NAME: pathname is too long +//! - ERROR_OUTOFMEMORY insufficient kernel memory +//! +//! @retval 0 if successful +//! @retval -1 if failed +//! + +int32_t GetLStat(const char* path, struct stat* buf) +{ + errno = 0; + + if (!path) + { + errno = ERROR_INVALID_PARAMETER; + return -1; + } + + int32_t ret = lstat(path, buf); + + if (ret != 0) + { + switch(errno) + { + case EACCES: + errno = ERROR_ACCESS_DENIED; + break; + case EBADF: + errno = ERROR_FILE_NOT_FOUND; + break; + case EFAULT: + errno = ERROR_INVALID_ADDRESS; + break; + case ELOOP: + errno = ERROR_STOPPED_ON_SYMLINK; + break; + case ENAMETOOLONG: + errno = ERROR_GEN_FAILURE; + break; + case ENOENT: + errno = ERROR_FILE_NOT_FOUND; + break; + case ENOMEM: + errno = ERROR_NO_SUCH_USER; + break; + case ENOTDIR: + errno = ERROR_INVALID_NAME; + break; + case EOVERFLOW: + errno = ERROR_BUFFER_OVERFLOW; + break; + default: + errno = ERROR_INVALID_FUNCTION; + } + } + + return ret; +} diff --git a/src/libpsl-native/src/getlstat.h b/src/libpsl-native/src/getlstat.h new file mode 100644 index 0000000000..ba746dd35a --- /dev/null +++ b/src/libpsl-native/src/getlstat.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int32_t GetLStat(const char* path, struct stat* buf); + +PAL_END_EXTERNC diff --git a/src/libpsl-native/src/getstat.cpp b/src/libpsl-native/src/getstat.cpp index 3e89d1a6ed..8fd6662219 100644 --- a/src/libpsl-native/src/getstat.cpp +++ b/src/libpsl-native/src/getstat.cpp @@ -89,8 +89,7 @@ int32_t GetStat(const char* path, struct stat* buf) default: errno = ERROR_INVALID_FUNCTION; } - return -1; } - return 0; + return ret; } diff --git a/src/libpsl-native/src/isdirectory.cpp b/src/libpsl-native/src/isdirectory.cpp index 01ca0d9bb1..f8b6bfe742 100644 --- a/src/libpsl-native/src/isdirectory.cpp +++ b/src/libpsl-native/src/isdirectory.cpp @@ -31,7 +31,6 @@ //! bool IsDirectory(const char* path) { - int32_t ret = 0; errno = 0; if (!path) @@ -41,7 +40,7 @@ bool IsDirectory(const char* path) } struct stat buf; - ret = GetStat(path, &buf); + int32_t ret = GetStat(path, &buf); if (ret != 0) { return false; diff --git a/src/libpsl-native/src/isfile.cpp b/src/libpsl-native/src/isfile.cpp index 89c415f472..1f6d0c59e5 100644 --- a/src/libpsl-native/src/isfile.cpp +++ b/src/libpsl-native/src/isfile.cpp @@ -9,6 +9,7 @@ #include #include #include +#include "getlstat.h" #include "isfile.h" //! @brief returns if the path is a file or directory @@ -37,6 +38,6 @@ bool IsFile(const char* path) return false; } - // Resolve relative paths to cwd of process, and do not follow symlinks - return faccessat(AT_FDCWD, path, F_OK, AT_SYMLINK_NOFOLLOW) != -1; + struct stat buf; + return GetLStat(path, &buf) == 0; } diff --git a/src/libpsl-native/src/issymlink.cpp b/src/libpsl-native/src/issymlink.cpp index dfd37d8bc5..87a8a2e8db 100644 --- a/src/libpsl-native/src/issymlink.cpp +++ b/src/libpsl-native/src/issymlink.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "getlstat.h" #include "issymlink.h" //! @brief IsSymlink determines if path is a symbolic link @@ -48,46 +49,12 @@ bool IsSymLink(const char* path) return false; } - struct stat statBuf; - - int ret = lstat(path, &statBuf); - + struct stat buf; + int32_t ret = GetLStat(path, &buf); if (ret != 0) { - switch(errno) - { - case EACCES: - errno = ERROR_ACCESS_DENIED; - break; - case EBADF: - errno = ERROR_FILE_NOT_FOUND; - break; - case EFAULT: - errno = ERROR_INVALID_ADDRESS; - break; - case ELOOP: - errno = ERROR_STOPPED_ON_SYMLINK; - break; - case ENAMETOOLONG: - errno = ERROR_GEN_FAILURE; - break; - case ENOENT: - errno = ERROR_FILE_NOT_FOUND; - break; - case ENOMEM: - errno = ERROR_NO_SUCH_USER; - break; - case ENOTDIR: - errno = ERROR_INVALID_NAME; - break; - case EOVERFLOW: - errno = ERROR_BUFFER_OVERFLOW; - break; - default: - errno = ERROR_INVALID_FUNCTION; - } return false; } - return S_ISLNK(statBuf.st_mode); + return S_ISLNK(buf.st_mode); }