[Vm-dev] VM Maker: FileAttributesPlugin.oscog-AlistairGrant.38.mcz

commits at source.squeak.org commits at source.squeak.org
Fri Nov 29 20:38:50 UTC 2019


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

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

Name: FileAttributesPlugin.oscog-AlistairGrant.38
Author: AlistairGrant
Time: 2 October 2018, 8:40:30.106841 am
UUID: f0fcdb0f-e642-4f87-8a9f-d35ffa0d05ff
Ancestors: FileAttributesPlugin.oscog-eem.37

FileAttributesPlugin 2.0.0: Fixes UTF8 on Windows

Restructure FileAttributesPlugin to move platform specific functionality
out to separate files.  This is required as Windows requires the "wide"
versions of posix functions to be used, e.g. access() vs.  _waccess(),
while other seem to require the Windows native functions, e.g.  iterating
over directories, and interleaving #ifdef _WIN32 was becoming unwieldy.

=============== Diff against FileAttributesPlugin.oscog-eem.37 ===============

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: '<errno.h>'.
  	cg addHeaderFile: '<limits.h>'.
  	cg addHeaderFile: '<sys/types.h>'.
  	cg addHeaderFile: '<unistd.h>'.
  	cg addHeaderFile: '<dirent.h>
  #if _WIN32 || _WIN64
  # include <windows.h>
  # include <winbase.h>
  # define FAIL() { return -1; }
  # include "sqWin32File.h"
  # if !!defined(PATH_MAX) /* work around bug in 64-bit cygwin; sigh :-( */
  #	define PATH_MAX 4096
  # endif
  # define HAVE_CHMOD 0
  # define HAVE_CHOWN 0
  #else
  #define HAVE_CHMOD 1
  #define HAVE_CHOWN 1
+ #endif'.
+ 	cg addHeaderFile: '"faCommon.h"'.
- # include "sqUnixCharConv.h"
- #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) && !!defined(_WIN64)
  # define HAVE_LSTAT 1
  #endif'.
  	cg addHeaderFile: '<unistd.h>
  /* AKG 2018 - ', self moduleName, '.c translated from class ', self name, ' */'!

Item was removed:
- ----- Method: FileAttributesPlugin>>accessAttributesForFilename:into:startingAt: (in category 'private - file') -----
- accessAttributesForFilename: cPathName into: attributeArray startingAt: offset
- 	"Call access() for each access type (R, W, X) on the c string cPathName, storing the results in the st array attributeArray."
- 
- 	| index boolean |
- 	<var: 'cPathName' type: #'char *'>
- 	index := offset.
- 	((self acc: cPathName ess: self fileReadableFlag) = 0)
- 		ifTrue: [boolean := interpreterProxy trueObject]
- 		ifFalse: [boolean := interpreterProxy falseObject].
- 	interpreterProxy
- 		storePointer: index
- 		ofObject: attributeArray
- 		withValue: boolean.
- 	index := index + 1.
- 	boolean := ((self acc: cPathName ess: self fileWriteableFlag) = 0)
- 					ifTrue: [interpreterProxy trueObject]
- 					ifFalse: [interpreterProxy falseObject].
- 	interpreterProxy
- 		storePointer: index
- 		ofObject: attributeArray
- 		withValue: boolean.
- 	index := index + 1.
- 	boolean := ((self acc: cPathName ess: self fileExecutableFlag) = 0)
- 					ifTrue: [interpreterProxy trueObject]
- 					ifFalse: [interpreterProxy falseObject].
- 	interpreterProxy
- 		storePointer: index
- 		ofObject: attributeArray
- 		withValue: boolean.
- !

Item was removed:
- ----- Method: FileAttributesPlugin>>byteArrayFromCString:to: (in category 'private') -----
- byteArrayFromCString: aCString to: byteArrayOop
- 	"Answer a new ByteArray copied from a null-terminated C string.
- 	Caution: This may invoke the garbage collector."
- 
- 	| len newByteArray byteArrayPtr |
- 	<var: 'aCString' type: #'const char *'>
- 	<var: 'byteArrayPtr' type: #'unsigned char *'>
- 	<var: 'byteArrayOop' type: #'sqInt *'>
- 	len := self strlen: aCString.
- 	"We never return strings longer than PATH_MAX"
- 	len > #PATH_MAX ifTrue: [^self stringTooLong].
- 	newByteArray := interpreterProxy
- 		instantiateClass: interpreterProxy classByteArray
- 		indexableSize: len.
- 	newByteArray ifNil:
- 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 	byteArrayPtr := interpreterProxy arrayValueOf: newByteArray.
- 	self memcpy: byteArrayPtr _: aCString _: len.
- 	byteArrayOop at: 0 put: newByteArray.
- 	^0!

Item was changed:
+ ----- Method: FileAttributesPlugin>>cantAllocateMemory (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>cantAllocateMemory (in category 'errors') -----
  cantAllocateMemory
  	<inline: #always>
  	^-10!

Item was changed:
+ ----- Method: FileAttributesPlugin>>cantOpenDir (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>cantOpenDir (in category 'errors') -----
  cantOpenDir
  	<inline: #always>
  	^-9!

Item was changed:
+ ----- Method: FileAttributesPlugin>>cantReadlink (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>cantReadlink (in category 'errors') -----
  cantReadlink
  	<inline: #always>
  	^-8!

Item was changed:
+ ----- Method: FileAttributesPlugin>>cantStatPath (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>cantStatPath (in category 'errors') -----
  cantStatPath
  	"SecurityPlugin determined that the requested path cannot be accessed."
  	<inline: #always>
  	^-3!

Item was changed:
  ----- 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' type: #'SYSTEMTIME'>
  	<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>>corruptValue (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>corruptValue (in category 'errors') -----
  corruptValue
  	<inline: #always>
  	^-7!

Item was removed:
- ----- Method: FileAttributesPlugin>>faConvertUnixToLongSqueakTime: (in category 'private - posix') -----
- faConvertUnixToLongSqueakTime: unixTime
- "Convert the supplied Unix (UTC) time to Squeak time.
- 
- Squeak time has an epoch of 1901 and uses local time
- i.e. timezone + daylight savings
- 
- Answer an sqLong which is guaranteed to be 64 bits on all platforms."
- 
- 	| squeakTime |
- 
- 	<returnTypeC: #'sqLong'>
- 	<var: 'unixTime' type: #'time_t'>
- 	<var: 'squeakTime' type: #'sqLong'>
- 
- 	self cppIf: #_WIN32 defined ifTrue: 
- 		[squeakTime := 0] 
- 	ifFalse: [
- 		squeakTime := unixTime.
- 		self cppIf: (self defined: #HAVE_TM_GMTOFF) ifTrue: 
- 			[ squeakTime := squeakTime + (self cCode: 'localtime(&unixTime)->tm_gmtoff')]
- 		ifFalse: [ self cppIf: (self defined: #HAVE_TIMEZONE) ifTrue:
- 			[ squeakTime := squeakTime + (self cCode: '(daylight*60*60) - timezone')]
- 		ifFalse: [ self cPreprocessorDirective: '#error: cannot determine timezone correction']].
- 		"Squeak epoch is Jan 1, 1901.  Unix epoch is Jan 1, 1970: 17 leap years
- 		and 52 non-leap years later than Squeak."
- 		squeakTime := squeakTime + 
- 			(self cCode: '(52*365UL + 17*366UL) * 24*60*60UL'
- 				inSmalltalk: [((52*365) + (17*366)) * 24*60*60]) ].
- 	^squeakTime
- 
- 
- !

Item was removed:
- ----- Method: FileAttributesPlugin>>fileCreationTimeFor:length:to: (in category 'private - windows') -----
- fileCreationTimeFor: 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 winFileCreationTimeFor: (self addressOf: winAttrs) to: creationDate.
- 	status = 0 ifFalse: [^status].
- 
- 	^0!

Item was removed:
- ----- 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 removed:
- ----- 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 changed:
  ----- Method: FileAttributesPlugin>>fileToAttributeArray:mask:array: (in category 'private - file') -----
+ fileToAttributeArray: faPath mask: attributeMask array: attributeArray
- fileToAttributeArray: cPathName mask: attributeMask array: attributeArray
  	"Answer a file attribute array from pathNameOop."
  
  	| getStats useLstat getAccess statArray accessArray combinedArray status fileNameOop statBuf  |
  	<returnTypeC: #'int'>
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'cPathName' type: #'char *'>
  	<var: 'attributeArray' type: #'sqInt *'>
+ 	<var: 'statBuf' type: #'faStatStruct'>
- 	<var: 'statBuf' type: #'struct stat'>
  
  	"Determine which attributes to retrieve"
  	getStats := attributeMask anyMask: 1.
  	getAccess := attributeMask anyMask: 2.
  	(getStats or: [getAccess]) ifFalse:
  		["No information has been requested, which doesn't make sense"
  		^self invalidArguments].
  	getStats ifTrue: 
  		[
  		useLstat := attributeMask anyMask: 4.
  		statArray := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 12.
  		statArray ifNil:
  			[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  		status := useLstat ifFalse:
+ 					[ self faStat: faPath _: (self addressOf: statBuf ) _: (self addressOf: fileNameOop) ]
- 					[ self putStatFor: cPathName
- 							intoBuffer: (self addressOf: statBuf)
- 							targetName:  (self addressOf: fileNameOop) ]
  				ifTrue:
+ 					[ self faLinkStat: faPath _: (self addressOf: statBuf ) _: (self addressOf: fileNameOop) ].
- 					[ self putLStatFor: cPathName
- 							intoBuffer: (self addressOf: statBuf)
- 							targetName:  (self addressOf: fileNameOop) ].
  		status ~= 0 ifTrue: [^status].
+ 		status := self statArrayFor: faPath toArray: statArray from: (self addressOf: statBuf) fileName: fileNameOop.
- 		status := self statArrayFor: cPathName toArray: statArray from: (self addressOf: statBuf) fileName: fileNameOop.
  		status ~= 0 ifTrue: [^status].
  		"Set attributeArray in case only stat() attributes have been requested"
  		attributeArray at: 0 put: statArray
  		].
  	getAccess ifTrue: 
  		[
  		accessArray := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 3.
  		accessArray ifNil:
  			[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 		self faAccessAttributes: faPath _: accessArray _: 0.
- 		self accessAttributesForFilename: cPathName into: accessArray startingAt: 0.
  		"Set attributeArray in case only access() attributes have been requested"
  		attributeArray at: 0 put: accessArray
  		].
  	[getStats and: [getAccess]] ifTrue: 
  		[
  		combinedArray := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.
  		combinedArray ifNil:
  			[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  		attributeArray at: 0 put: combinedArray.
  		interpreterProxy
  			storePointer: 0 ofObject: combinedArray withValue: statArray;
  			storePointer: 1 ofObject: combinedArray withValue: accessArray
  		].
  
  	^0!

Item was changed:
+ ----- Method: FileAttributesPlugin>>getAttributesFailed (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>getAttributesFailed (in category 'errors') -----
  getAttributesFailed
  	<inline: #always>
  	^-4!

Item was changed:
+ ----- Method: FileAttributesPlugin>>invalidArguments (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>invalidArguments (in category 'errors') -----
  invalidArguments
  	<inline: #always>
  	^-6!

Item was changed:
+ ----- Method: FileAttributesPlugin>>invalidRequest (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>invalidRequest (in category 'errors') -----
  invalidRequest
  	<inline: #always>
  	^-11!

Item was removed:
- ----- Method: FileAttributesPlugin>>isSymlink:boolean: (in category 'private - file') -----
- isSymlink: cPathName boolean: resultOop
- 	"Set resultOop to a boolean indicating whether cPathName is a symbolic link.
- 	Answer status (0 = success)"
- 
- 	| status statBuf |
- 	<var: 'cPathName' type: #'char *'>
- 	<var: 'resultOop' type: #'sqInt *'>
- 	<var: 'statBuf' type: #'struct stat'>
- 	self touch: statBuf.
- 	self cppIf: #HAVE_LSTAT == 1 ifTrue:
- 		[status := self lst: cPathName at: (self addressOf: statBuf).
- 		status ~= 0 ifTrue: [^self cantStatPath].
- 		(self S_ISLNK: statBuf st_mode) = 0
- 			ifFalse: [resultOop at: 0 put: interpreterProxy trueObject]
- 			ifTrue: [resultOop at: 0 put: interpreterProxy falseObject].
- 		^0].
- 	^self unsupportedOperation!

Item was added:
+ ----- Method: FileAttributesPlugin>>noMoreData (in category 'errors / status') -----
+ noMoreData
+ 	<inline: #always>
+ 	^1!

Item was removed:
- ----- Method: FileAttributesPlugin>>openDirectoryStream:ptr: (in category 'private - directory') -----
- openDirectoryStream: cPathName ptr: osdirPtr
- 	"Open a new directory stream. Answer a pointer to the directory stream or NULL."
- 
- 	| len dir |
- 	<var: 'osdirPtr' type: #'osdir **'>
- 	<var: 'dir' type: #'osdir *'>
- 	<var: 'cPathName' type: 'char *'>
- 	<returnTypeC: #'int'>
- 
- 	len := self strlen: cPathName.
- 	"The path buffer needs room for a trailing slash and the file name, so subtracting 2 is conservative"
- 	len > (#PATH_MAX - 2) ifTrue: [^self stringTooLong].
- 	(self canOpenDirectoryStreamFor: cPathName length: len)
- 		ifTrue:
- 			[
- 			dir := self cCode: '(osdir *) malloc(sizeof(osdir))'.
- 			dir = nil ifTrue: [^self cantAllocateMemory].
- 			self memcpy: dir path _: cPathName _: len.
- 			"Ensure path has a trailing slash"
- 			self cCode: 'if (dir->path[len-1] !!= ''/'') {
- 				dir->path[len++] = ''/'';
- 				}'.
- 			self cCode: 'dir->path_file = dir->path + len'.
- 			self cCode: 'dir->path_file[0] = ''\0'''.
- 			self cCode: 'dir->path_len = len'.
- 			self cCode: 'dir->dp =  opendir(dir->path)'.
- 			dir dp ifNil:
- 				[self free: dir.
- 				^self cantOpenDir].
- 			osdirPtr at: 0 put: dir.
- 			^0
- 			].
- 	"If we get here, we can't open the directory"
- 	^self cantOpenDir
- !

Item was changed:
  ----- Method: FileAttributesPlugin>>posixFileTimesFrom:to: (in category 'private - posix') -----
  posixFileTimesFrom: statBufPointer to: attributeArray
  	"Populate attributeArray with the file times from statBufPointer"
  
  	| attributeDate |
  
+ 	<var: 'statBufPointer' type: #'faStatStruct *'>
- 	<var: 'statBufPointer' type: #'struct stat *'>
  	<var: 'attributeDate' type: #'sqLong'>
  
  	self cppIf: #_WIN32 defined ifTrue: [] ifFalse: [
+ 	attributeDate := self faConvertUnixToLongSqueakTime: (self cCode: 'statBufPointer->st_atime').
- 	attributeDate := self faConvertUnixToLongSqueakTime: statBufPointer st_atime.
  	interpreterProxy
  		storePointer: 8
  			ofObject: attributeArray
  				withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+ 	attributeDate := self faConvertUnixToLongSqueakTime: (self cCode: 'statBufPointer->st_mtime').
- 	attributeDate := self faConvertUnixToLongSqueakTime: statBufPointer st_mtime.
  	interpreterProxy
  		storePointer: 9
  			ofObject: attributeArray
  				withValue: (interpreterProxy signed64BitIntegerFor: attributeDate).
+ 	attributeDate := self faConvertUnixToLongSqueakTime: (self cCode: 'statBufPointer->st_ctime').
- 	attributeDate := self faConvertUnixToLongSqueakTime: 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>>primitiveChangeMode (in category 'file primitives') -----
  primitiveChangeMode
  	"Set the mode of the supplied file using chmod()."
  
  	| fileNameOop newMode cString status |
  	<export: true>
  	<var: 'newMode' type: #'sqInt'>
  	<var: 'cString' declareC: 'char cString[PATH_MAX+1]'>
  
  	fileNameOop := interpreterProxy stackObjectValue: 1.
  	newMode := interpreterProxy stackIntegerValue: 0.
  	(interpreterProxy failed
  		or: [(interpreterProxy isBytes: fileNameOop) not]) ifTrue:
  			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
- 	self squeakPath: fileNameOop toUnix: cString maxLen: #PATH_MAX.
- 	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailForOSError: interpreterProxy primitiveFailureCode].
  	self cppIf: #HAVE_CHMOD ifTrue: [
+ 		self squeakPath: fileNameOop toPlatform: cString maxLen: #PATH_MAX.
+ 		interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailForOSError: interpreterProxy primitiveFailureCode].
  		status := self ch: cString mod: newMode.
  		status ~= 0 ifTrue:
  			[^interpreterProxy primitiveFailForOSError: (self cCode: 'errno')].
  		^interpreterProxy methodReturnValue: interpreterProxy nilObject.
  		].
  	^interpreterProxy primitiveFailForOSError: self unsupportedOperation.
  !

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveChangeOwner (in category 'file primitives') -----
  primitiveChangeOwner
  	"Set the owner of the supplied file using chown()."
  
  	| fileNameOop ownerId groupId cString status |
  	<export: true>
+ 	<var: 'cString' declareC: 'char cString[FA_PATH_MAX]'>
- 	<var: 'newMode' type: #'sqInt'>
- 	<var: 'cString' declareC: 'char cString[PATH_MAX+1]'>
  
  	fileNameOop := interpreterProxy stackObjectValue: 2.
  	ownerId := interpreterProxy stackIntegerValue: 1.
  	groupId := interpreterProxy stackIntegerValue: 0.
  	(interpreterProxy failed
  		or: [(interpreterProxy isBytes: fileNameOop) not]) ifTrue:
  			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
- 	self squeakPath: fileNameOop toUnix: cString maxLen: #PATH_MAX.
- 	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailForOSError: interpreterProxy primitiveFailureCode].
  	self cppIf: #HAVE_CHOWN ifTrue: [
+ 		self squeakPath: fileNameOop toPlatform: cString maxLen: #FA_PATH_MAX.
+ 		interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailForOSError: interpreterProxy primitiveFailureCode].
+ 		status := self chown: cString _: ownerId _: groupId.
- 		status := self ch: cString o: ownerId wn: groupId.
  		status ~= 0 ifTrue:
  			[^interpreterProxy primitiveFailForOSError: (self cCode: 'errno')].
  		^interpreterProxy methodReturnValue: interpreterProxy nilObject.
  		].
  	^interpreterProxy primitiveFailForOSError: self unsupportedOperation.
  !

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveClosedir (in category 'file primitives') -----
  primitiveClosedir
  	"Close the directory stream for dirPointerOop. Answer dirPointerOop on success.
  	Raise PrimErrBadArgument if the parameter is not a ByteArray length size(void *).
  	If closedir() returns an error raise PrimitiveOSError."
  
+ 	| dirPointerOop faPath result |
- 	| dirPointerOop dirStream result |
  	<export: true>
+ 	<var: 'fapath' type: #'faPath *'>
+ 
- 	<var: 'dirStream' type: #'osdir *'>
  	dirPointerOop := interpreterProxy stackValue: 0.
+ 	faPath := self pointerFrom: dirPointerOop.
+ 	faPath ifNil:
- 	dirStream := self pointerFrom: dirPointerOop.
- 	dirStream ifNil:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	result := self faCloseDirectory: faPath.
- 	result := self closedir: dirStream dp.
  	result = 0 ifFalse:
+ 		[^interpreterProxy primitiveFailForOSError: result].
+ 	self free: faPath.
- 		[^interpreterProxy primitiveFailForOSError: self unableToCloseDir].
- 	self free: dirStream.
  	interpreterProxy pop: 2 thenPush: dirPointerOop!

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 faPath |
- 	| fileName attributeNumber resultOop fileNameOop statBuf cPathName sizeIfFile mode attributeDate status |
  	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'statBuf' type: #'struct stat'>
- 	<var: 'cPathName' declareC: 'char cPathName[PATH_MAX+1]'>
- 	<var: 'attributeDate' type: #'sqLong'>
  
  	fileName := interpreterProxy stackObjectValue: 1.
  	attributeNumber := interpreterProxy stackIntegerValue: 0.
  	(interpreterProxy failed
  		or: [(attributeNumber between: 1 and: 16) not
  		or: [(interpreterProxy isBytes: fileName) not]]) ifTrue:
  			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	faPath := self cCode: '(fapath *) calloc(1, sizeof(fapath))'.
+ 	faPath = nil ifTrue: [^interpreterProxy primitiveFailForOSError: self cantAllocateMemory].
+ 	self faSetStPathOop: faPath _: fileName.
- 	self squeakPath: fileName toUnix: cPathName maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
- 	resultOop := 0.
  
+ 	resultOop := self faFileAttribute: faPath _: attributeNumber.
+ 	interpreterProxy failed ifTrue:
+ 		[^interpreterProxy primitiveFailureCode].
- 	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 faConvertUnixToLongSqueakTime: 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 faConvertUnixToLongSqueakTime: statBuf st_mtime.
- 				resultOop := interpreterProxy signed64BitIntegerFor: attributeDate]].
- 		attributeNumber = 11 ifTrue: [ "Change Time"
- 			self cppIf: #_WIN32 defined ifTrue: 
- 				[resultOop := interpreterProxy nilObject]
- 			ifFalse: [
- 				attributeDate := self faConvertUnixToLongSqueakTime: statBuf st_ctime.
- 				resultOop := interpreterProxy signed64BitIntegerFor: attributeDate]].
- 		]
- 	ifFalse: [attributeNumber = 12  ifTrue: [ "Creation Time"
- 		self cppIf: #_WIN32 defined ifTrue: [
- 			status := self fileCreationTimeFor: cPathName
- 				length: cPathName strlen
- 				to: (self addressOf: attributeDate put: [:val| attributeDate := val]).
- 			status ~= 0 ifTrue:
- 				[^interpreterProxy primitiveFailForOSError: status].
- 			resultOop := interpreterProxy signed64BitIntegerFor: attributeDate ] 
- 		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"
- 		[
- 		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 primitiveFailForOSError: self unexpectedError]
  		ifFalse: [interpreterProxy pop: 3 thenPush: resultOop]!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveFileAttributes (in category 'file primitives') -----
  primitiveFileAttributes
  	"Answer an array of file attributes.
  	primFileAttributes: aString mask: attributeMask
  	aString is the path to the file
  	attributeMask indicates which attributes to retrieve:
  	bit 0 - get stat() attributes
  	bit 1 - get access() attributes
  	bit 2 - use lstat() instead of stat()
  	On error answer the appropriate error code (Integer)"
  
+ 	| fileName attributeMask attributeArray faPath status |
- 	| fileName attributeMask attributeArray cPathName status |
  	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'cPathName' declareC: 'char cPathName[PATH_MAX+1]'>
  
  	fileName := interpreterProxy stackObjectValue: 1.
  	attributeMask := interpreterProxy stackIntegerValue: 0.
  	(interpreterProxy failed
  	or: [(interpreterProxy isBytes: fileName) not]) ifTrue:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	faPath := self cCode: '(fapath *) calloc(1, sizeof(fapath))'.
+ 	faPath = nil ifTrue: [^interpreterProxy primitiveFailForOSError: self cantAllocateMemory].
+ 	self faSet: faPath StPathOop: fileName.
- 	self squeakPath: fileName toUnix: cPathName maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
  
+ 	status := self fileToAttributeArray: faPath
- 	status := self fileToAttributeArray: cPathName 
  					mask: attributeMask 
  					array: (self addressOf: attributeArray put: [:val| attributeArray := val]).
  	status ~= 0
  		ifTrue: [interpreterProxy primitiveFailForOSError: status]
  		ifFalse: [interpreterProxy pop: 3 thenPush: attributeArray]!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveFileExists (in category 'file primitives') -----
  primitiveFileExists
  	"Check for existence of a file with a call to access()."
  
+ 	| fileNameOop faPath |
- 	| fileNameOop accessFlag cString |
  	<export: true>
  	<var: 'accessFlag' type: #'sqInt'>
+ 	<var: 'faPath'type: #'fapath *'>
- 	<var: 'cString' declareC: 'char cString[PATH_MAX+1]'>
  
  	fileNameOop := interpreterProxy stackObjectValue: 0.
  	(interpreterProxy isBytes: fileNameOop) ifFalse:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	faPath := self cCode: '(fapath *) calloc(1, sizeof(fapath))'.
+ 	faPath = nil ifTrue: [^interpreterProxy primitiveFailForOSError: self cantAllocateMemory].
+ 	self faSetStPathOop: faPath _: fileNameOop.
- 	self squeakPath: fileNameOop toUnix: cString maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
+ 
+ 	^interpreterProxy methodReturnValue: (self faExists: faPath).
+ !
- 	accessFlag := (self acc: cString ess: (self fileOKFlag)).
- 	interpreterProxy pop: 2 thenPush: (accessFlag = 0
- 									ifTrue: [interpreterProxy trueObject]
- 									ifFalse: [interpreterProxy falseObject])!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveLogicalDrives (in category 'file primitives') -----
  primitiveLogicalDrives
  	"Answer the logical drive mask on windows"
  
+ 	| mask |
  	<export: true>
  	<var: 'mask' type: #'unsigned int'>
  	self cppIf: #_WIN32 defined
  		ifTrue:
+ 			[
- 			[| mask |
  			 mask := self GetLogicalDrives.
  			 mask ~= 0 ifTrue:
  				[^interpreterProxy pop: 1 thenPush: (interpreterProxy positive32BitIntegerFor: mask)]].
  	interpreterProxy primitiveFail!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveOpendir (in category 'file primitives') -----
  primitiveOpendir
  
  	"self primOpendir: '/etc'"
  
+ 	| dirName faPath dirOop status resultOop |
- 	| dirName dir dirOop status cPathName |
  	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'dir' type: #'osdir *'>
- 	<var: 'cPathName' declareC: 'char cPathName[PATH_MAX+1]'>
  
  	dirName := interpreterProxy stackObjectValue: 0.
  	(interpreterProxy isBytes: dirName) ifFalse:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
  
+ 	faPath := self cCode: '(fapath *) calloc(1, sizeof(fapath))'.
+ 	faPath = nil ifTrue: [^interpreterProxy primitiveFailForOSError: self cantAllocateMemory].
+ 	self faSet: faPath StDirOop: dirName.
+ 
+ 	(self canOpenDirectoryStreamFor: (self faGetStPath: faPath) length: (self faGetStPathLen: faPath)) ifFalse: [
+ 		self free: faPath.
+ 		^interpreterProxy primitiveFailForOSError: self cantOpenDir].
+ 
+ 	status := self faOpenDirectory: faPath.
+ 	status = self noMoreData ifTrue:
+ 		[^interpreterProxy pop: 2 thenPush: interpreterProxy nilObject].
+ 	status < 0 ifTrue: [
+ 		self free: faPath.
+ 		^interpreterProxy primitiveFailForOSError: status].
+ 	resultOop := self processDirectory: faPath.
+ 	interpreterProxy failed ifTrue: [
+ 		self free: faPath.
+ 		^interpreterProxy primitiveFailureCode ].
+ 
+ 	self remapOop: resultOop in:
+ 		[ dirOop := self addressObjectFor: faPath ].
+ 	^interpreterProxy 
+ 		storePointer: 2 ofObject: resultOop withValue: dirOop;
+ 		pop: 2 thenPush: resultOop.!
- 	self squeakPath: dirName toUnix: cPathName maxLen: #PATH_MAX.
- 	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
- 	status := self openDirectoryStream: cPathName ptr: (self addressOf: dir).
- 	status ~= 0 ifTrue: [^interpreterProxy primitiveFailForOSError: status].
- 	dirOop := self addressObjectFor: dir.
- 	interpreterProxy pop: 2 thenPush: dirOop!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitivePathMax (in category 'file primitives') -----
  primitivePathMax
  	"Answer the value of PATH_MAX for the current VM"
  
  	<export: true>
+ 	^interpreterProxy pop: 1 thenPush: (interpreterProxy integerObjectOf: #FA_PATH_MAX)!
- 	^interpreterProxy pop: 1 thenPush: (interpreterProxy integerObjectOf: #PATH_MAX)!

Item was added:
+ ----- Method: FileAttributesPlugin>>primitivePlatToStPath (in category 'file primitives') -----
+ primitivePlatToStPath
+ 	"Convert the supplied file name (platform encoded) to the St UTF8 encoded byte array"
+ 
+ 	| fileName faPath resultOop byteArrayPtr |
+ 	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
+ 	<var: 'byteArrayPtr' type: #'unsigned char *'>
+ 
+ 	fileName := interpreterProxy stackObjectValue: 0.
+ 	(interpreterProxy failed
+ 		or: [(interpreterProxy isBytes: fileName) not]) ifTrue:
+ 			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	faPath := self cCode: '(fapath *) calloc(1, sizeof(fapath))'.
+ 	faPath = nil ifTrue: [^interpreterProxy primitiveFailForOSError: self cantAllocateMemory].
+ 	self faSetPlatPathOop: faPath _: fileName.
+ 	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
+ 
+ 	resultOop := interpreterProxy
+ 		instantiateClass: interpreterProxy classByteArray
+ 		indexableSize: (self faGetStPathLen: faPath).
+ 	resultOop ifNil:
+ 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 	byteArrayPtr := interpreterProxy arrayValueOf: resultOop.
+ 	self memcpy:byteArrayPtr _: (self faGetStPath: faPath) _: (self faGetStPathLen: faPath).
+ 
+ 	^interpreterProxy methodReturnValue: resultOop.
+ !

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveReaddir (in category 'file primitives') -----
  primitiveReaddir
  	"Get the next entry in the directory stream. Answer the name of the entry, or
  	nil for the end of the directory stream.
  	Arguments:
  	- directoryPointer (ByteArray)"
  
+ 	| dirPointerOop faPath resultArray status |
- 	| dirPointerOop dirStream ent entryName attributeArray resultArray haveEntry entry_len status |
  	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'ent' type: #'struct dirent *'>
- 	<var: 'dirStream' type: #'osdir *'>
- 	<var: 'haveEntry' type: #int>
  
  	dirPointerOop := interpreterProxy stackValue: 0.
+ 	faPath := self pointerFrom: dirPointerOop.
+ 	faPath ifNil:
- 	dirStream := self pointerFrom: dirPointerOop.
- 	dirStream ifNil:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	status := self faReadDirectory: faPath.
+ 	status = self noMoreData ifTrue:
- 	haveEntry := 0.
- 	[ent := self readdir: dirStream dp.
- 	 self cCode: 'if (ent == NULL ||
-                  		((!! (ent->d_name[0] == ''.'' && strlen(ent->d_name) == 1)) && strcmp(ent->d_name, "..")))
-                      		haveEntry = 1'.
- 	 haveEntry = 0] whileTrue.
- 	ent ifNil: "This is the normal case for the end of a directory stream,
- 			although it may indicate other error conditions for which errno would be updated.
- 			Assume the normal case here."
  		[^interpreterProxy pop: 2 thenPush: interpreterProxy nilObject].
+ 	status < 0 ifTrue:
+ 		[^interpreterProxy primitiveFailForOSError: status].
+ 	resultArray := self processDirectory: faPath.
+ 	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
- 	entryName := self unixPathToOop: ent d_name.
- 	"Build the path name (append the entry name to the path name)"
- 	entry_len := self strlen: ent d_name.
- 	[dirStream path_len + entry_len > (#PATH_MAX - 1)] ifTrue:
- 		[^interpreterProxy primitiveFailForOSError: self stringTooLong].
- 	self memcpy: dirStream path_file _: ent d_name _: entry_len.
- 	dirStream path_file at: entry_len put: 0.
  
- 	status := self fileToAttributeArray: dirStream path mask: 1 array: (self addressOf: attributeArray put: [:val| attributeArray := val]).
- 	"If the stat() fails, still return the filename, just no attributes"
- 	status ~= 0 ifTrue: [attributeArray := interpreterProxy nilObject].
- 
- 	self remapOop: #(entryName attributeArray)
- 		in: [resultArray := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2].
- 	resultArray ifNil:
- 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  	interpreterProxy
- 		storePointer: 0 ofObject: resultArray withValue: entryName;
- 		storePointer: 1 ofObject: resultArray withValue: attributeArray;
  		pop: 2 thenPush: resultArray!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveRewinddir (in category 'file primitives') -----
  primitiveRewinddir
  	"Set directoryStream to first entry. Answer dirPointerOop."
  
+ 	| dirPointerOop faPath |
- 	| dirPointerOop dirStream |
  	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'dirStream' type: #'osdir *'>
  	dirPointerOop := interpreterProxy stackValue: 0.
+ 	faPath := self pointerFrom: dirPointerOop.
+ 	faPath ifNil:
- 	dirStream := self pointerFrom: dirPointerOop.
- 	dirStream ifNil:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 	^interpreterProxy primitiveFailForOSError: self unexpectedError.
+ 	"self rewinddir: dirStream dp."
+ 	"interpreterProxy pop: 2 thenPush: dirPointerOop"!
- 	self rewinddir: dirStream dp.
- 	interpreterProxy pop: 2 thenPush: dirPointerOop!

Item was added:
+ ----- Method: FileAttributesPlugin>>primitiveStToPlatPath (in category 'file primitives') -----
+ primitiveStToPlatPath
+ 	"Convert the supplied file name (UTF8 encoded) to the platform encoded byte array"
+ 
+ 	| fileName faPath resultOop byteArrayPtr |
+ 	<export: true>
+ 	<var: 'faPath' type: #'fapath *'>
+ 	<var: 'byteArrayPtr' type: #'unsigned char *'>
+ 
+ 	fileName := interpreterProxy stackObjectValue: 0.
+ 	(interpreterProxy failed
+ 		or: [(interpreterProxy isBytes: fileName) not]) ifTrue:
+ 			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	faPath := self cCode: '(fapath *) calloc(1, sizeof(fapath))'.
+ 	faPath = nil ifTrue: [^interpreterProxy primitiveFailForOSError: self cantAllocateMemory].
+ 	self faSetStPathOop: faPath _: fileName.
+ 	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
+ 
+ 	resultOop := interpreterProxy
+ 		instantiateClass: interpreterProxy classByteArray
+ 		indexableSize: (self faGetPlatPathByteCount: faPath).
+ 	resultOop ifNil:
+ 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 	byteArrayPtr := interpreterProxy arrayValueOf: resultOop.
+ 	self memcpy:byteArrayPtr _: (self faGetPlatPath: faPath) _: (self faGetPlatPathByteCount: faPath).
+ 
+ 	^interpreterProxy methodReturnValue: resultOop.
+ !

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveSymlinkChangeOwner (in category 'file primitives') -----
  primitiveSymlinkChangeOwner
  	"Set the owner of the supplied file using chown()."
  
  	| fileNameOop ownerId groupId cString status |
  	<export: true>
- 	<var: 'newMode' type: #'sqInt'>
  	<var: 'cString' declareC: 'char cString[PATH_MAX+1]'>
  
  	fileNameOop := interpreterProxy stackObjectValue: 2.
  	ownerId := interpreterProxy stackIntegerValue: 1.
  	groupId := interpreterProxy stackIntegerValue: 0.
  	(interpreterProxy failed
  		or: [(interpreterProxy isBytes: fileNameOop) not]) ifTrue:
  			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 	self squeakPath: fileNameOop toPlatform: cString maxLen: #PATH_MAX.
- 	self squeakPath: fileNameOop toUnix: cString maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailForOSError: interpreterProxy primitiveFailureCode].
  	self cppIf: #HAVE_CHOWN ifTrue: [
  		status := self lch: cString o: ownerId wn: groupId.
  		status ~= 0 ifTrue:
  			[^interpreterProxy primitiveFailForOSError: (self cCode: 'errno')].
  		^interpreterProxy methodReturnValue: interpreterProxy nilObject.
  		].
  	^interpreterProxy primitiveFailForOSError: self unsupportedOperation.
  !

Item was added:
+ ----- Method: FileAttributesPlugin>>processDirectory: (in category 'private') -----
+ processDirectory: faPath
+ 
+ 	| status entryName attributeArray resultArray |
+ 
+ 	<var: 'faPath' type: #'fapath *'>
+ 
+ 	status := self faChar: (self faGetStFile: faPath) 
+ 				ToByteArray: (self addressOf: entryName put: [:val | entryName := val]).
+ 	status ~= 0 ifTrue:
+ 		[ ^interpreterProxy primitiveFailForOSError: status].
+ 
+ 	status := self fileToAttributeArray: faPath mask: 1 array: (self addressOf: attributeArray put: [:val| attributeArray := val]).
+ 	"If the stat() fails, still return the filename, just no attributes"
+ 	status ~= 0 ifTrue: [attributeArray := interpreterProxy nilObject].
+ 
+ 	"resultArray: entryName, attributeArray, dirPtrOop"
+ 	self remapOop: #(entryName attributeArray)
+ 		in: [resultArray := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 3].
+ 	resultArray ifNil:
+ 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 	interpreterProxy
+ 		storePointer: 0 ofObject: resultArray withValue: entryName;
+ 		storePointer: 1 ofObject: resultArray withValue: attributeArray.
+ 	^resultArray!

Item was removed:
- ----- Method: FileAttributesPlugin>>putLStatFor:intoBuffer:targetName: (in category 'private - file') -----
- putLStatFor: cPathName intoBuffer: statBufPointer targetName: fileNameOop
- 	"Call stat() on cPathName, storing the results in
- 	the buffer at statBufPointer."
- 
- 	| cLinkName len status |
- 	<returnTypeC: #'sqInt'>
- 	<var: 'cPathName' type: #'char *'>
- 	<var: 'statBufPointer' type: #'struct stat *'>
- 	<var: 'cLinkName' declareC: 'char cLinkName[PATH_MAX]'>
- 	<var: 'fileNameOop' type: #'sqInt *'>
- 
- 	self cppIf: #HAVE_LSTAT = 1 ifTrue: [
- 		status := self lst: cPathName at: statBufPointer.
- 		status ~= 0 ifTrue: [^self cantStatPath].
- 		(self S_ISLNK: statBufPointer st_mode) = 0
- 			ifFalse: [
- 				len := self readLink: cPathName into: cLinkName maxLength: #PATH_MAX.
- 				len < 0 ifTrue: [^len].
- 				status := self byteArrayFromCString: cLinkName to: fileNameOop]
- 			ifTrue:
- 				[fileNameOop at: 0 put: interpreterProxy nilObject].
- 	] ifFalse: [ "#HAVE_LSTAT = 1"
- 		status := self invalidRequest.
- 	].
- 	^status
- !

Item was removed:
- ----- 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].
- 	fileNameOop at: 0 put: interpreterProxy nilObject.
- 	^0!

Item was added:
+ ----- Method: FileAttributesPlugin>>squeakPath:toPlatform:maxLen: (in category 'private') -----
+ squeakPath: pathOop toPlatform: cPathString maxLen: maxLength
+ 	"Convert the supplied path string oop to a unix c path string.
+ 	Parameter checking is done in the main primitive, so pathOop is assumed to be valid.
+ 	pathOop is supplied as a precomposed UTF8 string.
+ 	cPathString must be encoded using the host OS conventions, e.g. decomposed UTF8 on MacOS.
+ 	Signal primitive failure on error."
+ 
+ 	| status uxName |
+ 	<var: 'cPathString' type: 'char *'>
+ 	<var: 'uxName' declareC: 'char uxName[FA_PATH_MAX]'>
+ 
+ 	(maxLength >= (self cCode: 'FA_PATH_MAX' inSmalltalk: [4096])) ifTrue:
+ 		[^interpreterProxy primitiveFailForOSError: self invalidArguments].
+ 	self cppIf: #_WIN32 ifTrue: [
+ 		status := self pathOop: pathOop toBuffer: cPathString maxLen: maxLength.
+ 		status ~= 0 ifTrue:
+ 			[^interpreterProxy primitiveFailForOSError: status]]
+ 	ifFalse: [
+ 		status := self pathOop: pathOop toBuffer: uxName maxLen: #PATH_MAX.
+ 		status ~= 0 ifTrue:
+ 			[^interpreterProxy primitiveFailForOSError: status].
+ 		status := self sq2uxPath: uxName _: (self strlen: uxName) _: cPathString _: maxLength _: 1.
+ 		status = 0 ifTrue:
+ 			[^interpreterProxy primitiveFailForOSError: self invalidArguments]. ].
+ 	^0!

Item was removed:
- ----- Method: FileAttributesPlugin>>squeakPath:toUnix:maxLen: (in category 'private - posix') -----
- squeakPath: pathOop toUnix: cPathString maxLen: maxLength
- 	"Convert the supplied path string oop to a unix c path string.
- 	Parameter checking is done in the main primitive, so pathOop is assumed to be valid.
- 	pathOop is supplied as a precomposed UTF8 string.
- 	cPathString must be encoded using the host OS conventions, e.g. decomposed UTF8 on MacOS.
- 	Signal primitive failure on error."
- 
- 	| status uxName |
- 	<var: 'cPathString' type: 'char *'>
- 	<var: 'uxName' declareC: 'char uxName[PATH_MAX+1]'>
- 
- 	(maxLength > (self cCode: 'PATH_MAX+1' inSmalltalk: [4097])) ifTrue:
- 		[^interpreterProxy primitiveFailForOSError: self invalidArguments].
- 	self cppIf: #_WIN32 ifTrue: [
- 		status := self pathOop: pathOop toBuffer: cPathString maxLen: maxLength.
- 		status ~= 0 ifTrue:
- 			[^interpreterProxy primitiveFailForOSError: status]]
- 	ifFalse: [
- 		status := self pathOop: pathOop toBuffer: uxName maxLen: #PATH_MAX.
- 		status ~= 0 ifTrue:
- 			[^interpreterProxy primitiveFailForOSError: status].
- 		status := self sq2: uxName u: (self strlen: uxName) x: cPathString Pa: maxLength th: 1.
- 		status = 0 ifTrue:
- 			[^interpreterProxy primitiveFailForOSError: self invalidArguments]. ].
- 	^0!

Item was changed:
  ----- Method: FileAttributesPlugin>>statArrayFor:toArray:from:fileName: (in category 'private - file') -----
+ statArrayFor: faPath toArray: attributeArray from: statBufPointer fileName: fileNameOop
- statArrayFor: cPathName toArray: attributeArray from: statBufPointer fileName: fileNameOop
  	"Answer a file entry array from the supplied statBufPointer"
  
  	| sizeIfFile status |
+ 	<var: 'faPath' type: #'fapath *'>
+ 	<var: 'statBufPointer' type: #'faStatStruct *'>
- 	<var: 'cPathName' type: #'char *'>
- 	<var: 'statBufPointer' type: #'struct stat *'>
  
+ 	sizeIfFile := (self cCode: 'S_ISDIR(statBufPointer->st_mode)') = 0
+ 					ifTrue: [self cCode: 'statBufPointer->st_size']
- 	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 positive64BitIntegerFor: (self cCode: 'statBufPointer->st_mode'));
- 				withValue: (interpreterProxy positiveMachineIntegerFor: statBufPointer st_mode);
  		storePointer: 2
  			ofObject: attributeArray
+ 				withValue: (interpreterProxy positive64BitIntegerFor: (self cCode: 'statBufPointer->st_ino'));
- 				withValue: (interpreterProxy positive64BitIntegerFor: statBufPointer st_ino);
  		storePointer: 3
  			ofObject: attributeArray
+ 				withValue: (interpreterProxy positive64BitIntegerFor: (self cCode: 'statBufPointer->st_dev'));
- 				withValue: (interpreterProxy positive64BitIntegerFor: statBufPointer st_dev);
  		storePointer: 4
  			ofObject: attributeArray
+ 				withValue: (interpreterProxy positive64BitIntegerFor: (self cCode: 'statBufPointer->st_nlink'));
- 				withValue: (interpreterProxy positive64BitIntegerFor: statBufPointer st_nlink);
  		storePointer: 5
  			ofObject: attributeArray
+ 				withValue: (interpreterProxy positive64BitIntegerFor: (self cCode: 'statBufPointer->st_uid'));
- 				withValue: (interpreterProxy positiveMachineIntegerFor: statBufPointer st_uid);
  		storePointer: 6
  			ofObject: attributeArray
+ 				withValue: (interpreterProxy positive64BitIntegerFor: (self cCode: 'statBufPointer->st_gid'));
- 				withValue: (interpreterProxy positiveMachineIntegerFor: statBufPointer st_gid);
  		storePointer: 7
  			ofObject: attributeArray
  				withValue: (interpreterProxy positive64BitIntegerFor: sizeIfFile).
  
  	self cppIf: #_WIN32 defined
+ 		ifTrue: [ status := self winFileTimesFor: faPath to: attributeArray ]
- 		ifTrue: [ status := self winFileTimesFor: cPathName to: attributeArray ]
  		ifFalse: [ status := self posixFileTimesFrom: statBufPointer to: attributeArray ].
  
  	^status
  !

Item was changed:
+ ----- Method: FileAttributesPlugin>>statFailed (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>statFailed (in category 'errors') -----
  statFailed
  	"A call to stat() failed"
  	<inline: #always>
  	^-2!

Item was changed:
+ ----- Method: FileAttributesPlugin>>stringTooLong (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>stringTooLong (in category 'errors') -----
  stringTooLong
  	"String too long.  A file path name was longer than PATH_MAX"
  	<inline: #always>
  	^-1!

Item was changed:
+ ----- Method: FileAttributesPlugin>>timeConversionFailed (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>timeConversionFailed (in category 'errors') -----
  timeConversionFailed
  	<inline: #always>
  	^-5!

Item was changed:
+ ----- Method: FileAttributesPlugin>>unableToCloseDir (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>unableToCloseDir (in category 'errors') -----
  unableToCloseDir
  	"The call to closedir() failed"
  	<inline: #always>
  	^-12!

Item was changed:
+ ----- Method: FileAttributesPlugin>>unexpectedError (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>unexpectedError (in category 'errors') -----
  unexpectedError
  	"This is normally used where a catch-all is placed, but not expected to be used"
  	<inline: #always>
  	^-14!

Item was removed:
- ----- Method: FileAttributesPlugin>>unixPathToOop: (in category 'private - posix') -----
- unixPathToOop: cPathString
- 	"Convert the supplied cPathString to a ByteArray.
- 	cPathString is encoded using the host OS conventions, e.g. decomposed UTF8 on MacOS."
- 
- 	| pathOop status uxName |
- 	<var: 'cPathString' type: #'char *'>
- 	<var: 'uxName' declareC: 'char uxName[PATH_MAX+1]'>
- 
- 	(self strlen: cPathString) > (self cCode: 'PATH_MAX+1' inSmalltalk: [4097]) ifTrue:
- 		[^interpreterProxy primitiveFailForOSError: self stringTooLong].
- 	pathOop := 0.
- 	self cppIf: #_WIN32 ifTrue: 
- 		[status := self byteArrayFromCString: cPathString to: (self addressOf: pathOop put: [:val| pathOop := val]).]
- 	ifFalse: [
- 		status := self ux2: cPathString s: (self strlen: cPathString) q: uxName Pa: #PATH_MAX th: 1.
- 		status = 0 ifTrue:
- 			[^interpreterProxy primitiveFailForOSError: self invalidArguments].
- 		status := self byteArrayFromCString: uxName to: (self addressOf: pathOop put: [:val| pathOop := val]). ].
- 	status ~= 0 ifTrue:
- 		[^interpreterProxy primitiveFailForOSError: status].
- 	^pathOop
- !

Item was changed:
+ ----- Method: FileAttributesPlugin>>unsupportedOperation (in category 'errors / status') -----
- ----- Method: FileAttributesPlugin>>unsupportedOperation (in category 'errors') -----
  unsupportedOperation
  	"The requested operation is not supported on the current platform"
  	<inline: #always>
  	^-13!

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

Item was removed:
- ----- 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 changed:
  ----- Method: FileAttributesPlugin>>winFileTimesFor:to: (in category 'private - windows') -----
+ winFileTimesFor: faPath to: attributeArray
- winFileTimesFor: cPathName to: attributeArray
  	<inline: #never>
  	<option: #_WIN32>
  
  	| winAttrs attributeDate status |
+ 	<var: 'faPath' type: #'fapath *'>
- 	<var: 'cPathName' type: #'char *'>
  	<var: 'attributeDate' type: #'sqLong'>
  	<var: 'winAttrs' type: #'WIN32_FILE_ATTRIBUTE_DATA'>
  
  	"Get the file attributes"
+ 	status := self cCode: 'GetFileAttributesExW(faGetPlatPath2(faPath), GetFileExInfoStandard, &winAttrs)'.
+ 	status = 0 ifTrue: [^self getAttributesFailed].
- 	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 modifiedDate"
- 	"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
  !



More information about the Vm-dev mailing list