summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixFCmd.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-11-07 15:39:37 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-11-07 15:39:37 (GMT)
commitd6d77a73bef59053e103b7d28390ade0e651a8cc (patch)
tree2b5525e94553d4e1348506e2c741cf863d9e8fcb /unix/tclUnixFCmd.c
parent9348f2301275b473b59425310f3ac4beb7e545c0 (diff)
parent22c56e716cf046ee48897490b5b2264d8c9cb328 (diff)
downloadtcl-d6d77a73bef59053e103b7d28390ade0e651a8cc.zip
tcl-d6d77a73bef59053e103b7d28390ade0e651a8cc.tar.gz
tcl-d6d77a73bef59053e103b7d28390ade0e651a8cc.tar.bz2
Merge 8.7
Diffstat (limited to 'unix/tclUnixFCmd.c')
-rw-r--r--unix/tclUnixFCmd.c110
1 files changed, 54 insertions, 56 deletions
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c
index 6f60664..463f642 100644
--- a/unix/tclUnixFCmd.c
+++ b/unix/tclUnixFCmd.c
@@ -1923,17 +1923,14 @@ GetModeFromPermString(
*
* TclpObjNormalizePath --
*
- * This function scans through a path specification and replaces it, in
- * place, with a normalized version. A normalized version is one in which
- * all symlinks in the path are replaced with their expanded form (except
- * a symlink at the very end of the path).
+ * Replaces each component except that last one in a pathname that is a
+ * symbolic link with the fully resolved target of that link.
*
* Results:
- * The new 'nextCheckpoint' value, giving as far as we could understand
- * in the path.
+ * Stores the resulting path in pathPtr and returns the offset of the last
+ * byte processed to obtain the resulting path.
*
* Side effects:
- * The pathPtr string, is modified.
*
*---------------------------------------------------------------------------
*/
@@ -1941,8 +1938,14 @@ GetModeFromPermString(
int
TclpObjNormalizePath(
Tcl_Interp *dummy,
- Tcl_Obj *pathPtr,
- int nextCheckpoint)
+ Tcl_Obj *pathPtr, /* An unshared object containing the path to
+ * normalize. */
+ int nextCheckpoint) /* offset to start at in pathPtr. Must either
+ * be 0 or the offset of a directory separator
+ * at the end of a path part that is already
+ * normalized. I.e. this is not the index of
+ * the byte just after the separator. */
+
{
const char *currentPathEndPosition;
char cur;
@@ -1955,23 +1958,17 @@ TclpObjNormalizePath(
#endif
(void)dummy;
- /*
- * We add '1' here because if nextCheckpoint is zero we know that '/'
- * exists, and if it isn't zero, it must point at a directory separator
- * which we also know exists.
- */
-
currentPathEndPosition = path + nextCheckpoint;
if (*currentPathEndPosition == '/') {
currentPathEndPosition++;
}
#ifndef NO_REALPATH
- /*
- * For speed, try to get the entire path in one go.
- */
-
if (nextCheckpoint == 0 && haveRealpath) {
+ /*
+ * Try to get the entire path in one go
+ */
+
const char *lastDir = strrchr(currentPathEndPosition, '/');
if (lastDir != NULL) {
@@ -1980,8 +1977,13 @@ TclpObjNormalizePath(
if (Realpath(nativePath, normPath) != NULL) {
if (*nativePath != '/' && *normPath == '/') {
/*
- * realpath has transformed a relative path into an
- * absolute path, we do not know how to handle this.
+ * realpath transformed a relative path into an
+ * absolute path. Fall back to the long way.
+ */
+
+ /*
+ * To do: This logic seems to be out of date. This whole
+ * routine should be reviewed and cleaed up.
*/
} else {
nextCheckpoint = lastDir - path;
@@ -2020,13 +2022,13 @@ TclpObjNormalizePath(
}
/*
- * Update the acceptable point.
+ * Assign the end of the current component to nextCheckpoint
*/
nextCheckpoint = currentPathEndPosition - path;
} else if (cur == 0) {
/*
- * Reached end of string.
+ * The end of the string.
*/
break;
@@ -2035,22 +2037,19 @@ TclpObjNormalizePath(
}
/*
- * We should really now convert this to a canonical path. We do that with
- * 'realpath' if we have it available. Otherwise we could step through
- * every single path component, checking whether it is a symlink, but that
- * would be a lot of work, and most modern OSes have 'realpath'.
+ * Call 'realpath' to obtain a canonical path.
*/
#ifndef NO_REALPATH
if (haveRealpath) {
- /*
- * If we only had '/foo' or '/' then we never increment nextCheckpoint
- * and we don't need or want to go through 'Realpath'. Also, on some
- * platforms, passing an empty string to 'Realpath' will give us the
- * normalized pwd, which is not what we want at all!
- */
-
if (nextCheckpoint == 0) {
+ /*
+ * The path contains at most one component, e.g. '/foo' or '/', so
+ * so there is nothing to resolve. Also, on some platforms
+ * 'Realpath' transforms an empty string into the normalized pwd,
+ * which is the wrong answer.
+ */
+
return 0;
}
@@ -2063,18 +2062,19 @@ TclpObjNormalizePath(
if ((newNormLen == Tcl_DStringLength(&ds))
&& (strcmp(normPath, nativePath) == 0)) {
/*
- * String is unchanged.
+ * The original path is unchanged.
*/
Tcl_DStringFree(&ds);
/*
- * Enable this to have the native FS claim normalization of
- * the whole path for existing files. That would permit the
- * caller to declare normalization complete without calls to
- * additional filesystems. Saving lots of calls is probably
- * worth the extra access() time here. When no other FS's are
- * registered though, things are less clear.
+ * Uncommenting this would mean that this native filesystem
+ * routine claims the path is normalized if the file exists,
+ * which would permit the caller to avoid iterating through
+ * other filesystems filesystems. Saving lots of calls is
+ * probably worth the extra access() time, but in the common
+ * case that no other filesystems are registered this is an
+ * unnecessary expense.
*
if (0 == access(normPath, F_OK)) {
return pathLen;
@@ -2085,8 +2085,7 @@ TclpObjNormalizePath(
}
/*
- * Free up the native path and put in its place the converted,
- * normalized path.
+ * Free the original path and replace it with the normalized path.
*/
Tcl_DStringFree(&ds);
@@ -2094,7 +2093,7 @@ TclpObjNormalizePath(
if (path[nextCheckpoint] != '\0') {
/*
- * Not at end, append remaining path.
+ * Append the remaining path components.
*/
int normLen = Tcl_DStringLength(&ds);
@@ -2103,7 +2102,8 @@ TclpObjNormalizePath(
pathLen - nextCheckpoint);
/*
- * We recognise up to and including the directory separator.
+ * characters up to and including the directory separator have
+ * been processed
*/
nextCheckpoint = normLen + 1;
@@ -2115,10 +2115,6 @@ TclpObjNormalizePath(
nextCheckpoint = Tcl_DStringLength(&ds);
}
- /*
- * Overwrite with the normalized path.
- */
-
Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds),
Tcl_DStringLength(&ds));
}
@@ -2391,24 +2387,26 @@ static const int attributeArray[] = {
*
* GetUnixFileAttributes
*
- * Gets the readonly attribute of a file.
+ * Gets an attribute of a file.
*
* Results:
- * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
- * is no error. The object will have ref count 0.
+ * A standard Tcl result.
*
* Side effects:
- * A new object is allocated.
+ * If there is no error assigns to *attributePtrPtr the address of a new
+ * Tcl_Obj having a refCount of zero and containing the value of the
+ * specified attribute.
+ *
*
*----------------------------------------------------------------------
*/
static int
GetUnixFileAttributes(
- Tcl_Interp *interp, /* The interp we are using for errors. */
+ Tcl_Interp *interp, /* The interp to report errors to. */
int objIndex, /* The index of the attribute. */
- Tcl_Obj *fileName, /* The name of the file (UTF-8). */
- Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+ Tcl_Obj *fileName, /* The pathname of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* Where to store the result. */
{
int fileAttributes;
WCHAR *winPath = winPathFromObj(fileName);