Fix SetDate

And use a bunch of unsafe code because of concerns about stack size.
This commit is contained in:
Andrew Schwartzmeyer
2016-10-14 15:43:00 -07:00
parent cdcd2c25c8
commit 24d0ce36e6
4 changed files with 43 additions and 67 deletions
@@ -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,
+2 -17
View File
@@ -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;
+3 -14
View File
@@ -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"
}
}