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 + ! |
Free forum by Nabble | Edit this page |