271 "Modified: / 29-08-2006 / 12:40:28 / cg" |
273 "Modified: / 29-08-2006 / 12:40:28 / cg" |
272 ! ! |
274 ! ! |
273 |
275 |
274 !Filename class methodsFor:'instance creation'! |
276 !Filename class methodsFor:'instance creation'! |
275 |
277 |
|
278 applicationDataDirectory |
|
279 "return the directory, where user-and-application-specific private files are to be |
|
280 located (ini-files, preferences etc.). |
|
281 Under windows, something like 'C:\Users\Administrator\AppData\Roaming\<appName>' |
|
282 is returned, under unix, we use ~/.<appName> (but see details in UnixOS). |
|
283 For smalltalk itself (the IDE), 'smalltalk' is used as appName. |
|
284 If the directory does not exist, it is created" |
|
285 |
|
286 |exeName| |
|
287 |
|
288 Smalltalk isStandAloneApp ifTrue:[ |
|
289 exeName := OperatingSystem nameOfSTXExecutable. |
|
290 ] ifFalse:[ |
|
291 exeName := 'smalltalk' |
|
292 ]. |
|
293 ^ self applicationDataDirectoryFor:exeName |
|
294 |
|
295 " |
|
296 Filename applicationDataDirectory |
|
297 " |
|
298 ! |
|
299 |
276 applicationDataDirectoryFor:appName |
300 applicationDataDirectoryFor:appName |
277 "return the directory, where user-and-application-specific private files are to be |
301 "return the directory, where user-and-application-specific private files are to be |
278 located (ini-files, preferences etc.). |
302 located (ini-files, preferences etc.). |
279 Under windows, something like 'C:\Users\Administrator\AppData\Roaming\<appName>' |
303 Under windows, something like 'C:\Users\Administrator\AppData\Roaming\<appName>' |
280 is returned, under unix, we use ~/.<appName> (but see details in UnixOS). |
304 is returned, under unix, we use ~/.<appName> (but see details in UnixOS). |
781 TMPDIR environment variable to have her temp files somewhere else." |
812 TMPDIR environment variable to have her temp files somewhere else." |
782 |
813 |
783 |tempDir| |
814 |tempDir| |
784 |
815 |
785 TempDirectory isNil ifTrue:[ |
816 TempDirectory isNil ifTrue:[ |
786 #('STX_TMPDIR' 'ST_TMPDIR' 'TMPDIR' 'TEMPDIR' 'TEMP' 'TMP') do:[:envVar | |
817 tempDir := self named:(self defaultTempDirectoryName pathName). |
787 tempDir isNil ifTrue:[ |
818 tempDir exists ifFalse:[ |
788 tempDir := OperatingSystem getEnvironment:envVar. |
819 tempDir |
789 tempDir notNil ifTrue:[ |
820 makeDirectory; |
790 tempDir := self named:tempDir. |
821 addAccessRights:#(readUser readGroup readOthers |
791 tempDir exists ifFalse:[ |
822 writeUser writeGroup writeOthers |
792 tempDir := nil. |
823 executeUser executeGroup executeOthers |
793 ]. |
824 removeOnlyByOwner). |
794 ]. |
|
795 ]. |
|
796 ]. |
|
797 tempDir isNil ifTrue:[ |
|
798 tempDir := self named:(self defaultTempDirectoryName pathName). |
|
799 tempDir exists ifFalse:[ |
|
800 tempDir |
|
801 makeDirectory; |
|
802 addAccessRights:#(readUser readGroup readOthers |
|
803 writeUser writeGroup writeOthers |
|
804 executeUser executeGroup executeOthers |
|
805 removeOnlyByOwner). |
|
806 ]. |
|
807 ]. |
825 ]. |
808 TempDirectory := DefaultTempDirectory := tempDir construct:'stx_tmp'. |
826 TempDirectory := DefaultTempDirectory := tempDir construct:'stx_tmp'. |
809 ]. |
827 ]. |
810 |
828 |
811 "Make sure, that the TempDirectory exists - it might have been removed |
829 "Make sure, that the TempDirectory exists - it might have been removed |
891 "Modified: 8.9.1997 / 00:24:53 / cg" |
940 "Modified: 8.9.1997 / 00:24:53 / cg" |
892 ! ! |
941 ! ! |
893 |
942 |
894 !Filename class methodsFor:'misc'! |
943 !Filename class methodsFor:'misc'! |
895 |
944 |
896 canonicalize:aPathString |
|
897 "convert the argument, aPathString to a good format. |
|
898 This should eliminate useless directory components (i.e. '././') |
|
899 and useless tree walks (i.e. '../foo/..')." |
|
900 |
|
901 |comps newComps parentName currentName rootName| |
|
902 |
|
903 parentName := self parentDirectoryName. |
|
904 currentName := self currentDirectoryName. |
|
905 rootName := self rootDirectory name. |
|
906 |
|
907 comps := self components:aPathString. |
|
908 newComps := OrderedCollection new. |
|
909 comps do:[:eachComponent | |
|
910 (eachComponent ~= currentName |
|
911 and:[eachComponent notEmpty or:[newComps size == 1]]) ifTrue:[ |
|
912 eachComponent = parentName ifTrue:[ |
|
913 (newComps isEmpty |
|
914 or:[newComps = (Array with:rootName) |
|
915 or:[newComps last = parentName]]) ifTrue:[ |
|
916 newComps add:eachComponent |
|
917 ] ifFalse:[ |
|
918 newComps removeLast |
|
919 ]. |
|
920 ] ifFalse:[ |
|
921 newComps add:eachComponent |
|
922 ]. |
|
923 ] |
|
924 ]. |
|
925 "/ add current Directory if empty |
|
926 newComps isEmpty ifTrue:[ |
|
927 newComps add:currentName. |
|
928 ]. |
|
929 ^ self nameFromComponents:newComps |
|
930 |
|
931 " |
|
932 Filename canonicalize:'/etc/../etc' |
|
933 Filename canonicalize:'/home/cg/../' |
|
934 Filename canonicalize:'/home/cg/../././' |
|
935 Filename canonicalize:'./home/cg/../././' |
|
936 Filename canonicalize:'/home/././cg/../././' |
|
937 Filename canonicalize:'/home/././cg/././' |
|
938 Filename canonicalize:'/home/cg/../../..' |
|
939 Filename canonicalize:'cg/../../..' |
|
940 Filename canonicalize:'./' |
|
941 Filename canonicalize:'/home/.' |
|
942 Filename canonicalize:'/home/../..' |
|
943 Filename canonicalize:'//foo' |
|
944 Filename canonicalize:'///foo' |
|
945 Filename canonicalize:'//foo//bar' |
|
946 " |
|
947 ! |
|
948 |
|
949 filterSeps:aFilenameString |
945 filterSeps:aFilenameString |
950 "ST80 compatibility: |
946 "ST80 compatibility: |
951 filter out (invalid) separators in aFilenameString. |
947 filter out (invalid) separators in aFilenameString. |
952 We recommend using #makeLegalFilename" |
948 We recommend using #makeLegalFilename" |
953 |
949 |
954 ^ aFilenameString copyReplaceAll:(Character space) with:$_. |
950 ^ aFilenameString copyReplaceAll:(Character space) with:$_ ifNone:aFilenameString. |
955 |
951 |
956 "Created: / 1.11.1997 / 12:39:50 / cg" |
952 "Created: / 1.11.1997 / 12:39:50 / cg" |
957 "Modified: / 18.7.1998 / 22:53:24 / cg" |
953 "Modified: / 18.7.1998 / 22:53:24 / cg" |
958 ! |
954 ! |
959 |
955 |
1023 PCFilename new nameWithSpecialExpansions:'~foo' |
1019 PCFilename new nameWithSpecialExpansions:'~foo' |
1024 PCFilename new nameWithSpecialExpansions:'~foo\bar' |
1020 PCFilename new nameWithSpecialExpansions:'~foo\bar' |
1025 " |
1021 " |
1026 ! |
1022 ! |
1027 |
1023 |
|
1024 possiblyQuotedPathname:aPath |
|
1025 "return a filename path usable as command line argument, |
|
1026 by quoting in double quotes if there are any embedded special characters. |
|
1027 On Unix systems, special characters might also be prefixed by a backslash character." |
|
1028 |
|
1029 (aPath startsWith:'"') ifFalse:[ |
|
1030 (aPath includes:Character space) ifTrue:[ |
|
1031 ^ '"',aPath,'"' |
|
1032 ]. |
|
1033 ]. |
|
1034 ^ aPath |
|
1035 |
|
1036 |
|
1037 " |
|
1038 Filename possiblyQuotedPathname:'/tmp/bla' |
|
1039 Filename possiblyQuotedPathname:'/tmp directory/bla' |
|
1040 Filename possiblyQuotedPathname:'/tmp directory/bla file' |
|
1041 " |
|
1042 ! |
|
1043 |
1028 suggest:aFilenameString |
1044 suggest:aFilenameString |
1029 "return a fileNamestring based on the argument, |
1045 "return a fileNamestring based on the argument, |
1030 which is legal on the current platform." |
1046 which is legal on the current platform." |
1031 |
1047 |
1032 ^ self canonicalize:aFilenameString |
1048 ^ self canonicalize:aFilenameString |
1033 |
1049 |
1034 "Created: / 1.11.1997 / 12:42:39 / cg" |
1050 "Created: / 1.11.1997 / 12:42:39 / cg" |
1035 ! ! |
1051 ! ! |
1036 |
1052 |
1037 !Filename class methodsFor:'queries'! |
1053 !Filename class methodsFor:'queries'! |
1038 |
|
1039 components:aString |
|
1040 "separate the pathName given by aString into |
|
1041 a collection containing the directory components and the files name as |
|
1042 the final component. |
|
1043 If the argument names an absolute path, the first component will be the |
|
1044 name of the root directory (i.e. '/')." |
|
1045 |
|
1046 |sep f vol rest components| |
|
1047 |
|
1048 self isAbstract ifTrue:[ |
|
1049 ^ ConcreteClass components:aString |
|
1050 ]. |
|
1051 |
|
1052 "/ the following works on Unix & MSDOS (but not on openVMS) |
|
1053 "/ However, MSDOS drive-letters and network drives are |
|
1054 "/ not correctly handled here. |
|
1055 |
|
1056 sep := self separator. |
|
1057 f := aString asFilename. |
|
1058 vol := f volume. |
|
1059 vol size ~~ 0 ifTrue:[ |
|
1060 rest := f localPathName. |
|
1061 ] ifFalse:[ |
|
1062 rest := aString |
|
1063 ]. |
|
1064 |
|
1065 components := rest asCollectionOfSubstringsSeparatedBy:sep. |
|
1066 components first isEmpty ifTrue:[ |
|
1067 components at:1 put:(sep asString) |
|
1068 ]. |
|
1069 |
|
1070 "/ prepend volume to first component (the root directory) |
|
1071 vol size ~~ 0 ifTrue:[ |
|
1072 components at:1 put:(vol , (components at:1)). |
|
1073 ]. |
|
1074 components last isEmpty ifTrue:[ |
|
1075 ^ components copyButLast:1 |
|
1076 ]. |
|
1077 ^ components |
|
1078 |
|
1079 " |
|
1080 Filename components:'/foo/bar/baz' |
|
1081 Filename components:'/' |
|
1082 Filename components:'foo/bar/baz' |
|
1083 Filename components:'foo/bar' |
|
1084 Filename components:'foo' |
|
1085 Filename components:'/foo' |
|
1086 |
|
1087 Filename components:'\' |
|
1088 Filename components:'\foo' |
|
1089 Filename components:'\foo\' |
|
1090 Filename components:'\foo\bar' |
|
1091 Filename components:'\foo\bar\' |
|
1092 Filename components:'c:' |
|
1093 Filename components:'c:\' |
|
1094 Filename components:'c:\foo' |
|
1095 Filename components:'c:\foo\' |
|
1096 Filename components:'c:\foo\bar' |
|
1097 Filename components:'c:\foo\bar\' |
|
1098 Filename components:'\\idefix' |
|
1099 Filename components:'\\idefix\home' |
|
1100 Filename components:'\\idefix\home\bar' |
|
1101 " |
|
1102 |
|
1103 "Modified: / 24.9.1998 / 19:10:52 / cg" |
|
1104 ! |
|
1105 |
1054 |
1106 currentDirectoryName |
1055 currentDirectoryName |
1107 "return a filename for the current directory" |
1056 "return a filename for the current directory" |
1108 |
1057 |
1109 self isAbstract ifTrue:[ |
1058 self isAbstract ifTrue:[ |
1470 " |
1419 " |
1471 ! ! |
1420 ! ! |
1472 |
1421 |
1473 !Filename class methodsFor:'utilities'! |
1422 !Filename class methodsFor:'utilities'! |
1474 |
1423 |
|
1424 canonicalize:aPathString |
|
1425 "convert the argument, aPathString to a good format. |
|
1426 This should eliminate useless directory components (i.e. '././') |
|
1427 and useless tree walks (i.e. '../foo/..')." |
|
1428 |
|
1429 ^ self nameFromComponents:(self canonicalizedNameComponents:aPathString) |
|
1430 |
|
1431 " |
|
1432 Filename canonicalize:'/etc/../etc' |
|
1433 Filename canonicalize:'/home/cg/../' |
|
1434 Filename canonicalize:'/home/cg/../././' |
|
1435 Filename canonicalize:'./home/cg/../././' |
|
1436 Filename canonicalize:'/home/././cg/../././' |
|
1437 Filename canonicalize:'/home/././cg/././' |
|
1438 Filename canonicalize:'/home/cg/../../..' |
|
1439 Filename canonicalize:'cg/../../..' |
|
1440 Filename canonicalize:'./' |
|
1441 Filename canonicalize:'/home/.' |
|
1442 Filename canonicalize:'/home/../..' |
|
1443 Filename canonicalize:'//foo' |
|
1444 Filename canonicalize:'///foo' |
|
1445 Filename canonicalize:'//foo//bar' |
|
1446 " |
|
1447 ! |
|
1448 |
|
1449 canonicalizedNameComponents:aPathString |
|
1450 "convert the argument, aPathString to a good format. |
|
1451 This should eliminate useless directory components (i.e. '././') |
|
1452 and useless tree walks (i.e. '../foo/..'). |
|
1453 |
|
1454 Answer a sequenceable collection of name components." |
|
1455 |
|
1456 |comps newComps rootName dotDot dot| |
|
1457 |
|
1458 dotDot := self parentDirectoryName. |
|
1459 dot := self currentDirectoryName. |
|
1460 rootName := self separatorString. |
|
1461 |
|
1462 comps := self components:aPathString. |
|
1463 newComps := OrderedCollection new:comps size. |
|
1464 comps do:[:eachComponent | |
|
1465 eachComponent ~= dot ifTrue:[ |
|
1466 eachComponent = dotDot ifTrue:[ |
|
1467 (newComps isEmpty |
|
1468 or:[(newComps size == 1 and:[newComps first startsWith:rootName]) |
|
1469 or:[newComps last = dotDot]]) ifTrue:[ |
|
1470 newComps add:eachComponent |
|
1471 ] ifFalse:[ |
|
1472 newComps removeLast |
|
1473 ]. |
|
1474 ] ifFalse:[ |
|
1475 newComps add:eachComponent |
|
1476 ]. |
|
1477 ] |
|
1478 ]. |
|
1479 "/ add current Directory if empty |
|
1480 newComps isEmpty ifTrue:[ |
|
1481 newComps add:dot. |
|
1482 ]. |
|
1483 ^ newComps |
|
1484 |
|
1485 " |
|
1486 Filename canonicalizedNameComponents:'/etc/../etc' |
|
1487 Filename canonicalizedNameComponents:'/home/cg/../' |
|
1488 Filename canonicalizedNameComponents:'/home/cg/../././' |
|
1489 Filename canonicalizedNameComponents:'./home/cg/../././' |
|
1490 Filename canonicalizedNameComponents:'/home/././cg/../././' |
|
1491 Filename canonicalizedNameComponents:'/home/././cg/././' |
|
1492 Filename canonicalizedNameComponents:'/home/cg/../../..' |
|
1493 Filename canonicalizedNameComponents:'cg/../../..' |
|
1494 Filename canonicalizedNameComponents:'/' |
|
1495 Filename canonicalizedNameComponents:'./' |
|
1496 Filename canonicalizedNameComponents:'/.' |
|
1497 Filename canonicalizedNameComponents:'/home/.' |
|
1498 Filename canonicalizedNameComponents:'/home' |
|
1499 Filename canonicalizedNameComponents:'/home/../..' |
|
1500 Filename canonicalizedNameComponents:'//foo' |
|
1501 Filename canonicalizedNameComponents:'///foo' |
|
1502 Filename canonicalizedNameComponents:'//foo//bar' |
|
1503 " |
|
1504 ! |
|
1505 |
|
1506 components:aString |
|
1507 "separate the pathName given by aString into |
|
1508 a collection containing the directory components and the file's name as |
|
1509 the final component. |
|
1510 If the argument names an absolute path, the first component will be the |
|
1511 name of the root directory (i.e. '/')." |
|
1512 |
|
1513 |sep f vol rest components| |
|
1514 |
|
1515 self isAbstract ifTrue:[ |
|
1516 ^ ConcreteClass components:aString |
|
1517 ]. |
|
1518 |
|
1519 "/ the following works on Unix & MSDOS (but not on openVMS) |
|
1520 "/ However, MSDOS drive-letters and network drives are |
|
1521 "/ not correctly handled here. |
|
1522 |
|
1523 sep := self separator. |
|
1524 f := aString asFilename. |
|
1525 vol := f volume. |
|
1526 vol size ~~ 0 ifTrue:[ |
|
1527 rest := f localPathName. |
|
1528 ] ifFalse:[ |
|
1529 rest := aString |
|
1530 ]. |
|
1531 |
|
1532 components := rest asCollectionOfSubstringsSeparatedBy:sep. |
|
1533 (rest startsWith:sep) ifTrue:[ |
|
1534 "first was a separator - root directory - restore" |
|
1535 (rest size > 1 and:[rest second = sep and:[vol isEmptyOrNil]]) ifTrue:[ |
|
1536 "keep \\ for windows network paths" |
|
1537 components at:1 put:(String with:sep with:sep). |
|
1538 ] ifFalse:[ |
|
1539 components at:1 put:sep asString. |
|
1540 ]. |
|
1541 ]. |
|
1542 components := components select:[:each| each notEmpty]. |
|
1543 |
|
1544 "/ prepend volume to first component (the root directory) |
|
1545 vol size ~~ 0 ifTrue:[ |
|
1546 components at:1 put:(vol , (components at:1)). |
|
1547 ]. |
|
1548 ^ components |
|
1549 |
|
1550 " |
|
1551 Filename components:'/foo/bar/baz' |
|
1552 Filename components:'/' |
|
1553 Filename components:'//' |
|
1554 Filename components:'foo/bar/baz' |
|
1555 Filename components:'foo/bar' |
|
1556 Filename components:'foo' |
|
1557 Filename components:'/foo' |
|
1558 Filename components:'//foo' |
|
1559 Filename components:'' |
|
1560 |
|
1561 Filename components:'\' |
|
1562 Filename components:'\foo' |
|
1563 Filename components:'\foo\' |
|
1564 Filename components:'\foo\bar' |
|
1565 Filename components:'\foo\bar\' |
|
1566 Filename components:'c:' |
|
1567 Filename components:'c:\' |
|
1568 Filename components:'c:\foo' |
|
1569 Filename components:'c:\foo\' |
|
1570 Filename components:'c:\foo\bar' |
|
1571 Filename components:'c:\foo\bar\' |
|
1572 Filename components:'\\idefix' |
|
1573 Filename components:'\\idefix\home' |
|
1574 Filename components:'\\idefix\home\bar' |
|
1575 " |
|
1576 |
|
1577 "Modified: / 24.9.1998 / 19:10:52 / cg" |
|
1578 ! |
|
1579 |
1475 nameFromComponents:aCollectionOfDirectoryNames |
1580 nameFromComponents:aCollectionOfDirectoryNames |
1476 "return a filenameString from components given in aCollectionOfDirectoryNames. |
1581 "return a filenameString from components given in aCollectionOfDirectoryNames. |
1477 If the first component is the name of the root directory (i.e. '/'), |
1582 If the first component is the name of the root directory (i.e. '/'), |
1478 an absolute path-string is returned." |
1583 an absolute path-string is returned." |
1479 |
1584 |
2029 "evaluate aBlock for directories contained in the directory represented by the receiver. |
2146 "evaluate aBlock for directories contained in the directory represented by the receiver. |
2030 The block is invoked with a filename-arguments. |
2147 The block is invoked with a filename-arguments. |
2031 The enumerations order is undefined - i.e. usually NOT sorted by |
2148 The enumerations order is undefined - i.e. usually NOT sorted by |
2032 filenames (but by creation time - on some systems). |
2149 filenames (but by creation time - on some systems). |
2033 This excludes entries for '.' or '..'. |
2150 This excludes entries for '.' or '..'. |
2034 NoOp for non-existing directories; however, this behavior |
2151 OpenError is raised if I represent a non-existant or non-readable directories. |
2035 may be changed in the near future, to raise an exception instead. |
|
2036 So users of this method better test for existing directory before." |
2152 So users of this method better test for existing directory before." |
2037 |
2153 |
2038 self directoryContentsAsFilenamesDo:[:eachFileOrDirectory | |
2154 self directoryContentsAsFilenamesDo:[:eachFileOrDirectory | |
2039 eachFileOrDirectory isDirectory ifTrue:[ |
2155 eachFileOrDirectory isDirectory ifTrue:[ |
2040 aBlock value:eachFileOrDirectory |
2156 aBlock value:eachFileOrDirectory |
2050 "evaluate aBlock for each file in the directory represented by the receiver. |
2166 "evaluate aBlock for each file in the directory represented by the receiver. |
2051 The block is invoked with a filename-argument. |
2167 The block is invoked with a filename-argument. |
2052 The enumerations order is undefined - i.e. usually NOT sorted by |
2168 The enumerations order is undefined - i.e. usually NOT sorted by |
2053 filenames (but by creation time - on some systems). |
2169 filenames (but by creation time - on some systems). |
2054 This excludes entries for '.' or '..'. |
2170 This excludes entries for '.' or '..'. |
2055 NoOp for non-existing directories; however, this behavior |
2171 An OpenError exception is raised it the directory does not exist or is not readable. |
2056 may be changed in the near future, to raise an exception instead. |
|
2057 So users of this method better test for existing directory before. |
2172 So users of this method better test for existing directory before. |
2058 Notice: this enumerates fileName objects; see also |
2173 Notice: this enumerates fileName objects; see also |
2059 #directoryContentsDo:, which enumerates strings." |
2174 #directoryContentsDo:, which enumerates strings." |
2060 |
2175 |
2061 self directoryContentsDo:[:entry | |
2176 self directoryContentsDo:[:entry | |
2074 "evaluate aBlock for each file in the directory represented by the receiver. |
2189 "evaluate aBlock for each file in the directory represented by the receiver. |
2075 The block is invoked with a string as argument. |
2190 The block is invoked with a string as argument. |
2076 The enumerations order is undefined - i.e. usually NOT sorted by |
2191 The enumerations order is undefined - i.e. usually NOT sorted by |
2077 filenames (but by creation time - on some systems). |
2192 filenames (but by creation time - on some systems). |
2078 This excludes entries for '.' or '..'. |
2193 This excludes entries for '.' or '..'. |
2079 An exception is raised it the directory does not exist.. |
2194 An OpenError exception is raised it the directory does not exist or is not readable. |
2080 So users of this method better test for existing directory before. |
2195 So users of this method better test for existing directory before. |
2081 Notice: this enumerates strings; see also |
2196 Notice: this enumerates strings; see also |
2082 #directoryContentsAsFilenamesDo:, which enumerates fileName objects." |
2197 #directoryContentsAsFilenamesDo:, which enumerates fileName objects." |
2083 |
2198 |
2084 |s fn| |
2199 |s| |
2085 |
2200 |
2086 FileStream openErrorSignal |
2201 s := DirectoryStream directoryNamed:self osNameForDirectoryContents. |
2087 handle:[:ex |] |
2202 "check for nil, in order to allow to proceed from an OpenError" |
2088 do:[ |
2203 s notNil ifTrue:[ |
2089 s := DirectoryStream directoryNamed:(self osNameForDirectoryContents). |
2204 [ |
|
2205 [s atEnd] whileFalse:[ |
|
2206 |fn| |
|
2207 |
|
2208 fn := s nextLine. |
|
2209 (fn ~= '.' and:[fn ~= '..']) ifTrue:[ |
|
2210 aBlock value:fn |
|
2211 ]. |
|
2212 ]. |
|
2213 ] ensure:[ |
|
2214 s close. |
2090 ]. |
2215 ]. |
2091 s isNil ifTrue:[^ self]. |
|
2092 |
|
2093 [ |
|
2094 [s atEnd] whileFalse:[ |
|
2095 fn := s nextLine. |
|
2096 ((fn ~= '.') and:[fn ~= '..']) ifTrue:[ |
|
2097 aBlock value:fn |
|
2098 ] |
|
2099 ] |
|
2100 ] ensure:[ |
|
2101 s close |
|
2102 ]. |
2216 ]. |
2103 |
2217 |
2104 " |
2218 " |
2105 '.' asFilename directoryContentsDo:[:fn | Transcript showCR:fn]. |
2219 '.' asFilename directoryContentsDo:[:fn | Transcript showCR:fn]. |
2106 'doeSnotExIST' asFilename directoryContentsDo:[:fn | Transcript showCR:fn]. |
2220 'doeSnotExIST' asFilename directoryContentsDo:[:fn | Transcript showCR:fn]. |
|
2221 [ |
|
2222 'doeSnotExIST' asFilename directoryContentsDo:[:fn | Transcript showCR:fn]. |
|
2223 ] on:OpenError do:[:ex| ex proceed] |
2107 " |
2224 " |
2108 |
2225 |
2109 "Modified: / 18.9.1997 / 18:42:23 / stefan" |
2226 "Modified: / 18.9.1997 / 18:42:23 / stefan" |
2110 "Modified: / 23.12.1999 / 20:56:35 / cg" |
2227 "Modified: / 23.12.1999 / 20:56:35 / cg" |
2111 ! |
2228 ! |
2112 |
2229 |
2113 files |
2230 files |
2114 "return a collection of files contained in the directory represented by the receiver." |
2231 "return a collection of files contained in the directory represented by the receiver." |
2115 |
2232 |
2116 ^ self directoryContentsAsFilenames |
2233 |collection| |
2117 reject:[:eachFileOrDirectory | eachFileOrDirectory isDirectory ] |
2234 |
|
2235 collection := OrderedCollection new. |
|
2236 self directoryContentsAsFilenamesDo:[:eachFileName | |
|
2237 eachFileName isRegularFile ifTrue:[ |
|
2238 collection add:eachFileName |
|
2239 ]. |
|
2240 ]. |
|
2241 ^ collection. |
2118 |
2242 |
2119 " |
2243 " |
2120 '.' asFilename files. |
2244 '.' asFilename files. |
2121 " |
2245 " |
2122 |
2246 |
2221 "evaluate aBlock for myself and all (recursive) directories contained in the directory represented by the receiver. |
2345 "evaluate aBlock for myself and all (recursive) directories contained in the directory represented by the receiver. |
2222 The block is invoked with a filename-arguments. |
2346 The block is invoked with a filename-arguments. |
2223 The enumerations order within a directory is undefined - i.e. usually NOT sorted by |
2347 The enumerations order within a directory is undefined - i.e. usually NOT sorted by |
2224 filenames (but by creation time - on some systems). |
2348 filenames (but by creation time - on some systems). |
2225 This excludes entries for '.' or '..'. |
2349 This excludes entries for '.' or '..'. |
2226 NoOp for non-existing directories; however, this behavior |
2350 OpenError is raised if the name I represent does not exist or is not readable. |
2227 may be changed in the near future, to raise an exception instead. |
|
2228 So users of this method better test for existing directory before." |
2351 So users of this method better test for existing directory before." |
2229 |
2352 |
2230 self isDirectory ifTrue:[ |
2353 self isDirectory ifTrue:[ |
2231 aBlock value:self. |
2354 aBlock value:self. |
2232 self allDirectoriesDo:aBlock |
2355 ]. |
2233 ]. |
2356 self allDirectoriesDo:aBlock. |
2234 |
2357 |
2235 " |
2358 " |
2236 '.' asFilename withAllDirectoriesDo:[:fn | Transcript showCR:fn name]. |
2359 '.' asFilename withAllDirectoriesDo:[:fn | Transcript showCR:fn name]. |
|
2360 'IdoNOTexist' asFilename withAllDirectoriesDo:[:fn | Transcript showCR:fn name]. |
|
2361 '/etc/hosts' asFilename withAllDirectoriesDo:[:fn | Transcript showCR:fn name]. |
2237 " |
2362 " |
2238 ! ! |
2363 ! ! |
2239 |
2364 |
2240 !Filename methodsFor:'error handling'! |
2365 !Filename methodsFor:'error handling'! |
2241 |
2366 |
2988 |
3134 |
2989 recursiveCopyTo:destination |
3135 recursiveCopyTo:destination |
2990 "if I represent a regular file, copy it. |
3136 "if I represent a regular file, copy it. |
2991 Otherwise, copy the directory and recursively |
3137 Otherwise, copy the directory and recursively |
2992 all of its subfiles/subdirectories. |
3138 all of its subfiles/subdirectories. |
2993 Raises an exception if not successful." |
3139 |
2994 |
3140 Raises an exception if not successful. |
2995 |ok d| |
3141 Do not resolve symbolic links. |
2996 |
3142 If a whole directory is to be copied and the destination directory |
|
3143 does not exist, it will be created." |
|
3144 |
|
3145 |ok destinationFilename| |
|
3146 |
|
3147 destinationFilename := destination asFilename. |
2997 self isDirectory ifFalse:[ |
3148 self isDirectory ifFalse:[ |
2998 d := destination asFilename. |
3149 destinationFilename isDirectory ifTrue:[ |
2999 d isDirectory ifTrue:[ |
3150 destinationFilename := destinationFilename construct:self baseName. |
3000 d := d construct:self baseName. |
|
3001 ]. |
3151 ]. |
3002 self copyTo:d. |
3152 self copyTo:destinationFilename. |
3003 ^ self. |
3153 ^ self. |
3004 ]. |
3154 ]. |
3005 |
3155 |
3006 "/ typically, an 'cp -r' is faster; |
3156 "/ typically, an 'cp -r' is faster; |
3007 "/ however, if the command fails (or the OS does not support it), |
3157 "/ however, if the command fails (or the OS does not support it), |
3008 "/ fallBack doing a manual directory walk. |
3158 "/ fallBack doing a manual directory walk. |
3009 |
3159 |
3010 ok := OperatingSystem |
3160 ok := OperatingSystem |
3011 recursiveCopyDirectory:(self osNameForDirectory) |
3161 recursiveCopyDirectory:(self osNameForDirectory) |
3012 to:(destination asFilename osNameForDirectory). |
3162 to:(destinationFilename osNameForDirectory). |
3013 |
3163 |
3014 ok ifFalse:[ |
3164 ok ifFalse:[ |
3015 self recursiveCopyWithoutOSCommandTo:destination |
3165 self recursiveCopyWithoutOSCommandTo:destinationFilename |
3016 ]. |
3166 ]. |
|
3167 |
|
3168 " |
|
3169 '.' asFilename recursiveCopyTo:'/tmp/xxx'. |
|
3170 " |
3017 |
3171 |
3018 "Created: / 05-05-1999 / 13:35:01 / cg" |
3172 "Created: / 05-05-1999 / 13:35:01 / cg" |
3019 "Modified: / 31-05-1999 / 13:11:34 / cg" |
3173 "Modified: / 31-05-1999 / 13:11:34 / cg" |
3020 "Modified: / 29-07-2010 / 12:41:06 / sr" |
3174 "Modified: / 29-07-2010 / 12:41:06 / sr" |
3021 ! |
3175 ! |
3022 |
3176 |
3023 recursiveCopyWithoutOSCommandTo:destination |
3177 recursiveCopyWithoutOSCommandTo:destination |
3024 "if I represent a regular file, copy it. |
3178 "if I represent a regular file, copy it. |
3025 Otherwise, copy the directory and all of its subfiles/subdirectories. |
3179 Otherwise, copy the directory and all of its subfiles/subdirectories. |
3026 This one walks down the directory hierarchy, not using any OS command to do the copy. |
3180 This one walks down the directory hierarchy, not using any OS command to do the copy. |
3027 Raises an exception if not successful." |
3181 Raises an exception if not successful. |
|
3182 |
|
3183 Do not resolve symbolic links. |
|
3184 If a whole directory is to be copied and the destination directory |
|
3185 does not exist, it will be created." |
3028 |
3186 |
3029 |destinationFilename| |
3187 |destinationFilename| |
3030 |
3188 |
3031 destinationFilename := destination asFilename. |
3189 destinationFilename := destination asFilename. |
3032 |
3190 |
3033 self isDirectory ifTrue:[ |
3191 self isDirectory ifTrue:[ |
3034 destinationFilename exists ifTrue:[ |
3192 destinationFilename exists ifFalse:[ |
3035 destinationFilename := destinationFilename construct:self baseName. |
|
3036 destinationFilename makeDirectory. |
|
3037 ] ifFalse:[ |
|
3038 destinationFilename makeDirectory. |
3193 destinationFilename makeDirectory. |
3039 destinationFilename accessRights:self accessRights. |
3194 destinationFilename accessRights:self accessRights. |
3040 ]. |
3195 ]. |
3041 |
3196 |
3042 self directoryContents do:[:aFilenameString | |
3197 self directoryContents do:[:aFilenameString | |
3043 |src dst| |
3198 |src dst| |
3044 |
3199 |
3045 src := self construct:aFilenameString. |
3200 src := self construct:aFilenameString. |
|
3201 dst := destinationFilename construct:aFilenameString. |
|
3202 |
3046 src isDirectory ifTrue:[ |
3203 src isDirectory ifTrue:[ |
3047 src recursiveCopyWithoutOSCommandTo:destinationFilename |
3204 src recursiveCopyWithoutOSCommandTo:dst |
|
3205 ] ifFalse:[src isSymbolicLink ifTrue:[ |
|
3206 dst |
|
3207 remove; |
|
3208 createAsSymbolicLinkTo:src linkInfo path. |
3048 ] ifFalse:[ |
3209 ] ifFalse:[ |
3049 src copyTo:(destinationFilename construct:aFilenameString) |
3210 src copyTo:dst. |
3050 ]. |
3211 ]]. |
3051 ] |
3212 ]. |
3052 ] ifFalse:[ |
3213 ] ifFalse:[ |
3053 self copyTo:destinationFilename |
3214 destinationFilename isDirectory ifTrue:[ |
|
3215 destinationFilename := destinationFilename construct:self baseName. |
|
3216 ]. |
|
3217 self copyTo:destinationFilename. |
3054 ] |
3218 ] |
3055 |
3219 |
3056 " |
3220 " |
3057 '.' asFilename recursiveCopyWithoutOSCommandTo:'/tmp/xxx'. |
3221 '.' asFilename recursiveCopyWithoutOSCommandTo:'/tmp/xxx'. |
3058 'smalltalk.rc' asFilename recursiveCopyWithoutOSCommandTo:'/tmp/xxx'. |
3222 'smalltalk.rc' asFilename recursiveCopyWithoutOSCommandTo:'/tmp/xxx'. |
3288 'foo' asFilename makeDirectory. |
3452 'foo' asFilename makeDirectory. |
3289 'foo' asFilename removeFile |
3453 'foo' asFilename removeFile |
3290 " |
3454 " |
3291 ! |
3455 ! |
3292 |
3456 |
3293 renameTo:newName |
3457 renameTo:newNameArg |
3294 "rename the file - the argument must be convertable to a String. |
3458 "rename the file - the argument must be convertable to a String. |
3295 Raises an exception if not successful. |
3459 Raises an exception if not successful. |
3296 If newName already exists, it will be replaced by myself." |
3460 If newName already exists, it will be replaced by myself." |
3297 |
3461 |
3298 |errno| |
3462 |errno newName| |
3299 |
3463 |
|
3464 newName := newNameArg asFilename. |
3300 (OperatingSystem |
3465 (OperatingSystem |
3301 renameFile:(self osNameForFile) |
3466 renameFile:(self osNameForFile) |
3302 to:(newName asFilename osNameForFile) |
3467 to:(newName osNameForFile) |
3303 ) ifFalse:[ |
3468 ) ifFalse:[ |
3304 errno := OperatingSystem lastErrorNumber. |
3469 errno := OperatingSystem lastErrorNumber. |
3305 |
3470 |
3306 self exists ifFalse:[ |
3471 self exists ifFalse:[ |
3307 ^ self fileNotFoundError:self |
3472 ^ self fileNotFoundError:self |
3308 ]. |
3473 ]. |
3309 (OperatingSystem errorHolderForNumber:errno) |
3474 (OperatingSystem errorHolderForNumber:errno) |
3310 parameter:newName asFilename; |
3475 parameter:newName; |
3311 reportError. |
3476 reportError. |
3312 ]. |
3477 ]. |
3313 |
3478 |
3314 " |
3479 " |
3315 '/tmp/foo' asFilename renameTo:'/tmp/bar' |
3480 '/tmp/foo' asFilename renameTo:'/tmp/bar' |
3523 ]. |
3688 ]. |
3524 |
3689 |
3525 self isReadable ifFalse:[^ 'unreadable']. |
3690 self isReadable ifFalse:[^ 'unreadable']. |
3526 info fileSize == 0 ifTrue:[^ 'empty']. |
3691 info fileSize == 0 ifTrue:[^ 'empty']. |
3527 |
3692 |
3528 suffix := self suffix asLowercase. |
3693 "/ suffix := self suffix asLowercase. |
3529 baseNm := self withoutSuffix baseName asLowercase. |
3694 "/ baseNm := self withoutSuffix baseName asLowercase. |
3530 |
3695 |
3531 ((#('st' 'rc' 'chg' 'htm' 'html' 'ps' 'cls' 'pac') includes:suffix) |
3696 mime := self mimeTypeOfContents. |
3532 or:[#('makefile') includes:baseNm]) ifTrue:[ |
3697 mime notNil ifTrue:[ |
3533 |
3698 "/ kludge to avoid making libview a prereq. of libbasic |
3534 buffer := String new:2048. |
3699 (Smalltalk at:#MIMETypes) notNil ifTrue:[ |
3535 s := self readStreamOrNil. |
3700 info := (Smalltalk at:#MIMETypes) fileInfoForMimeType:mime. |
3536 s notNil ifTrue:[ |
3701 info notNil ifTrue:[^ info]. |
3537 n := s nextBytes:buffer size into:buffer. |
3702 ]. |
3538 s close. |
3703 ]. |
3539 buffer := buffer asLowercase. |
|
3540 (#('st' 'cls') includes:suffix) ifTrue:[ |
|
3541 #( |
|
3542 ('from squeak' 'smalltalk source (Squeak)') |
|
3543 ('from dolphin' 'smalltalk source (Dolphin)') |
|
3544 ('from visualworks' 'smalltalk source (VisualWorks)') |
|
3545 ('categoriesforclass' 'smalltalk source (Dolphin)') |
|
3546 ('methodsfor!!' 'smalltalk source (Dolphin, ST/V or V''age)') |
|
3547 ('subclass:' 'smalltalk source') |
|
3548 ('methodsfor:' 'smalltalk source') |
|
3549 ) pairsDo:[:pattern :what | |
|
3550 (buffer findString:pattern) ~~ 0 ifTrue:[ |
|
3551 ^ what |
|
3552 ] |
|
3553 ]. |
|
3554 ]. |
|
3555 |
|
3556 (buffer findString:'methodsfor:') ~~ 0 ifTrue:[ |
|
3557 ^ 'smalltalk changes / method source' |
|
3558 ]. |
|
3559 |
|
3560 (suffix = 'rc') ifTrue:[ |
|
3561 (buffer findString:'st/x startup') ~~ 0 ifTrue:[ |
|
3562 ^ 'smalltalk startup script' |
|
3563 ]. |
|
3564 ]. |
|
3565 |
|
3566 (suffix = 'htm' or:[suffix = 'html']) ifTrue:[ |
|
3567 (idx := buffer findString:'<h') ~~ 0 ifTrue:[ |
|
3568 ((buffer continuesWith:'<head' startingAt:idx) |
|
3569 or:[(buffer continuesWith:'<html' startingAt:idx) |
|
3570 or:[(buffer continuesWith:'<h1' startingAt:idx) |
|
3571 or:[(buffer continuesWith:'<h2' startingAt:idx) |
|
3572 or:[(buffer continuesWith:'<h3' startingAt:idx) |
|
3573 or:[(buffer continuesWith:'<h4' startingAt:idx) |
|
3574 or:[(buffer continuesWith:'<h5' startingAt:idx) |
|
3575 or:[(buffer continuesWith:'<h6' startingAt:idx)]]]]]]]) |
|
3576 ifTrue:[ |
|
3577 ^ 'HTML document text' |
|
3578 ] |
|
3579 ]. |
|
3580 ]. |
|
3581 |
|
3582 (suffix = 'ps') ifTrue:[ |
|
3583 (buffer findString:'%!!ps-adobe') ~~ 0 ifTrue:[ |
|
3584 ^ 'PostScript document' |
|
3585 ]. |
|
3586 ]. |
|
3587 |
|
3588 (baseNm = 'makefile') ifTrue:[ |
|
3589 (buffer startsWith:'#') ifTrue:[ |
|
3590 ^ 'make rules' |
|
3591 ] |
|
3592 ] |
|
3593 ] |
|
3594 ]. |
|
3595 |
|
3596 ^ 'file' |
3704 ^ 'file' |
3597 |
3705 |
3598 " |
3706 " |
3599 'Makefile' asFilename fileType |
3707 'Makefile' asFilename fileType |
3600 '.' asFilename fileType |
3708 '.' asFilename fileType |
4021 |
4130 |
4022 OperatingSystem isOSXlike ifFalse:[ |
4131 OperatingSystem isOSXlike ifFalse:[ |
4023 self warn:'sorry - this operation is only available under osx'. |
4132 self warn:'sorry - this operation is only available under osx'. |
4024 ]. |
4133 ]. |
4025 |
4134 |
4026 OperatingSystem executeCommand:'open ',self pathName |
4135 OperatingSystem executeCommand:'open "',self pathName,'"' |
4027 ! |
4136 ! |
4028 |
4137 |
4029 openTerminal |
4138 openTerminal |
4030 "open a terminal window on the directory represented by the receiver. |
4139 "open a terminal window on the directory represented by the receiver; |
4031 On non-osx systems, an error is raised" |
4140 on osx, a terminal app is opened, |
|
4141 on windows a cmd.exe window, |
|
4142 on unix, an xterm is opened." |
|
4143 |
|
4144 OperatingSystem isOSXlike ifTrue:[ |
|
4145 "/ I dont know yet how to tell the terminal to |
|
4146 "/ go to a particular directory. |
|
4147 "/ therefore, use the built in terminal |
|
4148 VT100TerminalView openShellIn:self pathName. |
|
4149 ^ self. |
|
4150 ]. |
4032 |
4151 |
4033 [ |
4152 [ |
|
4153 |cmd| |
|
4154 |
4034 OperatingSystem isOSXlike ifTrue:[ |
4155 OperatingSystem isOSXlike ifTrue:[ |
4035 OperatingSystem executeCommand:'/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal ' inDirectory:self pathName. |
4156 cmd := '/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal ' |
4036 ] ifFalse:[ |
4157 ] ifFalse:[ |
4037 OperatingSystem executeCommand:'xterm ' inDirectory:self pathName. |
4158 OperatingSystem isMSWINDOWSlike ifTrue:[ |
4038 ] |
4159 cmd := 'c:\windows\System32\cmd.exe' |
|
4160 ] ifFalse:[ |
|
4161 "/ VT100TerminalView openShellIn:self pathName |
|
4162 cmd := 'xterm' |
|
4163 ] |
|
4164 ]. |
|
4165 OperatingSystem |
|
4166 executeCommand:cmd |
|
4167 inDirectory:self pathName. |
4039 ] fork |
4168 ] fork |
4040 ! ! |
4169 ! ! |
4041 |
4170 |
4042 !Filename methodsFor:'printing & storing'! |
4171 !Filename methodsFor:'printing & storing'! |
4043 |
4172 |
4389 ] do:[ |
4524 ] do:[ |
4390 size := s nextBytes:buffer size into:buffer. |
4525 size := s nextBytes:buffer size into:buffer. |
4391 ]. |
4526 ]. |
4392 s close. |
4527 s close. |
4393 |
4528 |
4394 ^ MIMETypes mimeTypeOfData:buffer |
4529 "/ kludge to avoid making libview a prereq. of libbasic |
4395 |
4530 (mimeTypes := Smalltalk at:#MIMETypes) notNil ifTrue:[ |
4396 "/ lcBuffer := buffer asLowercase. |
4531 ^ mimeTypes mimeTypeOfData:buffer suffix:self suffix. |
4397 "/ |
4532 ]. |
4398 "/ (idx := lcBuffer findString:'mimetype:') ~~ 0 ifTrue:[ |
4533 ^ nil |
4399 "/ idx := idx + 'mimetype:' size. |
|
4400 "/ idx := lcBuffer indexOfNonSeparatorStartingAt:idx. |
|
4401 "/ idx2 := lcBuffer indexOfSeparatorStartingAt:idx. |
|
4402 "/ idx2 > idx ifTrue:[ |
|
4403 "/ ^ lcBuffer copyFrom:idx to:idx2-1 |
|
4404 "/ ]. |
|
4405 "/ ]. |
|
4406 "/ |
|
4407 "/ #( |
|
4408 "/ ( 'lnk' #[16r4C 16r00 16r00 16r00 16r01 16r14 16r02 16r00 16r00 16r00 16r00 16r00 16rC0 16r00 16r00 16r00 16r00 16r00 16r00 16r46] |
|
4409 "/ #'application/x-ms-shortcut' ) |
|
4410 "/ ( 'top' 'WALTOP' |
|
4411 "/ #'application/x-waltop-digital-notepad' ) |
|
4412 "/ ) triplesDo:[:suffixMatch :pattern :what | |
|
4413 "/ |patternString| |
|
4414 "/ |
|
4415 "/ (suffixMatch isNil or:[suffixMatch match:self suffix ignoreCase:true]) ifTrue:[ |
|
4416 "/ patternString := pattern asString. |
|
4417 "/ (buffer startsWith:patternString) ifTrue:[ |
|
4418 "/ ^ what |
|
4419 "/ ] |
|
4420 "/ ] |
|
4421 "/ ]. |
|
4422 "/ |
|
4423 "/ #( |
|
4424 "/ ('<body:' #'text/html') |
|
4425 "/ ('%!!ps-adobe' #'application/postscript') |
|
4426 "/ ('%PDF-' #'application/pdf') |
|
4427 "/ ('#!! /bin/sh' #'application/x-sh') |
|
4428 "/ ('#!!/bin/sh' #'application/x-sh') |
|
4429 "/ "/ ('#!! /bin/bash' 'application/x-bash') |
|
4430 "/ "/ ('#!!/bin/bash' 'application/x-bash') |
|
4431 "/ ('<?xml version=' #'text/xml') |
|
4432 "/ |
|
4433 "/ ('from dolphin' #'application/x-smalltalk-source') |
|
4434 "/ ('from visualworks' #'application/x-smalltalk-source') |
|
4435 "/ ('categoriesforclass' #'application/x-smalltalk-source') |
|
4436 "/ ('methodsfor!!' #'application/x-smalltalk-source') |
|
4437 "/ ('subclass:' #'application/x-smalltalk-source') |
|
4438 "/ ('methodsfor:' #'application/x-smalltalk-source') |
|
4439 "/ ('interchangeversion:' #'application/x-smalltalk-source-sif') |
|
4440 "/ ('subclass:' #'application/x-smalltalk-source') |
|
4441 "/ ('methodsfor:' #'application/x-smalltalk-source') |
|
4442 "/ |
|
4443 "/ ) pairsDo:[:pattern :what | |
|
4444 "/ (lcBuffer findString:pattern) ~~ 0 ifTrue:[ |
|
4445 "/ ^ what |
|
4446 "/ ] |
|
4447 "/ ]. |
|
4448 "/ |
|
4449 "/ (idx := lcBuffer findString:'<h') ~~ 0 ifTrue:[ |
|
4450 "/ ((lcBuffer continuesWith:'<head' startingAt:idx) |
|
4451 "/ or:[(lcBuffer continuesWith:'<html' startingAt:idx) |
|
4452 "/ or:[(lcBuffer continuesWith:'<h1' startingAt:idx) |
|
4453 "/ or:[(lcBuffer continuesWith:'<h2' startingAt:idx) |
|
4454 "/ or:[(lcBuffer continuesWith:'<h3' startingAt:idx) |
|
4455 "/ or:[(lcBuffer continuesWith:'<h4' startingAt:idx) |
|
4456 "/ or:[(lcBuffer continuesWith:'<h5' startingAt:idx) |
|
4457 "/ or:[(lcBuffer continuesWith:'<h6' startingAt:idx)]]]]]]]) |
|
4458 "/ ifTrue:[ |
|
4459 "/ ^ #'text/html' |
|
4460 "/ ] |
|
4461 "/ ]. |
|
4462 "/ |
|
4463 "/ [size ~~ 0 and:[(buffer at:size) isPrintable]] whileTrue:[size := size - 1]. |
|
4464 "/ |
|
4465 "/ size == 0 ifTrue:[ |
|
4466 "/ ^ #'text/plain' |
|
4467 "/ ]. |
|
4468 "/ ^ nil |
|
4469 |
4534 |
4470 " |
4535 " |
4471 'Makefile' asFilename mimeTypeOfContents |
4536 'Makefile' asFilename mimeTypeOfContents |
4472 '.' asFilename mimeTypeOfContents |
4537 '.' asFilename mimeTypeOfContents |
4473 '/dev/null' asFilename mimeTypeOfContents |
4538 '/dev/null' asFilename mimeTypeOfContents |
4564 a string instead of a Filename instance). |
4629 a string instead of a Filename instance). |
4565 |
4630 |
4566 See also: #pathName, #directoryPathName and #baseName. |
4631 See also: #pathName, #directoryPathName and #baseName. |
4567 Compatibility note: use #head for ST-80 compatibility." |
4632 Compatibility note: use #head for ST-80 compatibility." |
4568 |
4633 |
4569 |index sep sepString p rest| |
4634 |index sep sepString p rest parentDirectoryString| |
4570 |
4635 |
4571 sep := self separator. |
4636 sep := self separator. |
4572 sepString := sep asString. |
4637 sepString := sep asString. |
4573 (nameString = sepString) ifTrue:[ |
4638 (nameString = sepString) ifTrue:[ |
4574 "/ |
4639 "/ |
4575 "/ the trivial '/' case |
4640 "/ the trivial '/' case |
4576 "/ |
4641 "/ |
4577 ^ nameString |
4642 ^ sepString |
4578 ]. |
4643 ]. |
4579 |
4644 |
4580 "/ |
4645 "/ |
4581 "/ strip off multiple trailing slashes |
4646 "/ strip off multiple trailing slashes |
4582 "/ |
4647 "/ |
4583 p := nameString. |
4648 p := nameString. |
4584 [p endsWith:sepString] whileTrue:[ |
4649 [p endsWith:sep] whileTrue:[ |
4585 (p = sepString) ifTrue:[ |
4650 (p = sepString) ifTrue:[ |
4586 ^ p |
4651 ^ sepString |
4587 ]. |
4652 ]. |
4588 p := p copyButLast:1 |
4653 p := p copyButLast:1 |
4589 ]. |
4654 ]. |
4590 |
4655 |
|
4656 parentDirectoryString := self class parentDirectoryName. |
|
4657 |
4591 "/ strip off trailing components |
4658 "/ strip off trailing components |
4592 |
|
4593 index := p lastIndexOf:sep startingAt:p size. |
4659 index := p lastIndexOf:sep startingAt:p size. |
4594 index == 0 ifTrue:[ |
4660 index == 0 ifTrue:[ |
4595 "/ no separator found |
4661 "/ no separator found |
4596 p = '.' ifTrue:[ |
4662 p = '.' ifTrue:[ |
4597 ^ '..' |
4663 ^ parentDirectoryString |
4598 ]. |
4664 ]. |
4599 p = '..' ifTrue:[ |
4665 p = '..' ifTrue:[ |
4600 ^ '../..' |
4666 ^ parentDirectoryString, sepString, parentDirectoryString |
4601 ]. |
4667 ]. |
4602 ^ '.' |
4668 ^ '.' |
4603 ]. |
4669 ]. |
4604 rest := p copyFrom:(index+1). |
4670 rest := p copyFrom:(index+1). |
4605 (rest = '.') ifTrue:[ |
4671 (rest = '.') ifTrue:[ |
4606 ^ p copyTo:index-1. |
4672 ^ p copyTo:index-1. |
4607 ]. |
4673 ]. |
4608 (rest = '..') ifTrue:[ |
4674 (rest = parentDirectoryString) ifTrue:[ |
4609 ^ (self species named:(p copyTo:(index-1))) directoryName |
4675 ^ (self species named:(p copyTo:(index-1))) directoryName |
4610 ]. |
4676 ]. |
4611 index == 1 ifTrue:[ |
4677 index == 1 ifTrue:[ |
4612 ^ '/' |
4678 ^ sepString |
4613 ]. |
4679 ]. |
4614 ^ p copyTo:(index - 1) |
4680 ^ p copyTo:(index - 1) |
4615 |
4681 |
4616 " |
4682 " |
4617 '/home' asFilename directoryName |
4683 '/home' asFilename directoryName |
4921 |
4989 |
4922 "Created: 18.9.1997 / 18:04:51 / stefan" |
4990 "Created: 18.9.1997 / 18:04:51 / stefan" |
4923 ! |
4991 ! |
4924 |
4992 |
4925 isParentDirectoryOf:aFilenameOrString |
4993 isParentDirectoryOf:aFilenameOrString |
4926 "warning: may lead to automounting" |
4994 "Answer true, if myself is a parent directory of aFilenameOrString. |
4927 |
4995 Unexpected results may be returned, if one of myself or aFilenameOrString does |
4928 |filenameArg otherName myName| |
4996 not exist and relative and absolute path names are mixed |
|
4997 ('/' asFilename isParentDirectoryOf:'../noExistant' -> false) |
|
4998 |
|
4999 Warning: maybe symbolic links must be resolved which could lead to automounting" |
|
5000 |
|
5001 |filenameArg otherNames myNames myName| |
4929 |
5002 |
4930 filenameArg := aFilenameOrString asFilename. |
5003 filenameArg := aFilenameOrString asFilename. |
4931 filenameArg isDirectory ifFalse:[ |
5004 |
4932 filenameArg := filenameArg directory. |
5005 "first do a simple comparison" |
4933 ]. |
5006 otherNames := self class canonicalizedNameComponents:filenameArg name. |
4934 |
5007 myNames := self class canonicalizedNameComponents:self name. |
4935 otherName := filenameArg name. |
5008 ((otherNames startsWith:myNames) and:[myNames first ~= self class parentDirectoryName]) ifTrue:[ |
4936 myName := self name. |
5009 ^ otherNames ~= myNames |
4937 (otherName startsWith:myName ) ifTrue:[ |
5010 ]. |
4938 ^ (otherName ~= myName) |
5011 |
4939 ]. |
5012 "fall back - try it again with ~ substitution and symbolic links resolved" |
4940 |
5013 otherNames := self class canonicalizedNameComponents:filenameArg pathName. |
4941 otherName := filenameArg pathName. |
5014 myNames := self class canonicalizedNameComponents:self pathName. |
4942 myName := self pathName. |
5015 (otherNames startsWith:myNames) ifTrue:[ |
4943 (otherName startsWith:myName ) ifTrue:[ |
5016 ^ otherNames ~= myNames |
4944 ^ (otherName ~= myName) |
5017 ]. |
4945 ]. |
5018 |
4946 |
5019 myName := self class nameFromComponents:myNames. |
4947 filenameArg allParentDirectoriesDo:[:parent | |
5020 filenameArg allParentDirectoriesDo:[:parent | |
4948 parent pathName = myName ifTrue:[^ true]. |
5021 parent pathName = myName ifTrue:[^ true]. |
4949 ]. |
5022 ]. |
4950 ^ false. |
5023 ^ false. |
4951 |
5024 |
4952 " |
5025 " |
4953 '/etc' asFilename isParentDirectoryOf:'/etc/passwd' |
5026 '/etc' asFilename isParentDirectoryOf:'/etc/passwd' |
|
5027 'etc' asFilename isParentDirectoryOf:'etc/passwd' |
4954 '/etc' asFilename isParentDirectoryOf:'/etc/' |
5028 '/etc' asFilename isParentDirectoryOf:'/etc/' |
4955 '/etc' asFilename isParentDirectoryOf:'/etc' |
5029 '/etc' asFilename isParentDirectoryOf:'/etc' |
|
5030 '/et' asFilename isParentDirectoryOf:'/etc' |
4956 '/home' asFilename isParentDirectoryOf:Filename currentDirectory |
5031 '/home' asFilename isParentDirectoryOf:Filename currentDirectory |
|
5032 '~' asFilename isParentDirectoryOf:Filename currentDirectory |
|
5033 '~' asFilename isParentDirectoryOf:'.' |
|
5034 '~' asFilename isParentDirectoryOf:'..' |
|
5035 '~' asFilename isParentDirectoryOf:'../smalltalk' |
|
5036 '../..' asFilename isParentDirectoryOf:'../nonExistant' |
|
5037 '..' asFilename isParentDirectoryOf:'../../nonExistant' |
|
5038 '/' asFilename isParentDirectoryOf:'../nonExistant' |
4957 '/' asFilename isParentDirectoryOf:'/phys/qnx' |
5039 '/' asFilename isParentDirectoryOf:'/phys/qnx' |
4958 " |
5040 " |
4959 ! |
5041 ! |
4960 |
5042 |
4961 isRelative |
5043 isRelative |
5820 prefixAndSuffix |
5902 prefixAndSuffix |
5821 "return an array consisting of my prefix and suffix. |
5903 "return an array consisting of my prefix and suffix. |
5822 The suffix is the namepart after the final period character, |
5904 The suffix is the namepart after the final period character, |
5823 the prefix everything before, except for the period. |
5905 the prefix everything before, except for the period. |
5824 The directory name part is stripped off (i.e. the returned prefix |
5906 The directory name part is stripped off (i.e. the returned prefix |
5825 will consist of the files basename only.) |
5907 will consist of the file's basename only.) |
5826 (on some systems, the suffix-character may be different from a period). |
5908 (on some systems, the suffix-character may be different from a period). |
5827 For example, foo.bar.baz has a prefix of 'foo.bar' and a suffix of '.baz'. |
5909 For example, foo.bar.baz has a prefix of 'foo.bar' and a suffix of '.baz'. |
5828 An exception to the above: if the name starts with the suffixCharacter, |
5910 An exception to the above: if the name starts with the suffixCharacter, |
5829 that part is NOT considered a suffix. Thus, '.foorc' has no suffix and a prefix of |
5911 that part is NOT considered a suffix. Thus, '.foorc' has no suffix and a prefix of |
5830 '.foorc'. |
5912 '.foorc'. |