#FEATURE by stefan
class: FileStream class
changed: #newTemporaryIn:nameTemplate:
create unique temp files even if the name template
does not ensure unique names.
--- a/FileStream.st Tue Apr 28 16:22:44 2020 +0200
+++ b/FileStream.st Wed Apr 29 10:31:29 2020 +0200
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -448,56 +446,64 @@
with every call to this method respectively.
See also: #newTemporary which looks for a good temp directory."
- |nameString random prevRandom prevNameString newTempFilename stream|
+ |nameString random prevRandom prevNameString newTempFilename stream nextSeqNr fn|
[
- prevRandom := random.
- prevNameString := nameString.
+ prevRandom := random.
+ prevNameString := nameString.
+
+ "Use random numbers in order to improve the security
+ by making the generated names less predictable"
+ [
+ random := RandomGenerator nextLettersOrDigits:4.
+ ] doWhile:[random = prevRandom].
- "Use random numbers in order to improve the security
- by making the generated names less predictable"
- [
- random := RandomGenerator nextLettersOrDigits:4.
- ] doWhile:[random = prevRandom].
-
- nameString := template bindWith:(OperatingSystem getProcessId) with:random.
+ nameString := template bindWith:(OperatingSystem getProcessId) with:random.
+ (prevNameString = nameString) ifTrue:[
+ "/ ouch - the given template seems to not generate unique file names.
+ "/ append a sequence number
+ nextSeqNr := (nextSeqNr ? 0) + 1.
+ fn := nameString asFilename.
+ nameString := (fn withoutSuffix name, '_', nextSeqNr asString) asFilename withSuffix:fn suffix.
+ ].
- aDirectoryOrNil isNil ifTrue:[
- newTempFilename := nameString.
- ] ifFalse:[
- newTempFilename := aDirectoryOrNil asFilename constructString:nameString.
- ].
+ aDirectoryOrNil isNil ifTrue:[
+ newTempFilename := nameString.
+ ] ifFalse:[
+ newTempFilename := aDirectoryOrNil asFilename constructString:nameString.
+ ].
- [
- stream := self open:newTempFilename withMode:#(CREATE_NEW GENERIC_READ_WRITE FILE_SHARE_WRITE FILE_SHARE_READ).
- ] on:OpenError do:[:ex|
- ex errorCategory ~~ #existingReferentSignal ifTrue:[
- "some fundamental error, raise exception"
- ex reject.
- ].
- prevNameString = nameString ifTrue:[
- "no more names - probably a bad template"
- ex reject.
- ].
- "file exists, retry another one"
- ].
+ [
+ stream := self open:newTempFilename withMode:#(CREATE_NEW GENERIC_READ_WRITE FILE_SHARE_WRITE FILE_SHARE_READ).
+ ] on:OpenError do:[:ex|
+ ex errorCategory ~~ #existingReferentSignal ifTrue:[
+ "some fundamental error, raise exception"
+ ex reject.
+ ].
+ prevNameString = nameString ifTrue:[
+ "no more names - probably a bad template"
+ ex reject.
+ ].
+ "file exists, retry another one"
+ ].
] doWhile:[
- stream isNil and:[prevNameString ~= nameString] "/ if namestring didn't change, the template is bad
+ stream isNil and:[prevNameString ~= nameString] "/ if namestring didn't change, the template is bad
].
^ stream
"temp files in '/tmp':
- FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo%1_%2'
+ FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo%1_%2'
This must fail on the second try:
- FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo'
- FileStream newTemporaryIn:'c:\temp' asFilename nameTemplate:'foo'
+ FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo'
+ FileStream newTemporaryIn:'c:\temp' asFilename nameTemplate:'foo'
"
"temp files somewhere
(not recommended - use above since it can be controlled via shell variables):
+ FileStream newTemporaryIn:'/tmp' nameTemplate:'foo'
FileStream newTemporaryIn:'/tmp' nameTemplate:'foo%1_%2'
FileStream newTemporaryIn:'/tmp' nameTemplate:'foo%1_%2'
FileStream newTemporaryIn:'/usr/tmp' nameTemplate:'foo%1_%2'
@@ -512,7 +518,7 @@
FileStream newTemporaryIn:('source' asFilename) nameTemplate:'foo%1_%2'
"
- "Modified: / 12-10-2018 / 10:45:25 / Stefan Vogel"
+ "Modified: / 29-04-2020 / 09:38:15 / Stefan Vogel"
!
newTemporaryIn:aDirectoryOrNil withSuffix:aSuffixString