mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix SetDate
And use a bunch of unsafe code because of concerns about stack size.
This commit is contained in:
@@ -403,10 +403,10 @@ namespace System.Management.Automation
|
||||
return Unix.NativeMethods.CreateHardLink(path, strTargetPath) == 0;
|
||||
}
|
||||
|
||||
internal static bool NonWindowsSetDate(DateTime dateToUse)
|
||||
internal static unsafe bool NonWindowsSetDate(DateTime dateToUse)
|
||||
{
|
||||
Unix.SetDateInfoInternal date = new Unix.SetDateInfoInternal(dateToUse);
|
||||
return Unix.NativeMethods.SetDate(date) == 0;
|
||||
Unix.NativeMethods.UnixTm tm = Unix.NativeMethods.DateTimeToUnixTm(dateToUse);
|
||||
return Unix.NativeMethods.SetDate(&tm) == 0;
|
||||
}
|
||||
|
||||
internal static string NonWindowsGetDomainName()
|
||||
@@ -526,37 +526,6 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
[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;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class NativeMethods
|
||||
{
|
||||
private const string psLib = "libpsl-native";
|
||||
@@ -587,8 +556,38 @@ namespace System.Management.Automation
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static extern string GetFullyQualifiedName();
|
||||
|
||||
// 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)]
|
||||
internal static extern int SetDate(SetDateInfoInternal info);
|
||||
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,
|
||||
|
||||
@@ -17,34 +17,19 @@
|
||||
//!
|
||||
//! SetDate
|
||||
//!
|
||||
//! @param[in] info
|
||||
//! @parblock
|
||||
//! A struct that contains program to execute and its parameters
|
||||
//!
|
||||
//! @retval 0 successfully set date
|
||||
//! @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
|
||||
assert(nl_langinfo(CODESET) == std::string("UTF-8"));
|
||||
|
||||
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)
|
||||
{
|
||||
return -1;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user