| ︙ | | |
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
-
+
|
/*
* struct FilesystemRecord --
*
* An item in a linked list of registered filesystems
*/
typedef struct FilesystemRecord {
ClientData clientData; /* Client-specific data for the filesystem
void *clientData; /* Client-specific data for the filesystem
* (can be NULL) */
const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */
struct FilesystemRecord *nextPtr;
/* The next registered filesystem, or NULL to
* indicate the end of the list. */
struct FilesystemRecord *prevPtr;
/* The previous filesystem, or NULL to indicate
|
| ︙ | | |
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
-
+
-
+
-
+
|
* determine whether cwdPathPtr is stale.
*/
size_t filesystemEpoch;
Tcl_Obj *cwdPathPtr; /* A private copy of cwdPathPtr. Updated when
* the value is accessed and cwdPathEpoch has
* changed.
*/
ClientData cwdClientData;
void *cwdClientData;
FilesystemRecord *filesystemList;
size_t claims;
} ThreadSpecificData;
/*
* Forward declarations.
*/
static Tcl_NRPostProc EvalFileCallback;
static FilesystemRecord*FsGetFirstFilesystem(void);
static void FsThrExitProc(ClientData cd);
static void FsThrExitProc(void *cd);
static Tcl_Obj * FsListMounts(Tcl_Obj *pathPtr, const char *pattern);
static void FsAddMountsToGlobResult(Tcl_Obj *resultPtr,
Tcl_Obj *pathPtr, const char *pattern,
Tcl_GlobTypeData *types);
static void FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData);
static void FsUpdateCwd(Tcl_Obj *cwdObj, void *clientData);
static void FsRecacheFilesystemList(void);
static void Claim(void);
static void Disclaim(void);
static void * DivertFindSymbol(Tcl_Interp *interp,
Tcl_LoadHandle loadHandle, const char *symbol);
static void DivertUnloadFile(Tcl_LoadHandle loadHandle);
|
| ︙ | | |
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
-
+
-
+
|
/*
* A files-system indepent sense of the current directory.
*/
static Tcl_Obj *cwdPathPtr = NULL;
static size_t cwdPathEpoch = 0; /* The pathname of the current directory */
static ClientData cwdClientData = NULL;
static void *cwdClientData = NULL;
TCL_DECLARE_MUTEX(cwdMutex)
static Tcl_ThreadDataKey fsDataKey;
/*
* When a temporary copy of a file is created on the native filesystem in order
* to load the file, an FsDivertLoad structure is created to track both the
* actual unloadProc/clientData combination which was used, and the original and
* modified filenames. This makes it possible to correctly undo the entire
* operation in order to unload the library.
*/
typedef struct {
Tcl_LoadHandle loadHandle;
Tcl_FSUnloadFileProc *unloadProcPtr;
Tcl_Obj *divertedFile;
const Tcl_Filesystem *divertedFilesystem;
ClientData divertedFileNativeRep;
void *divertedFileNativeRep;
} FsDivertLoad;
/*
* Obsolete string-based APIs that should be removed in a future release,
* perhaps in Tcl 9.
*/
|
| ︙ | | |
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
|
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
|
-
+
|
/*
* The basic filesystem implementation.
*/
static void
FsThrExitProc(
ClientData cd)
void *cd)
{
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)cd;
FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;
/*
* Discard the cwd copy.
*/
|
| ︙ | | |
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
-
+
|
if (pathPtrPtr == NULL) {
return (tsdPtr->cwdPathPtr == NULL);
}
if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
return 1;
} else {
int len1, len2;
Tcl_Size len1, len2;
const char *str1, *str2;
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = TclGetStringFromObj(*pathPtrPtr, &len2);
if ((len1 == len2) && !memcmp(str1, str2, len1)) {
/*
* The values are equal but the objects are different. Cache the
|
| ︙ | | |
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
|
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
|
-
+
-
+
|
/*
* If non-NULL, take posession of clientData and free it later.
*/
static void
FsUpdateCwd(
Tcl_Obj *cwdObj,
ClientData clientData)
void *clientData)
{
int len;
Tcl_Size len;
const char *str = NULL;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);
if (cwdObj != NULL) {
str = TclGetStringFromObj(cwdObj, &len);
}
|
| ︙ | | |
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
|
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
|
-
+
|
* registered filesystems.
*
*----------------------------------------------------------------------
*/
int
Tcl_FSRegister(
ClientData clientData, /* Client-specific data for this filesystem. */
void *clientData, /* Client-specific data for this filesystem. */
const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */
{
FilesystemRecord *newFilesystemPtr;
if (fsPtr == NULL) {
return TCL_ERROR;
}
|
| ︙ | | |
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
|
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
|
-
+
+
|
* of the correct type. */
Tcl_GlobTypeData *types) /* Specifies acceptable types.
* May be NULL. The directory flag is
* particularly significant. */
{
const Tcl_Filesystem *fsPtr;
Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr;
int resLength, i, ret = -1;
Tcl_Size resLength, i;
int ret = -1;
if (types != NULL && (types->type & TCL_GLOB_TYPE_MOUNT)) {
/*
* Currently external callers may not query mounts, which would be a
* valuable future step. This is the only routine that knows about
* mounts, so we're being called recursively by ourself. Return no
* matches.
|
| ︙ | | |
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
|
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
|
-
+
-
+
|
* not be shared. */
Tcl_Obj *pathPtr, /* The directory that was searched. */
const char *pattern, /* Pattern to match mounts against. */
Tcl_GlobTypeData *types) /* Acceptable types. May be NULL. The
* directory flag is particularly significant.
*/
{
int mLength, gLength, i;
Tcl_Size mLength, gLength, i;
int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR));
Tcl_Obj *mounts = FsListMounts(pathPtr, pattern);
if (mounts == NULL) {
return;
}
if (TclListObjLengthM(NULL, mounts, &mLength) != TCL_OK || mLength == 0) {
goto endOfMounts;
}
if (TclListObjLengthM(NULL, resultPtr, &gLength) != TCL_OK) {
goto endOfMounts;
}
for (i=0 ; i<mLength ; i++) {
Tcl_Obj *mElt;
int j;
Tcl_Size j;
int found = 0;
Tcl_ListObjIndex(NULL, mounts, i, &mElt);
for (j=0 ; j<gLength ; j++) {
Tcl_Obj *gElt;
|
| ︙ | | |
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
|
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
|
-
+
|
gLength--;
}
break; /* Break out of for loop. */
}
}
if (!found && dir) {
Tcl_Obj *norm;
int len, mlen;
Tcl_Size len, mlen;
/*
* mElt is normalized and lies inside pathPtr so
* add to the result the right representation of mElt,
* i.e. the representation relative to pathPtr.
*/
|
| ︙ | | |
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
|
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
|
-
+
-
+
|
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
void *
Tcl_FSData(
const Tcl_Filesystem *fsPtr) /* The filesystem to find in the list of
* registered filesystems. */
{
ClientData retVal = NULL;
void *retVal = NULL;
FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
/*
* Find the filesystem in and retrieve its clientData.
*/
while ((retVal == NULL) && (fsRecPtr != NULL)) {
|
| ︙ | | |
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
|
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
|
-
+
|
* Must either be 0 or offset of a directory
* separator at the end of a pathname part that
* is already normalized, I.e. not the index of
* the byte just after the separator. */
{
FilesystemRecord *fsRecPtr, *firstFsRecPtr;
int i;
Tcl_Size i;
int isVfsPath = 0;
const char *path;
/*
* Pathnames starting with a UNC prefix and ending with a colon character
* are reserved for VFS use. These names can not conflict with real UNC
* pathnames per https://msdn.microsoft.com/en-us/library/gg465305.aspx and
|
| ︙ | | |
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
|
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
|
-
+
+
|
const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */
int *seekFlagPtr, /* Sets this to 1 to tell the the caller to seek to
* EOF after opening the file, and 0 otherwise. */
int *binaryPtr) /* Sets this to 1 to tell the caller to
* configure the channel for binary
* operations after opening the file. */
{
int mode, modeArgc, c, i, gotRW;
int mode, c, gotRW;
Tcl_Size modeArgc, i;
const char **modeArgv, *flag;
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)
/*
* Check for the simpler fopen-like access modes like "r" which are
* distinguished from the POSIX access modes by the presence of a
* lower-case first letter.
|
| ︙ | | |
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
|
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
|
+
-
+
|
Tcl_Interp *interp, /* Interpreter that evaluates the script. */
Tcl_Obj *pathPtr, /* Pathname of the file to process.
* Tilde-substitution is performed on this
* pathname. */
const char *encodingName) /* Either the name of an encoding or NULL to
use the utf-8 encoding. */
{
Tcl_Size length;
int length, result = TCL_ERROR;
int result = TCL_ERROR;
Tcl_StatBuf statBuf;
Tcl_Obj *oldScriptFile;
Interp *iPtr;
const char *string;
Tcl_Channel chan;
Tcl_Obj *objPtr;
|
| ︙ | | |
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
|
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
|
-
-
+
+
-
+
|
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
Tcl_GetString(pathPtr), Tcl_PosixError(interp)));
return result;
}
/*
* The eof character is \32 (^Z). This is standard on Windows, and Tcl
* uses it on every platform to allow for scripted documents. [Bug: 2040]
* The eof character is \x1A (^Z). Tcl uses it on every platform to allow
* for scripted documents. [Bug: 2040]
*/
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
Tcl_SetChannelOption(interp, chan, "-eofchar", "\x1A {}");
/*
* If the encoding is specified, set the channel to that encoding.
* Otherwise use utf-8. If the encoding is unknown report an error.
*/
if (encodingName == NULL) {
|
| ︙ | | |
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
|
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
|
-
+
|
string = Tcl_GetString(objPtr);
/*
* If first character is not a BOM, append the remaining characters.
* Otherwise, replace them. [Bug 3466099]
*/
if (Tcl_ReadChars(chan, objPtr, -1,
if (Tcl_ReadChars(chan, objPtr, TCL_INDEX_NONE,
memcmp(string, "\xEF\xBB\xBF", 3)) == TCL_IO_FAILURE) {
Tcl_Close(interp, chan);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
Tcl_GetString(pathPtr), Tcl_PosixError(interp)));
goto end;
}
|
| ︙ | | |
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
|
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
|
-
-
+
+
-
+
|
"couldn't read file \"%s\": %s",
Tcl_GetString(pathPtr), Tcl_PosixError(interp)));
return TCL_ERROR;
}
TclPkgFileSeen(interp, Tcl_GetString(pathPtr));
/*
* The eof character is \32 (^Z). This is standard on Windows, and Tcl
* uses it on every platform to allow for scripted documents. [Bug: 2040]
* The eof character is \x1A (^Z). Tcl uses it on every platform to allow
* for scripted documents. [Bug: 2040]
*/
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
Tcl_SetChannelOption(interp, chan, "-eofchar", "\x1A {}");
/*
* If the encoding is specified, set the channel to that encoding.
* Otherwise use utf-8. If the encoding is unknown report an error.
*/
if (encodingName == NULL) {
|
| ︙ | | |
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
|
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
|
-
+
|
string = Tcl_GetString(objPtr);
/*
* If first character is not a BOM, append the remaining characters.
* Otherwise, replace them. [Bug 3466099]
*/
if (Tcl_ReadChars(chan, objPtr, -1,
if (Tcl_ReadChars(chan, objPtr, TCL_INDEX_NONE,
memcmp(string, "\xEF\xBB\xBF", 3)) == TCL_IO_FAILURE) {
Tcl_Close(interp, chan);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't read file \"%s\": %s",
Tcl_GetString(pathPtr), Tcl_PosixError(interp)));
Tcl_DecrRefCount(objPtr);
return TCL_ERROR;
|
| ︙ | | |
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
|
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
|
-
+
|
TclNRAddCallback(interp, EvalFileCallback, oldScriptFile, pathPtr, objPtr,
NULL);
return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN);
}
static int
EvalFileCallback(
ClientData data[],
void *data[],
Tcl_Interp *interp,
int result)
{
Interp *iPtr = (Interp *) interp;
Tcl_Obj *oldScriptFile = (Tcl_Obj *)data[0];
Tcl_Obj *pathPtr = (Tcl_Obj *)data[1];
Tcl_Obj *objPtr = (Tcl_Obj *)data[2];
|
| ︙ | | |
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
|
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
|
-
+
|
if (result == TCL_RETURN) {
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
/*
* Record information about where the error occurred.
*/
int length;
Tcl_Size length;
const char *pathString = TclGetStringFromObj(pathPtr, &length);
const int limit = 150;
int overflow = (length > limit);
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (file \"%.*s%s\" line %d)",
(overflow ? limit : length), pathString,
|
| ︙ | | |
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
|
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
|
-
+
|
}
return result;
} else if (listObj != NULL) {
/*
* It's a non-constant attribute list, so do a literal search.
*/
int i, objc;
Tcl_Size i, objc;
Tcl_Obj **objv;
if (TclListObjGetElementsM(NULL, listObj, &objc, &objv) != TCL_OK) {
TclDecrRefCount(listObj);
return TCL_ERROR;
}
for (i=0 ; i<objc ; i++) {
|
| ︙ | | |
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
|
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
|
-
+
|
* current directory.
*/
fsRecPtr = FsGetFirstFilesystem();
Claim();
for (; (retVal == NULL) && (fsRecPtr != NULL);
fsRecPtr = fsRecPtr->nextPtr) {
ClientData retCd;
void *retCd;
TclFSGetCwdProc2 *proc2;
if (fsRecPtr->fsPtr->getCwdProc == NULL) {
continue;
}
if (fsRecPtr->fsPtr->version == TCL_FILESYSTEM_VERSION_1) {
|
| ︙ | | |
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
|
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
|
-
+
|
* if it is out-of-date. This allows an error to be thrown if, for
* example, the permissions on the current working directory have
* changed.
*/
const Tcl_Filesystem *fsPtr =
Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr);
ClientData retCd = NULL;
void *retCd = NULL;
Tcl_Obj *retVal, *norm;
if (fsPtr == NULL || fsPtr->getCwdProc == NULL) {
/*
* There is no corresponding filesystem or the filesystem does not
* have a getCwd routine. Just assume current local value is ok.
*/
|
| ︙ | | |
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
|
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
|
-
+
|
* Determine whether the filesystem's answer is the same as the
* cached local value. Since both 'norm' and 'tsdPtr->cwdPathPtr'
* are normalized pathnames, do something more efficient than
* calling 'Tcl_FSEqualPaths', and in addition avoid a nasty
* infinite loop bug when trying to normalize tsdPtr->cwdPathPtr.
*/
int len1, len2;
Tcl_Size len1, len2;
const char *str1, *str2;
str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
str2 = TclGetStringFromObj(norm, &len2);
if ((len1 == len2) && (strcmp(str1, str2) == 0)) {
/*
* The pathname values are equal so retain the old pathname
|
| ︙ | | |
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
|
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
|
-
-
+
+
|
if (normDirName == NULL) {
/* Not really true, but what else to do? */
Tcl_SetErrno(ENOENT);
return -1;
}
if (fsPtr == &tclNativeFilesystem) {
ClientData cd;
ClientData oldcd = tsdPtr->cwdClientData;
void *cd;
void *oldcd = tsdPtr->cwdClientData;
/*
* Assume that the native filesystem has a getCwdProc and that it
* is at version 2.
*/
TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc;
|
| ︙ | | |
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
|
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
|
-
-
+
-
+
|
*
* Side effects:
* If lenPtr is not null, sets it to the number of elements in the result.
*
*---------------------------------------------------------------------------
*/
#undef Tcl_FSSplitPath
Tcl_Obj *
Tcl_FSSplitPath(
Tcl_Obj *pathPtr, /* The pathname to split. */
int *lenPtr) /* A place to hold the number of pathname
Tcl_Size *lenPtr) /* A place to hold the number of pathname
* elements. */
{
Tcl_Obj *result = NULL; /* Just to squelch gcc warnings. */
const Tcl_Filesystem *fsPtr;
char separator = '/';
int driveNameLength;
Tcl_Size driveNameLength;
const char *p;
/*
* Perform platform-specific splitting.
*/
if (TclFSGetPathType(pathPtr, &fsPtr,
|
| ︙ | | |
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
|
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
|
-
+
|
/*
* Add the remaining pathname elements to the list.
*/
for (;;) {
const char *elementStart = p;
int length;
Tcl_Size length;
while ((*p != '\0') && (*p != separator)) {
p++;
}
length = p - elementStart;
if (length > 0) {
Tcl_Obj *nextElt;
|
| ︙ | | |
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
|
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
|
-
+
-
+
|
Tcl_PathType
TclGetPathType(
Tcl_Obj *pathPtr, /* Pathname to determine type of. */
const Tcl_Filesystem **filesystemPtrPtr,
/* If not NULL, a place in which to store a
* pointer to the filesystem for this pathname
* if it is absolute. */
int *driveNameLengthPtr, /* If not NULL, a place in which to store the
Tcl_Size *driveNameLengthPtr, /* If not NULL, a place in which to store the
* length of the volume name. */
Tcl_Obj **driveNameRef) /* If not NULL, for an absolute pathname, a
* place to store a pointer to an object with a
* refCount of 1, and whose value is the name
* of the volume. */
{
int pathLen;
Tcl_Size pathLen;
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
Tcl_PathType type;
type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
driveNameLengthPtr, driveNameRef);
if (type != TCL_PATH_ABSOLUTE) {
|
| ︙ | | |
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
|
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
|
-
+
-
+
|
*
*----------------------------------------------------------------------
*/
Tcl_PathType
TclFSNonnativePathType(
const char *path, /* Pathname to determine the type of. */
int pathLen, /* Length of the pathname. */
Tcl_Size pathLen, /* Length of the pathname. */
const Tcl_Filesystem **filesystemPtrPtr,
/* If not NULL, a place to store a pointer to
* the filesystem for this pathname when it is
* an absolute pathname. */
int *driveNameLengthPtr, /* If not NULL, a place to store the length of
Tcl_Size *driveNameLengthPtr,/* If not NULL, a place to store the length of
* the volume name if the pathname is absolute.
*/
Tcl_Obj **driveNameRef) /* If not NULL, a place to store a pointer to
* an object having its its refCount already
* incremented, and contining the name of the
* volume if the pathname is absolute. */
{
|
| ︙ | | |
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
|
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
|
-
+
-
+
-
+
|
* no reason to waste time doing that in this frequently-called
* function. It is better to save the overhead of the native
* filesystem continuously returning a list of volumes.
*/
if ((fsRecPtr->fsPtr != &tclNativeFilesystem)
&& (fsRecPtr->fsPtr->listVolumesProc != NULL)) {
int numVolumes;
Tcl_Size numVolumes;
Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc();
if (thisFsVolumes != NULL) {
if (TclListObjLengthM(NULL, thisFsVolumes, &numVolumes)
!= TCL_OK) {
/*
* This is VERY bad; the listVolumesProc didn't return a
* valid list. Set numVolumes to -1 to skip the loop below
* and just return with the current value of 'type'.
*
* It would be better to signal an error here, but
* Tcl_Panic seems a bit excessive.
*/
numVolumes = -1;
numVolumes = TCL_INDEX_NONE;
}
while (numVolumes > 0) {
Tcl_Obj *vol;
int len;
Tcl_Size len;
const char *strVol;
numVolumes--;
Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
strVol = TclGetStringFromObj(vol,&len);
if (pathLen < len) {
continue;
|
| ︙ | | |
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
|
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
|
-
+
-
+
|
return -1;
}
if (recursive) {
Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
if (cwdPtr != NULL) {
const char *cwdStr, *normPathStr;
int cwdLen, normLen;
Tcl_Size cwdLen, normLen;
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
if (normPath != NULL) {
normPathStr = TclGetStringFromObj(normPath, &normLen);
cwdStr = TclGetStringFromObj(cwdPtr, &cwdLen);
if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
(size_t) normLen) == 0)) {
normLen) == 0)) {
/*
* The cwd is inside the directory to be removed. Change
* the cwd to [file dirname $path].
*/
Tcl_Obj *dirPtr = TclPathPart(NULL, pathPtr,
TCL_PATH_DIRNAME);
|
| ︙ | | |
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
|
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
|
-
+
|
}
/*
* Call each of the "pathInFilesystem" functions in succession until the
* corresponding filesystem is found.
*/
for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) {
ClientData clientData = NULL;
void *clientData = NULL;
if (fsRecPtr->fsPtr->pathInFilesystemProc == NULL) {
continue;
}
if (fsRecPtr->fsPtr->pathInFilesystemProc(pathPtr, &clientData)!=-1) {
/* This is the filesystem for pathPtr. Assume the type of pathPtr
|
| ︙ | | |
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
|
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
|
-
+
|
* Memory is released.
*
*---------------------------------------------------------------------------
*/
static void
NativeFreeInternalRep(
ClientData clientData)
void *clientData)
{
ckfree(clientData);
}
/*
*---------------------------------------------------------------------------
*
|
| ︙ | | |