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