mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add GetLStat
faccessat() does not support AT_SYMLINK_NOFOLLOW on OS X, so instead, we use the success of lstat() to determine if the file (not following symbolic links) exists. Also allowed for some refactoring.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
add_library(psl-native SHARED
|
||||
getstat.cpp
|
||||
getlstat.cpp
|
||||
getpwuid.cpp
|
||||
getuserfrompid.cpp
|
||||
getfileowner.cpp
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
//! @file getlstat.cpp
|
||||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief returns the lstat of a file
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetLStat(const char* path, struct stat* buf);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -89,8 +89,7 @@ int32_t GetStat(const char* path, struct stat* buf)
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user