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

commits at source.squeak.org commits at source.squeak.org
Fri Nov 29 20:26:37 UTC 2019


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

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

Name: FileAttributesPlugin.oscog-AlistairGrant.36
Author: AlistairGrant
Time: 28 August 2018, 2:33:50.748205 pm
UUID: eb4e9dcc-d749-4b64-820b-b7fb8e9d9991
Ancestors: FileAttributesPlugin.oscog-AlistairGrant.35

FileAttributes 1.4.0: File permissions and ownership

Add the ability to modify the posix permissions (chmod()) and user and group ids (chown()).

Also properly declare cPathString in unixPathToOop:.

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

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
  # 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 changed:
  ----- 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!
- 			ifTrue: [resultOop at: 0 put: interpreterProxy falseObject]].
- 	^0!

Item was added:
+ ----- 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: [
+ 		status := self ch: cString mod: newMode.
+ 		status ~= 0 ifTrue:
+ 			[^interpreterProxy primitiveFailForOSError: (self cCode: 'errno')].
+ 		^interpreterProxy methodReturnValue: interpreterProxy nilObject.
+ 		].
+ 	^interpreterProxy primitiveFailForOSError: self unsupportedOperation.
+ !

Item was added:
+ ----- 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: '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: [
+ 		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>>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 |
  	<export: true>
  	<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:
- 		or: [(interpreterProxy is: fileName KindOf: 'String') not]]) ifTrue:
  			[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
  	self squeakPath: fileName toUnix: cPathName maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
  	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 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]
- 			interpreterProxy primitiveFail]
  		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 cPathName status |
  	<export: true>
  	<var: 'cPathName' declareC: 'char cPathName[PATH_MAX+1]'>
  
  	fileName := interpreterProxy stackObjectValue: 1.
  	attributeMask := interpreterProxy stackIntegerValue: 0.
  	(interpreterProxy failed
+ 	or: [(interpreterProxy isBytes: fileName) not]) ifTrue:
- 	or: [(interpreterProxy is: fileName KindOf: 'String') not]) ifTrue:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
  	self squeakPath: fileName toUnix: cPathName maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
  
  	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 accessFlag cString |
  	<export: true>
  	<var: 'accessFlag' type: #'sqInt'>
  	<var: 'cString' declareC: 'char cString[PATH_MAX+1]'>
  
  	fileNameOop := interpreterProxy stackObjectValue: 0.
+ 	(interpreterProxy isBytes: fileNameOop) ifFalse:
- 	(interpreterProxy is: fileNameOop KindOf: 'String') ifFalse:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
  	self squeakPath: fileNameOop toUnix: cString maxLen: #PATH_MAX.
  	interpreterProxy failed ifTrue: [^interpreterProxy primitiveFailureCode].
  	accessFlag := (self acc: cString ess: (self fileOKFlag)).
  	interpreterProxy pop: 2 thenPush: (accessFlag = 0
  									ifTrue: [interpreterProxy trueObject]
  									ifFalse: [interpreterProxy falseObject])!

Item was changed:
  ----- Method: FileAttributesPlugin>>primitiveOpendir (in category 'file primitives') -----
  primitiveOpendir
  
  	"self primOpendir: '/etc'"
  
  	| dirName dir dirOop status cPathName |
  	<export: true>
  	<var: 'dir' type: #'osdir *'>
  	<var: 'cPathName' declareC: 'char cPathName[PATH_MAX+1]'>
  
  	dirName := interpreterProxy stackObjectValue: 0.
+ 	(interpreterProxy isBytes: dirName) ifFalse:
- 	(interpreterProxy is: dirName KindOf: 'String') ifFalse:
  		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
  
  	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 added:
+ ----- 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 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>>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 changed:
  ----- 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 added:
+ ----- 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>
+ 	^'1.4.0'!
- 	^'1.3.3'!



More information about the Vm-dev mailing list