FileStream.st
branchjv
changeset 18078 7ef3221b036d
parent 18071 009cf668b0ed
parent 15542 3a22ba499a82
child 18079 7b5afc0ad3d5
equal deleted inserted replaced
18077:5844a3bcdd52 18078:7ef3221b036d
   228     byte boundaries if the file is a variable-record-RMS file.
   228     byte boundaries if the file is a variable-record-RMS file.
   229     (stupid enough, this is the default for textfiles as created by some tools ...)
   229     (stupid enough, this is the default for textfiles as created by some tools ...)
   230     Therefore, the instance variable canPosition is set according to
   230     Therefore, the instance variable canPosition is set according to
   231     this and an error is raised, if a position: is attemted.
   231     this and an error is raised, if a position: is attemted.
   232     I know, this is ugly, but what else could we do ?
   232     I know, this is ugly, but what else could we do ?
   233     Late note: who cares for VMS these days? 
   233     Late note: who cares for VMS these days?
   234                (and how much useless effort has been put in the past, 
   234 	       (and how much useless effort has been put in the past,
   235                 to support lousy operating systems?)
   235 		to support lousy operating systems?)
   236 
   236 
   237     [instance variables:]
   237     [instance variables:]
   238         pathName        <String>        the files path (if known)
   238 	pathName        <String>        the files path (if known)
   239         canPosition     <Boolean>       positionable - read above comment
   239 	canPosition     <Boolean>       positionable - read above comment
   240 
   240 
   241     [author:]
   241     [author:]
   242         Claus Gittinger
   242 	Claus Gittinger
   243 
   243 
   244     [see also:]
   244     [see also:]
   245         Filename DirectoryStream PipeStream Socket
   245 	Filename DirectoryStream PipeStream Socket
   246 "
   246 "
   247 !
   247 !
   248 
   248 
   249 examples
   249 examples
   250 "
   250 "
   391 
   391 
   392 newTemporary
   392 newTemporary
   393     "create atomically a new file and return the file stream - use this for temporary files.
   393     "create atomically a new file and return the file stream - use this for temporary files.
   394      The created file has the name '/tmp/stxtmp_xx_nn' where xx is our
   394      The created file has the name '/tmp/stxtmp_xx_nn' where xx is our
   395      unix process id, and nn is a unique number, incremented with every call to this method.
   395      unix process id, and nn is a unique number, incremented with every call to this method.
   396      If any of the environment variables ST_TMPDIR or TMPDIR is set, 
   396      If any of the environment variables ST_TMPDIR or TMPDIR is set,
   397      its value defines the temp directory."
   397      its value defines the temp directory."
   398 
   398 
   399     ^ self newTemporaryIn:Filename tempDirectory
   399     ^ self newTemporaryIn:Filename tempDirectory
   400 
   400 
   401     "
   401     "
   402      FileStream newTemporary    
   402      FileStream newTemporary
   403      FileStream newTemporary     
   403      FileStream newTemporary
   404     "
   404     "
   405 !
   405 !
   406 
   406 
   407 newTemporaryIn:aDirectoryOrNil
   407 newTemporaryIn:aDirectoryOrNil
   408     "create atomically a new file and return the file stream - use this for temporary files.
   408     "create atomically a new file and return the file stream - use this for temporary files.
   409      The created file is in aDirectoryPrefix and named 'stxtmp_xx_nn',
   409      The created file is in aDirectoryPrefix and named 'stxtmp_xx_nn',
   410      where xx is our unix process id, and nn is a unique number, incremented 
   410      where xx is our unix process id, and nn is a unique number, incremented
   411      with every call to this method."
   411      with every call to this method."
   412 
   412 
   413     ^ self newTemporaryIn:aDirectoryOrNil nameTemplate:Filename tempFileNameTemplate
   413     ^ self newTemporaryIn:aDirectoryOrNil nameTemplate:Filename tempFileNameTemplate
   414 
   414 
   415     "temp files in '/tmp':
   415     "temp files in '/tmp':
   416 
   416 
   417      FileStream newTemporary    
   417      FileStream newTemporary
   418     "
   418     "
   419 
   419 
   420     "temp files somewhere 
   420     "temp files somewhere
   421      (not recommended - use above since it can be controlled via shell variables):
   421      (not recommended - use above since it can be controlled via shell variables):
   422 
   422 
   423      FileStream newTemporaryIn:'/tmp'    
   423      FileStream newTemporaryIn:'/tmp'
   424      FileStream newTemporaryIn:'/tmp'  
   424      FileStream newTemporaryIn:'/tmp'
   425      FileStream newTemporaryIn:'/usr/tmp'    
   425      FileStream newTemporaryIn:'/usr/tmp'
   426      FileStream newTemporaryIn:'/'  
   426      FileStream newTemporaryIn:'/'
   427     "
   427     "
   428 
   428 
   429     "a local temp file:
   429     "a local temp file:
   430 
   430 
   431      FileStream newTemporaryIn:''         
   431      FileStream newTemporaryIn:''
   432      FileStream newTemporaryIn:nil         
   432      FileStream newTemporaryIn:nil
   433      FileStream newTemporaryIn:'.'         
   433      FileStream newTemporaryIn:'.'
   434      FileStream newTemporaryIn:('source' asFilename) 
   434      FileStream newTemporaryIn:('source' asFilename)
   435     "
   435     "
   436 !
   436 !
   437 
   437 
   438 newTemporaryIn:aDirectoryOrNil nameTemplate:template
   438 newTemporaryIn:aDirectoryOrNil nameTemplate:template
   439     "create atomically a new file and return the file stream - use this for temporary files.
   439     "create atomically a new file and return the file stream - use this for temporary files.
   443      See also: #newTemporary which looks for a good temp directory."
   443      See also: #newTemporary which looks for a good temp directory."
   444 
   444 
   445     |nameString random prevRandom prevNameString newTempFilename stream|
   445     |nameString random prevRandom prevNameString newTempFilename stream|
   446 
   446 
   447     [
   447     [
   448         prevRandom := random.
   448 	prevRandom := random.
   449         prevNameString := nameString.
   449 	prevNameString := nameString.
   450 
   450 
   451         "Use random numbers in order to improve the security
   451 	"Use random numbers in order to improve the security
   452          by making the generated names less predictable"
   452 	 by making the generated names less predictable"
   453         [
   453 	[
   454             random := RandomGenerator new nextInteger.
   454 	    random := RandomGenerator new nextInteger.
   455         ] doWhile:[random = prevRandom].
   455 	] doWhile:[random = prevRandom].
   456 
   456 
   457         nameString := template bindWith:(OperatingSystem getProcessId) with:random.
   457 	nameString := template bindWith:(OperatingSystem getProcessId) with:random.
   458 
   458 
   459         aDirectoryOrNil isNil ifTrue:[
   459 	aDirectoryOrNil isNil ifTrue:[
   460             newTempFilename := nameString.
   460 	    newTempFilename := nameString.
   461         ] ifFalse:[
   461 	] ifFalse:[
   462             newTempFilename := aDirectoryOrNil asFilename constructString:nameString.
   462 	    newTempFilename := aDirectoryOrNil asFilename constructString:nameString.
   463         ].
   463 	].
   464 
   464 
   465         [
   465 	[
   466             stream := self open:newTempFilename withMode:#(CREATE_NEW GENERIC_READ_WRITE).
   466 	    stream := self open:newTempFilename withMode:#(CREATE_NEW GENERIC_READ_WRITE).
   467         ] on:OpenError do:[:ex|
   467 	] on:OpenError do:[:ex|
   468             (OperatingSystem errorHolderForNumber:ex errorCode) errorCategory ~~ #existingReferentSignal ifFalse:[
   468 	    (OperatingSystem errorHolderForNumber:ex errorCode) errorCategory ~~ #existingReferentSignal ifFalse:[
   469                 "some fundamental error, raise exception"
   469 		"some fundamental error, raise exception"
   470                 ex reject.
   470 		ex reject.
   471             ].
   471 	    ].
   472             prevNameString = nameString ifTrue:[
   472 	    prevNameString = nameString ifTrue:[
   473                 "no more names - probably a bad template"
   473 		"no more names - probably a bad template"
   474                 ex reject.
   474 		ex reject.
   475             ].
   475 	    ].
   476             "file exists, retry another one"
   476 	    "file exists, retry another one"
   477         ].
   477 	].
   478     ] doWhile:[
   478     ] doWhile:[
   479         stream isNil and:[prevNameString ~= nameString]   "/ if namestring didn't change, the template is bad
   479 	stream isNil and:[prevNameString ~= nameString]   "/ if namestring didn't change, the template is bad
   480     ].
   480     ].
   481     ^ stream
   481     ^ stream
   482 
   482 
   483     "temp files in '/tmp':
   483     "temp files in '/tmp':
   484 
   484 
   485         FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo%1_%2'
   485 	FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo%1_%2'
   486 
   486 
   487      This must fail on the second try:
   487      This must fail on the second try:
   488         FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo'
   488 	FileStream newTemporaryIn:'/tmp' asFilename nameTemplate:'foo'
   489         FileStream newTemporaryIn:'c:\temp' asFilename nameTemplate:'foo'
   489 	FileStream newTemporaryIn:'c:\temp' asFilename nameTemplate:'foo'
   490     "
   490     "
   491 
   491 
   492     "temp files somewhere
   492     "temp files somewhere
   493      (not recommended - use above since it can be controlled via shell variables):
   493      (not recommended - use above since it can be controlled via shell variables):
   494 
   494 
   505      FileStream newTemporaryIn:'.'            nameTemplate:'foo%1_%2'
   505      FileStream newTemporaryIn:'.'            nameTemplate:'foo%1_%2'
   506      FileStream newTemporaryIn:('source' asFilename) nameTemplate:'foo%1_%2'
   506      FileStream newTemporaryIn:('source' asFilename) nameTemplate:'foo%1_%2'
   507     "
   507     "
   508 !
   508 !
   509 
   509 
   510 newTemporaryIn:aDirectoryOrNil withSuffix:aSuffixString 
   510 newTemporaryIn:aDirectoryOrNil withSuffix:aSuffixString
   511     "create atomically a new file and return the file stream - use this for temporary files.
   511     "create atomically a new file and return the file stream - use this for temporary files.
   512      The created file is in aDirectoryPrefix and named 'stxtmp_xx_nn',
   512      The created file is in aDirectoryPrefix and named 'stxtmp_xx_nn',
   513      where xx is our unix process id, and nn is a unique number, incremented
   513      where xx is our unix process id, and nn is a unique number, incremented
   514      with every call to this method."
   514      with every call to this method."
   515     
   515 
   516     ^ self 
   516     ^ self
   517         newTemporaryIn:aDirectoryOrNil
   517 	newTemporaryIn:aDirectoryOrNil
   518         nameTemplate:(Filename tempFileNameTemplate asFilename 
   518 	nameTemplate:(Filename tempFileNameTemplate asFilename
   519                                         withSuffix:aSuffixString) asString
   519 					withSuffix:aSuffixString) asString
   520 
   520 
   521     "
   521     "
   522      FileStream newTemporaryWithSuffix:'txt'
   522      FileStream newTemporaryWithSuffix:'txt'
   523      FileStream newTemporaryIn:'/tmp' withSuffix:'txt'
   523      FileStream newTemporaryIn:'/tmp' withSuffix:'txt'
   524     "
   524     "
   578      The file is opened for read/write access."
   578      The file is opened for read/write access."
   579 
   579 
   580     |stream|
   580     |stream|
   581 
   581 
   582     stream := self new pathName:aFilenameString.
   582     stream := self new pathName:aFilenameString.
   583     stream 
   583     stream
   584         readwrite;        "/ assume read/write mode, but this depends on the args
   584 	readwrite;        "/ assume read/write mode, but this depends on the args
   585         openWithMode:anArrayOrString attributes:nil.
   585 	openWithMode:anArrayOrString attributes:nil.
   586 
   586 
   587     ^ stream
   587     ^ stream
   588 !
   588 !
   589 
   589 
   590 readonlyFileNamed:filename
   590 readonlyFileNamed:filename
   729 
   729 
   730     ^ OperatingSystem accessModeOfFd:self fileDescriptor.
   730     ^ OperatingSystem accessModeOfFd:self fileDescriptor.
   731 
   731 
   732     "
   732     "
   733       'Make.proto' asFilename readingFileDo:[:s|
   733       'Make.proto' asFilename readingFileDo:[:s|
   734           s accessRights
   734 	  s accessRights
   735       ]
   735       ]
   736     "
   736     "
   737 !
   737 !
   738 
   738 
   739 accessRights:opaqueData
   739 accessRights:opaqueData
   740     "set the access rights of the file to opaqueData,
   740     "set the access rights of the file to opaqueData,
   741      which is normally retrieved by Filename>>#accessRights
   741      which is normally retrieved by Filename>>#accessRights
   742      or FileStreamm>>#accessRights."
   742      or FileStreamm>>#accessRights."
   743 
   743 
   744     (OperatingSystem changeAccessModeOfFd:self fileDescriptor to:opaqueData) ifFalse:[
   744     (OperatingSystem changeAccessModeOfFd:self fileDescriptor to:opaqueData) ifFalse:[
   745         ^ self fileName accessDeniedError:self
   745 	^ self fileName accessDeniedError:self
   746     ].
   746     ].
   747 
   747 
   748     "
   748     "
   749       'Make.proto' asFilename readingFileDo:[:s|
   749       'Make.proto' asFilename readingFileDo:[:s|
   750           s accessRights:s accessRights
   750 	  s accessRights:s accessRights
   751       ]
   751       ]
   752     "
   752     "
   753 
   753 
   754     "
   754     "
   755       '/' asFilename readingFileDo:[:s|
   755       '/' asFilename readingFileDo:[:s|
   756           s accessRights:s accessRights
   756 	  s accessRights:s accessRights
   757       ]
   757       ]
   758     "
   758     "
   759 ! !
   759 ! !
   760 
   760 
   761 !FileStream methodsFor:'accessing'!
   761 !FileStream methodsFor:'accessing'!
   857 executor
   857 executor
   858     |executor|
   858     |executor|
   859 
   859 
   860     executor := super executor.
   860     executor := super executor.
   861     removeOnClose == true ifTrue:[
   861     removeOnClose == true ifTrue:[
   862         executor setPathName:pathName removeOnClose:true.
   862 	executor setPathName:pathName removeOnClose:true.
   863     ].
   863     ].
   864     ^ executor
   864     ^ executor
   865 ! !
   865 ! !
   866 
   866 
   867 !FileStream methodsFor:'misc functions'!
   867 !FileStream methodsFor:'misc functions'!
  1168     "position the file by re-reading everything up-to newPos.
  1168     "position the file by re-reading everything up-to newPos.
  1169      The effect is the same as that of #position:, but its much slower.
  1169      The effect is the same as that of #position:, but its much slower.
  1170      This is required to reposition nonPositionable streams, such
  1170      This is required to reposition nonPositionable streams, such
  1171      as tape-streams or variable-record-RMS files under VMS.
  1171      as tape-streams or variable-record-RMS files under VMS.
  1172      Caveat:
  1172      Caveat:
  1173          This should really be done transparently by the stdio library."
  1173 	 This should really be done transparently by the stdio library."
  1174 
  1174 
  1175     ^ self slowPosition0Based:newPos
  1175     ^ self slowPosition0Based:newPos
  1176 ! !
  1176 ! !
  1177 
  1177 
  1178 !FileStream methodsFor:'printing & storing'!
  1178 !FileStream methodsFor:'printing & storing'!
  1195      from which a copy can be reconstructed later."
  1195      from which a copy can be reconstructed later."
  1196 
  1196 
  1197     aStream nextPutAll:'(FileStream oldFileNamed:'.
  1197     aStream nextPutAll:'(FileStream oldFileNamed:'.
  1198     aStream nextPutAll:pathName storeString.
  1198     aStream nextPutAll:pathName storeString.
  1199     (self position ~~ 0) ifTrue:[
  1199     (self position ~~ 0) ifTrue:[
  1200         aStream nextPutAll:'; position:'.
  1200 	aStream nextPutAll:'; position:'.
  1201         self position storeOn:aStream
  1201 	self position storeOn:aStream
  1202     ].
  1202     ].
  1203     aStream nextPut:$)
  1203     aStream nextPut:$)
  1204 
  1204 
  1205     "Modified: 30.7.1997 / 16:43:50 / cg"
  1205     "Modified: 30.7.1997 / 16:43:50 / cg"
  1206 ! !
  1206 ! !
  1260 %{
  1260 %{
  1261     HFILE f = NULL;
  1261     HFILE f = NULL;
  1262     int pass = 0;
  1262     int pass = 0;
  1263 
  1263 
  1264     if (!__isNonNilObject(encodedPathName)
  1264     if (!__isNonNilObject(encodedPathName)
  1265         || !(__isStringLike(openmode) || __isArrayLike(openmode)))
  1265 	|| !(__isStringLike(openmode) || __isArrayLike(openmode)))
  1266             goto badArgument;
  1266 	    goto badArgument;
  1267 
  1267 
  1268 retry:
  1268 retry:
  1269 #ifdef __VMS__
  1269 #ifdef __VMS__
  1270       if (__isStringLike(encodedPathName)) {
  1270       if (__isStringLike(encodedPathName)) {
  1271         do {
  1271 	do {
  1272             /*
  1272 	    /*
  1273              * allow passing additional RMS arguments.
  1273 	     * allow passing additional RMS arguments.
  1274              * stupid: DEC does not seem to offer an interface for passing a char **.
  1274 	     * stupid: DEC does not seem to offer an interface for passing a char **.
  1275              */
  1275 	     */
  1276             __threadErrno = 0;
  1276 	    __threadErrno = 0;
  1277 
  1277 
  1278             {
  1278 	    {
  1279                 if (__isArray(attributeSpec)) {
  1279 		if (__isArray(attributeSpec)) {
  1280                     OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
  1280 		    OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
  1281                     int numAttrib = 0;
  1281 		    int numAttrib = 0;
  1282                     int i;
  1282 		    int i;
  1283 
  1283 
  1284                     numAttrib = __arraySize(attributeSpec);
  1284 		    numAttrib = __arraySize(attributeSpec);
  1285                     for (i=0; i<numAttrib;i++) {
  1285 		    for (i=0; i<numAttrib;i++) {
  1286                         if (! __isStringLike(ap[i])) {
  1286 			if (! __isStringLike(ap[i])) {
  1287                             __threadErrno = EINVAL; /* invalid argument */
  1287 			    __threadErrno = EINVAL; /* invalid argument */
  1288                             goto getOutOfHere;
  1288 			    goto getOutOfHere;
  1289                         }
  1289 			}
  1290                     }
  1290 		    }
  1291                     switch (numAttrib) {
  1291 		    switch (numAttrib) {
  1292                         case 0:
  1292 			case 0:
  1293                             __BEGIN_INTERRUPTABLE__
  1293 			    __BEGIN_INTERRUPTABLE__
  1294                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1294 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1295                             __END_INTERRUPTABLE__
  1295 			    __END_INTERRUPTABLE__
  1296                             break;
  1296 			    break;
  1297                         case 1:
  1297 			case 1:
  1298                             __BEGIN_INTERRUPTABLE__
  1298 			    __BEGIN_INTERRUPTABLE__
  1299                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1299 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1300                                       __stringVal(ap[0]));
  1300 				      __stringVal(ap[0]));
  1301                             __END_INTERRUPTABLE__
  1301 			    __END_INTERRUPTABLE__
  1302                             break;
  1302 			    break;
  1303                         case 2:
  1303 			case 2:
  1304                             __BEGIN_INTERRUPTABLE__
  1304 			    __BEGIN_INTERRUPTABLE__
  1305                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1305 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1306                                       __stringVal(ap[0]), __stringVal(ap[1]));
  1306 				      __stringVal(ap[0]), __stringVal(ap[1]));
  1307                             __END_INTERRUPTABLE__
  1307 			    __END_INTERRUPTABLE__
  1308                             break;
  1308 			    break;
  1309                         case 3:
  1309 			case 3:
  1310                             __BEGIN_INTERRUPTABLE__
  1310 			    __BEGIN_INTERRUPTABLE__
  1311                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1311 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1312                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1312 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1313                             __END_INTERRUPTABLE__
  1313 			    __END_INTERRUPTABLE__
  1314                             break;
  1314 			    break;
  1315                         case 4:
  1315 			case 4:
  1316                             __BEGIN_INTERRUPTABLE__
  1316 			    __BEGIN_INTERRUPTABLE__
  1317                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1317 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1318                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1318 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1319                                       __stringVal(ap[3]));
  1319 				      __stringVal(ap[3]));
  1320                             __END_INTERRUPTABLE__
  1320 			    __END_INTERRUPTABLE__
  1321                             break;
  1321 			    break;
  1322                         case 5:
  1322 			case 5:
  1323                             __BEGIN_INTERRUPTABLE__
  1323 			    __BEGIN_INTERRUPTABLE__
  1324                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1324 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1325                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1325 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1326                                       __stringVal(ap[3]), __stringVal(ap[4]));
  1326 				      __stringVal(ap[3]), __stringVal(ap[4]));
  1327                             __END_INTERRUPTABLE__
  1327 			    __END_INTERRUPTABLE__
  1328                             break;
  1328 			    break;
  1329                         case 6:
  1329 			case 6:
  1330                             __BEGIN_INTERRUPTABLE__
  1330 			    __BEGIN_INTERRUPTABLE__
  1331                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1331 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1332                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1332 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1333                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1333 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1334                             __END_INTERRUPTABLE__
  1334 			    __END_INTERRUPTABLE__
  1335                             break;
  1335 			    break;
  1336                         case 7:
  1336 			case 7:
  1337                             __BEGIN_INTERRUPTABLE__
  1337 			    __BEGIN_INTERRUPTABLE__
  1338                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1338 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1339                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1339 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1340                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1340 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1341                                       __stringVal(ap[6]));
  1341 				      __stringVal(ap[6]));
  1342                             __END_INTERRUPTABLE__
  1342 			    __END_INTERRUPTABLE__
  1343                             break;
  1343 			    break;
  1344                         case 8:
  1344 			case 8:
  1345                             __BEGIN_INTERRUPTABLE__
  1345 			    __BEGIN_INTERRUPTABLE__
  1346                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1346 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1347                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1347 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1348                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1348 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1349                                       __stringVal(ap[6]), __stringVal(ap[7]));
  1349 				      __stringVal(ap[6]), __stringVal(ap[7]));
  1350                             __END_INTERRUPTABLE__
  1350 			    __END_INTERRUPTABLE__
  1351                             break;
  1351 			    break;
  1352                         case 9:
  1352 			case 9:
  1353                             __BEGIN_INTERRUPTABLE__
  1353 			    __BEGIN_INTERRUPTABLE__
  1354                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1354 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1355                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1355 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1356                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1356 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1357                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1357 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1358                             __END_INTERRUPTABLE__
  1358 			    __END_INTERRUPTABLE__
  1359                             break;
  1359 			    break;
  1360                         case 10:
  1360 			case 10:
  1361                             __BEGIN_INTERRUPTABLE__
  1361 			    __BEGIN_INTERRUPTABLE__
  1362                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1362 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1363                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1363 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1364                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1364 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1365                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1365 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1366                                       __stringVal(ap[9]));
  1366 				      __stringVal(ap[9]));
  1367                             __END_INTERRUPTABLE__
  1367 			    __END_INTERRUPTABLE__
  1368                             break;
  1368 			    break;
  1369                         default:
  1369 			default:
  1370                             __threadErrno = E2BIG; /* too many args */
  1370 			    __threadErrno = E2BIG; /* too many args */
  1371                             goto getOutOfHere;
  1371 			    goto getOutOfHere;
  1372                     }
  1372 		    }
  1373                 } else if (attributeSpec != nil) {
  1373 		} else if (attributeSpec != nil) {
  1374                     __threadErrno = EINVAL; /* invalid argument */
  1374 		    __threadErrno = EINVAL; /* invalid argument */
  1375                     goto getOutOfHere;
  1375 		    goto getOutOfHere;
  1376                 } else {
  1376 		} else {
  1377                     /*
  1377 		    /*
  1378                      * create file as sequential streamLF by default.
  1378 		     * create file as sequential streamLF by default.
  1379                      */
  1379 		     */
  1380                     __BEGIN_INTERRUPTABLE__
  1380 		    __BEGIN_INTERRUPTABLE__
  1381                     f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1381 		    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1382                     __END_INTERRUPTABLE__
  1382 		    __END_INTERRUPTABLE__
  1383                 }
  1383 		}
  1384             }
  1384 	    }
  1385         } while ((f == NULL) && (__threadErrno == EINTR));
  1385 	} while ((f == NULL) && (__threadErrno == EINTR));
  1386       }
  1386       }
  1387 #else /* not VMS */
  1387 #else /* not VMS */
  1388 
  1388 
  1389 # ifdef WIN32
  1389 # ifdef WIN32
  1390     {
  1390     {
  1391           DWORD share = 0, access = 0, create = 0, attr = 0;
  1391 	  DWORD share = 0, access = 0, create = 0, attr = 0;
  1392           char * __openmode;
  1392 	  char * __openmode;
  1393           HANDLE handle;
  1393 	  HANDLE handle;
  1394           SECURITY_ATTRIBUTES sa;
  1394 	  SECURITY_ATTRIBUTES sa;
  1395 
  1395 
  1396           if (__isStringLike(openmode)) {
  1396 	  if (__isStringLike(openmode)) {
  1397               share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  1397 	      share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  1398               __openmode = __stringVal(openmode);
  1398 	      __openmode = __stringVal(openmode);
  1399               if (strcmp(__openmode, "rb") == 0) {
  1399 	      if (strcmp(__openmode, "rb") == 0) {
  1400                   access = GENERIC_READ;
  1400 		  access = GENERIC_READ;
  1401                   create = OPEN_EXISTING;
  1401 		  create = OPEN_EXISTING;
  1402               } else if (strcmp(__openmode, "rb+") == 0) {
  1402 	      } else if (strcmp(__openmode, "rb+") == 0) {
  1403                   access = GENERIC_READ | GENERIC_WRITE;
  1403 		  access = GENERIC_READ | GENERIC_WRITE;
  1404                   create = OPEN_EXISTING;
  1404 		  create = OPEN_EXISTING;
  1405               } else if (strcmp(__openmode, "wb") == 0) {
  1405 	      } else if (strcmp(__openmode, "wb") == 0) {
  1406                   access = GENERIC_WRITE;
  1406 		  access = GENERIC_WRITE;
  1407                   create = CREATE_ALWAYS;
  1407 		  create = CREATE_ALWAYS;
  1408               } else if (strcmp(__openmode, "wb+") == 0) {
  1408 	      } else if (strcmp(__openmode, "wb+") == 0) {
  1409                   access = GENERIC_READ | GENERIC_WRITE;
  1409 		  access = GENERIC_READ | GENERIC_WRITE;
  1410                   create = CREATE_ALWAYS;
  1410 		  create = CREATE_ALWAYS;
  1411               } else if (strcmp(__openmode, "ab") == 0) {
  1411 	      } else if (strcmp(__openmode, "ab") == 0) {
  1412                   access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1412 		  access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1413                                 STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1413 				STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1414                   create = OPEN_ALWAYS;
  1414 		  create = OPEN_ALWAYS;
  1415               } else if (strcmp(__openmode, "ab+") == 0) {
  1415 	      } else if (strcmp(__openmode, "ab+") == 0) {
  1416                   access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1416 		  access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
  1417                                 STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1417 				STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
  1418                   create = OPEN_ALWAYS;
  1418 		  create = OPEN_ALWAYS;
  1419               } else {
  1419 	      } else {
  1420                   console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1420 		  console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1421               }
  1421 	      }
  1422           } else if (__isArrayLike(openmode)) {
  1422 	  } else if (__isArrayLike(openmode)) {
  1423               OBJ *ap = __arrayVal(openmode);
  1423 	      OBJ *ap = __arrayVal(openmode);
  1424               int numAttrib = __arraySize(openmode);
  1424 	      int numAttrib = __arraySize(openmode);
  1425               int i;
  1425 	      int i;
  1426 
  1426 
  1427               __openmode = "rb+";
  1427 	      __openmode = "rb+";
  1428 
  1428 
  1429               for (i=0; i<numAttrib; i++) {
  1429 	      for (i=0; i<numAttrib; i++) {
  1430                   OBJ attrSym = ap[i];
  1430 		  OBJ attrSym = ap[i];
  1431 
  1431 
  1432                   if (attrSym == @symbol(FILE_SHARE_READ)) {
  1432 		  if (attrSym == @symbol(FILE_SHARE_READ)) {
  1433                       share |= FILE_SHARE_READ;
  1433 		      share |= FILE_SHARE_READ;
  1434                   } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1434 		  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1435                       share |= FILE_SHARE_WRITE;
  1435 		      share |= FILE_SHARE_WRITE;
  1436 
  1436 
  1437                   } else if (attrSym == @symbol(GENERIC_READ)) {
  1437 		  } else if (attrSym == @symbol(GENERIC_READ)) {
  1438                       access |= GENERIC_READ;
  1438 		      access |= GENERIC_READ;
  1439                   } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1439 		  } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1440                       access |= GENERIC_WRITE;
  1440 		      access |= GENERIC_WRITE;
  1441                   } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1441 		  } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1442                       access |= GENERIC_READ|GENERIC_WRITE;
  1442 		      access |= GENERIC_READ|GENERIC_WRITE;
  1443 
  1443 
  1444                   } else if (attrSym == @symbol(CREATE_NEW)) {
  1444 		  } else if (attrSym == @symbol(CREATE_NEW)) {
  1445                       create |= CREATE_NEW;
  1445 		      create |= CREATE_NEW;
  1446                   } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1446 		  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1447                       create |= CREATE_ALWAYS;
  1447 		      create |= CREATE_ALWAYS;
  1448                   } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1448 		  } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1449                       create |= OPEN_EXISTING;
  1449 		      create |= OPEN_EXISTING;
  1450                   } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1450 		  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1451                       create |= OPEN_ALWAYS;
  1451 		      create |= OPEN_ALWAYS;
  1452                   } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1452 		  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1453                       create |= TRUNCATE_EXISTING;
  1453 		      create |= TRUNCATE_EXISTING;
  1454 
  1454 
  1455                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1455 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1456                       attr |= FILE_ATTRIBUTE_HIDDEN;
  1456 		      attr |= FILE_ATTRIBUTE_HIDDEN;
  1457                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1457 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1458                       attr |= FILE_ATTRIBUTE_READONLY;
  1458 		      attr |= FILE_ATTRIBUTE_READONLY;
  1459                   } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1459 		  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1460                       attr |= FILE_FLAG_WRITE_THROUGH;
  1460 		      attr |= FILE_FLAG_WRITE_THROUGH;
  1461                   } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1461 		  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1462                       attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  1462 		      attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  1463                   } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1463 		  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1464                       attr |= FILE_FLAG_DELETE_ON_CLOSE;
  1464 		      attr |= FILE_FLAG_DELETE_ON_CLOSE;
  1465                   } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1465 		  } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1466                       __openmode = __stringVal(attrSym);
  1466 		      __openmode = __stringVal(attrSym);
  1467                   } else {
  1467 		  } else {
  1468                       console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1468 		      console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
  1469                   }
  1469 		  }
  1470               }
  1470 	      }
  1471           }
  1471 	  }
  1472           if (create == 0) {
  1472 	  if (create == 0) {
  1473 //              argumentError = @symbol(missingCreateMode);
  1473 //              argumentError = @symbol(missingCreateMode);
  1474               goto badArgument;
  1474 	      goto badArgument;
  1475           }
  1475 	  }
  1476           if (attr == 0) {
  1476 	  if (attr == 0) {
  1477               attr = FILE_ATTRIBUTE_NORMAL;
  1477 	      attr = FILE_ATTRIBUTE_NORMAL;
  1478           }
  1478 	  }
  1479 
  1479 
  1480           /*
  1480 	  /*
  1481            * create security attributes - make handle inheritable by subprocesses
  1481 	   * create security attributes - make handle inheritable by subprocesses
  1482            */
  1482 	   */
  1483           memset(&sa, 0, sizeof (sa));
  1483 	  memset(&sa, 0, sizeof (sa));
  1484           sa.nLength = sizeof( sa );
  1484 	  sa.nLength = sizeof( sa );
  1485           sa.bInheritHandle = TRUE;
  1485 	  // sa.bInheritHandle = TRUE;
  1486 
  1486 	  sa.bInheritHandle = FALSE;
  1487           if (__isStringLike(pathName)) {
  1487 
  1488                 char _aPathName[MAXPATHLEN];
  1488 	  if (__isStringLike(pathName)) {
  1489 
  1489 		char _aPathName[MAXPATHLEN];
  1490                 strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1490 
  1491                 do {
  1491 		strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1492                     __threadErrno = 0;
  1492 		do {
  1493                     handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1493 		    __threadErrno = 0;
  1494                     if (__threadErrno == EINTR) {
  1494 		    handle = STX_API_NOINT_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1495                         handle = INVALID_HANDLE_VALUE;
  1495 		    if (__threadErrno == EINTR) {
  1496                     }
  1496 			handle = INVALID_HANDLE_VALUE;
  1497                 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1497 		    }
  1498           } else if (__isUnicode16String(pathName)) {
  1498 		} while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1499                 wchar_t _aPathName[MAXPATHLEN+1];
  1499 	  } else if (__isUnicode16String(pathName)) {
  1500                 int i, l;
  1500 		wchar_t _aPathName[MAXPATHLEN+1];
  1501 
  1501 		int i, l;
  1502                 l = __unicode16StringSize(pathName);
  1502 
  1503                 if (l > MAXPATHLEN) l = MAXPATHLEN;
  1503 		l = __unicode16StringSize(pathName);
  1504                 for (i=0; i<l; i++) {
  1504 		if (l > MAXPATHLEN) l = MAXPATHLEN;
  1505                     _aPathName[i] = __unicode16StringVal(pathName)[i];
  1505 		for (i=0; i<l; i++) {
  1506                 }
  1506 		    _aPathName[i] = __unicode16StringVal(pathName)[i];
  1507                 _aPathName[i] = 0;
  1507 		}
  1508 
  1508 		_aPathName[i] = 0;
  1509                 do {
  1509 
  1510                     __threadErrno = 0;
  1510 		do {
  1511                     handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1511 		    __threadErrno = 0;
  1512                     if (__threadErrno == EINTR) {
  1512 		    handle = STX_API_NOINT_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, &sa, create, attr, 0 /* hTempl */);
  1513                         handle = INVALID_HANDLE_VALUE;
  1513 		    if (__threadErrno == EINTR) {
  1514                     }
  1514 			handle = INVALID_HANDLE_VALUE;
  1515                 } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1515 		    }
  1516           }
  1516 		} while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
  1517           if (handle != INVALID_HANDLE_VALUE) {
  1517 	  }
  1518               int fd;
  1518 	  if (handle != INVALID_HANDLE_VALUE) {
  1519               extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical();
  1519 	      int fd;
  1520 
  1520 	      extern void __stxWrapApiEnterCritical(), __stxWrapApiLeaveCritical();
  1521               __stxWrapApiEnterCritical();
  1521 
  1522               fd = _open_osfhandle((long)handle, O_BINARY);
  1522 	      __stxWrapApiEnterCritical();
  1523               if (fd < 0) {
  1523 	      fd = _open_osfhandle((long)handle, O_BINARY);
  1524                   if (__threadErrno == 0) {
  1524 	      if (fd < 0) {
  1525                       // no more file descriptors
  1525 		  if (__threadErrno == 0) {
  1526                       __threadErrno = EMFILE;
  1526 		      // no more file descriptors
  1527                   }
  1527 		      __threadErrno = EMFILE;
  1528                   CloseHandle(handle);
  1528 		  }
  1529               } else {
  1529 		  CloseHandle(handle);
  1530                   f = fdopen(fd, __openmode);
  1530 	      } else {
  1531               }
  1531 		  f = fdopen(fd, __openmode);
  1532               __stxWrapApiLeaveCritical();
  1532 	      }
  1533           }  else {
  1533 	      __stxWrapApiLeaveCritical();
  1534             __threadErrno = __WIN32_ERR(GetLastError());
  1534 	  }  else {
  1535           }
  1535 	    __threadErrno = __WIN32_ERR(GetLastError());
       
  1536 	  }
  1536       }
  1537       }
  1537 # else /* not WIN32 */
  1538 # else /* not WIN32 */
  1538 
  1539 
  1539       if (__isStringLike(encodedPathName)) {
  1540       if (__isStringLike(encodedPathName)) {
  1540           int accessMode = 0666;        // default access mode of fopen(), relies on umask()
  1541 	  int accessMode = 0666;        // default access mode of fopen(), relies on umask()
  1541           int flags = 0;
  1542 	  int flags = 0;
  1542           int fd;
  1543 	  int fd;
  1543           char * __openmode;
  1544 	  char * __openmode;
  1544 
  1545 
  1545           if (__isStringLike(openmode)) {
  1546 	  if (__isStringLike(openmode)) {
  1546               __openmode = __stringVal(openmode);
  1547 	      __openmode = __stringVal(openmode);
  1547               if (strcmp(__openmode, "r") == 0) {
  1548 	      if (strcmp(__openmode, "r") == 0) {
  1548                   flags = O_RDONLY;
  1549 		  flags = O_RDONLY;
  1549               } else if (strcmp(__openmode, "r+") == 0) {
  1550 	      } else if (strcmp(__openmode, "r+") == 0) {
  1550                   flags = O_RDWR;
  1551 		  flags = O_RDWR;
  1551               } else if (strcmp(__openmode, "w") == 0) {
  1552 	      } else if (strcmp(__openmode, "w") == 0) {
  1552                   flags = O_WRONLY | O_CREAT | O_TRUNC;
  1553 		  flags = O_WRONLY | O_CREAT | O_TRUNC;
  1553               } else if (strcmp(__openmode, "w+") == 0) {
  1554 	      } else if (strcmp(__openmode, "w+") == 0) {
  1554                   flags = O_RDWR | O_CREAT | O_TRUNC;
  1555 		  flags = O_RDWR | O_CREAT | O_TRUNC;
  1555               } else if (strcmp(__openmode, "a") == 0) {
  1556 	      } else if (strcmp(__openmode, "a") == 0) {
  1556                   flags = O_WRONLY | O_CREAT | O_APPEND;
  1557 		  flags = O_WRONLY | O_CREAT | O_APPEND;
  1557               } else if (strcmp(__openmode, "a+") == 0) {
  1558 	      } else if (strcmp(__openmode, "a+") == 0) {
  1558                   flags = O_RDWR | O_CREAT| O_APPEND;
  1559 		  flags = O_RDWR | O_CREAT| O_APPEND;
  1559               } else {
  1560 	      } else {
  1560                   console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1561 		  console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1561               }
  1562 	      }
  1562           } else if (__isArrayLike(openmode)) {
  1563 	  } else if (__isArrayLike(openmode)) {
  1563               OBJ *ap = __arrayVal(openmode);
  1564 	      OBJ *ap = __arrayVal(openmode);
  1564               int numAttrib = __arraySize(openmode);
  1565 	      int numAttrib = __arraySize(openmode);
  1565               int i;
  1566 	      int i;
  1566 
  1567 
  1567               __openmode = "r+";
  1568 	      __openmode = "r+";
  1568 
  1569 
  1569               for (i=0; i<numAttrib; i++) {
  1570 	      for (i=0; i<numAttrib; i++) {
  1570                   OBJ attrSym = ap[i];
  1571 		  OBJ attrSym = ap[i];
  1571 
  1572 
  1572                   if (attrSym == @symbol(FILE_SHARE_READ)) {
  1573 		  if (attrSym == @symbol(FILE_SHARE_READ)) {
  1573                       // ignore
  1574 		      // ignore
  1574                   } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1575 		  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
  1575                      // ignore
  1576 		     // ignore
  1576                   } else if (attrSym == @symbol(GENERIC_READ)) {
  1577 		  } else if (attrSym == @symbol(GENERIC_READ)) {
  1577                       flags |= O_RDONLY;
  1578 		      flags |= O_RDONLY;
  1578                   } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1579 		  } else if (attrSym == @symbol(GENERIC_WRITE)) {
  1579                       flags |= O_WRONLY;
  1580 		      flags |= O_WRONLY;
  1580                   } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1581 		  } else if (attrSym == @symbol(GENERIC_READ_WRITE)) {
  1581                       flags |= O_RDWR;
  1582 		      flags |= O_RDWR;
  1582 
  1583 
  1583                   } else if (attrSym == @symbol(CREATE_NEW)) {
  1584 		  } else if (attrSym == @symbol(CREATE_NEW)) {
  1584                       flags |= O_CREAT|O_EXCL;
  1585 		      flags |= O_CREAT|O_EXCL;
  1585                       accessMode = 0600;     // simulate mkstemp()
  1586 		      accessMode = 0600;     // simulate mkstemp()
  1586                   } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1587 		  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
  1587                       flags |= O_CREAT|O_TRUNC;
  1588 		      flags |= O_CREAT|O_TRUNC;
  1588                   } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1589 		  } else if (attrSym == @symbol(OPEN_EXISTING)) {
  1589                       // nothing to be set
  1590 		      // nothing to be set
  1590                   } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1591 		  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
  1591                       flags |= O_CREAT;
  1592 		      flags |= O_CREAT;
  1592                   } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1593 		  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
  1593                       flags |= O_TRUNC;
  1594 		      flags |= O_TRUNC;
  1594 
  1595 
  1595                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1596 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
  1596                       // ignore
  1597 		      // ignore
  1597                   } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1598 		  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
  1598                       accessMode &= 0444;
  1599 		      accessMode &= 0444;
  1599                   } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1600 		  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
  1600 #ifdef O_DIRECT
  1601 #ifdef O_DIRECT
  1601                       flags |= O_DIRECT;
  1602 		      flags |= O_DIRECT;
  1602 #endif
  1603 #endif
  1603                   } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1604 		  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
  1604                       // ignore
  1605 		      // ignore
  1605                   } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1606 		  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
  1606                       // ignore;
  1607 		      // ignore;
  1607                   } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1608 		  } else if (!__isSymbol(attrSym) && __isStringLike(attrSym)) {
  1608                       __openmode = __stringVal(attrSym);
  1609 		      __openmode = __stringVal(attrSym);
  1609                   } else {
  1610 		  } else {
  1610                       console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1611 		      console_fprintf(stderr, "UNIXOS [warning]: unsupported open mode\n");
  1611                   }
  1612 		  }
  1612               }
  1613 	      }
  1613           }
  1614 	  }
  1614           do {
  1615 	  do {
  1615               __BEGIN_INTERRUPTABLE__
  1616 	      __BEGIN_INTERRUPTABLE__
  1616               fd = open((char *) __stringVal(encodedPathName), flags, accessMode);
  1617 	      fd = open((char *) __stringVal(encodedPathName), flags, accessMode);
  1617               __END_INTERRUPTABLE__
  1618 	      __END_INTERRUPTABLE__
  1618           } while ((fd < 0) && (__threadErrno == EINTR));
  1619 	  } while ((fd < 0) && (__threadErrno == EINTR));
  1619 
  1620 
  1620           if (fd >= 0) {
  1621 	  if (fd >= 0) {
  1621               __threadErrno = 0;
  1622 	      __threadErrno = 0;
  1622               f = fdopen(fd, __openmode);
  1623 	      f = fdopen(fd, __openmode);
  1623               if (f == NULL) {
  1624 	      if (f == NULL) {
  1624                   close(fd);            // fdopen failed, close before retry.
  1625 		  close(fd);            // fdopen failed, close before retry.
  1625               }
  1626 	      }
  1626           }
  1627 	  }
  1627       }
  1628       }
  1628 
  1629 
  1629 # endif /* not WIN32 */
  1630 # endif /* not WIN32 */
  1630 #endif /* not VMS */
  1631 #endif /* not VMS */
  1631 
  1632 
  1632 
  1633 
  1633     if (f == NULL) {
  1634     if (f == NULL) {
  1634         /*
  1635 	/*
  1635          * If no filedescriptors available, try to finalize
  1636 	 * If no filedescriptors available, try to finalize
  1636          * possibly collected fd's and try again.
  1637 	 * possibly collected fd's and try again.
  1637          */
  1638 	 */
  1638         if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) {
  1639 	if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) {
  1639             pass = 1;
  1640 	    pass = 1;
  1640             __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1641 	    __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1641             __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1642 	    __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1642             goto retry;
  1643 	    goto retry;
  1643         }
  1644 	}
  1644     badArgument:
  1645     badArgument:
  1645     getOutOfHere:
  1646     getOutOfHere:
  1646         __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  1647 	__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  1647         __INST(position) = nil;
  1648 	__INST(position) = nil;
  1648     } else {
  1649     } else {
  1649 #ifdef __VMS__
  1650 #ifdef __VMS__
  1650         /*
  1651 	/*
  1651          * check to see if this is positionable ...
  1652 	 * check to see if this is positionable ...
  1652          */
  1653 	 */
  1653         __INST(canPosition) = false;
  1654 	__INST(canPosition) = false;
  1654 # ifndef _POSIX_C_SOURCE
  1655 # ifndef _POSIX_C_SOURCE
  1655         {
  1656 	{
  1656             struct stat statBuffer;
  1657 	    struct stat statBuffer;
  1657 
  1658 
  1658             if (fstat(fileno(f), &statBuffer) >= 0) {
  1659 	    if (fstat(fileno(f), &statBuffer) >= 0) {
  1659                 switch (statBuffer.st_fab_rfm) {
  1660 		switch (statBuffer.st_fab_rfm) {
  1660                     case FAB$C_UDF: /* undefined (also stream binary)   */
  1661 		    case FAB$C_UDF: /* undefined (also stream binary)   */
  1661                     case FAB$C_VAR: /* variable length records          */
  1662 		    case FAB$C_VAR: /* variable length records          */
  1662                     case FAB$C_VFC: /* variable fixed control           */
  1663 		    case FAB$C_VFC: /* variable fixed control           */
  1663                     case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */
  1664 		    case FAB$C_STM: /* RMS-11 stream (valid only for sequen) */
  1664                     default:
  1665 		    default:
  1665                         __INST(canPosition) = false;
  1666 			__INST(canPosition) = false;
  1666                         break;
  1667 			break;
  1667 
  1668 
  1668                     case FAB$C_FIX: /* fixed length records             */
  1669 		    case FAB$C_FIX: /* fixed length records             */
  1669                     case FAB$C_STMLF: /* LF stream (valid only for sequential) */
  1670 		    case FAB$C_STMLF: /* LF stream (valid only for sequential) */
  1670                     case FAB$C_STMCR: /* CR stream (valid only for sequential) */
  1671 		    case FAB$C_STMCR: /* CR stream (valid only for sequential) */
  1671                         __INST(canPosition) = true;
  1672 			__INST(canPosition) = true;
  1672                         break;
  1673 			break;
  1673                 }
  1674 		}
  1674             }
  1675 	    }
  1675         }
  1676 	}
  1676 # endif
  1677 # endif
  1677 #else /* not VMS */
  1678 #else /* not VMS */
  1678         __INST(canPosition) = true;
  1679 	__INST(canPosition) = true;
  1679 #endif /* not VMS */
  1680 #endif /* not VMS */
  1680 
  1681 
  1681         if (@global(FileOpenTrace) == true) {
  1682 	if (@global(FileOpenTrace) == true) {
  1682             console_fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f);
  1683 	    console_fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f);
  1683         }
  1684 	}
  1684         if (f != NULL) {
  1685 	if (f != NULL) {
  1685             OBJ fp;
  1686 	    OBJ fp;
  1686 
  1687 
  1687             wasBlocked = __BLOCKINTERRUPTS();
  1688 	    wasBlocked = __BLOCKINTERRUPTS();
  1688 #if 0
  1689 #if 0
  1689             // The original code was:
  1690 	    // The original code was:
  1690             __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp);
  1691 	    __INST(handle) = fp = __MKEXTERNALADDRESS(f); __STORE(self, fp);
  1691             // but for that, gcc generates wrong code, which loads self (volatile) into
  1692 	    // but for that, gcc generates wrong code, which loads self (volatile) into
  1692             // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
  1693 	    // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
  1693             // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
  1694 	    // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
  1694             // object.
  1695 	    // object.
  1695 #else
  1696 #else
  1696             fp = __MKEXTERNALADDRESS(f);
  1697 	    fp = __MKEXTERNALADDRESS(f);
  1697             __INST(handle) = fp;
  1698 	    __INST(handle) = fp;
  1698             __STORE(self, fp);
  1699 	    __STORE(self, fp);
  1699 #endif
  1700 #endif
  1700         }
  1701 	}
  1701     }
  1702     }
  1702 %}.
  1703 %}.
  1703     handle notNil ifTrue:[
  1704     handle notNil ifTrue:[
  1704         position := 0.
  1705 	position := 0.
  1705         handleType := #filePointer.
  1706 	handleType := #filePointer.
  1706         Lobby register:self.
  1707 	Lobby register:self.
  1707         wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts].
  1708 	wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts].
  1708     ].
  1709     ].
  1709     ^ handle
  1710     ^ handle
  1710 !
  1711 !
  1711 
  1712 
  1712 openForAppending
  1713 openForAppending
  1777 
  1778 
  1778     handle notNil ifTrue:[^ self errorAlreadyOpen].
  1779     handle notNil ifTrue:[^ self errorAlreadyOpen].
  1779 
  1780 
  1780     handle := self openFile:pathName withMode:openmode attributes:attributeSpec.
  1781     handle := self openFile:pathName withMode:openmode attributes:attributeSpec.
  1781     handle isNil ifTrue:[
  1782     handle isNil ifTrue:[
  1782         "
  1783 	"
  1783          the open failed for some reason ...
  1784 	 the open failed for some reason ...
  1784         "
  1785 	"
  1785         ^ self openError:lastErrorNumber.
  1786 	^ self openError:lastErrorNumber.
  1786     ].
  1787     ].
  1787     position := 0.
  1788     position := 0.
  1788     buffered isNil ifTrue:[
  1789     buffered isNil ifTrue:[
  1789         buffered := true.       "default is buffered"
  1790 	buffered := true.       "default is buffered"
  1790     ].
  1791     ].
  1791 !
  1792 !
  1792 
  1793 
  1793 pathName:filename
  1794 pathName:filename
  1794     "set the pathname"
  1795     "set the pathname"
  1995 ! !
  1996 ! !
  1996 
  1997 
  1997 !FileStream class methodsFor:'documentation'!
  1998 !FileStream class methodsFor:'documentation'!
  1998 
  1999 
  1999 version
  2000 version
  2000     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.166 2013-07-08 19:22:38 stefan Exp $'
  2001     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.167 2013-07-24 19:56:49 cg Exp $'
  2001 !
  2002 !
  2002 
  2003 
  2003 version_CVS
  2004 version_CVS
  2004     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.166 2013-07-08 19:22:38 stefan Exp $'
  2005     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.167 2013-07-24 19:56:49 cg Exp $'
  2005 ! !
  2006 ! !
  2006 
  2007 
  2007 
  2008 
  2008 FileStream initialize!
  2009 FileStream initialize!