Support for mkdtemp and chmod.
Paolo 2007-07-04 Paolo Bonzini <[hidden email]> * kernel/Directory.st: Add binding for mkdtemp. * kernel/File.st: Add #mode/#mode: * kernel/VFS.st: Add #mode/#mode: and replace isDir variables with it. * packages/vfs/VFS.st: Add support for #mode. * libgst/cint.c: Add binding for mkdtemp and chmod. --- orig/kernel/Directory.st +++ mod/kernel/Directory.st @@ -48,6 +48,9 @@ virtual one).'! !Directory class methodsFor: 'C call-outs'! +primCreateTemporary: dirName + <cCall: 'mkdtemp' returning: #void args: #(#stringOut)>! + primWorking: dirName <cCall: 'chdir' returning: #void args: #(#string)>! ! @@ -157,6 +160,15 @@ working: dirName self checkError ! +createTemporary: prefix + "Create an empty directory whose name starts with prefix and answer it." + | name | + name := prefix, 'XXXXXX'. + self primCreateTemporary: name. + self checkError. + ^Directory name: name +! + allFilesMatching: aPattern do: aBlock (self name: (self working)) allFilesMatching: aPattern do: aBlock --- orig/kernel/File.st +++ mod/kernel/File.st @@ -339,11 +339,22 @@ name ^vfsHandler fullName ! +mode + "Answer the permission bits for the file identified by the receiver" + ^vfsHandler mode +! + size "Answer the size of the file identified by the receiver" ^vfsHandler size ! +mode: anInteger + "Set the permission bits for the file identified by the receiver to be + anInteger." + vfsHandler mode: anInteger +! + lastAccessTime: aDateTime "Update the last access time of the file corresponding to the receiver, to be aDateTime." --- orig/kernel/VFS.st +++ mod/kernel/VFS.st @@ -8,7 +8,7 @@ "====================================================================== | -| Copyright 2002, 2005 Free Software Foundation, Inc. +| Copyright 2002, 2005, 2007 Free Software Foundation, Inc. | Written by Paolo Bonzini. | | This file is part of the GNU Smalltalk class library. @@ -99,7 +99,7 @@ ZipFileHandler comment: 'ZipFileHandler files from a ZIP archive.'! VFSHandler subclass: #ArchiveMemberHandler - instanceVariableNames: 'parent size stCtime stMtime stAtime isDirectory realFileName' + instanceVariableNames: 'parent mode size stCtime stMtime stAtime realFileName' classVariableNames: '' poolDictionaries: '' category: 'Streams-Files' @@ -139,6 +139,9 @@ openDir: dirName closeDir: dirObject <cCall: 'closedir' returning: #int args: #(#cObject)>! +primChmod: name mode: mode + <cCall: 'chmod' returning: #int args: #(#string #int)>! + primIsReadable: name <cCall: 'fileIsReadable' returning: #boolean args: #(#string)>! @@ -474,6 +477,17 @@ size ^self stat stSize value ! +mode + "Answer the octal permissions for the file." + ^self stat stMode value bitAnd: 8r7777 +! + +mode: mode + "Set the octal permissions for the file to be `mode'." + self primChmod: (self name) mode: (mode bitAnd: 8r7777). + File checkError +! + isDirectory "Answer whether the file is a directory." ^(self stat stMode value bitAnd: 8r170000) = 8r040000 @@ -867,7 +881,7 @@ fillMember: anArchiveMemberHandler stCtime: self lastModifyTime stMtime: (data at: 2) stAtime: self lastAccessTime - isDirectory: (data at: 3) notNil. + mode: (data at: 3). ^true! @@ -880,26 +894,30 @@ member: anArchiveMemberHandler do: aBloc data := allFiles at: anArchiveMemberHandler name ifAbsent: [ nil ]. data isNil ifTrue: [ ^SystemExceptions.FileError signal: 'File not found' ]. - (data at: 3) isNil + (data at: 4) isNil ifTrue: [ ^SystemExceptions.FileError signal: 'Not a directory' ]. - (data at: 3) do: aBlock! + (data at: 4) do: aBlock! refresh "Extract the directory listing from the archive" - | pipe line isDir size date path parentPath name - current currentPath directoryTree directory | + | pipe line parentPath name current currentPath directoryTree directory | super refresh. current := currentPath := nil. allFiles := LookupTable new. directoryTree := LookupTable new. - self files do: [ :data || path size date | + self files do: [ :data || path size date mode | path := data at: 1. size := data at: 2. date := data at: 3. - isDir := data at: 4. + mode := data at: 4. + + mode isCharacter ifTrue: [ mode := (mode == $d) ]. + mode == true ifTrue: [ mode := 8r040755 ]. + mode == false ifTrue: [ mode := 8r644 ]. + mode isString ifTrue: [ mode := self convertModeString: mode ]. path last = $/ ifTrue: [ path := path copyFrom: 1 to: path size - 1 ]. @@ -916,21 +934,26 @@ refresh "Create an item in the tree for directories, and add an association to the allFiles SortedCollection" - directory := isDir + directory := (mode bitAnd: 8r170000) = 8r40000 ifTrue: [ current at: name put: LookupTable new ] ifFalse: [ current at: name put: nil ]. - allFiles at: path put: { size. date. directory } ]. + allFiles at: path put: { size. date. mode. directory } ]. "Leave the LookupTables to be garbage collected, we are now interested in the file names only." topLevelFiles := directoryTree keys asArray. allFiles do: [ :data | - (data at: 3) isNil ifFalse: [ - data at: 3 put: (data at: 3) keys asArray + (data at: 4) isNil ifFalse: [ + data at: 4 put: (data at: 4) keys asArray ] ]! +member: anArchiveMemberHandler mode: bits + "Set the permission bits for the file in anArchiveMemberHandler." + + self subclassResponsibility! + removeMember: anArchiveMemberHandler "Remove the member represented by anArchiveMemberHandler." @@ -945,6 +968,20 @@ updateMember: anArchiveMemberHandler !ArchiveFileHandler methodsFor: 'private'! +convertModeString: modeString + "Convert the mode from a string to an octal number." + | mode | + mode := 0. + (modeString at: 1) = $l ifTrue: [ mode := 8r120000 ]. + (modeString at: 1) = $d ifTrue: [ mode := 8r040000 ]. + (modeString at: 4) asLowercase = $s ifTrue: [ mode := mode + 8r04000 ]. + (modeString at: 7) asLowercase = $s ifTrue: [ mode := mode + 8r02000 ]. + (modeString at: 10) asLowercase = $t ifTrue: [ mode := mode + 8r01000 ]. + modeString from: 2 to: 10 keysAndValuesDo: [ :i :ch | + ch isLowercase ifTrue: [ mode := mode setBit: 11 - i ] ]. + ^mode +! + findDirectory: path into: tree "Look up into tree (which is a tree of Dictionaries) the directory that is the parent of the file named `path'." @@ -999,6 +1036,11 @@ createDir: dirName self notYetImplemented! +member: anArchiveMemberHandler mode: bits + "Set the permission bits for the file in anArchiveMemberHandler." + + self notYetImplemented! + extractMember: anArchiveMemberHandler into: temp "Extract the contents of anArchiveMemberHandler into a file that resides on disk, and answer the name of the file." @@ -1026,16 +1068,16 @@ files popen: 'unzip -Z ', self realFileName dir: FileStream read. - pipe linesDo: [ :l || result isDir size path date | + pipe linesDo: [ :l || result mode size path date | "Extract first character, fourth field, seventh+eighth field, rest of line." result := l searchRegex: - '^(.)\S+\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+(\S+\s+\S+)\s(.*?)(?: -> |$)'. + '^(.{10})\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+(\S+\s+\S+)\s(.*?)(?: -> |$)'. result matched ifTrue: [ - isDir := (result at: 1) = $d. + mode := result at: 1. size := (result at: 2) asInteger. date := DateTime readFrom: (result at: 3) readStream. path := result at: 4. - gen yield: { path. size. date. isDir } ] ]. + gen yield: { path. size. date. mode } ] ]. pipe close ]! ! @@ -1047,14 +1089,14 @@ parent: anArchiveFileHandler parent := anArchiveFileHandler! -size: bytes stCtime: ctime stMtime: mtime stAtime: atime isDirectory: isDir +size: bytes stCtime: ctime stMtime: mtime stAtime: atime mode: modeBits "Called back by the receiver's parent when the ArchiveMemberHandler asks for file information." size := bytes. stCtime := ctime. stMtime := mtime. stAtime := atime. - isDirectory := isDir! ! + mode := modeBits! ! !ArchiveMemberHandler methodsFor: 'accessing'! @@ -1127,11 +1169,23 @@ exists "Answer whether a file with the name contained in the receiver does exist." ^self parent fillMember: self! +mode + "Answer the octal permissions for the file." + size isNil ifTrue: [ self refresh ]. + ^mode bitAnd: 8r7777 +! + +mode: mode + "Set the octal permissions for the file to be `mode'." + self parent member: self mode: (mode bitAnd: 8r7777). +! + isDirectory "Answer whether a file with the name contained in the receiver does exist and identifies a directory." size isNil ifTrue: [ self refresh ]. - ^isDirectory! + ^(mode bitAnd: 8r170000) = 8r040000 +! isReadable "Answer whether a file with the name contained in the receiver does exist --- orig/libgst/cint.c +++ mod/libgst/cint.c @@ -508,6 +508,7 @@ _gst_init_cfuncs (void) _gst_define_cfunc ("stat", my_stat); _gst_define_cfunc ("lstat", my_lstat); _gst_define_cfunc ("utime", _gst_set_file_access_times); + _gst_define_cfunc ("chmod", chmod); _gst_define_cfunc ("opendir", my_opendir); _gst_define_cfunc ("closedir", closedir); @@ -521,6 +522,7 @@ _gst_init_cfuncs (void) _gst_define_cfunc ("rmdir", rmdir); _gst_define_cfunc ("chdir", my_chdir); _gst_define_cfunc ("mkdir", mkdir); + _gst_define_cfunc ("mkdtemp", mkdtemp); _gst_define_cfunc ("getCurDirName", _gst_get_cur_dir_name); _gst_define_cfunc ("fileIsReadable", _gst_file_is_readable); --- orig/packages/vfs/VFS.st +++ mod/packages/vfs/VFS.st @@ -97,6 +97,11 @@ createDir: dirName !ExternalArchiveFileHandler methodsFor: 'ArchiveMemberHandler protocol'! +member: anArchiveMemberHandler mode: bits + "Set the permission bits for the file in anArchiveMemberHandler." + + self notYetImplemented! + extractMember: anArchiveMemberHandler into: file "Extract the contents of anArchiveMemberHandler into a file that resides on disk, and answer the name of the file." @@ -136,11 +141,14 @@ files popen: self command, ' list ', self realFileName dir: FileStream read. - pipe linesDo: [ :l || line isDir size path date | + pipe linesDo: [ :l || line mode size path date | line := l readStream. - isDir := line next = $d. + mode := line next: 10. + line peek isSeparator ifFalse: [ line skipTo: Character space ]. + line skipSeparators. + "Attributes, number of links, owner, group" - 4 timesRepeat: [ + 3 timesRepeat: [ line skipTo: Character space. line skipSeparators ]. @@ -150,7 +158,7 @@ files line skipSeparators. path := line upToAll: ' -> '. "Path" - gen yield: { path. size. date. isDir } ]. + gen yield: { path. size. date. mode } ]. pipe close ]! ! _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |