VM Maker: FileAttributesPlugin.oscog-AlistairGrant.29.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: FileAttributesPlugin.oscog-AlistairGrant.29.mcz

commits-2
 
Eliot Miranda uploaded a new version of FileAttributesPlugin to project VM Maker:
http://source.squeak.org/VMMaker/FileAttributesPlugin.oscog-AlistairGrant.29.mcz

==================== Summary ====================

Name: FileAttributesPlugin.oscog-AlistairGrant.29
Author: AlistairGrant
Time: 16 June 2018, 2:49:28.03222 pm
UUID: 9c55f745-9933-4291-abb7-f278da431090
Ancestors: FileAttributesPlugin.oscog-AlistairGrant.28

1.3.0: Change from Unix (UTC) timestamps to Squeak timestamps for file attributes.

The posix routines just don't seem to handle timezones and DST correctly.

=============== Diff against FileAttributesPlugin.oscog-AlistairGrant.28 ===============

Item was changed:
  ----- Method: FileAttributesPlugin class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: cg
 
  self declareC:  #('sCLPfn' 'sCOFfn')
  as: #'void *'
  in: cg.
  "Assume the security plugin can be loaded until proven otherwise"
  cg var: 'hasSecurityPlugin' declareC: 'int hasSecurityPlugin = 1'.
 
  cg addHeaderFile: '<limits.h>'.
  cg addHeaderFile: '<sys/types.h>'.
  cg addHeaderFile: '<dirent.h>
  #ifdef _WIN32
  #include <windows.h>
  #include <winbase.h>
  #define FAIL() { return -1; }
  #include "sqWin32File.h"
+ #else
+ #include "sqMemoryAccess.h"
+ extern sqLong convertToLongSqueakTime(time_t unixTime);
  #endif
  typedef struct dirptrstruct {
      DIR *dp;
  int path_len;
      char *path_file;
      char path[PATH_MAX+4];
      } osdir;'.
  cg addHeaderFile: '<sys/stat.h>
  #if !!defined(HAVE_LSTAT) && !!defined(_WIN32)
  #define HAVE_LSTAT 1
  #endif'.
  cg addHeaderFile: '<unistd.h>
  /* AKG 2017 - ', self moduleName, '.c translated from class ', self name, ' */'!

Item was added:
+ ----- Method: FileAttributesPlugin>>convertWinToSqueakTime: (in category 'private - windows') -----
+ convertWinToSqueakTime: st
+ "Convert the supplied Windows SYSTEMTIME to Squeak time"
+ <option: #_WIN32>
+
+ | dy secs nDaysPerMonth |
+
+ <returnTypeC: 'sqLong'>
+ <var: 'st' declareC: 'SYSTEMTIME st'>
+ <var: 'dy' type: 'sqLong'>
+ <var: 'secs' type: 'sqLong'>
+ <var: 'nDaysPerMonth' declareC: 'static sqLong nDaysPerMonth[14] = {
+ 0,  0,  31,  59,  90, 120, 151,
+ 181, 212, 243, 273, 304, 334, 365 }'>
+ self touch: nDaysPerMonth.
+
+ "Squeak epoch is Jan 1, 1901"
+ "compute delta year"
+ dy := (self cCode: 'st.wYear') - 1901.
+ secs := (dy * 365 * 24 * 60 * 60)       "base seconds"
+ + ((dy bitShift: -2) * 24 * 60 * 60).   "seconds of leap years"
+ "check if month > 2 and current year is a leap year"
+ [ (self cCode: 'st.wMonth') > 2 and: [ (dy bitAnd: 16r0003) = 16r0003 ]] ifTrue: [
+ "add one day"
+ secs := secs + (24 * 60 * 60) ].
+ "add the days from the beginning of the year"
+ secs := secs + (self cCode: '(nDaysPerMonth[st.wMonth] + st.wDay - 1) * 24 * 60 * 60').
+ "add the hours, minutes, and seconds"
+ secs := secs + (self cCode: 'st.wSecond + 60*(st.wMinute + 60*st.wHour)').
+ ^secs
+ !

Item was changed:
  ----- Method: FileAttributesPlugin>>fileCreationTimeFor:length:to: (in category 'private - windows') -----
  fileCreationTimeFor: pathString length: pathLength to: creationDate
+ "Get the creationDate for the supplied file."
+ <inline: #never>
- "Get the creationDate for the supplied file.
- Linux kernel 4.11 should have statx(), so hopefully there will be a cross-platform
- solution soon.  Just dump the c-code and hope to remove it soon."
  <option: #_WIN32>
+ | winAttrs status |
- | tm winAttrs win32Path sysTime |
  <var: 'pathString' type: 'char *'>
+ <var: 'creationDate' type: 'sqLong *'>
- <var: 'creationDate' type: 'time_t *'>
- <var: 'tm' type: 'struct tm'>
  <var: 'winAttrs' type: 'WIN32_FILE_ATTRIBUTE_DATA'>
- <var: 'win32Path' type: 'WCHAR *'>
- <var: 'sysTime' type: 'SYSTEMTIME'>
- self touch: winAttrs.
- self touch: sysTime.
- self me: (self addressOf: tm) ms: 0 et: tm sizeof.
- "convert the supplied path name into a wide string"
- self ALLOC_: win32Path WIN32_: pathString PATH: pathLength.
- (self cCode: 'GetFileAttributesExW(win32Path, 0, &winAttrs)') = 0 ifTrue:
-   [^self getAttributesFailed].
- (self cCode: 'FileTimeToSystemTime(&winAttrs.ftCreationTime, &sysTime)') = 0 ifTrue:
-   [^self timeConversionFailed].
 
+ "Get the file attributes"
+ status := self winFileAttributesFor: pathString length: pathLength to: (self addressOf: winAttrs).
+ status = 0 ifFalse: [^status].
- self cCode: '
- tm.tm_year = sysTime.wYear - 1900;
- tm.tm_mon = sysTime.wMonth - 1;
- tm.tm_mday = sysTime.wDay;
 
+ "Set the creationDate"
+ status := self winFileCreationTimeFor: (self addressOf: winAttrs) to: creationDate.
+ status = 0 ifFalse: [^status].
- tm.tm_hour = sysTime.wHour;
- tm.tm_min = sysTime.wMinute;
- tm.tm_sec = sysTime.wSecond;
- tm.tm_isdst = 0;
- *creationDate = mktime(&tm)'.
 
  ^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>fileLastAccessTimeFor:length:to: (in category 'private - windows') -----
+ fileLastAccessTimeFor: pathString length: pathLength to: creationDate
+ "Get the creationDate for the supplied file."
+ <inline: #never>
+ <option: #_WIN32>
+ | winAttrs status |
+ <var: 'pathString' type: 'char *'>
+ <var: 'creationDate' type: 'sqLong *'>
+ <var: 'winAttrs' type: 'WIN32_FILE_ATTRIBUTE_DATA'>
+
+ "Get the file attributes"
+ status := self winFileAttributesFor: pathString length: pathLength to: (self addressOf: winAttrs).
+ status = 0 ifFalse: [^status].
+
+ "Set the creationDate"
+ status := self winFileLastAccessTimeFor: (self addressOf: winAttrs) to: creationDate.
+ status = 0 ifFalse: [^status].
+
+ ^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>fileLastWriteTimeFor:length:to: (in category 'private - windows') -----
+ fileLastWriteTimeFor: pathString length: pathLength to: creationDate
+ "Get the creationDate for the supplied file."
+ <inline: #never>
+ <option: #_WIN32>
+ | winAttrs status |
+ <var: 'pathString' type: 'char *'>
+ <var: 'creationDate' type: 'sqLong *'>
+ <var: 'winAttrs' type: 'WIN32_FILE_ATTRIBUTE_DATA'>
+
+ "Get the file attributes"
+ status := self winFileAttributesFor: pathString length: pathLength to: (self addressOf: winAttrs).
+ status = 0 ifFalse: [^status].
+
+ "Set the creationDate"
+ status := self winFileLastWriteTimeFor: (self addressOf: winAttrs) to: creationDate.
+ status = 0 ifFalse: [^status].
+
+ ^0!

Item was removed:
- ----- Method: FileAttributesPlugin>>offsetStatBufTimesForWIN32: (in category 'private - windows') -----
- offsetStatBufTimesForWIN32: statBufPointer
- "Adjust the statBuffer to UTC, see https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx"
- <option: #_WIN32>
- <var: 'statBufPointer' type: 'struct stat *'>
- | status  dtzi offset |
- <var: 'offset' type: 'long'>
- <var: 'dtzi' type: 'TIME_ZONE_INFORMATION'>
- status := self GetTimeZoneInformation: (self addressOf: dtzi).
- offset := (self cCode: 'dtzi.Bias' inSmalltalk: [0]) * 60.
- "Adjust for DST if required"
- status = 2 ifTrue: [offset := offset - 3600].
- self cCode: 'statBufPointer->st_atime += offset'.
- self cCode: 'statBufPointer->st_mtime += offset'.
- self cCode: 'statBufPointer->st_ctime += offset'.!

Item was removed:
- ----- Method: FileAttributesPlugin>>oopFromTimeT: (in category 'private') -----
- oopFromTimeT: posixSeconds
- "Answer an object representation of the provided time (time_t).
- The size of time_t is platform dependent, so check the size and convert appropriately."
-
- <var: 'posixSeconds' type: 'time_t'>
-
- ^(self sizeof: #time_t) = 4 ifTrue:
- [interpreterProxy signed32BitIntegerFor: posixSeconds]
- ifFalse:
- [interpreterProxy signed64BitIntegerFor: posixSeconds].
- !

Item was added:
+ ----- Method: FileAttributesPlugin>>posixFileTimesFrom:to: (in category 'private - posix') -----
+ posixFileTimesFrom: statBufPointer to: attributeArray
+ "Populate attributeArray with the file times from statBufPointer"
+
+ | attributeDate |
+
+ <var: 'statBufPointer' type: 'struct stat *'>
+ <var: 'attributeDate' type: 'sqLong'>
+
+ self cppIf: #_WIN32 defined ifTrue: [] ifFalse: [
+ attributeDate := self convertToLongSqueakTime: statBufPointer st_atime.
+ interpreterProxy
+ storePointer: 8
+ ofObject: attributeArray
+ withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+ attributeDate := self convertToLongSqueakTime: statBufPointer st_mtime.
+ interpreterProxy
+ storePointer: 9
+ ofObject: attributeArray
+ withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+ attributeDate := self convertToLongSqueakTime: statBufPointer st_ctime.
+ interpreterProxy
+ storePointer: 10
+ ofObject: attributeArray
+ withValue: (interpreterProxy signed64BitIntegerFor: attributeDate);
+ storePointer: 11
+ ofObject: attributeArray
+ withValue: interpreterProxy nilObject ].
+ ^0!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveFileAttribute (in category 'file primitives') -----
  primitiveFileAttribute
  "Answer a single file attribute.
  primFileAttributes: aString attributeNumber: attributeNumber
  aString is the path to the file
  attributeNumber identifies which attribute to return:
  1 - 12: stat(): name, mode, ino, dev, nlink, uid, gid, size, accessDate, modifiedDate, changeDate, creationDate
  13 - 15: access(): R_OK, W_OK, X_OK
  16: isSymlink
  On error, answer a single element array containing the appropriate error code."
 
+ | fileName attributeNumber resultOop fileNameOop statBuf cPathName sizeIfFile mode attributeDate status |
- | fileName attributeNumber resultOop fileNameOop statBuf cPathName sizeIfFile mode creationDate status |
  <export: true>
  <var: 'statBuf' type: 'struct stat'>
  <var: 'cPathName' declareC: 'char cPathName[PATH_MAX]'>
+ <var: 'attributeDate' type: 'sqLong'>
- <var: 'creationDate' type: 'time_t'>
 
  fileName := interpreterProxy stackObjectValue: 1.
  attributeNumber := interpreterProxy stackIntegerValue: 0.
  (interpreterProxy failed
  or: [(attributeNumber between: 1 and: 16) not
  or: [(interpreterProxy is: fileName KindOf: 'String') not]]) ifTrue:
  [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
  status := self pathOop: fileName toBuffer: cPathName maxLen: #PATH_MAX.
  status ~= 0 ifTrue:
  [^interpreterProxy primitiveFailForOSError: status].
  resultOop := 0.
 
  attributeNumber < 12 ifTrue:
  "Get requested stat entry"
  [
  status := self
  putStatFor: cPathName
  intoBuffer: (self addressOf: statBuf)
  targetName: (self addressOf: fileNameOop).
  status ~= 0 ifTrue:
  [^interpreterProxy primitiveFailForOSError: status].
  "In C, this would naturally be a switch statement,
  but I don't know to mix in the smalltalk code"
  attributeNumber = 1 ifTrue: [resultOop := fileNameOop].
  attributeNumber = 2 ifTrue:
  [resultOop := interpreterProxy positiveMachineIntegerFor: statBuf st_mode].
  attributeNumber = 3 ifTrue:
  [resultOop := interpreterProxy positive64BitIntegerFor: statBuf st_ino].
  attributeNumber = 4 ifTrue:
  [resultOop := interpreterProxy positive64BitIntegerFor: statBuf st_dev].
  attributeNumber = 5 ifTrue:
  [resultOop := interpreterProxy positive64BitIntegerFor: statBuf st_nlink].
  attributeNumber = 6 ifTrue:
  [resultOop := interpreterProxy positiveMachineIntegerFor: statBuf st_uid].
  attributeNumber = 7 ifTrue:
  [resultOop := interpreterProxy positiveMachineIntegerFor: statBuf st_gid].
  attributeNumber = 8 ifTrue:
  [
  sizeIfFile := ((self S_ISDIR: statBuf st_mode) = 0)
  ifTrue: [statBuf st_size]
  ifFalse: [0].
  resultOop := interpreterProxy positiveMachineIntegerFor: sizeIfFile
  ].
+ attributeNumber = 9 ifTrue: [ "Access Time"
+ self cppIf: #_WIN32 defined ifTrue: [
+ status := self fileLastAccessTimeFor: cPathName
+ length: cPathName strlen
+ to: (self addressOf: attributeDate put: [:val| attributeDate := val]).
+ status ~= 0 ifTrue:
+ [^interpreterProxy primitiveFailForOSError: status].
+ resultOop := interpreterProxy signed64BitIntegerFor: attributeDate ]
+ ifFalse: [
+ attributeDate := self convertToLongSqueakTime: statBuf st_atime.
+ resultOop := interpreterProxy signed64BitIntegerFor: attributeDate]].
+ attributeNumber = 10 ifTrue: [ "Modified Time"
+ self cppIf: #_WIN32 defined ifTrue: [
+ status := self fileLastWriteTimeFor: cPathName
+ length: cPathName strlen
+ to: (self addressOf: attributeDate put: [:val| attributeDate := val]).
+ status ~= 0 ifTrue:
+ [^interpreterProxy primitiveFailForOSError: status].
+ resultOop := interpreterProxy signed64BitIntegerFor: attributeDate ]
+ ifFalse: [
+ attributeDate := self convertToLongSqueakTime: statBuf st_mtime.
+ resultOop := interpreterProxy signed64BitIntegerFor: attributeDate]].
+ attributeNumber = 11 ifTrue: [ "Change Time"
+ self cppIf: #_WIN32 defined ifTrue:
+ [resultOop := interpreterProxy nilObject]
+ ifFalse: [
+ attributeDate := self convertToLongSqueakTime: statBuf st_ctime.
+ resultOop := interpreterProxy signed64BitIntegerFor: attributeDate]].
- attributeNumber = 9 ifTrue:
- [resultOop := self oopFromTimeT: statBuf st_atime].
- attributeNumber = 10 ifTrue:
- [resultOop := self oopFromTimeT: statBuf st_mtime].
- attributeNumber = 11 ifTrue:
- [resultOop := self oopFromTimeT: statBuf st_ctime].
  ]
+ ifFalse: [attributeNumber = 12  ifTrue: [ "Creation Time"
- ifFalse: [attributeNumber = 12  ifTrue:
- [
  self cppIf: #_WIN32 defined ifTrue: [
  status := self fileCreationTimeFor: cPathName
  length: cPathName strlen
+ to: (self addressOf: attributeDate put: [:val| attributeDate := val]).
- to: (self addressOf: creationDate put: [:val| creationDate := val]).
  status ~= 0 ifTrue:
  [^interpreterProxy primitiveFailForOSError: status].
+ resultOop := interpreterProxy signed64BitIntegerFor: attributeDate ]
- resultOop := self oopFromTimeT: creationDate ]
  ifFalse: [
  resultOop := interpreterProxy nilObject ]
  ]
  ifFalse: [attributeNumber < 16 ifTrue:
  "Get requested access entry"
  [
  attributeNumber = 13 ifTrue: [mode := self fileReadableFlag].
  attributeNumber = 14 ifTrue: [mode := self fileWriteableFlag].
  attributeNumber = 15 ifTrue: [mode := self fileExecutableFlag].
  resultOop := ((self acc: cPathName ess: mode) = 0)
  ifTrue: [interpreterProxy trueObject]
  ifFalse: [interpreterProxy falseObject].
  ]
+ ifFalse: "attributeNumber = 16, #isSymlink"
- ifFalse: "attributeNumber = 16"
  [
  status := self isSymlink: cPathName boolean: (self addressOf: resultOop put: [:val| resultOop := val]).
  status ~= 0 ifTrue:
  [^interpreterProxy primitiveFailForOSError: status].
  ]]].
 
  resultOop = 0
  ifTrue: ["It shouldn't be possible to get here"
  interpreterProxy primitiveFail]
  ifFalse: [interpreterProxy pop: 3 thenPush: resultOop]!

Item was changed:
  ----- Method: FileAttributesPlugin>>putStatFor:intoBuffer:targetName: (in category 'private - file') -----
  putStatFor: cPathName intoBuffer: statBufPointer targetName: fileNameOop
  "Call stat() on cPathName, storing the results in
  the buffer at statBufPointer."
 
  | status |
  <var: 'cPathName' type: 'char *'>
  <var: 'statBufPointer' type: 'struct stat *'>
  <var: 'fileNameOop' type: 'sqInt *'>
 
  status := self st: cPathName at: statBufPointer.
  status ~= 0 ifTrue: [^self cantStatPath].
- self cppIf: #_WIN32 defined
- ifTrue: [self offsetStatBufTimesForWIN32: statBufPointer].
  fileNameOop at: 0 put: interpreterProxy nilObject.
  ^0!

Item was changed:
  ----- Method: FileAttributesPlugin>>statArrayFor:toArray:from:fileName: (in category 'private - file') -----
  statArrayFor: cPathName toArray: attributeArray from: statBufPointer fileName: fileNameOop
  "Answer a file entry array from the supplied statBufPointer"
 
+ | sizeIfFile status |
- | sizeIfFile creationDate status |
  <var: 'cPathName' type: 'char *'>
  <var: 'statBufPointer' type: 'struct stat *'>
- <var: 'creationDate' type: 'time_t'>
 
  sizeIfFile := (self S_ISDIR: statBufPointer st_mode) = 0
  ifTrue: [statBufPointer st_size]
  ifFalse: [0].
  interpreterProxy
  storePointer: 0
  ofObject: attributeArray
  withValue: fileNameOop;
  storePointer: 1
  ofObject: attributeArray
  withValue: (interpreterProxy positiveMachineIntegerFor: statBufPointer st_mode);
  storePointer: 2
  ofObject: attributeArray
  withValue: (interpreterProxy positive64BitIntegerFor: statBufPointer st_ino);
  storePointer: 3
  ofObject: attributeArray
  withValue: (interpreterProxy positive64BitIntegerFor: statBufPointer st_dev);
  storePointer: 4
  ofObject: attributeArray
  withValue: (interpreterProxy positive64BitIntegerFor: statBufPointer st_nlink);
  storePointer: 5
  ofObject: attributeArray
  withValue: (interpreterProxy positiveMachineIntegerFor: statBufPointer st_uid);
  storePointer: 6
  ofObject: attributeArray
  withValue: (interpreterProxy positiveMachineIntegerFor: statBufPointer st_gid);
  storePointer: 7
  ofObject: attributeArray
+ withValue: (interpreterProxy positive64BitIntegerFor: sizeIfFile).
+
- withValue: (interpreterProxy positive64BitIntegerFor: sizeIfFile);
- storePointer: 8
- ofObject: attributeArray
- withValue: (self oopFromTimeT: statBufPointer st_atime);
- storePointer: 9
- ofObject: attributeArray
- withValue: (self oopFromTimeT: statBufPointer st_mtime);
- storePointer: 10
- ofObject: attributeArray
- withValue: (self oopFromTimeT: statBufPointer st_ctime).
  self cppIf: #_WIN32 defined
+ ifTrue: [ status := self winFileTimesFor: cPathName to: attributeArray ]
+ ifFalse: [ status := self posixFileTimesFrom: statBufPointer to: attributeArray ].
+
+ ^status
+ !
- ifTrue:
- [status := self fileCreationTimeFor: cPathName
- length: cPathName strlen
- to: (self addressOf: creationDate put: [:val| creationDate := val]).
- interpreterProxy
- storePointer: 11
- ofObject: attributeArray
- withValue: (status = 0
- ifTrue:  [self oopFromTimeT: creationDate]
- ifFalse: [interpreterProxy nilObject])]
- ifFalse:
- [interpreterProxy
- storePointer: 11
- ofObject: attributeArray
- withValue: interpreterProxy nilObject].
- ^0!

Item was changed:
  ----- Method: FileAttributesPlugin>>versionString (in category 'version string') -----
  versionString
  "Answer a string containing the version string for this plugin."
  <inline: #always>
+ ^'1.3.0'!
- ^'1.2.6'!

Item was added:
+ ----- Method: FileAttributesPlugin>>winFileAttributesFor:length:to: (in category 'private - windows') -----
+ winFileAttributesFor: pathString length: pathLength to: winAttrs
+ "Populate the supplied Win32 file attribute structure"
+
+ <option: #_WIN32>
+
+ | win32Path |
+ <var: 'pathString' type: 'char *'>
+ <var: 'winAttrs' type: 'WIN32_FILE_ATTRIBUTE_DATA *'>
+ <var: 'win32Path' type: 'WCHAR *'>
+
+ self touch: winAttrs.
+ "convert the supplied path name into a wide string"
+ self ALLOC_: win32Path WIN32_: pathString PATH: pathLength.
+ "Populate the supplied winAttrs structure"
+ (self cCode: 'GetFileAttributesExW(win32Path, GetFileExInfoStandard, winAttrs)') = 0 ifTrue:
+   [^self getAttributesFailed].
+ ^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>winFileCreationTimeFor:to: (in category 'private - windows') -----
+ winFileCreationTimeFor: winAttrs to: creationDate
+ "Set the file creation time from the supplied attributes."
+ <option: #_WIN32>
+
+ | sysTime fileTime |
+
+ <var: 'winAttrs' declareC: 'WIN32_FILE_ATTRIBUTE_DATA *winAttrs'>
+ <var: 'creationDate' declareC: 'sqLong *creationDate'>
+ <var: 'fileTime' type: 'FILETIME'>
+ <var: 'sysTime' type: 'SYSTEMTIME'>
+
+ self touch: winAttrs.
+ self touch: sysTime.
+ self touch: fileTime.
+
+ (self cCode: 'FileTimeToLocalFileTime(&winAttrs->ftCreationTime, &fileTime)') = 0 ifTrue:
+   [^self timeConversionFailed].
+ (self cCode: 'FileTimeToSystemTime(&fileTime, &sysTime)') = 0 ifTrue:
+   [^self timeConversionFailed].
+ self cCode: '*creationDate = convertWinToSqueakTime(sysTime)'.
+
+ ^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>winFileLastAccessTimeFor:to: (in category 'private - windows') -----
+ winFileLastAccessTimeFor: winAttrs to: accessDate
+ "Set the file creation time from the supplied attributes."
+ <option: #_WIN32>
+
+ | sysTime fileTime |
+
+ <var: 'winAttrs' declareC: 'WIN32_FILE_ATTRIBUTE_DATA *winAttrs'>
+ <var: 'accessDate' declareC: 'sqLong *accessDate'>
+ <var: 'fileTime' type: 'FILETIME'>
+ <var: 'sysTime' type: 'SYSTEMTIME'>
+
+ self touch: winAttrs.
+ self touch: sysTime.
+ self touch: fileTime.
+
+ (self cCode: 'FileTimeToLocalFileTime(&winAttrs->ftLastAccessTime, &fileTime)') = 0 ifTrue:
+   [^self timeConversionFailed].
+ (self cCode: 'FileTimeToSystemTime(&fileTime, &sysTime)') = 0 ifTrue:
+   [^self timeConversionFailed].
+ self cCode: '*accessDate = convertWinToSqueakTime(sysTime)'.
+
+ ^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>winFileLastWriteTimeFor:to: (in category 'private - windows') -----
+ winFileLastWriteTimeFor: winAttrs to: writeDate
+ "Set the file write time from the supplied attributes."
+ <option: #_WIN32>
+
+ | sysTime fileTime |
+
+ <var: 'winAttrs' declareC: 'WIN32_FILE_ATTRIBUTE_DATA *winAttrs'>
+ <var: 'writeDate' declareC: 'sqLong *writeDate'>
+ <var: 'fileTime' type: 'FILETIME'>
+ <var: 'sysTime' type: 'SYSTEMTIME'>
+
+ self touch: winAttrs.
+ self touch: sysTime.
+ self touch: fileTime.
+
+ (self cCode: 'FileTimeToLocalFileTime(&winAttrs->ftLastWriteTime, &fileTime)') = 0 ifTrue:
+   [^self timeConversionFailed].
+ (self cCode: 'FileTimeToSystemTime(&fileTime, &sysTime)') = 0 ifTrue:
+   [^self timeConversionFailed].
+ self cCode: '*writeDate = convertWinToSqueakTime(sysTime)'.
+
+ ^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>winFileTimesFor:to: (in category 'private - windows') -----
+ winFileTimesFor: cPathName to: attributeArray
+ <inline: #never>
+ <option: #_WIN32>
+
+ | winAttrs attributeDate status |
+ <var: 'cPathName' declareC: 'char *cPathName'>
+ <var: 'attributeDate' type: 'sqLong'>
+ <var: 'winAttrs' type: 'WIN32_FILE_ATTRIBUTE_DATA'>
+
+ "Get the file attributes"
+ status := self winFileAttributesFor: cPathName
+ length: cPathName strlen
+ to: (self addressOf: winAttrs put: [ :val | winAttrs := val ]).
+ status = 0 ifFalse: [^status].
+
+ "Set the accessDate"
+ status := self winFileLastAccessTimeFor: (self addressOf: winAttrs) to: (self addressOf: attributeDate).
+ status = 0 ifFalse: [^status].
+ interpreterProxy
+ storePointer: 8
+ ofObject: attributeArray
+ withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+
+ "Set the accessDate"
+ status := self winFileLastWriteTimeFor: (self addressOf: winAttrs) to: (self addressOf: attributeDate).
+ status = 0 ifFalse: [^status].
+ interpreterProxy
+ storePointer: 9
+ ofObject: attributeArray
+ withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+
+ "Set the changeDate"
+ interpreterProxy
+ storePointer: 10
+ ofObject: attributeArray
+ withValue: interpreterProxy nilObject.
+
+ "Set the creationDate"
+ status := self winFileCreationTimeFor: (self addressOf: winAttrs) to: (self addressOf: attributeDate).
+ status = 0 ifFalse: [^status].
+ interpreterProxy
+ storePointer: 11
+ ofObject: attributeArray
+ withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+
+ ^0
+ !