Merge pull request #2441 from andschwa/native-perror
Fix error handling of libpsl-native
This commit is contained in:
commit
8e3861a64b
|
@ -69,42 +69,37 @@ namespace Microsoft.PowerShell.Commands
|
|||
goto case "Date";
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// build up the SystemTime struct to pass to SetSystemTime
|
||||
NativeMethods.SystemTime systemTime = new NativeMethods.SystemTime();
|
||||
systemTime.Year = (UInt16)dateToUse.Year;
|
||||
systemTime.Month = (UInt16)dateToUse.Month;
|
||||
systemTime.Day = (UInt16)dateToUse.Day;
|
||||
systemTime.Hour = (UInt16)dateToUse.Hour;
|
||||
systemTime.Minute = (UInt16)dateToUse.Minute;
|
||||
systemTime.Second = (UInt16)dateToUse.Second;
|
||||
systemTime.Milliseconds = (UInt16)dateToUse.Millisecond;
|
||||
|
||||
if (ShouldProcess(dateToUse.ToString()))
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
#if UNIX
|
||||
if (!Platform.NonWindowsSetDate(dateToUse))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
#else
|
||||
// build up the SystemTime struct to pass to SetSystemTime
|
||||
NativeMethods.SystemTime systemTime = new NativeMethods.SystemTime();
|
||||
systemTime.Year = (UInt16)dateToUse.Year;
|
||||
systemTime.Month = (UInt16)dateToUse.Month;
|
||||
systemTime.Day = (UInt16)dateToUse.Day;
|
||||
systemTime.Hour = (UInt16)dateToUse.Hour;
|
||||
systemTime.Minute = (UInt16)dateToUse.Minute;
|
||||
systemTime.Second = (UInt16)dateToUse.Second;
|
||||
systemTime.Milliseconds = (UInt16)dateToUse.Millisecond;
|
||||
#pragma warning disable 56523
|
||||
|
||||
if (!NativeMethods.SetLocalTime(ref systemTime))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
// MSDN says to call this twice to account for changes
|
||||
// between DST
|
||||
if (!NativeMethods.SetLocalTime(ref systemTime))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
#pragma warning restore 56523
|
||||
}
|
||||
else
|
||||
if (!NativeMethods.SetLocalTime(ref systemTime))
|
||||
{
|
||||
Platform.NonWindowsSetDate(dateToUse);
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
// MSDN says to call this twice to account for changes
|
||||
// between DST
|
||||
if (!NativeMethods.SetLocalTime(ref systemTime))
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
#pragma warning restore 56523
|
||||
#endif
|
||||
}
|
||||
|
||||
//output DateTime object wrapped in an PSObject with DisplayHint attached
|
||||
|
@ -121,7 +116,8 @@ namespace Microsoft.PowerShell.Commands
|
|||
|
||||
internal static class NativeMethods
|
||||
{
|
||||
public struct SystemTime
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class SystemTime
|
||||
{
|
||||
public UInt16 Year;
|
||||
public UInt16 Month;
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
"allowUnsafe": true
|
||||
},
|
||||
|
||||
"configurations": {
|
||||
"Linux": {
|
||||
"buildOptions": {
|
||||
"define": [ "UNIX" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"System.Management.Automation": "1.0.0-*"
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@ Copyright (c) Microsoft Corporation. All rights reserved.
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Win32;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System.IO;
|
||||
|
@ -394,18 +395,18 @@ namespace System.Management.Automation
|
|||
internal static bool NonWindowsCreateSymbolicLink(string path, string target)
|
||||
{
|
||||
// Linux doesn't care if target is a directory or not
|
||||
return Unix.NativeMethods.CreateSymLink(path, target);
|
||||
return Unix.NativeMethods.CreateSymLink(path, target) == 0;
|
||||
}
|
||||
|
||||
internal static bool NonWindowsCreateHardLink(string path, string strTargetPath)
|
||||
{
|
||||
return Unix.CreateHardLink(path, strTargetPath);
|
||||
return Unix.NativeMethods.CreateHardLink(path, strTargetPath) == 0;
|
||||
}
|
||||
|
||||
internal static void NonWindowsSetDate(DateTime dateToUse)
|
||||
internal static unsafe bool NonWindowsSetDate(DateTime dateToUse)
|
||||
{
|
||||
Unix.SetDateInfoInternal date = new Unix.SetDateInfoInternal(dateToUse);
|
||||
Unix.SetDate(date);
|
||||
Unix.NativeMethods.UnixTm tm = Unix.NativeMethods.DateTimeToUnixTm(dateToUse);
|
||||
return Unix.NativeMethods.SetDate(&tm) == 0;
|
||||
}
|
||||
|
||||
internal static string NonWindowsGetDomainName()
|
||||
|
@ -447,12 +448,24 @@ namespace System.Management.Automation
|
|||
|
||||
internal static uint NonWindowsGetThreadId()
|
||||
{
|
||||
// TODO:PSL clean this up
|
||||
return 0;
|
||||
return Unix.NativeMethods.GetCurrentThreadId();
|
||||
}
|
||||
|
||||
// Unix specific implementations of required functionality
|
||||
//
|
||||
// Please note that `Win32Exception(Marshal.GetLastWin32Error())`
|
||||
// works *correctly* on Linux in that it creates an exception with
|
||||
// the string perror would give you for the last set value of errno.
|
||||
// No manual mapping is required. .NET Core maps the Linux errno
|
||||
// to a PAL value and calls strerror_r underneath to generate the message.
|
||||
internal static class Unix
|
||||
{
|
||||
// This is a helper that attempts to map errno into a PowerShell ErrorCategory
|
||||
internal static ErrorCategory GetErrorCategory(int errno)
|
||||
{
|
||||
return (ErrorCategory)Unix.NativeMethods.GetErrorCategory(errno);
|
||||
}
|
||||
|
||||
private static string s_userName;
|
||||
public static string UserName
|
||||
{
|
||||
|
@ -502,61 +515,13 @@ namespace System.Management.Automation
|
|||
int count;
|
||||
string filePath = fs.FullName;
|
||||
int ret = NativeMethods.GetLinkCount(filePath, out count);
|
||||
if (ret == 1)
|
||||
if (ret == 0)
|
||||
{
|
||||
return count > 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
throw new InvalidOperationException("Unix.IsHardLink error: " + lastError);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetDate(SetDateInfoInternal info)
|
||||
{
|
||||
int ret = NativeMethods.SetDate(info);
|
||||
if (ret == -1)
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
throw new InvalidOperationException("Unix.NonWindowsSetDate error: " + lastError);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CreateHardLink(string path, string strTargetPath)
|
||||
{
|
||||
int ret = NativeMethods.CreateHardLink(path, strTargetPath);
|
||||
return ret == 1 ? true : false;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class SetDateInfoInternal
|
||||
{
|
||||
public int Year;
|
||||
public int Month;
|
||||
public int Day;
|
||||
public int Hour;
|
||||
public int Minute;
|
||||
public int Second;
|
||||
public int Millisecond;
|
||||
public int DST;
|
||||
|
||||
public SetDateInfoInternal(DateTime d)
|
||||
{
|
||||
Year = d.Year;
|
||||
Month = d.Month;
|
||||
Day = d.Day;
|
||||
Hour = d.Hour;
|
||||
Minute = d.Minute;
|
||||
Second = d.Second;
|
||||
Millisecond = d.Millisecond;
|
||||
DST = d.IsDaylightSavingTime() ? 1 : 0;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string ret = String.Format("Year = {0}; Month = {1}; Day = {2}; Hour = {3}; Minute = {4}; Second = {5}; Millisec = {6}; DST = {7}", Year, Month, Day, Hour, Minute, Second, Millisecond, DST);
|
||||
return ret;
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,6 +533,9 @@ namespace System.Management.Automation
|
|||
|
||||
// C bools are 1 byte and so must be marshaled as I1
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi)]
|
||||
internal static extern int GetErrorCategory(int errno);
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static extern string GetUserName();
|
||||
|
@ -583,17 +551,49 @@ namespace System.Management.Automation
|
|||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
internal static extern bool IsExecutable([MarshalAs(UnmanagedType.LPStr)]string filePath);
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi)]
|
||||
internal static extern uint GetCurrentThreadId();
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static extern string GetFullyQualifiedName();
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
internal static extern int SetDate(SetDateInfoInternal info);
|
||||
// This is a struct tm from <time.h>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct UnixTm
|
||||
{
|
||||
public int tm_sec; /* Seconds (0-60) */
|
||||
public int tm_min; /* Minutes (0-59) */
|
||||
public int tm_hour; /* Hours (0-23) */
|
||||
public int tm_mday; /* Day of the month (1-31) */
|
||||
public int tm_mon; /* Month (0-11) */
|
||||
public int tm_year; /* Year - 1900 */
|
||||
public int tm_wday; /* Day of the week (0-6, Sunday = 0) */
|
||||
public int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
|
||||
public int tm_isdst; /* Daylight saving time */
|
||||
}
|
||||
|
||||
internal static UnixTm DateTimeToUnixTm(DateTime date)
|
||||
{
|
||||
UnixTm tm;
|
||||
tm.tm_sec = date.Second;
|
||||
tm.tm_min = date.Minute;
|
||||
tm.tm_hour = date.Hour;
|
||||
tm.tm_mday = date.Day;
|
||||
tm.tm_mon = date.Month - 1; // needs to be 0 indexed
|
||||
tm.tm_year = date.Year - 1900; // years since 1900
|
||||
tm.tm_wday = 0; // this is ignored by mktime
|
||||
tm.tm_yday = 0; // this is also ignored
|
||||
tm.tm_isdst = date.IsDaylightSavingTime() ? 1 : 0;
|
||||
return tm;
|
||||
}
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
internal static extern bool CreateSymLink([MarshalAs(UnmanagedType.LPStr)]string filePath,
|
||||
[MarshalAs(UnmanagedType.LPStr)]string target);
|
||||
internal static extern unsafe int SetDate(UnixTm* tm);
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
internal static extern int CreateSymLink([MarshalAs(UnmanagedType.LPStr)]string filePath,
|
||||
[MarshalAs(UnmanagedType.LPStr)]string target);
|
||||
|
||||
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
internal static extern int CreateHardLink([MarshalAs(UnmanagedType.LPStr)]string filePath,
|
||||
|
|
|
@ -2208,34 +2208,33 @@ namespace Microsoft.PowerShell.Commands
|
|||
|
||||
if (itemType == ItemType.SymbolicLink)
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
{
|
||||
success = WinCreateSymbolicLink(path, strTargetPath, isDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = Platform.NonWindowsCreateSymbolicLink(path, strTargetPath);
|
||||
}
|
||||
#if UNIX
|
||||
success = Platform.NonWindowsCreateSymbolicLink(path, strTargetPath);
|
||||
#else
|
||||
success = WinCreateSymbolicLink(path, strTargetPath, isDirectory);
|
||||
#endif
|
||||
}
|
||||
else if (itemType == ItemType.HardLink)
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
{
|
||||
success = WinCreateHardLink(path, strTargetPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = Platform.NonWindowsCreateHardLink(path, strTargetPath);
|
||||
}
|
||||
#if UNIX
|
||||
success = Platform.NonWindowsCreateHardLink(path, strTargetPath);
|
||||
#else
|
||||
success = WinCreateHardLink(path, strTargetPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// Porting note: The Win32Exception will report the correct error on Linux
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
|
||||
Win32Exception w32Exception = new Win32Exception((int)errorCode);
|
||||
|
||||
#if UNIX
|
||||
if (Platform.Unix.GetErrorCategory(errorCode) == ErrorCategory.PermissionDenied)
|
||||
#else
|
||||
if (errorCode == 1314) //ERROR_PRIVILEGE_NOT_HELD
|
||||
#endif
|
||||
{
|
||||
string message = FileSystemProviderStrings.ElevationRequired;
|
||||
WriteError(new ErrorRecord(new UnauthorizedAccessException(message, w32Exception), "NewItemSymbolicLinkElevationRequired", ErrorCategory.PermissionDenied, value.ToString()));
|
||||
|
@ -8028,17 +8027,18 @@ namespace Microsoft.PowerShell.Commands
|
|||
private static List<string> InternalGetTarget(string filePath)
|
||||
{
|
||||
var links = new List<string>();
|
||||
if (!Platform.IsWindows)
|
||||
#if UNIX
|
||||
string link = Platform.NonWindowsInternalGetTarget(filePath);
|
||||
if (!String.IsNullOrEmpty(link))
|
||||
{
|
||||
string link = Platform.NonWindowsInternalGetTarget(filePath);
|
||||
if (!String.IsNullOrEmpty(link))
|
||||
{
|
||||
links.Add(link);
|
||||
}
|
||||
return links;
|
||||
links.Add(link);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
#if !CORECLR //FindFirstFileName, FindNextFileName and FindClose are not available on Core Clr
|
||||
#elif !CORECLR //FindFirstFileName, FindNextFileName and FindClose are not available on Core Clr
|
||||
UInt32 linkStringLength = 0;
|
||||
var linkName = new StringBuilder();
|
||||
|
||||
|
@ -8096,7 +8096,7 @@ namespace Microsoft.PowerShell.Commands
|
|||
{
|
||||
InternalSymbolicLinkLinkCodeMethods.FindClose(fileHandle);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return links;
|
||||
}
|
||||
|
||||
|
@ -8179,10 +8179,11 @@ namespace Microsoft.PowerShell.Commands
|
|||
|
||||
internal static bool IsHardLink(FileSystemInfo fileInfo)
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
return WinIsHardLink(fileInfo);
|
||||
else
|
||||
return Platform.NonWindowsIsHardLink(fileInfo);
|
||||
#if UNIX
|
||||
return Platform.NonWindowsIsHardLink(fileInfo);
|
||||
#else
|
||||
return WinIsHardLink(fileInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static bool IsReparsePoint(FileSystemInfo fileInfo)
|
||||
|
@ -8238,10 +8239,11 @@ namespace Microsoft.PowerShell.Commands
|
|||
|
||||
internal static bool IsHardLink(ref IntPtr handle)
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
return WinIsHardLink(ref handle);
|
||||
else
|
||||
return Platform.NonWindowsIsHardLink(ref handle);
|
||||
#if UNIX
|
||||
return Platform.NonWindowsIsHardLink(ref handle);
|
||||
#else
|
||||
return WinIsHardLink(ref handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
|
||||
|
|
|
@ -624,19 +624,11 @@ namespace System.Management.Automation
|
|||
|
||||
internal static uint GetNativeThreadId()
|
||||
{
|
||||
if (Platform.IsWindows)
|
||||
{
|
||||
return WinGetNativeThreadId();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Platform.NonWindowsGetThreadId();
|
||||
}
|
||||
}
|
||||
|
||||
internal static uint WinGetNativeThreadId()
|
||||
{
|
||||
#if UNIX
|
||||
return Platform.NonWindowsGetThreadId();
|
||||
#else
|
||||
return NativeMethods.GetCurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static class NativeMethods
|
||||
|
|
|
@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8.11)
|
|||
project(PSL-NATIVE)
|
||||
|
||||
# Can't use add_compile_options with 2.8.11
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror")
|
||||
set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/../powershell-unix")
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
add_library(psl-native SHARED
|
||||
getstat.cpp
|
||||
getlstat.cpp
|
||||
getpwuid.cpp
|
||||
getuserfrompid.cpp
|
||||
getfileowner.cpp
|
||||
getcurrentthreadid.cpp
|
||||
getcurrentprocessorid.cpp
|
||||
getusername.cpp
|
||||
getcomputername.cpp
|
||||
getlinkcount.cpp
|
||||
getfullyqualifiedname.cpp
|
||||
geterrorcategory.cpp
|
||||
isfile.cpp
|
||||
isdirectory.cpp
|
||||
issymlink.cpp
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief create new hard link
|
||||
|
||||
#include <errno.h>
|
||||
#include "createhardlink.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "createhardlink.h"
|
||||
|
||||
//! @brief Createhardlink create new symbolic link
|
||||
//!
|
||||
|
@ -25,91 +26,13 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @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_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_TOO_MANY_LINK: max number of hard links has been exceeded
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval 1 if creation is successful
|
||||
//! @retval 0 if creation failed
|
||||
//! @retval 0 if successful, otherwise -1
|
||||
//!
|
||||
|
||||
int32_t CreateHardLink(const char *newlink, const char *target)
|
||||
{
|
||||
errno = 0;
|
||||
assert(newlink);
|
||||
assert(target);
|
||||
|
||||
// Check parameters
|
||||
if (!newlink || !target)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int returnCode = link(target, newlink);
|
||||
|
||||
if (returnCode == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EDQUOT:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EEXIST:
|
||||
errno = ERROR_FILE_EXISTS;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case EIO:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_TOO_MANY_LINKS;
|
||||
break;
|
||||
case EMLINK:
|
||||
errno = ERROR_TOO_MANY_LINKS;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case ENOSPC:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EPERM:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EROFS:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EXDEV:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return 0;
|
||||
return link(target, newlink);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief create new symbolic link
|
||||
|
||||
#include "createsymlink.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "createsymlink.h"
|
||||
|
||||
//! @brief Createsymlink create new symbolic link
|
||||
//!
|
||||
|
@ -25,82 +27,15 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @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_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval boolean successful
|
||||
//! @retval 0 if successful, -1 otherwise
|
||||
//!
|
||||
|
||||
bool CreateSymLink(const char *link, const char *target)
|
||||
int32_t CreateSymLink(const char *link, const char *target)
|
||||
{
|
||||
assert(link);
|
||||
assert(target);
|
||||
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!link || !target)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
|
||||
int ret = symlink(target, link);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EDQUOT:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EEXIST:
|
||||
errno = ERROR_FILE_EXISTS;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case EIO:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case ENOSPC:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EPERM:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
|
||||
return false;
|
||||
return symlink(target, link);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
bool CreateSymLink(const char *link, const char *target);
|
||||
int32_t CreateSymLink(const char *link, const char *target);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
|
|
@ -2,16 +2,15 @@
|
|||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief returns whether a path is a symbolic link
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "followsymlink.h"
|
||||
#include "issymlink.h"
|
||||
|
||||
//! @brief Followsymlink determines target path of a sym link
|
||||
//!
|
||||
//! Followsymlink
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
|
||||
//! @brief FollowSymLink determines target path of a sym link
|
||||
//!
|
||||
//! @param[in] fileName
|
||||
//! @parblock
|
||||
|
@ -20,31 +19,14 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @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 target path, or NULL if unsuccessful
|
||||
//!
|
||||
|
||||
char* FollowSymLink(const char* fileName)
|
||||
{
|
||||
assert(fileName);
|
||||
errno = 0;
|
||||
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// return null for non symlinks
|
||||
if (!IsSymLink(fileName))
|
||||
{
|
||||
|
@ -64,38 +46,6 @@ char* FollowSymLink(const char* fileName)
|
|||
ssize_t sz = readlink(fileName, buffer, PATH_MAX);
|
||||
if (sz == -1)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case EINVAL:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
case EIO:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,44 +2,29 @@
|
|||
//! @author George Fleming <v-geflem@microsoft>
|
||||
//! @brief Implements GetComputerName Win32 API
|
||||
|
||||
#include "getcomputername.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "getcomputername.h"
|
||||
|
||||
//! @brief GetComputerName retrieves the name of the host associated with
|
||||
//! the current thread.
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code
|
||||
//! - ERROR_INVALID_ADDRESS: buffer is an invalid address
|
||||
//! - ERROR_GEN_FAILURE: buffer not large enough
|
||||
//!
|
||||
//! @retval username as UTF-8 string, or null if unsuccessful
|
||||
|
||||
char* GetComputerName()
|
||||
{
|
||||
errno = 0;
|
||||
errno = 0;
|
||||
// Get computername from system, note that gethostname(2) gets the
|
||||
// nodename from uname
|
||||
std::string computername(_POSIX_HOST_NAME_MAX, 0);
|
||||
int err = gethostname(&computername[0], computername.length());
|
||||
int32_t ret = gethostname(&computername[0], computername.length());
|
||||
// Map errno to Win32 Error Codes
|
||||
if (err != 0)
|
||||
if (ret != 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return strdup(computername.c_str());
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#include "getcurrentprocessorid.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int32_t GetCurrentProcessId()
|
||||
pid_t GetCurrentProcessId()
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
return static_cast<int32_t>(pid);
|
||||
return getpid();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetCurrentProcessId();
|
||||
pid_t GetCurrentProcessId();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
#include "getcurrentthreadid.h"
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
HANDLE GetCurrentThreadId()
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
pid_t GetCurrentThreadId()
|
||||
{
|
||||
pid_t tid = pthread_self();
|
||||
return reinterpret_cast<HANDLE>(tid);
|
||||
pid_t tid = 0;
|
||||
#if defined(__linux__)
|
||||
tid = syscall(SYS_gettid);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
tid = syscall(SYS_thread_selfid);
|
||||
#endif
|
||||
return tid;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
#include "pal.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
HANDLE GetCurrentThreadId();
|
||||
pid_t GetCurrentThreadId();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
||||
|
|
63
src/libpsl-native/src/geterrorcategory.cpp
Normal file
63
src/libpsl-native/src/geterrorcategory.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include "geterrorcategory.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Copy of PowerShell ErrorCategory enum from ErrorPackage.cs
|
||||
enum ErrorCategory {
|
||||
NotSpecified = 0,
|
||||
OpenError = 1,
|
||||
CloseError = 2,
|
||||
DeviceError = 3,
|
||||
DeadlockDetected = 4,
|
||||
InvalidArgument = 5,
|
||||
InvalidData = 6,
|
||||
InvalidOperation = 7,
|
||||
InvalidResult = 8,
|
||||
InvalidType = 9,
|
||||
MetadataError = 10,
|
||||
NotImplemented = 11,
|
||||
NotInstalled = 12,
|
||||
ObjectNotFound = 13,
|
||||
OperationStopped = 14,
|
||||
OperationTimeout = 15,
|
||||
SyntaxError = 16,
|
||||
ParserError = 17,
|
||||
PermissionDenied = 18,
|
||||
ResourceBusy = 19,
|
||||
ResourceExists = 20,
|
||||
ResourceUnavailable = 21,
|
||||
ReadError = 22,
|
||||
WriteError = 23,
|
||||
FromStdErr = 24,
|
||||
SecurityError = 25,
|
||||
ProtocolError = 26,
|
||||
ConnectionError = 27,
|
||||
AuthenticationError = 28,
|
||||
LimitsExceeded = 29,
|
||||
QuotaExceeded = 30,
|
||||
NotEnabled = 31,
|
||||
};
|
||||
|
||||
//! @brief Maps Linux errno to PowerShell ErrorCategory
|
||||
int32_t GetErrorCategory(int32_t errnum)
|
||||
{
|
||||
switch (errnum)
|
||||
{
|
||||
case EINVAL:
|
||||
return InvalidArgument;
|
||||
case ENOENT:
|
||||
case ESRCH:
|
||||
return ObjectNotFound;
|
||||
case EINTR:
|
||||
return OperationStopped;
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
return PermissionDenied;
|
||||
default:
|
||||
return NotSpecified;
|
||||
}
|
||||
}
|
9
src/libpsl-native/src/geterrorcategory.h
Normal file
9
src/libpsl-native/src/geterrorcategory.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetErrorCategory(int32_t);
|
||||
|
||||
PAL_END_EXTERNC
|
|
@ -2,15 +2,17 @@
|
|||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief returns the owner of a file
|
||||
|
||||
#include "getstat.h"
|
||||
#include "getpwuid.h"
|
||||
#include "getfileowner.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "getstat.h"
|
||||
#include "getpwuid.h"
|
||||
#include "getfileowner.h"
|
||||
|
||||
//! @brief GetFileOwner returns the owner of a file
|
||||
//!
|
||||
|
@ -23,24 +25,15 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes this error via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//!
|
||||
//! @retval file owner, or NULL if unsuccessful
|
||||
//!
|
||||
char* GetFileOwner(const char* fileName)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
assert(fileName);
|
||||
errno = 0;
|
||||
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct stat buf;
|
||||
ret = GetStat(fileName, &buf);
|
||||
int32_t ret = GetStat(fileName, &buf);
|
||||
if (ret != 0)
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements GetFullyQualifiedName on Linux
|
||||
|
||||
#include "getcomputername.h"
|
||||
#include "getfullyqualifiedname.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include "getcomputername.h"
|
||||
#include "getfullyqualifiedname.h"
|
||||
|
||||
//! @brief GetFullyQualifiedName retrieves the fully qualified dns name of the host
|
||||
//!
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief Retrieve link count of a file
|
||||
|
||||
#include "getlinkcount.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "getlinkcount.h"
|
||||
|
||||
//! @brief GetLinkCount retrieves the file link count (number of hard links)
|
||||
//! for the given file
|
||||
|
@ -27,21 +29,7 @@
|
|||
//! This function returns the number of hard links associated with this file
|
||||
//! @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_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval 1 If the function succeeds, and the variable pointed to by buffer contains
|
||||
//! @retval 1 If the function succeeds, and the variable pointed to by buffer contains
|
||||
//! information about the files
|
||||
//! @retval 0 If the function fails, the return value is zero. To get
|
||||
//! extended error information, call GetLastError.
|
||||
|
@ -49,56 +37,14 @@
|
|||
|
||||
int32_t GetLinkCount(const char* fileName, int32_t *count)
|
||||
{
|
||||
assert(fileName);
|
||||
assert(count);
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct stat statBuf;
|
||||
|
||||
int returnCode = lstat(fileName, &statBuf);
|
||||
|
||||
if (returnCode != 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 0;
|
||||
}
|
||||
int32_t ret = lstat(fileName, &statBuf);
|
||||
|
||||
*count = statBuf.st_nlink;
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
//! @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;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetLStat(const char* path, struct stat* buf);
|
||||
|
||||
PAL_END_EXTERNC
|
|
@ -2,13 +2,14 @@
|
|||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief returns the username for a uid
|
||||
|
||||
#include "getpwuid.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "getpwuid.h"
|
||||
|
||||
//! @brief GetPwUid returns the username for a uid
|
||||
//!
|
||||
|
@ -19,11 +20,6 @@
|
|||
//! The user identifier to lookup.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_NO_SUCH_USER: user lookup unsuccessful
|
||||
//! - ERROR_OUTOFMEMORY insufficient kernel memory
|
||||
//! - ERROR_GEN_FAILURE: anything else
|
||||
//!
|
||||
//! @retval username as UTF-8 string, or NULL if unsuccessful
|
||||
//!
|
||||
char* GetPwUid(uid_t uid)
|
||||
|
@ -42,27 +38,16 @@ char* GetPwUid(uid_t uid)
|
|||
allocate:
|
||||
buf = (char*)calloc(buflen, sizeof(char));
|
||||
|
||||
errno = 0;
|
||||
ret = getpwuid_r(uid, &pwd, buf, buflen, &result);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
switch(errno)
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
case ERANGE:
|
||||
free(buf);
|
||||
buflen *= 2;
|
||||
goto allocate;
|
||||
case ENOENT:
|
||||
case ESRCH:
|
||||
case EBADF:
|
||||
case EPERM:
|
||||
errno = ERROR_NO_SUCH_USER;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "pal.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* GetPwUid(uid_t uid);
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief returns the stat of a file
|
||||
|
||||
#include "getstat.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "getstat.h"
|
||||
|
||||
//! @brief GetStat returns the stat of a file. This simply delegates to the
|
||||
//! stat() system call and maps errno to the expected values for GetLastError.
|
||||
|
@ -27,69 +29,14 @@
|
|||
//! A pointer to the buffer in which to place the stat 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 GetStat(const char* path, struct stat* buf)
|
||||
{
|
||||
assert(path);
|
||||
errno = 0;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t ret = stat(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;
|
||||
return stat(path, buf);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "pal.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetStat(const char* path, struct stat* buf);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
#include <errno.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include "pal.h"
|
||||
#include "getfileowner.h"
|
||||
#include "getpwuid.h"
|
||||
#include "getuserfrompid.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <errno.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
char* GetUserFromPid(pid_t pid)
|
||||
{
|
||||
|
||||
|
@ -32,7 +33,6 @@ char* GetUserFromPid(pid_t pid)
|
|||
int ret = sysctl(name, namelen, &oldp, &oldlenp, NULL, 0);
|
||||
if (ret != 0 || oldlenp == 0)
|
||||
{
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "pal.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* GetUserFromPid(pid_t pid);
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief Implements GetUserName for Linux
|
||||
|
||||
#include <unistd.h>
|
||||
#include "getpwuid.h"
|
||||
#include "getusername.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
//! @brief GetUserName retrieves the name of the user associated with
|
||||
//! the current thread.
|
||||
//!
|
||||
|
|
|
@ -2,16 +2,17 @@
|
|||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief returns if the path is a directory
|
||||
|
||||
#include <errno.h>
|
||||
#include "getstat.h"
|
||||
#include "getpwuid.h"
|
||||
#include "getfileowner.h"
|
||||
#include "isdirectory.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "getstat.h"
|
||||
#include "getpwuid.h"
|
||||
#include "getfileowner.h"
|
||||
#include "isdirectory.h"
|
||||
|
||||
//! @brief returns if the path is a directory; uses stat and so follows symlinks
|
||||
//!
|
||||
|
@ -24,20 +25,11 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes this error via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//!
|
||||
//! @retval true if directory, false otherwise
|
||||
//!
|
||||
bool IsDirectory(const char* path)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
assert(path);
|
||||
|
||||
struct stat buf;
|
||||
int32_t ret = GetStat(path, &buf);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief returns whether a file is executable
|
||||
|
||||
#include <errno.h>
|
||||
#include "isexecutable.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "isexecutable.h"
|
||||
|
||||
//! @brief IsExecutable determines if path is executable
|
||||
//!
|
||||
|
@ -18,22 +19,12 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//!
|
||||
//! @retval true if path is an executable, false otherwise
|
||||
//!
|
||||
|
||||
bool IsExecutable(const char* path)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!path)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
assert(path);
|
||||
|
||||
return access(path, X_OK) != -1;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief returns if the path exists
|
||||
|
||||
#include <errno.h>
|
||||
#include "isfile.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#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
|
||||
//!
|
||||
|
@ -23,21 +23,12 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes this error via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//!
|
||||
//! @retval true if path exists, false otherwise
|
||||
//!
|
||||
bool IsFile(const char* path)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
assert(path);
|
||||
|
||||
struct stat buf;
|
||||
return GetLStat(path, &buf) == 0;
|
||||
return lstat(path, &buf) == 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief returns whether a path is a symbolic link
|
||||
|
||||
#include <errno.h>
|
||||
#include "issymlink.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "getlstat.h"
|
||||
#include "issymlink.h"
|
||||
|
||||
//! @brief IsSymlink determines if path is a symbolic link
|
||||
//!
|
||||
|
@ -21,36 +21,15 @@
|
|||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @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_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval true if path is a symbolic link, false otherwise
|
||||
//!
|
||||
|
||||
bool IsSymLink(const char* path)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!path)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
assert(path);
|
||||
|
||||
struct stat buf;
|
||||
int32_t ret = GetLStat(path, &buf);
|
||||
int32_t ret = lstat(path, &buf);
|
||||
if (ret != 0)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
|
|
@ -5,27 +5,6 @@
|
|||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define ERROR_INVALID_PARAMETER 87
|
||||
#define ERROR_OUTOFMEMORY 14
|
||||
#define ERROR_BAD_ENVIRONMENT 0x0000000A
|
||||
#define ERROR_TOO_MANY_OPEN_FILES 0x00000004
|
||||
#define ERROR_INSUFFICIENT_BUFFER 0x0000007A
|
||||
#define ERROR_NO_ASSOCIATION 0x00000483
|
||||
#define ERROR_NO_SUCH_USER 0x00000525
|
||||
#define ERROR_INVALID_FUNCTION 0x00000001
|
||||
#define ERROR_INVALID_ADDRESS 0x000001e7
|
||||
#define ERROR_GEN_FAILURE 0x0000001F
|
||||
#define ERROR_ACCESS_DENIED 0x00000005
|
||||
#define ERROR_INVALID_NAME 0x0000007B
|
||||
#define ERROR_STOPPED_ON_SYMLINK 0x000002A9
|
||||
#define ERROR_BUFFER_OVERFLOW 0x0000006F
|
||||
#define ERROR_FILE_NOT_FOUND 0x00000002
|
||||
#define ERROR_BAD_PATH_NAME 0x000000A1
|
||||
#define ERROR_BAD_NET_NAME 0x00000043
|
||||
#define ERROR_DISK_FULL 0x00000070
|
||||
#define ERROR_FILE_EXISTS 0x00000050
|
||||
#define ERROR_TOO_MANY_LINKS 0x00000476
|
||||
|
||||
/*
|
||||
**==============================================================================
|
||||
**
|
||||
|
|
|
@ -2,72 +2,41 @@
|
|||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief set local/system date and time
|
||||
|
||||
#include "setdate.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "setdate.h"
|
||||
|
||||
//! @brief SetDate sets the date and time on local computer. You must
|
||||
//! be super-user to set the time.
|
||||
//! @brief SetDate sets the date and time on local computer.
|
||||
//! You must be super-user to set the time.
|
||||
//!
|
||||
//! SetDate
|
||||
//!
|
||||
//! @param[in] info
|
||||
//! @parblock
|
||||
//! A struct that contains program to execute and its parameters
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8
|
||||
//! - ERROR_INVALID_PARAMETER: time was not passed in correctly
|
||||
//! - ERROR_ACCESS_DENIED: you must be super-user to set the date
|
||||
//!
|
||||
//! @retval 0 successfully set date
|
||||
//! @retval -1 if failure occurred. To get extended error information, call GetLastError.
|
||||
//! @retval -1 if failure occurred.
|
||||
//!
|
||||
|
||||
int32_t SetDate(const SetDateInfo &info)
|
||||
int32_t SetDate(struct tm* time)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Select locale from environment
|
||||
setlocale(LC_ALL, "");
|
||||
// Check that locale is UTF-8
|
||||
if (nl_langinfo(CODESET) != std::string("UTF-8"))
|
||||
{
|
||||
errno = ERROR_BAD_ENVIRONMENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tm bdTime;
|
||||
struct timeval tv;
|
||||
|
||||
bdTime.tm_year = info.Year - 1900;
|
||||
bdTime.tm_mon = info.Month - 1; // This is zero-based
|
||||
bdTime.tm_mday = info.Day;
|
||||
bdTime.tm_hour = info.Hour;
|
||||
bdTime.tm_min = info.Minute;
|
||||
bdTime.tm_sec = info.Second;
|
||||
bdTime.tm_isdst = info.DST;
|
||||
|
||||
time_t newTime = mktime(&bdTime);
|
||||
time_t newTime = mktime(time);
|
||||
if (newTime == -1)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tv.tv_sec = newTime;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int result = settimeofday(&tv, NULL);
|
||||
if (result == -1)
|
||||
{
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return settimeofday(&tv, NULL);
|
||||
}
|
||||
|
|
|
@ -2,21 +2,10 @@
|
|||
|
||||
#include "pal.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
typedef struct setDateInfo
|
||||
{
|
||||
// the order of members does matter here
|
||||
int32_t Year;
|
||||
int32_t Month;
|
||||
int32_t Day;
|
||||
int32_t Hour;
|
||||
int32_t Minute;
|
||||
int32_t Second;
|
||||
int32_t Millisecond;
|
||||
int32_t DST;
|
||||
} SetDateInfo;
|
||||
|
||||
int32_t SetDate(const SetDateInfo &info);
|
||||
int32_t SetDate(struct tm* time);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//! @brief Implements test for CreateHardLink()
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "getlinkcount.h"
|
||||
#include "createhardlink.h"
|
||||
|
@ -31,19 +30,19 @@ protected:
|
|||
// First create a temp file
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
file = fileTemplateBuf;
|
||||
|
||||
// Create a temp directory
|
||||
dir = mkdtemp(dirTemplateBuf);
|
||||
// Create a temp directory
|
||||
dir = mkdtemp(dirTemplateBuf);
|
||||
EXPECT_TRUE(dir != NULL);
|
||||
|
||||
// Create hard link to file
|
||||
int ret1 = CreateHardLink(fileHardLink.c_str(), file);
|
||||
EXPECT_EQ(ret1, 1);
|
||||
|
||||
int ret = CreateHardLink(fileHardLink.c_str(), file);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
// Create hard link to directory - should fail
|
||||
int ret2 = CreateHardLink(dirHardLink.c_str(), dir);
|
||||
EXPECT_EQ(ret2, 0);
|
||||
ret = CreateHardLink(dirHardLink.c_str(), dir);
|
||||
EXPECT_EQ(ret, -1);
|
||||
}
|
||||
|
||||
~CreateHardLinkTest()
|
||||
|
@ -51,41 +50,33 @@ protected:
|
|||
int ret;
|
||||
|
||||
ret = unlink(fileHardLink.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = unlink(file);
|
||||
EXPECT_EQ(0, ret);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = rmdir(dir);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = rmdir(dir);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CreateHardLinkTest, FilePathNameIsNull)
|
||||
{
|
||||
int retVal = CreateHardLink(NULL, NULL);
|
||||
EXPECT_EQ(retVal, 0);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(CreateHardLinkTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/symlinktest_invalidFile";
|
||||
std::string invalidLink = "/tmp/symlinktest_invalidLink";
|
||||
|
||||
// make sure neither exists
|
||||
// make sure neither exists
|
||||
unlink(invalidFile.c_str());
|
||||
unlink(invalidLink.c_str());
|
||||
|
||||
int retVal = CreateHardLink(invalidLink.c_str(), invalidFile.c_str());
|
||||
EXPECT_EQ(retVal, 0);
|
||||
int ret = CreateHardLink(invalidLink.c_str(), invalidFile.c_str());
|
||||
EXPECT_EQ(-1, ret);
|
||||
}
|
||||
|
||||
TEST_F(CreateHardLinkTest, VerifyLinkCount)
|
||||
{
|
||||
int count = 0;
|
||||
int retVal = GetLinkCount(fileHardLink.c_str(), &count);
|
||||
EXPECT_EQ(1, retVal);
|
||||
int ret = GetLinkCount(fileHardLink.c_str(), &count);
|
||||
EXPECT_EQ(0, ret);
|
||||
EXPECT_EQ(2, count);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,12 +39,12 @@ protected:
|
|||
EXPECT_TRUE(dir != NULL);
|
||||
|
||||
// Create symbolic link to file
|
||||
bool ret1 = CreateSymLink(fileSymLink.c_str(), file);
|
||||
EXPECT_TRUE(ret1);
|
||||
int ret = CreateSymLink(fileSymLink.c_str(), file);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
// Create symbolic link to directory
|
||||
bool ret2 = CreateSymLink(dirSymLink.c_str(), dir);
|
||||
EXPECT_TRUE(ret2);
|
||||
ret = CreateSymLink(dirSymLink.c_str(), dir);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
~CreateSymLinkTest()
|
||||
|
@ -65,13 +65,6 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F(CreateSymLinkTest, FilePathNameIsNull)
|
||||
{
|
||||
bool retVal = CreateSymLink(NULL, NULL);
|
||||
EXPECT_FALSE(retVal);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/symlinktest_invalidFile";
|
||||
|
@ -82,8 +75,8 @@ TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist)
|
|||
unlink(invalidLink.c_str());
|
||||
|
||||
// Linux allows creation of symbolic link that points to an invalid file
|
||||
bool retVal = CreateSymLink(invalidLink.c_str(), invalidFile.c_str());
|
||||
EXPECT_TRUE(retVal);
|
||||
int ret = CreateSymLink(invalidLink.c_str(), invalidFile.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
std::string target = FollowSymLink(invalidLink.c_str());
|
||||
EXPECT_EQ(target, invalidFile);
|
||||
|
@ -93,8 +86,8 @@ TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist)
|
|||
|
||||
TEST_F(CreateSymLinkTest, SymLinkToFile)
|
||||
{
|
||||
bool retVal = IsSymLink(fileSymLink.c_str());
|
||||
EXPECT_TRUE(retVal);
|
||||
bool ret = IsSymLink(fileSymLink.c_str());
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
std::string target = FollowSymLink(fileSymLink.c_str());
|
||||
char buffer[PATH_MAX];
|
||||
|
@ -104,8 +97,8 @@ TEST_F(CreateSymLinkTest, SymLinkToFile)
|
|||
|
||||
TEST_F(CreateSymLinkTest, SymLinkToDirectory)
|
||||
{
|
||||
bool retVal = IsSymLink(dirSymLink.c_str());
|
||||
EXPECT_TRUE(retVal);
|
||||
bool ret = IsSymLink(dirSymLink.c_str());
|
||||
EXPECT_TRUE(ret);
|
||||
|
||||
std::string target = FollowSymLink(dirSymLink.c_str());
|
||||
char buffer[PATH_MAX];
|
||||
|
@ -115,7 +108,7 @@ TEST_F(CreateSymLinkTest, SymLinkToDirectory)
|
|||
|
||||
TEST_F(CreateSymLinkTest, SymLinkAgain)
|
||||
{
|
||||
bool retVal = CreateSymLink(fileSymLink.c_str(), file);
|
||||
EXPECT_FALSE(retVal);
|
||||
EXPECT_EQ(ERROR_FILE_EXISTS, errno);
|
||||
int ret = CreateSymLink(fileSymLink.c_str(), file);
|
||||
EXPECT_EQ(-1, ret);
|
||||
EXPECT_EQ(EEXIST, errno);
|
||||
}
|
||||
|
|
|
@ -15,11 +15,5 @@ TEST(GetFileOwnerTest, CanGetOwnerOfRoot)
|
|||
TEST(GetFileOwnerTest, CannotGetOwnerOfFakeFile)
|
||||
{
|
||||
EXPECT_STREQ(GetFileOwner("SomeMadeUpFileNameThatDoesNotExist"), NULL);
|
||||
EXPECT_EQ(errno, ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
TEST(GetFileOwnerTest, ReturnsNullForNullInput)
|
||||
{
|
||||
EXPECT_STREQ(GetFileOwner(NULL), NULL);
|
||||
EXPECT_EQ(errno, ERROR_INVALID_PARAMETER);
|
||||
EXPECT_EQ(ENOENT, errno);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ protected:
|
|||
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
file = fileTemplateBuf;
|
||||
}
|
||||
|
||||
void createFileForTesting(const std::string &theFile)
|
||||
|
@ -43,39 +43,32 @@ protected:
|
|||
std::string createHardLink(const std::string &origFile)
|
||||
{
|
||||
std::string newFile = origFile + "_link";
|
||||
int ret = link(origFile.c_str(), newFile.c_str());
|
||||
int ret = link(origFile.c_str(), newFile.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
return newFile;
|
||||
return newFile;
|
||||
}
|
||||
|
||||
void removeFile(const std::string &fileName)
|
||||
{
|
||||
int ret = unlink(fileName.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(getLinkCountTest, FilePathNameIsNull)
|
||||
{
|
||||
int32_t retVal = GetLinkCount(NULL, &count );
|
||||
ASSERT_FALSE(retVal);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(getLinkCountTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/createFile";
|
||||
int32_t retVal = GetLinkCount(invalidFile.c_str(), &count);
|
||||
ASSERT_FALSE(retVal);
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
|
||||
int32_t ret = GetLinkCount(invalidFile.c_str(), &count);
|
||||
ASSERT_EQ(-1, ret);
|
||||
EXPECT_EQ(ENOENT, errno);
|
||||
}
|
||||
|
||||
TEST_F(getLinkCountTest, LinkCountOfSinglyLinkedFile)
|
||||
{
|
||||
createFileForTesting(file);
|
||||
int32_t retVal = GetLinkCount(file, &count);
|
||||
ASSERT_TRUE(retVal);
|
||||
int32_t ret = GetLinkCount(file, &count);
|
||||
ASSERT_EQ(0, ret);
|
||||
EXPECT_EQ(1, count);
|
||||
|
||||
removeFile(file);
|
||||
|
@ -85,8 +78,8 @@ TEST_F(getLinkCountTest, LinkCountOfMultiplyLinkedFile)
|
|||
{
|
||||
createFileForTesting(file);
|
||||
std::string newFile = createHardLink(file);
|
||||
int32_t retVal = GetLinkCount(file, &count);
|
||||
ASSERT_TRUE(retVal);
|
||||
int32_t ret = GetLinkCount(file, &count);
|
||||
ASSERT_EQ(0, ret);
|
||||
EXPECT_EQ(2, count);
|
||||
|
||||
removeFile(file);
|
||||
|
|
|
@ -21,11 +21,5 @@ TEST(IsDirectoryTest, BinLsIsNotDirectory)
|
|||
TEST(IsDirectoryTest, ReturnsFalseForFakeDirectory)
|
||||
{
|
||||
EXPECT_FALSE(IsDirectory("SomeMadeUpFileNameThatDoesNotExist"));
|
||||
EXPECT_EQ(errno, ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
TEST(IsDirectoryTest, ReturnsFalseForNullInput)
|
||||
{
|
||||
EXPECT_FALSE(IsDirectory(NULL));
|
||||
EXPECT_EQ(errno, ERROR_INVALID_PARAMETER);
|
||||
EXPECT_EQ(ENOENT, errno);
|
||||
}
|
||||
|
|
|
@ -47,17 +47,11 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F(IsExecutableTest, FilePathNameIsNull)
|
||||
{
|
||||
EXPECT_FALSE(IsExecutable(NULL));
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(IsExecutableTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/isexecutabletest_invalidFile";
|
||||
EXPECT_FALSE(IsExecutable(invalidFile.c_str()));
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
|
||||
EXPECT_EQ(ENOENT, errno);
|
||||
}
|
||||
|
||||
TEST_F(IsExecutableTest, NormalFileIsNotIsexecutable)
|
||||
|
|
|
@ -20,11 +20,5 @@ TEST(IsFileTest, BinLsIsFile)
|
|||
TEST(IsFileTest, CannotGetOwnerOfFakeFile)
|
||||
{
|
||||
EXPECT_FALSE(IsFile("SomeMadeUpFileNameThatDoesNotExist"));
|
||||
EXPECT_EQ(errno, ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
TEST(IsFileTest, ReturnsFalseForNullInput)
|
||||
{
|
||||
EXPECT_FALSE(IsFile(NULL));
|
||||
EXPECT_EQ(errno, ERROR_INVALID_PARAMETER);
|
||||
EXPECT_EQ(errno, ENOENT);
|
||||
}
|
||||
|
|
|
@ -55,17 +55,11 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F(isSymLinkTest, FilePathNameIsNull)
|
||||
{
|
||||
EXPECT_FALSE(IsSymLink(NULL));
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/symlinktest_invalidFile";
|
||||
EXPECT_FALSE(IsSymLink(invalidFile.c_str()));
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
|
||||
EXPECT_EQ(ENOENT, errno);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, NormalFileIsNotSymLink)
|
||||
|
|
|
@ -171,4 +171,14 @@ Describe "New-Item with links" -Tags @('CI', 'RequireAdminOnWindows') {
|
|||
# Remove the link explicitly to avoid broken symlink issue
|
||||
Remove-Item $FullyQualifiedLink -Force
|
||||
}
|
||||
|
||||
It "Should error correctly when failing to create a symbolic link" -Skip:($IsWindows -or $IsElevated) {
|
||||
# This test expects that /sbin exists but is not writable by the user
|
||||
try {
|
||||
New-Item -ItemType SymbolicLink -Path "/sbin/powershell-test" -Target $FullyQualifiedFolder -ErrorAction Stop
|
||||
throw "Execution OK"
|
||||
} catch {
|
||||
$_.FullyQualifiedErrorId | Should Be "NewItemSymbolicLinkElevationRequired,Microsoft.PowerShell.Commands.NewItemCommand"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,13 @@ Describe "Set-Date" -Tag "CI" {
|
|||
Import-Module (join-path $psscriptroot "../../Common/Test.Helpers.psm1")
|
||||
$IsElevated = Test-IsElevated
|
||||
}
|
||||
|
||||
It "Set-Date should be able to set the date in an elevated context" -Skip:(! $IsElevated) {
|
||||
{ get-date | set-date } | Should not throw
|
||||
}
|
||||
|
||||
It "Set-Date should produce an error in a non-elevated context" -Skip:($IsElevated) {
|
||||
{ get-date |set-date} | should throw
|
||||
{ get-date | set-date} | should throw
|
||||
$Error[0].FullyQualifiedErrorId | should be "System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.SetDateCommand"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ Describe "Stream writer tests" -Tags "CI" {
|
|||
# redirect the streams is sufficient
|
||||
$result = Write-Information "Test Message" *>&1
|
||||
$result.GetType().Fullname | Should be "System.Management.Automation.InformationRecord"
|
||||
$result.NativeThreadId | Should Not Be 0
|
||||
"$result" | Should be "Test Message"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue