Filename.st
changeset 2922 e9ae6bea98cd
parent 2911 9964e6839a8e
child 2939 b7cebf237308
equal deleted inserted replaced
2921:f42da059311e 2922:e9ae6bea98cd
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 'From Smalltalk/X, Version:3.1.9 on 9-sep-1997 at 10:54:08 pm'                  !
    13 'From Smalltalk/X, Version:3.1.10 on 13-sep-1997 at 10:53:13 pm'                !
    14 
    14 
    15 Object subclass:#Filename
    15 Object subclass:#Filename
    16 	instanceVariableNames:'nameString'
    16 	instanceVariableNames:'nameString'
    17 	classVariableNames:'NextTempFilenameIndex ConcreteClass'
    17 	classVariableNames:'NextTempFilenameIndex ConcreteClass'
    18 	poolDictionaries:''
    18 	poolDictionaries:''
   263         ^ ConcreteClass currentDirectory
   263         ^ ConcreteClass currentDirectory
   264     ].
   264     ].
   265 
   265 
   266     "/ fallBack - works on Unix & MSDOS (but not on VMS)
   266     "/ fallBack - works on Unix & MSDOS (but not on VMS)
   267 
   267 
   268     ^ self named:('.' asFilename pathName)
   268     ^ self named:'.'
       
   269     "/ ^ self named:('.' asFilename pathName)
   269 
   270 
   270     "
   271     "
   271      Filename currentDirectory 
   272      Filename currentDirectory 
   272     "
   273     "
   273 
   274 
   495 
   496 
   496     "Modified: 7.9.1995 / 10:48:31 / claus"
   497     "Modified: 7.9.1995 / 10:48:31 / claus"
   497     "Modified: 8.9.1997 / 00:28:33 / cg"
   498     "Modified: 8.9.1997 / 00:28:33 / cg"
   498 !
   499 !
   499 
   500 
       
   501 rootDirectory
       
   502     "return a filename for the root directory"
       
   503 
       
   504     (self ~~ ConcreteClass) ifTrue:[
       
   505         ^ ConcreteClass rootDirectory
       
   506     ].
       
   507 
       
   508     "/ fallBack - works on Unix & MSDOS (but not on VMS)
       
   509 
       
   510     ^ self named:(self separator asString)
       
   511 
       
   512     "
       
   513      Filename rootDirectory
       
   514     "
       
   515 
       
   516     "Modified: 8.9.1997 / 00:24:15 / cg"
       
   517 !
       
   518 
   500 tempDirectory
   519 tempDirectory
   501     "return the temp directory as a filename.
   520     "return the temp directory as a filename.
   502      If any of the environment variables STX_TMPDIR, ST_TMPDIR,
   521      If any of the environment variables STX_TMPDIR, ST_TMPDIR,
   503      TMPDIR or TEMPDIR is set, its value defines the name, 
   522      TMPDIR or TEMPDIR is set, its value defines the name, 
   504      otherwise, '/tmp' is used. (at least on unix ...).
   523      otherwise, '/tmp' is used. (at least on unix ...).
   551      Since in ST/X, there is (currently) only one Filename class, return it here."
   570      Since in ST/X, there is (currently) only one Filename class, return it here."
   552 
   571 
   553     ^ ConcreteClass
   572     ^ ConcreteClass
   554 
   573 
   555     "Modified: 8.9.1997 / 00:36:01 / cg"
   574     "Modified: 8.9.1997 / 00:36:01 / cg"
       
   575 ! !
       
   576 
       
   577 !Filename class methodsFor:'misc'!
       
   578 
       
   579 canonicalize:aPathString
       
   580     ^ aPathString
       
   581 
       
   582     "Created: 13.9.1997 / 10:50:01 / cg"
   556 ! !
   583 ! !
   557 
   584 
   558 !Filename class methodsFor:'queries'!
   585 !Filename class methodsFor:'queries'!
   559 
   586 
   560 components:aString
   587 components:aString
   767 !
   794 !
   768 
   795 
   769 localNameStringFrom:aString
   796 localNameStringFrom:aString
   770     "ST-80 compatibility.
   797     "ST-80 compatibility.
   771      what does this do ? (used in FileNavigator-goody).
   798      what does this do ? (used in FileNavigator-goody).
   772      GUESS: does it strip off the voulume-character on MSDOS systems ?"
   799      GUESS: 
       
   800 	does it strip off any volume characters and make a path relative ?"
       
   801 
       
   802     |sep|
   773 
   803 
   774     (self ~~ ConcreteClass) ifTrue:[
   804     (self ~~ ConcreteClass) ifTrue:[
   775         ^ ConcreteClass localNameStringFrom:aString
   805         ^ ConcreteClass localNameStringFrom:aString
   776     ].
   806     ].
   777 
   807 
   778     (aString startsWith:'/') ifTrue:[
   808     sep := self separator asString.
   779         ^ aString copyFrom:2
   809     (aString startsWith:sep) ifTrue:[
       
   810 	^ aString copyFrom:sep size + 1
   780     ].
   811     ].
   781     ^ aString
   812     ^ aString
   782 
   813 
   783     "Modified: 7.9.1995 / 10:44:56 / claus"
   814     "Modified: 7.9.1995 / 10:44:56 / claus"
   784     "Modified: 8.9.1997 / 00:33:51 / cg"
   815     "Modified: 8.9.1997 / 00:33:51 / cg"
   944 
   975 
   945     "
   976     "
   946      actually, in Unix spaces are allowed - but it makes life
   977      actually, in Unix spaces are allowed - but it makes life
   947      so hard; therefore, replace them by underscores ...
   978      so hard; therefore, replace them by underscores ...
   948     "
   979     "
   949     nameString replaceAll:(Character space) by:$_.
   980     nameString replaceAll:(Character space) with:$_.
   950     "
   981     "
   951      need more - especially on SYS5.3 type systems, 
   982      need more - especially on SYS5.3 type systems, 
   952      we may want to contract the fileName to 14 characters.
   983      we may want to contract the fileName to 14 characters.
   953     "
   984     "
   954     ^ self
   985     ^ self
  1024 
  1055 
  1025 appendingWriteStream
  1056 appendingWriteStream
  1026     "return a stream for appending to the file represented by the receiver.
  1057     "return a stream for appending to the file represented by the receiver.
  1027      If the file does not already exist, it is created."
  1058      If the file does not already exist, it is created."
  1028 
  1059 
  1029     ^ FileStream appendingOldFileNamed:nameString 
  1060     ^ FileStream appendingOldFileNamed:(self osNameForFile)
  1030 !
  1061 !
  1031 
  1062 
  1032 newReadWriteStream
  1063 newReadWriteStream
  1033     "return a stream for read/write the file represented by the receiver.
  1064     "return a stream for read/write the file represented by the receiver.
  1034      If the file does not already exist, it is created."
  1065      If the file does not already exist, it is created."
  1035 
  1066 
  1036     ^ FileStream newFileNamed:nameString
  1067     ^ FileStream newFileNamed:(self osNameForFile)
  1037 !
  1068 !
  1038 
  1069 
  1039 readStream
  1070 readStream
  1040     "return a stream for reading from the file represented by the receiver.
  1071     "return a stream for reading from the file represented by the receiver.
  1041      If the file does not already exist, nil is returned."
  1072      If the file does not already exist, nil is returned."
  1042 
  1073 
  1043     ^ FileStream readonlyFileNamed:nameString
  1074     ^ FileStream readonlyFileNamed:(self osNameForFile)
  1044 
  1075 
  1045     "
  1076     "
  1046      '/tmp/foo' asFilename readStream 
  1077      '/tmp/foo' asFilename readStream 
  1047     "
  1078     "
  1048 !
  1079 !
  1070 addAccessRights:aCollection
  1101 addAccessRights:aCollection
  1071     "add the access rights as specified in aCollection for the file represented
  1102     "add the access rights as specified in aCollection for the file represented
  1072      by the receiver. The argument must be a collection of symbols,
  1103      by the receiver. The argument must be a collection of symbols,
  1073      such as #readUser, #writeGroup etc."
  1104      such as #readUser, #writeGroup etc."
  1074 
  1105 
  1075     |access|
  1106     |access osName|
  1076 
  1107 
  1077     access := OperatingSystem accessModeOf:nameString.
  1108     osName := self osNameForFile.
       
  1109     access := OperatingSystem accessModeOf:osName.
  1078     aCollection do:[:accessSymbol |
  1110     aCollection do:[:accessSymbol |
  1079 	access := access bitOr:(OperatingSystem accessMaskFor:accessSymbol).
  1111 	access := access bitOr:(OperatingSystem accessMaskFor:accessSymbol).
  1080     ].
  1112     ].
  1081     (OperatingSystem changeAccessModeOf:nameString to:access) ifFalse:[
  1113     (OperatingSystem changeAccessModeOf:osName to:access) ifFalse:[
  1082 	^ self accessDeniedError:self
  1114 	^ self accessDeniedError:self
  1083     ]
  1115     ]
  1084 
  1116 
  1085     "
  1117     "
  1086      'foo' asFilename writeStream close.
  1118      'foo' asFilename writeStream close.
  1131 
  1163 
  1132 makeDirectory
  1164 makeDirectory
  1133     "create a directory with the receivers name.
  1165     "create a directory with the receivers name.
  1134      Return true if successful, false if not."
  1166      Return true if successful, false if not."
  1135 
  1167 
  1136     (OperatingSystem createDirectory:nameString) ifFalse:[
  1168     (OperatingSystem createDirectory:(self osNameForDirectory)) ifFalse:[
  1137 	(self exists and:[self isDirectory]) ifFalse:[
  1169 	(self exists and:[self isDirectory]) ifFalse:[
  1138 	    ^ self fileCreationError:self
  1170 	    ^ self fileCreationError:self
  1139 	]
  1171 	]
  1140     ]
  1172     ]
  1141 
  1173 
  1202 recursiveMakeDirectory
  1234 recursiveMakeDirectory
  1203     "create a directory with the receivers name and all required intermediate
  1235     "create a directory with the receivers name and all required intermediate
  1204      directories.
  1236      directories.
  1205      Raise an error if not successful."
  1237      Raise an error if not successful."
  1206 
  1238 
  1207     (OperatingSystem recursiveCreateDirectory:nameString) ifFalse:[
  1239     (OperatingSystem recursiveCreateDirectory:(self osNameForDirectory)) ifFalse:[
  1208 	^ self fileCreationError:self
  1240 	^ self fileCreationError:self
  1209     ]
  1241     ]
  1210 
  1242 
  1211     "Created: 27.11.1995 / 23:36:40 / cg"
  1243     "Created: 27.11.1995 / 23:36:40 / cg"
  1212 !
  1244 !
  1215     "remove the directory and all of its subfiles/subdirectories.
  1247     "remove the directory and all of its subfiles/subdirectories.
  1216      Raise an error if not successful."
  1248      Raise an error if not successful."
  1217 
  1249 
  1218     |ok|
  1250     |ok|
  1219 
  1251 
  1220     ok := OperatingSystem recursiveRemoveDirectory:nameString.
  1252     ok := OperatingSystem recursiveRemoveDirectory:(self osNameForDirectory).
  1221     ok ifFalse:[
  1253     ok ifFalse:[
  1222 	self removeError:self
  1254 	self removeError:self
  1223     ].
  1255     ].
  1224 
  1256 
  1225     "
  1257     "
  1247 
  1279 
  1248     |ok|
  1280     |ok|
  1249 
  1281 
  1250     self exists ifFalse:[ ^ self].
  1282     self exists ifFalse:[ ^ self].
  1251     self isDirectory ifTrue:[
  1283     self isDirectory ifTrue:[
  1252 	ok := OperatingSystem removeDirectory:nameString
  1284 	ok := OperatingSystem removeDirectory:(self osNameForFile)
  1253     ] ifFalse:[
  1285     ] ifFalse:[
  1254 	ok := OperatingSystem removeFile:nameString
  1286 	ok := OperatingSystem removeFile:(self osNameForFile)
  1255     ].
  1287     ].
  1256     ok ifFalse:[
  1288     ok ifFalse:[
  1257 	self removeError:self
  1289 	self removeError:self
  1258     ].
  1290     ].
  1259 
  1291 
  1277     "remove the access rights as specified in aCollection for the file represented
  1309     "remove the access rights as specified in aCollection for the file represented
  1278      by the receiver. The argument must be a collection of symbols,
  1310      by the receiver. The argument must be a collection of symbols,
  1279      such as #readUser, #writeGroup etc.
  1311      such as #readUser, #writeGroup etc.
  1280      Raise an error if not successful."
  1312      Raise an error if not successful."
  1281 
  1313 
  1282     |access|
  1314     |access osName|
  1283 
  1315 
  1284     access := OperatingSystem accessModeOf:nameString.
  1316     osName := self osNameForFile.
       
  1317     access := OperatingSystem accessModeOf:osName.
  1285     aCollection do:[:accessSymbol |
  1318     aCollection do:[:accessSymbol |
  1286 	access := access bitAnd:(OperatingSystem accessMaskFor:accessSymbol) bitInvert.
  1319 	access := access bitAnd:(OperatingSystem accessMaskFor:accessSymbol) bitInvert.
  1287     ].
  1320     ].
  1288     (OperatingSystem changeAccessModeOf:nameString to:access) ifFalse:[
  1321     (OperatingSystem changeAccessModeOf:osName to:access) ifFalse:[
  1289 	^ self accessDeniedError:self
  1322 	^ self accessDeniedError:self
  1290     ].
  1323     ].
  1291 
  1324 
  1292     "
  1325     "
  1293      'foo' asFilename writeStream close.
  1326      'foo' asFilename writeStream close.
  1299 
  1332 
  1300 renameTo:newName
  1333 renameTo:newName
  1301     "rename the file - the argument must be convertable to a String.
  1334     "rename the file - the argument must be convertable to a String.
  1302      Raise an error if not successful."
  1335      Raise an error if not successful."
  1303 
  1336 
  1304     |ok|
  1337     (OperatingSystem 
  1305 
  1338 	renameFile:(self osNameForFile) 
  1306     ok := OperatingSystem renameFile:nameString to:(newName asString).
  1339 	to:(newName asFilename osNameForFile)
  1307     ok ifFalse:[
  1340     ) ifFalse:[
  1308 	self exists ifFalse:[
  1341 	self exists ifFalse:[
  1309 	    ^ self fileNotFoundError:self
  1342 	    ^ self fileNotFoundError:self
  1310 	].
  1343 	].
  1311 	^ self accessDeniedError:newName asFilename.
  1344 	^ self accessDeniedError:newName asFilename.
  1312     ].
  1345     ].
  1318 
  1351 
  1319 truncateTo:newSize
  1352 truncateTo:newSize
  1320     "change the files size.
  1353     "change the files size.
  1321      This may not be supported on all operating systems"
  1354      This may not be supported on all operating systems"
  1322 
  1355 
  1323     (OperatingSystem truncateFile:nameString to:newSize) ifFalse:[
  1356     (OperatingSystem truncateFile:(self osNameForFile) to:newSize) ifFalse:[
  1324 	^ self reportError:'unsupported operation' with:self
  1357 	^ self reportError:'unsupported operation' with:self
  1325     ]
  1358     ]
  1326 
  1359 
  1327     "
  1360     "
  1328      |s|
  1361      |s|
  1354 dates
  1387 dates
  1355     "return the files modification and access times as an object (currently a dictionary)
  1388     "return the files modification and access times as an object (currently a dictionary)
  1356      that responds to the at: message with arguments 
  1389      that responds to the at: message with arguments 
  1357      #modified, #accessed or #statusChanged."
  1390      #modified, #accessed or #statusChanged."
  1358 
  1391 
  1359     |info dates|
  1392     |info dates osName|
  1360 
  1393 
  1361     info := OperatingSystem infoOf:nameString.
  1394     osName := self osNameForFile.
       
  1395     info := OperatingSystem infoOf:osName.
  1362     info isNil ifTrue:[
  1396     info isNil ifTrue:[
  1363 	info := OperatingSystem linkInfoOf:nameString.
  1397 	info := OperatingSystem linkInfoOf:osName.
  1364 	info isNil ifTrue:[
  1398 	info isNil ifTrue:[
  1365 	    ^ nil
  1399 	    ^ nil
  1366 	]
  1400 	]
  1367     ].
  1401     ].
  1368     dates := IdentityDictionary new.
  1402     dates := IdentityDictionary new.
  1393 
  1427 
  1394 fileType
  1428 fileType
  1395     "this returns a string describing the type of contents of
  1429     "this returns a string describing the type of contents of
  1396      the file. This is done using the unix 'file' command,
  1430      the file. This is done using the unix 'file' command,
  1397      (which usually is configurable by /etc/magic).
  1431      (which usually is configurable by /etc/magic).
  1398      On non-unix systems, this may return an empty string, not knowning
  1432      On non-unix systems, this may return simply 'file', 
  1399      about the contents.
  1433      not knowning about the contents.
  1400      Since the returned string differs among systems (and language settings),
  1434      Warning:
  1401      it is only useful for user-information; NOT as a tag to be used by a program."
  1435          Since the returned string differs among systems (and language settings),
  1402 
  1436          it is only useful for user-information; NOT as a tag to be used by a program."
  1403     |buffer s n typeString suffix idx baseNm|
  1437 
       
  1438     |buffer s n suffix idx baseNm|
  1404 
  1439 
  1405     "/ since executing 'file' takes some time, do the most obvious
  1440     "/ since executing 'file' takes some time, do the most obvious
  1406     "/ ones here. 
  1441     "/ ones here. 
  1407     "/ (also useful for systems, which have no file command, such as NT)
  1442     "/ (also useful for systems, which have no file command, such as NT)
  1408 
  1443 
  1415         ^ 'directory'
  1450         ^ 'directory'
  1416     ].
  1451     ].
  1417     self isReadable ifFalse:[^ 'unreadable'].
  1452     self isReadable ifFalse:[^ 'unreadable'].
  1418     self fileSize == 0 ifTrue:[^ 'empty'].
  1453     self fileSize == 0 ifTrue:[^ 'empty'].
  1419 
  1454 
  1420     buffer := String new:2024.
  1455     suffix := self suffix asLowercase.
  1421     s := self readStream.
  1456     baseNm := self withoutSuffix baseName asLowercase.
  1422     s notNil ifTrue:[
  1457 
  1423         n := s nextBytes:buffer size into:buffer.
  1458     ((#('st' 'rc' 'chg' 'htm' 'html' 'ps') includes:suffix)
  1424         s close.
  1459     or:[#('makefile') includes:baseNm]) ifTrue:[
  1425 
  1460 
  1426         true "n == buffer size" ifTrue:[
  1461         buffer := String new:2024.
  1427             ((suffix := self suffix asLowercase) = 'st') ifTrue:[
  1462         s := self readStream.
       
  1463         s notNil ifTrue:[
       
  1464             n := s nextBytes:buffer size into:buffer.
       
  1465             s close.
       
  1466 
       
  1467             (suffix = 'st') ifTrue:[
  1428                 (buffer findString:'subclass:') ~~ 0 ifTrue:[
  1468                 (buffer findString:'subclass:') ~~ 0 ifTrue:[
  1429                     ^ 'smalltalk source'
  1469                     ^ 'smalltalk source'
  1430                 ].
  1470                 ].
  1431                 (buffer findString:'methodsFor:') ~~ 0 ifTrue:[
  1471                 (buffer findString:'methodsFor:') ~~ 0 ifTrue:[
  1432                     ^ 'smalltalk source'
  1472                     ^ 'smalltalk source'
  1440             (suffix = 'rc') ifTrue:[
  1480             (suffix = 'rc') ifTrue:[
  1441                 (buffer findString:'ST/X startup') ~~ 0 ifTrue:[
  1481                 (buffer findString:'ST/X startup') ~~ 0 ifTrue:[
  1442                     ^ 'smalltalk startup script'
  1482                     ^ 'smalltalk startup script'
  1443                 ].
  1483                 ].
  1444             ].
  1484             ].
       
  1485 
  1445             (suffix = 'htm' or:[suffix = 'html']) ifTrue:[
  1486             (suffix = 'htm' or:[suffix = 'html']) ifTrue:[
  1446                 (idx := buffer findString:'<H') ~~ 0 ifTrue:[
  1487                 (idx := buffer findString:'<H') ~~ 0 ifTrue:[
  1447                     ((buffer continuesWith:'<HEAD' startingAt:idx)
  1488                     ((buffer continuesWith:'<HEAD' startingAt:idx)
  1448                     or:[(buffer continuesWith:'<HTML' startingAt:idx)
  1489                     or:[(buffer continuesWith:'<HTML' startingAt:idx)
  1449                     or:[(buffer continuesWith:'<H1' startingAt:idx)
  1490                     or:[(buffer continuesWith:'<H1' startingAt:idx)
  1462                 (buffer findString:'%!!PS-Adobe') ~~ 0 ifTrue:[
  1503                 (buffer findString:'%!!PS-Adobe') ~~ 0 ifTrue:[
  1463                     ^ 'PostScript document'
  1504                     ^ 'PostScript document'
  1464                 ].
  1505                 ].
  1465             ].
  1506             ].
  1466 
  1507 
  1467             baseNm := self withoutSuffix baseName asLowercase.
       
  1468             (baseNm = 'makefile') ifTrue:[
  1508             (baseNm = 'makefile') ifTrue:[
  1469                 (buffer startsWith:'#') ifTrue:[
  1509                 (buffer startsWith:'#') ifTrue:[
  1470                     ^ 'make rules'
  1510                     ^ 'make rules'
  1471                 ]
  1511                 ]
  1472             ]
  1512 	    ]
  1473         ]
  1513         ]
  1474     ].
  1514     ].
  1475 
  1515 
  1476     ^ 'file'
  1516     ^ 'file'
  1477 
  1517 
  1487 !
  1527 !
  1488 
  1528 
  1489 id
  1529 id
  1490     "return the files/directories file-id (inode number)"
  1530     "return the files/directories file-id (inode number)"
  1491 
  1531 
  1492     ^ OperatingSystem idOf:(self pathName)
  1532     ^ OperatingSystem idOf:(self osNameForFile)
  1493 
  1533 
  1494     "
  1534     "
  1495      Filename currentDirectory id 
  1535      Filename currentDirectory id 
  1496     "
  1536     "
  1497 
  1537 
  1525      to either handle nil values,
  1565      to either handle nil values,
  1526      or (better) use one of isXXXX query methods. (Be prepared for DOS ...)
  1566      or (better) use one of isXXXX query methods. (Be prepared for DOS ...)
  1527      (i.e. instead of:
  1567      (i.e. instead of:
  1528 	someFilename type == #directory
  1568 	someFilename type == #directory
  1529       use
  1569       use
  1530 	someFIlename isDirectory
  1570 	someFilename isDirectory
  1531     "
  1571     "
  1532 
  1572 
  1533     ^ OperatingSystem infoOf:nameString
  1573     ^ OperatingSystem infoOf:(self osNameForFile)
  1534 
  1574 
  1535     "
  1575     "
  1536      Filename currentDirectory info
  1576      Filename currentDirectory info
  1537      '/dev/null' asFilename info 
  1577      '/dev/null' asFilename info 
  1538      'Make.proto' asFilename info
  1578      'Make.proto' asFilename info
  1556      In addition to the normal entries, Unix returns an additional entry:
  1596      In addition to the normal entries, Unix returns an additional entry:
  1557 	 path -> the target files pathname
  1597 	 path -> the target files pathname
  1558 
  1598 
  1559      See the comment in #info for more details."
  1599      See the comment in #info for more details."
  1560 
  1600 
  1561     ^ OperatingSystem linkInfoOf:nameString
  1601     ^ OperatingSystem linkInfoOf:(self osNameForFile)
  1562 
  1602 
  1563     "
  1603     "
  1564      Filename currentDirectory linkInfo 
  1604      Filename currentDirectory linkInfo 
  1565      '/dev/null' asFilename linkInfo    
  1605      '/dev/null' asFilename linkInfo    
  1566      'Make.proto' asFilename linkInfo   
  1606      'Make.proto' asFilename linkInfo   
  1585 !
  1625 !
  1586 
  1626 
  1587 type
  1627 type
  1588     "return the symbolic type of the file"
  1628     "return the symbolic type of the file"
  1589 
  1629 
  1590     ^ OperatingSystem typeOf:(self pathName)
  1630     ^ OperatingSystem typeOf:(self osNameForFile)
  1591 
  1631 
  1592     "
  1632     "
  1593      Filename currentDirectory type 
  1633      Filename currentDirectory type 
  1594     "
  1634     "
  1595 
  1635 
  1619 
  1659 
  1620 construct:subname
  1660 construct:subname
  1621     "taking the receiver as a directory name, construct a new
  1661     "taking the receiver as a directory name, construct a new
  1622      filename for an entry within this directory 
  1662      filename for an entry within this directory 
  1623      (i.e. for a file or a subdirectory in that directory).
  1663      (i.e. for a file or a subdirectory in that directory).
  1624      See also: #withSuffix: (which is different, but often needed)"
  1664      The argument may not specify an absolute path name.
       
  1665      Please do not use this to create filenames with suffixes,
       
  1666      since some systems require special naming conventions.
       
  1667      See also: #withSuffix: (which is different, but often needed)."
  1625 
  1668 
  1626     ^ self class named:(self constructString:subname)
  1669     ^ self class named:(self constructString:subname)
  1627 
  1670 
  1628     "
  1671     "
  1629      '/tmp' asFilename construct:'foo'    
  1672      '/tmp' asFilename construct:'foo'    
  1630      '/' asFilename construct:'foo'         
  1673      '/' asFilename construct:'foo'         
  1631      '/usr/tmp' asFilename construct:'foo'
  1674      '/usr/tmp' asFilename construct:'foo'
  1632      '/foo/bar' asFilename construct:'baz' 
  1675      '/foo/bar' asFilename construct:'baz' 
       
  1676 
       
  1677      Bad example; works on UNIX, but may not on others:
       
  1678        'foo/bar.baz' construct:'.suff'
  1633     "
  1679     "
  1634 
  1680 
  1635     "Modified: 29.2.1996 / 20:55:06 / cg"
  1681     "Modified: 29.2.1996 / 20:55:06 / cg"
  1636 !
  1682 !
  1637 
  1683 
  1638 constructString:subname
  1684 constructDirectory:subname
       
  1685     "same as #construct: on most systems.
       
  1686      (may allow different/relaxed name syntax of the argument on some systems)"
       
  1687      
       
  1688     ^ self class named:(self constructDirectoryString:subname)
       
  1689 !
       
  1690 
       
  1691 constructDirectoryString:subName
       
  1692     "same as #constructString: on most systems.
       
  1693      (may allow different/relaxed name syntax of the argument on some systems)"
       
  1694 
       
  1695     ^ self constructString:subName
       
  1696 !
       
  1697 
       
  1698 constructString:subName
  1639     "taking the receiver as a directory name, construct a new
  1699     "taking the receiver as a directory name, construct a new
  1640      filename-string for an entry within this directory 
  1700      filename-string for an entry within this directory 
  1641      (i.e. for a file or a subdirectory in that directory)."
  1701      (i.e. for a file or a subdirectory in that directory).
       
  1702      The argument may not specify an absolute path name."
  1642 
  1703 
  1643     |sepString|
  1704     |sepString|
  1644 
  1705 
  1645     sepString := self class separator asString.
  1706     sepString := self class separator asString.
  1646     nameString = sepString ifTrue:[
  1707     nameString = sepString ifTrue:[
  1647 	"I am the root"
  1708 	"I am the root"
  1648 	^ sepString  , subname
  1709 	^ sepString  , subName asString
  1649     ].
  1710     ].
  1650     ^ nameString , sepString , subname asString
  1711     ^ nameString , sepString , subName asString
  1651 
  1712 
  1652     "
  1713     "
  1653      '/tmp' asFilename constructString:'foo'   
  1714      '/tmp' asFilename constructString:'foo'   
  1654      '/' asFilename constructString:'foo'         
  1715      '/' asFilename constructString:'foo'         
  1655      '/usr/tmp' asFilename constructString:'foo'
  1716      '/usr/tmp' asFilename constructString:'foo'
  1728 !
  1789 !
  1729 
  1790 
  1730 exists
  1791 exists
  1731     "return true, if such a file exists."
  1792     "return true, if such a file exists."
  1732 
  1793 
  1733     ^ OperatingSystem isValidPath:nameString
  1794     ^ OperatingSystem isValidPath:(self osNameForFile)
  1734 
  1795 
  1735     "
  1796     "
  1736      '/foo/bar' asFilename exists 
  1797      '/foo/bar' asFilename exists 
  1737      '/tmp' asFilename exists  
  1798      '/tmp' asFilename exists  
  1738      'Makefile' asFilename exists   
  1799      'Makefile' asFilename exists   
  1805 
  1866 
  1806 isDirectory
  1867 isDirectory
  1807     "return true, if the receiver represents an existing,
  1868     "return true, if the receiver represents an existing,
  1808      readable directories pathname."
  1869      readable directories pathname."
  1809 
  1870 
  1810     ^ OperatingSystem isDirectory:nameString
  1871     ^ OperatingSystem isDirectory:(self osNameForFile)
  1811 
  1872 
  1812     "
  1873     "
  1813      '/foo/bar' asFilename isDirectory
  1874      '/foo/bar' asFilename isDirectory
  1814      '/tmp' asFilename isDirectory
  1875      '/tmp' asFilename isDirectory
  1815      'Makefile' asFilename isDirectory   
  1876      'Makefile' asFilename isDirectory   
  1819 isExecutable
  1880 isExecutable
  1820     "return true, if such a file exists and is executable (by Unix's definition).
  1881     "return true, if such a file exists and is executable (by Unix's definition).
  1821      For directories, true is returned if the directory can be entered.
  1882      For directories, true is returned if the directory can be entered.
  1822      See isExecutableProgram for a related check."
  1883      See isExecutableProgram for a related check."
  1823 
  1884 
  1824     ^ OperatingSystem isExecutable:nameString
  1885     ^ OperatingSystem isExecutable:(self osNameForFile)
  1825 
  1886 
  1826     "
  1887     "
  1827      '/foo/bar' asFilename isExecutable 
  1888      '/foo/bar' asFilename isExecutable 
  1828      '/tmp' asFilename isExecutable   
  1889      '/tmp' asFilename isExecutable   
  1829      'Makefile' asFilename isExecutable   
  1890      'Makefile' asFilename isExecutable   
  1833 
  1894 
  1834 isExecutableProgram
  1895 isExecutableProgram
  1835     "return true, if such a file exists and is an executable program.
  1896     "return true, if such a file exists and is an executable program.
  1836      (i.e. for directories, false is returned.)"
  1897      (i.e. for directories, false is returned.)"
  1837 
  1898 
  1838     ^ (OperatingSystem isExecutable:nameString)
  1899     |osName|
  1839       and:[(OperatingSystem isDirectory:nameString) not]
  1900 
       
  1901     osName := self osNameForFile.
       
  1902     ^ (OperatingSystem isExecutable:osName)
       
  1903       and:[(OperatingSystem isDirectory:osName) not]
  1840 
  1904 
  1841     "
  1905     "
  1842      '/tmp' asFilename isExecutable         
  1906      '/tmp' asFilename isExecutable         
  1843      '/bin/ls' asFilename isExecutable       
  1907      '/bin/ls' asFilename isExecutable       
  1844      '/tmp' asFilename isExecutableProgram   
  1908      '/tmp' asFilename isExecutableProgram   
  1845      '/bin/ls' asFilename isExecutableProgram    
  1909      '/bin/ls' asFilename isExecutableProgram    
  1846     "
  1910     "
  1847 !
  1911 !
  1848 
  1912 
       
  1913 isExplicitRelative
       
  1914     "return true, if this name is an explicit relative name
       
  1915      (i.e. starts with './' or '../', to avoid path-prepending)"
       
  1916 
       
  1917     ^ false
       
  1918 !
       
  1919 
       
  1920 isHidden
       
  1921     "return true, if the receiver represents a hidden file.
       
  1922      The definitions of hidden files depends on the OS used;
       
  1923      on UNIX, a name starting with a period is considered hidden;
       
  1924      on MSDOS, the files hidden attribute is used.
       
  1925      VMS has no concept of hidden files."
       
  1926 
       
  1927     ^ false
       
  1928 !
       
  1929 
  1849 isReadable
  1930 isReadable
  1850     "return true, if such a file exists and is readable."
  1931     "return true, if such a file exists and is readable."
  1851 
  1932 
  1852     ^ OperatingSystem isReadable:nameString
  1933     ^ OperatingSystem isReadable:(self osNameForFile)
  1853 
  1934 
  1854     "
  1935     "
  1855      '/foo/bar' asFilename isReadable   
  1936      '/foo/bar' asFilename isReadable   
  1856      '/tmp' asFilename isReadable      
  1937      '/tmp' asFilename isReadable      
  1857      'Makefile' asFilename isReadable   
  1938      'Makefile' asFilename isReadable   
  1877 isSymbolicLink
  1958 isSymbolicLink
  1878     "return true, if the file represented by the receiver is a symbolic
  1959     "return true, if the file represented by the receiver is a symbolic
  1879      link. Notice that not all OS's support symbolic links; those that do
  1960      link. Notice that not all OS's support symbolic links; those that do
  1880      not will always return false."
  1961      not will always return false."
  1881 
  1962 
  1882     ^ OperatingSystem isSymbolicLink:nameString
  1963     ^ OperatingSystem isSymbolicLink:(self osNameForFile)
  1883 
  1964 
  1884     "
  1965     "
  1885      'Make.proto' asFilename isSymbolicLink  
  1966      'Make.proto' asFilename isSymbolicLink  
  1886      'Makefile' asFilename isSymbolicLink   
  1967      'Makefile' asFilename isSymbolicLink   
  1887     "
  1968     "
  1897 !
  1978 !
  1898 
  1979 
  1899 isWritable
  1980 isWritable
  1900     "return true, if such a file exists and is writable."
  1981     "return true, if such a file exists and is writable."
  1901 
  1982 
  1902     ^ OperatingSystem isWritable:nameString
  1983     ^ OperatingSystem isWritable:(self osNameForFile)
  1903 
  1984 
  1904     "
  1985     "
  1905      '/foo/bar' asFilename isWritable 
  1986      '/foo/bar' asFilename isWritable 
  1906      '/tmp' asFilename isWritable   
  1987      '/tmp' asFilename isWritable   
  1907      'Makefile' asFilename isWritable   
  1988      'Makefile' asFilename isWritable   
  1968 !Filename methodsFor:'queries-path & name'!
  2049 !Filename methodsFor:'queries-path & name'!
  1969 
  2050 
  1970 baseName
  2051 baseName
  1971     "return my baseName as a string.
  2052     "return my baseName as a string.
  1972      - thats the file/directory name without leading parent-dirs.
  2053      - thats the file/directory name without leading parent-dirs.
       
  2054      (i.e. '/usr/lib/st/file' asFilename baseName -> 'file'
       
  2055        and '/usr/lib'         asFilename baseName -> lib).
       
  2056      This method does not check if the path is valid
       
  2057 
  1973      See also: #pathName, #directoryName and #directoryPathName.
  2058      See also: #pathName, #directoryName and #directoryPathName.
  1974      Compatibility note: use #tail for ST-80 compatibility."
  2059      Compatibility note: use #tail for ST-80 compatibility."
  1975 
  2060 
  1976     ^ OperatingSystem baseNameOf:nameString "/ (self pathName) 
  2061     |len index sep endIdx|
       
  2062 
       
  2063     sep := self separator.
       
  2064     len := nameString size.
       
  2065     ((len == 1) and:[(nameString at:1) == sep]) ifTrue:[
       
  2066         ^ nameString
       
  2067     ].
       
  2068 
       
  2069     endIdx := len.
       
  2070     len > 1 ifTrue:[
       
  2071         (nameString at:len) == sep ifTrue:[endIdx := endIdx - 1].
       
  2072     ].
       
  2073     index := nameString lastIndexOf:sep startingAt:len-1.
       
  2074     index == 0 ifTrue:[
       
  2075         ^ nameString copyTo:endIdx
       
  2076     ].
       
  2077     ^ nameString copyFrom:(index+1) to:endIdx
  1977 
  2078 
  1978     "
  2079     "
  1979      '/foo/bar' asFilename baseName  
  2080      '/foo/bar' asFilename baseName  
  1980      '.' asFilename baseName          
  2081      '.' asFilename baseName          
  1981      '..' asFilename baseName         
  2082      '..' asFilename baseName         
  1983      '../../libbasic' asFilename baseName        
  2084      '../../libbasic' asFilename baseName        
  1984      '../../libpr' asFilename baseName        
  2085      '../../libpr' asFilename baseName        
  1985      '../../libbasic/Object.st' asFilename baseName        
  2086      '../../libbasic/Object.st' asFilename baseName        
  1986     "
  2087     "
  1987 
  2088 
  1988     "Modified: 9.9.1997 / 10:53:57 / cg"
  2089     "Modified: 13.9.1997 / 09:32:49 / cg"
  1989 !
  2090 !
  1990 
  2091 
  1991 directory
  2092 directory
  1992     "return the directory name part of the file/directory as a new filename.
  2093     "return the directory name part of the file/directory as a new filename.
  1993      - thats a filename for the directory where the file/dir represented by
  2094      - thats a filename for the directory where the file/dir represented by
  2012 
  2113 
  2013 directoryName
  2114 directoryName
  2014     "return the directory name part of the file/directory as a string.
  2115     "return the directory name part of the file/directory as a string.
  2015      - thats the name of the directory where the file/dir represented by
  2116      - thats the name of the directory where the file/dir represented by
  2016        the receiver is contained in.
  2117        the receiver is contained in.
       
  2118      This method does not check if the path is valid.
       
  2119 
       
  2120      (i.e. '/usr/lib/st/file' asFilename directoryName -> '/usr/lib/st'
       
  2121        and '/usr/lib' asFilename directoryName         -> /usr').
       
  2122 
  2017      (this is almost equivalent to #directory, but returns
  2123      (this is almost equivalent to #directory, but returns
  2018       a string instead of a Filename instance).
  2124       a string instead of a Filename instance).
       
  2125 
  2019      See also: #pathName, #directoryPathName and #baseName.
  2126      See also: #pathName, #directoryPathName and #baseName.
  2020      Compatibility note: use #head for ST-80 compatibility."
  2127      Compatibility note: use #head for ST-80 compatibility."
  2021 
  2128 
  2022     ^ OperatingSystem directoryNameOf:nameString "/ (self pathName)
  2129     |last index sep sepString p|
       
  2130 
       
  2131     sep := self separator.
       
  2132     sepString := sep asString.
       
  2133     (nameString = sepString) ifTrue:[
       
  2134         "/
       
  2135         "/ the trivial '/' case
       
  2136         "/
       
  2137         ^ nameString
       
  2138     ].
       
  2139 
       
  2140     "/
       
  2141     "/ strip off multiple leading slashes
       
  2142     "/
       
  2143     p := nameString.
       
  2144     [p endsWith:sepString] whileTrue:[
       
  2145         (p = sepString) ifTrue:[
       
  2146             ^ p
       
  2147         ].
       
  2148         p := p copyWithoutLast:1
       
  2149     ].
       
  2150 
       
  2151     last := 1.
       
  2152     [true] whileTrue:[
       
  2153         index := p indexOf:sep startingAt:(last + 1).
       
  2154         index == 0 ifTrue:[
       
  2155             (last == 1) ifTrue:[
       
  2156                 (p startsWith:sepString) ifTrue:[
       
  2157                     ^ sepString
       
  2158                 ].
       
  2159                 ^ '.'
       
  2160             ].
       
  2161             ^ p copyTo:(last - 1)
       
  2162         ].  
       
  2163         last := index.
       
  2164     ].
       
  2165 
       
  2166     "/ notreached
  2023 
  2167 
  2024     "
  2168     "
  2025      '/foo/bar/' asFilename directoryName    
  2169      '/foo/bar/' asFilename directoryName    
  2026      '/foo/bar/' asFilename directory     
  2170      '/foo/bar/' asFilename directory     
  2027 
  2171 
  2042     "return the full directory pathname part of the file/directory as a string.
  2186     "return the full directory pathname part of the file/directory as a string.
  2043      - thats the full pathname of the directory where the file/dir represented by
  2187      - thats the full pathname of the directory where the file/dir represented by
  2044        the receiver is contained in.
  2188        the receiver is contained in.
  2045      See also: #pathName, #directoryName, #directory and #baseName"
  2189      See also: #pathName, #directoryName, #directory and #baseName"
  2046 
  2190 
  2047     ^ OperatingSystem directoryNameOf:(self pathName)
  2191     ^ self pathName asFilename directoryName
  2048 
  2192 
  2049     "
  2193     "
  2050      '/foo/bar/' asFilename directoryPathName    
  2194      '/foo/bar/' asFilename directoryPathName    
  2051      '/foo/bar' asFilename directoryPathName    
  2195      '/foo/bar' asFilename directoryPathName    
  2052 
  2196 
  2346     ^ ''
  2490     ^ ''
  2347 
  2491 
  2348     "Modified: 8.9.1997 / 00:37:33 / cg"
  2492     "Modified: 8.9.1997 / 00:37:33 / cg"
  2349 ! !
  2493 ! !
  2350 
  2494 
       
  2495 !Filename methodsFor:'special accessing'!
       
  2496 
       
  2497 osName
       
  2498     "special - return the OS's name for the receiver."
       
  2499 
       
  2500     self isDirectory ifTrue:[
       
  2501 	^ self osNameForDirectory
       
  2502     ].
       
  2503     ^ self osNameForFile
       
  2504 !
       
  2505 
       
  2506 osNameForDirectory
       
  2507     "special - return the OS's name for the receiver to
       
  2508      access it as a directory."
       
  2509 
       
  2510     ^ nameString
       
  2511 !
       
  2512 
       
  2513 osNameForFile
       
  2514     "internal - return the OS's name for the receiver to
       
  2515      access it as a file."
       
  2516 
       
  2517     ^ nameString
       
  2518 ! !
       
  2519 
  2351 !Filename methodsFor:'suffixes'!
  2520 !Filename methodsFor:'suffixes'!
  2352 
  2521 
  2353 hasSuffix:aSuffixString
  2522 hasSuffix:aSuffixString
  2354     "return true if my suffix is the same as aString.
  2523     "return true if my suffix is the same as aString.
  2355      This cares for systems, where case is ignored in filenames"
  2524      This cares for systems, where case is ignored in filenames"
  2424 
  2593 
  2425     "Modified: 7.9.1995 / 11:09:03 / claus"
  2594     "Modified: 7.9.1995 / 11:09:03 / claus"
  2426 !
  2595 !
  2427 
  2596 
  2428 withSuffix:aSuffix
  2597 withSuffix:aSuffix
  2429     "return a new filename for the receivers name with a suffix.
  2598     "return a new filename for the receivers name with a different suffix.
  2430      If the name already has a suffix, the new suffix replacaes it;
  2599      If the name already has a suffix, the new suffix replacaes it;
  2431      otherwise, the new suffix is simply appended to the name."
  2600      otherwise, the new suffix is simply appended to the name."
  2432 
  2601 
  2433     ^ self class named:
  2602     ^ self class named:
  2434 	(self withoutSuffix name 
  2603 	(self withoutSuffix name 
  2451 
  2620 
  2452 withoutSuffix
  2621 withoutSuffix
  2453     "return a new filename for the receivers name without the suffix.
  2622     "return a new filename for the receivers name without the suffix.
  2454      If the name has no suffix, the receiver is returned."
  2623      If the name has no suffix, the receiver is returned."
  2455 
  2624 
  2456     |lastComponentsIndex idx|
  2625     |nm idx|
  2457 
  2626 
  2458     lastComponentsIndex := nameString lastIndexOf:(self class separator).
  2627     nm := self baseName.
  2459 
       
  2460     idx := nameString lastIndexOf:(self class suffixSeparator).
  2628     idx := nameString lastIndexOf:(self class suffixSeparator).
  2461     (idx == 0 or:[idx <= lastComponentsIndex]) ifTrue:[^ self].
  2629     (idx == 0) ifTrue:[^ self].
  2462 
  2630 
  2463     ^ self class named:(nameString copyTo:(idx - 1))
  2631     ^ self class named:(nameString copyTo:(idx - 1))
  2464 
  2632 
  2465     "
  2633     "
  2466      'abc.st' asFilename withoutSuffix         
  2634      'abc.st' asFilename withoutSuffix         
  2476 ! !
  2644 ! !
  2477 
  2645 
  2478 !Filename class methodsFor:'documentation'!
  2646 !Filename class methodsFor:'documentation'!
  2479 
  2647 
  2480 version
  2648 version
  2481     ^ '$Header: /cvs/stx/stx/libbasic/Filename.st,v 1.97 1997-09-09 17:35:17 cg Exp $'
  2649     ^ '$Header: /cvs/stx/stx/libbasic/Filename.st,v 1.98 1997-09-15 20:37:49 cg Exp $'
  2482 ! !
  2650 ! !
  2483 Filename initialize!
  2651 Filename initialize!