summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixFCmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixFCmd.c')
-rw-r--r--unix/tclUnixFCmd.c944
1 files changed, 277 insertions, 667 deletions
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c
index cc8af05..b5450b1 100644
--- a/unix/tclUnixFCmd.c
+++ b/unix/tclUnixFCmd.c
@@ -1,11 +1,11 @@
/*
* tclUnixFCmd.c
*
- * This file implements the Unix specific portion of file manipulation
+ * This file implements the unix specific portion of file manipulation
* subcommands of the "file" command. All filename arguments should
* already be translated to native format.
*
- * Copyright © 1996-1998 Sun Microsystems, Inc.
+ * Copyright (c) 1996-1998 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -13,7 +13,7 @@
* Portions of this code were derived from NetBSD source code which has the
* following copyright notice:
*
- * Copyright © 1988, 1993, 1994
+ * Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
#ifndef NO_FSTATFS
#include <sys/statfs.h>
#endif
-#endif /* !HAVE_STRUCT_STAT_ST_BLKSIZE */
+#endif
#ifdef HAVE_FTS
#include <fts.h>
#endif
@@ -62,16 +62,6 @@
#define DOTREE_F 3 /* regular file */
/*
- * Fallback temporary file location the temporary file generation code. Can be
- * overridden at compile time for when it is known that temp files can't be
- * written to /tmp (hello, iOS!).
- */
-
-#ifndef TCL_TEMPORARY_FILE_DIRECTORY
-#define TCL_TEMPORARY_FILE_DIRECTORY "/tmp"
-#endif
-
-/*
* Callbacks for file attributes code.
*/
@@ -90,11 +80,11 @@ static int SetPermissionsAttribute(Tcl_Interp *interp,
int objIndex, Tcl_Obj *fileName,
Tcl_Obj *attributePtr);
static int GetModeFromPermString(Tcl_Interp *interp,
- const char *modeStringPtr, mode_t *modePtr);
-#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
-static int GetUnixFileAttributes(Tcl_Interp *interp, int objIndex,
+ char *modeStringPtr, mode_t *modePtr);
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+static int GetReadOnlyAttribute(Tcl_Interp *interp, int objIndex,
Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
-static int SetUnixFileAttributes(Tcl_Interp *interp, int objIndex,
+static int SetReadOnlyAttribute(Tcl_Interp *interp, int objIndex,
Tcl_Obj *fileName, Tcl_Obj *attributePtr);
#endif
@@ -103,7 +93,7 @@ static int SetUnixFileAttributes(Tcl_Interp *interp, int objIndex,
*/
typedef int (TraversalProc)(Tcl_DString *srcPtr, Tcl_DString *dstPtr,
- const Tcl_StatBuf *statBufPtr, int type, Tcl_DString *errorPtr);
+ CONST Tcl_StatBuf *statBufPtr, int type, Tcl_DString *errorPtr);
/*
* Constants and variables necessary for file attributes subcommand.
@@ -113,66 +103,47 @@ typedef int (TraversalProc)(Tcl_DString *srcPtr, Tcl_DString *dstPtr,
* elsewhere in Tcl's core.
*/
-#ifndef DJGPP
+#ifdef DJGPP
+/*
+ * See contrib/djgpp/tclDjgppFCmd.c for definition.
+ */
+
+extern TclFileAttrProcs tclpFileAttrProcs[];
+extern char *tclpFileAttrStrings[];
+
+#else
enum {
-#if defined(__CYGWIN__)
- UNIX_ARCHIVE_ATTRIBUTE,
-#endif
- UNIX_GROUP_ATTRIBUTE,
-#if defined(__CYGWIN__)
- UNIX_HIDDEN_ATTRIBUTE,
-#endif
- UNIX_OWNER_ATTRIBUTE, UNIX_PERMISSIONS_ATTRIBUTE,
-#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
+ UNIX_GROUP_ATTRIBUTE, UNIX_OWNER_ATTRIBUTE, UNIX_PERMISSIONS_ATTRIBUTE,
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
UNIX_READONLY_ATTRIBUTE,
#endif
-#if defined(__CYGWIN__)
- UNIX_SYSTEM_ATTRIBUTE,
-#endif
#ifdef MAC_OSX_TCL
MACOSX_CREATOR_ATTRIBUTE, MACOSX_TYPE_ATTRIBUTE, MACOSX_HIDDEN_ATTRIBUTE,
MACOSX_RSRCLENGTH_ATTRIBUTE,
#endif
- UNIX_INVALID_ATTRIBUTE
+ UNIX_INVALID_ATTRIBUTE /* lint - last enum value needs no trailing , */
};
-const char *const tclpFileAttrStrings[] = {
-#if defined(__CYGWIN__)
- "-archive",
-#endif
- "-group",
-#if defined(__CYGWIN__)
- "-hidden",
-#endif
- "-owner", "-permissions",
-#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
+MODULE_SCOPE CONST char *tclpFileAttrStrings[];
+CONST char *tclpFileAttrStrings[] = {
+ "-group", "-owner", "-permissions",
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
"-readonly",
#endif
-#if defined(__CYGWIN__)
- "-system",
-#endif
#ifdef MAC_OSX_TCL
"-creator", "-type", "-hidden", "-rsrclength",
#endif
NULL
};
-const TclFileAttrProcs tclpFileAttrProcs[] = {
-#if defined(__CYGWIN__)
- {GetUnixFileAttributes, SetUnixFileAttributes},
-#endif
+MODULE_SCOPE CONST TclFileAttrProcs tclpFileAttrProcs[];
+CONST TclFileAttrProcs tclpFileAttrProcs[] = {
{GetGroupAttribute, SetGroupAttribute},
-#if defined(__CYGWIN__)
- {GetUnixFileAttributes, SetUnixFileAttributes},
-#endif
{GetOwnerAttribute, SetOwnerAttribute},
{GetPermissionsAttribute, SetPermissionsAttribute},
-#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
- {GetUnixFileAttributes, SetUnixFileAttributes},
-#endif
-#if defined(__CYGWIN__)
- {GetUnixFileAttributes, SetUnixFileAttributes},
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+ {GetReadOnlyAttribute, SetReadOnlyAttribute},
#endif
#ifdef MAC_OSX_TCL
{TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
@@ -181,7 +152,7 @@ const TclFileAttrProcs tclpFileAttrProcs[] = {
{TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
#endif
};
-#endif /* DJGPP */
+#endif
/*
* This is the maximum number of consecutive readdir/unlink calls that can be
@@ -202,23 +173,20 @@ const TclFileAttrProcs tclpFileAttrProcs[] = {
* Declarations for local procedures defined in this file:
*/
-static int CopyFileAtts(const char *src,
- const char *dst, const Tcl_StatBuf *statBufPtr);
-static const char * DefaultTempDir(void);
-static int DoCopyFile(const char *srcPtr, const char *dstPtr,
- const Tcl_StatBuf *statBufPtr);
-static int DoCreateDirectory(const char *pathPtr);
+static int CopyFileAtts(CONST char *src,
+ CONST char *dst, CONST Tcl_StatBuf *statBufPtr);
+static int DoCopyFile(CONST char *srcPtr, CONST char *dstPtr,
+ CONST Tcl_StatBuf *statBufPtr);
+static int DoCreateDirectory(CONST char *pathPtr);
static int DoRemoveDirectory(Tcl_DString *pathPtr,
int recursive, Tcl_DString *errorPtr);
-static int DoRenameFile(const char *src, const char *dst);
+static int DoRenameFile(CONST char *src, CONST char *dst);
static int TraversalCopy(Tcl_DString *srcPtr,
- Tcl_DString *dstPtr,
- const Tcl_StatBuf *statBufPtr, int type,
- Tcl_DString *errorPtr);
+ Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr,
+ int type, Tcl_DString *errorPtr);
static int TraversalDelete(Tcl_DString *srcPtr,
- Tcl_DString *dstPtr,
- const Tcl_StatBuf *statBufPtr, int type,
- Tcl_DString *errorPtr);
+ Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr,
+ int type, Tcl_DString *errorPtr);
static int TraverseUnixTree(TraversalProc *traversalProc,
Tcl_DString *sourcePtr, Tcl_DString *destPtr,
Tcl_DString *errorPtr, int doRewind);
@@ -231,22 +199,22 @@ static int TraverseUnixTree(TraversalProc *traversalProc,
* passing the standard MAXPATHLEN size resolved arg.
*/
-static char * Realpath(const char *path, char *resolved);
+static char * Realpath(CONST char *path, char *resolved);
char *
Realpath(
- const char *path,
+ CONST char *path,
char *resolved)
{
memset(resolved, 0, MAXPATHLEN);
return realpath(path, resolved);
}
#else
-# define Realpath realpath
-#endif /* PURIFY */
+#define Realpath realpath
+#endif
#ifndef NO_REALPATH
-#if defined(__APPLE__) && TCL_THREADS && \
+#if defined(__APPLE__) && defined(TCL_THREADS) && \
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
MAC_OS_X_VERSION_MIN_REQUIRED < 1030
/*
@@ -256,16 +224,16 @@ Realpath(
*/
MODULE_SCOPE long tclMacOSXDarwinRelease;
-# define haveRealpath (tclMacOSXDarwinRelease >= 7)
+#define haveRealpath (tclMacOSXDarwinRelease >= 7)
#else
-# define haveRealpath 1
+#define haveRealpath 1
#endif
#endif /* NO_REALPATH */
#ifdef HAVE_FTS
#if defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
/* fts doesn't do stat64 */
-# define noFtsStat 1
+#define noFtsStat 1
#elif defined(__APPLE__) && defined(__LP64__) && \
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
MAC_OS_X_VERSION_MIN_REQUIRED < 1050
@@ -276,9 +244,9 @@ MODULE_SCOPE long tclMacOSXDarwinRelease;
*/
MODULE_SCOPE long tclMacOSXDarwinRelease;
-# define noFtsStat (tclMacOSXDarwinRelease < 9)
+#define noFtsStat (tclMacOSXDarwinRelease < 9)
#else
-# define noFtsStat 0
+#define noFtsStat 0
#endif
#endif /* HAVE_FTS */
@@ -321,15 +289,15 @@ TclpObjRenameFile(
Tcl_Obj *srcPathPtr,
Tcl_Obj *destPathPtr)
{
- return DoRenameFile((const char *)Tcl_FSGetNativePath(srcPathPtr),
- (const char *)Tcl_FSGetNativePath(destPathPtr));
+ return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr),
+ Tcl_FSGetNativePath(destPathPtr));
}
static int
DoRenameFile(
- const char *src, /* Pathname of file or dir to be renamed
+ CONST char *src, /* Pathname of file or dir to be renamed
* (native). */
- const char *dst) /* New pathname of file or directory
+ CONST char *dst) /* New pathname of file or directory
* (native). */
{
if (rename(src, dst) == 0) { /* INTL: Native. */
@@ -340,7 +308,7 @@ DoRenameFile(
}
/*
- * IRIX returns EIO when you attempt to move a directory into itself. We
+ * IRIX returns EIO when you attept to move a directory into itself. We
* just map EIO to EINVAL get the right message on SGI. Most platforms
* don't return EIO except in really strange cases.
*/
@@ -359,13 +327,13 @@ DoRenameFile(
if (errno == EINVAL && haveRealpath) {
char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN];
- TclDIR *dirPtr;
+ DIR *dirPtr;
Tcl_DirEntry *dirEntPtr;
if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */
&& (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native */
&& (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) {
- dirPtr = TclOSopendir(dst); /* INTL: Native. */
+ dirPtr = opendir(dst); /* INTL: Native. */
if (dirPtr != NULL) {
while (1) {
dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */
@@ -375,11 +343,11 @@ DoRenameFile(
if ((strcmp(dirEntPtr->d_name, ".") != 0) &&
(strcmp(dirEntPtr->d_name, "..") != 0)) {
errno = EEXIST;
- TclOSclosedir(dirPtr);
+ closedir(dirPtr);
return TCL_ERROR;
}
}
- TclOSclosedir(dirPtr);
+ closedir(dirPtr);
}
}
errno = EINVAL;
@@ -437,21 +405,21 @@ TclpObjCopyFile(
Tcl_Obj *srcPathPtr,
Tcl_Obj *destPathPtr)
{
- const char *src = (const char *)Tcl_FSGetNativePath(srcPathPtr);
+ CONST char *src = Tcl_FSGetNativePath(srcPathPtr);
Tcl_StatBuf srcStatBuf;
if (TclOSlstat(src, &srcStatBuf) != 0) { /* INTL: Native. */
return TCL_ERROR;
}
- return DoCopyFile(src, (const char *)Tcl_FSGetNativePath(destPathPtr), &srcStatBuf);
+ return DoCopyFile(src, Tcl_FSGetNativePath(destPathPtr), &srcStatBuf);
}
static int
DoCopyFile(
- const char *src, /* Pathname of file to be copied (native). */
- const char *dst, /* Pathname of file to copy to (native). */
- const Tcl_StatBuf *statBufPtr)
+ CONST char *src, /* Pathname of file to be copied (native). */
+ CONST char *dst, /* Pathname of file to copy to (native). */
+ CONST Tcl_StatBuf *statBufPtr)
/* Used to determine filetype. */
{
Tcl_StatBuf dstStatBuf;
@@ -481,15 +449,15 @@ DoCopyFile(
switch ((int) (statBufPtr->st_mode & S_IFMT)) {
#ifndef DJGPP
case S_IFLNK: {
- char linkBuf[MAXPATHLEN+1];
+ char link[MAXPATHLEN];
int length;
- length = readlink(src, linkBuf, MAXPATHLEN); /* INTL: Native. */
+ length = readlink(src, link, sizeof(link)); /* INTL: Native. */
if (length == -1) {
return TCL_ERROR;
}
- linkBuf[length] = '\0';
- if (symlink(linkBuf, dst) < 0) { /* INTL: Native. */
+ link[length] = '\0';
+ if (symlink(link, dst) < 0) { /* INTL: Native. */
return TCL_ERROR;
}
#ifdef MAC_OSX_TCL
@@ -497,7 +465,7 @@ DoCopyFile(
#endif
break;
}
-#endif /* !DJGPP */
+#endif
case S_IFBLK:
case S_IFCHR:
if (mknod(dst, statBufPtr->st_mode, /* INTL: Native. */
@@ -535,10 +503,10 @@ DoCopyFile(
int
TclUnixCopyFile(
- const char *src, /* Pathname of file to copy (native). */
- const char *dst, /* Pathname of file to create/overwrite
+ CONST char *src, /* Pathname of file to copy (native). */
+ CONST char *dst, /* Pathname of file to create/overwrite
* (native). */
- const Tcl_StatBuf *statBufPtr,
+ CONST Tcl_StatBuf *statBufPtr,
/* Used to determine mode and blocksize. */
int dontCopyAtts) /* If flag set, don't copy attributes. */
{
@@ -551,9 +519,7 @@ TclUnixCopyFile(
#define BINMODE |O_BINARY
#else
#define BINMODE
-#endif /* DJGPP */
-
-#define DEFAULT_COPY_BLOCK_SIZE 4096
+#endif
if ((srcFd = TclOSopen(src, O_RDONLY BINMODE, 0)) < 0) { /* INTL: Native */
return TCL_ERROR;
@@ -581,11 +547,11 @@ TclUnixCopyFile(
if (fstatfs(srcFd, &fs) == 0) {
blockSize = fs.f_bsize;
} else {
- blockSize = DEFAULT_COPY_BLOCK_SIZE;
+ blockSize = 4096;
}
}
#else
- blockSize = DEFAULT_COPY_BLOCK_SIZE;
+ blockSize = 4096;
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
/*
@@ -597,9 +563,9 @@ TclUnixCopyFile(
*/
if (blockSize <= 0) {
- blockSize = DEFAULT_COPY_BLOCK_SIZE;
+ blockSize = 4096;
}
- buffer = (char *)ckalloc(blockSize);
+ buffer = ckalloc(blockSize);
while (1) {
nread = (size_t) read(srcFd, buffer, blockSize);
if ((nread == (size_t) -1) || (nread == 0)) {
@@ -660,9 +626,9 @@ TclpObjDeleteFile(
int
TclpDeleteFile(
- const void *path) /* Pathname of file to be removed (native). */
+ CONST char *path) /* Pathname of file to be removed (native). */
{
- if (unlink((const char *)path) != 0) {
+ if (unlink(path) != 0) { /* INTL: Native. */
return TCL_ERROR;
}
return TCL_OK;
@@ -698,12 +664,12 @@ int
TclpObjCreateDirectory(
Tcl_Obj *pathPtr)
{
- return DoCreateDirectory((const char *)Tcl_FSGetNativePath(pathPtr));
+ return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr));
}
static int
DoCreateDirectory(
- const char *path) /* Pathname of directory to create (native). */
+ CONST char *path) /* Pathname of directory to create (native). */
{
mode_t mode;
@@ -729,7 +695,7 @@ DoCreateDirectory(
*
* Recursively copies a directory. The target directory dst must not
* already exist. Note that this function does not merge two directory
- * hierarchies, even if the target directory is an empty directory.
+ * hierarchies, even if the target directory is an an empty directory.
*
* Results:
* If the directory was successfully copied, returns TCL_OK. Otherwise
@@ -778,7 +744,7 @@ TclpObjCopyDirectory(
Tcl_DStringFree(&dstString);
if (ret != TCL_OK) {
- *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), TCL_INDEX_NONE);
+ *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
Tcl_DStringFree(&ds);
Tcl_IncrRefCount(*errorPtr);
}
@@ -832,7 +798,7 @@ TclpObjRemoveDirectory(
Tcl_DStringFree(&pathString);
if (ret != TCL_OK) {
- *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), TCL_INDEX_NONE);
+ *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
Tcl_DStringFree(&ds);
Tcl_IncrRefCount(*errorPtr);
}
@@ -850,7 +816,7 @@ DoRemoveDirectory(
* filled with UTF-8 name of file causing
* error. */
{
- const char *path;
+ CONST char *path;
mode_t oldPerm = 0;
int result;
@@ -882,7 +848,7 @@ DoRemoveDirectory(
result = TCL_OK;
if ((errno != EEXIST) || (recursive == 0)) {
if (errorPtr != NULL) {
- Tcl_ExternalToUtfDString(NULL, path, TCL_INDEX_NONE, errorPtr);
+ Tcl_ExternalToUtfDString(NULL, path, -1, errorPtr);
}
result = TCL_ERROR;
}
@@ -948,22 +914,22 @@ TraverseUnixTree(
* files. */
{
Tcl_StatBuf statBuf;
- const char *source, *errfile;
+ CONST char *source, *errfile;
int result, sourceLen;
int targetLen;
#ifndef HAVE_FTS
int numProcessed = 0;
Tcl_DirEntry *dirEntPtr;
- TclDIR *dirPtr;
+ DIR *dirPtr;
#else
- const char *paths[2] = {NULL, NULL};
+ CONST char *paths[2] = {NULL, NULL};
FTS *fts = NULL;
FTSENT *ent;
#endif
errfile = NULL;
result = TCL_OK;
- targetLen = 0;
+ targetLen = 0; /* lint. */
source = Tcl_DStringValue(sourcePtr);
if (TclOSlstat(source, &statBuf) != 0) { /* INTL: Native. */
@@ -975,11 +941,11 @@ TraverseUnixTree(
* Process the regular file
*/
- return traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_F,
+ return (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_F,
errorPtr);
}
#ifndef HAVE_FTS
- dirPtr = TclOSopendir(source); /* INTL: Native. */
+ dirPtr = opendir(source); /* INTL: Native. */
if (dirPtr == NULL) {
/*
* Can't read directory
@@ -988,18 +954,18 @@ TraverseUnixTree(
errfile = source;
goto end;
}
- result = traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_PRED,
+ result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_PRED,
errorPtr);
if (result != TCL_OK) {
- TclOSclosedir(dirPtr);
+ closedir(dirPtr);
return result;
}
- TclDStringAppendLiteral(sourcePtr, "/");
+ Tcl_DStringAppend(sourcePtr, "/", 1);
sourceLen = Tcl_DStringLength(sourcePtr);
if (targetPtr != NULL) {
- TclDStringAppendLiteral(targetPtr, "/");
+ Tcl_DStringAppend(targetPtr, "/", 1);
targetLen = Tcl_DStringLength(targetPtr);
}
@@ -1014,9 +980,9 @@ TraverseUnixTree(
* Append name after slash, and recurse on the file.
*/
- Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, TCL_INDEX_NONE);
+ Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, -1);
if (targetPtr != NULL) {
- Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, TCL_INDEX_NONE);
+ Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, -1);
}
result = TraverseUnixTree(traverseProc, sourcePtr, targetPtr,
errorPtr, doRewind);
@@ -1041,11 +1007,11 @@ TraverseUnixTree(
* NULL-return that may a symptom of a buggy readdir.
*/
- TclOSrewinddir(dirPtr);
+ rewinddir(dirPtr);
numProcessed = 0;
}
}
- TclOSclosedir(dirPtr);
+ closedir(dirPtr);
/*
* Strip off the trailing slash we added
@@ -1062,12 +1028,12 @@ TraverseUnixTree(
* that directory.
*/
- result = traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_POSTD,
+ result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_POSTD,
errorPtr);
}
#else /* HAVE_FTS */
paths[0] = source;
- fts = fts_open((char **) paths, FTS_PHYSICAL | FTS_NOCHDIR |
+ fts = fts_open((char**)paths, FTS_PHYSICAL | FTS_NOCHDIR |
(noFtsStat || doRewind ? FTS_NOSTAT : 0), NULL);
if (fts == NULL) {
errfile = source;
@@ -1085,7 +1051,7 @@ TraverseUnixTree(
unsigned short pathlen = ent->fts_pathlen - sourceLen;
int type;
Tcl_StatBuf *statBufPtr = NULL;
-
+
if (info == FTS_DNR || info == FTS_ERR || info == FTS_NS) {
errfile = ent->fts_path;
break;
@@ -1116,7 +1082,7 @@ TraverseUnixTree(
statBufPtr = (Tcl_StatBuf *) ent->fts_statp;
}
}
- result = traverseProc(sourcePtr, targetPtr, statBufPtr, type,
+ result = (*traverseProc)(sourcePtr, targetPtr, statBufPtr, type,
errorPtr);
if (result != TCL_OK) {
break;
@@ -1126,12 +1092,12 @@ TraverseUnixTree(
Tcl_DStringSetLength(targetPtr, targetLen);
}
}
-#endif /* !HAVE_FTS */
+#endif /* HAVE_FTS */
end:
if (errfile != NULL) {
if (errorPtr != NULL) {
- Tcl_ExternalToUtfDString(NULL, errfile, TCL_INDEX_NONE, errorPtr);
+ Tcl_ExternalToUtfDString(NULL, errfile, -1, errorPtr);
}
result = TCL_ERROR;
}
@@ -1166,7 +1132,7 @@ static int
TraversalCopy(
Tcl_DString *srcPtr, /* Source pathname to copy (native). */
Tcl_DString *dstPtr, /* Destination pathname of copy (native). */
- const Tcl_StatBuf *statBufPtr,
+ CONST Tcl_StatBuf *statBufPtr,
/* Stat info for file specified by srcPtr. */
int type, /* Reason for call - see TraverseUnixTree(). */
Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
@@ -1229,14 +1195,14 @@ TraversalCopy(
static int
TraversalDelete(
Tcl_DString *srcPtr, /* Source pathname (native). */
- TCL_UNUSED(Tcl_DString *),
- TCL_UNUSED(const Tcl_StatBuf *),
+ Tcl_DString *ignore, /* Destination pathname (not used). */
+ CONST Tcl_StatBuf *statBufPtr,
+ /* Stat info for file specified by srcPtr. */
int type, /* Reason for call - see TraverseUnixTree(). */
Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
* filled with UTF-8 name of file causing
* error. */
{
-
switch (type) {
case DOTREE_F:
if (TclpDeleteFile(Tcl_DStringValue(srcPtr)) == 0) {
@@ -1278,13 +1244,9 @@ TraversalDelete(
static int
CopyFileAtts(
-#ifdef MAC_OSX_TCL
- const char *src, /* Path name of source file (native). */
-#else
- TCL_UNUSED(const char *) /*src*/,
-#endif
- const char *dst, /* Path name of target file (native). */
- const Tcl_StatBuf *statBufPtr)
+ CONST char *src, /* Path name of source file (native). */
+ CONST char *dst, /* Path name of target file (native). */
+ CONST Tcl_StatBuf *statBufPtr)
/* Stat info for source file */
{
struct utimbuf tval;
@@ -1308,8 +1270,8 @@ CopyFileAtts(
}
}
- tval.actime = Tcl_GetAccessTimeFromStat(statBufPtr);
- tval.modtime = Tcl_GetModificationTimeFromStat(statBufPtr);
+ tval.actime = statBufPtr->st_atime;
+ tval.modtime = statBufPtr->st_mtime;
if (utime(dst, &tval)) { /* INTL: Native. */
return TCL_ERROR;
@@ -1340,7 +1302,7 @@ CopyFileAtts(
static int
GetGroupAttribute(
Tcl_Interp *interp, /* The interp we are using for errors. */
- TCL_UNUSED(int) /*objIndex*/,
+ 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. */
{
@@ -1352,9 +1314,9 @@ GetGroupAttribute(
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -1362,13 +1324,13 @@ GetGroupAttribute(
groupPtr = TclpGetGrGid(statBuf.st_gid);
if (groupPtr == NULL) {
- TclNewIntObj(*attributePtrPtr, statBuf.st_gid);
+ *attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_gid);
} else {
Tcl_DString ds;
- const char *utf;
+ CONST char *utf;
- utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, TCL_INDEX_NONE, &ds);
- *attributePtrPtr = Tcl_NewStringObj(utf, TCL_INDEX_NONE);
+ utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, -1, &ds);
+ *attributePtrPtr = Tcl_NewStringObj(utf, -1);
Tcl_DStringFree(&ds);
}
return TCL_OK;
@@ -1394,7 +1356,7 @@ GetGroupAttribute(
static int
GetOwnerAttribute(
Tcl_Interp *interp, /* The interp we are using for errors. */
- TCL_UNUSED(int) /*objIndex*/,
+ 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. */
{
@@ -1406,9 +1368,9 @@ GetOwnerAttribute(
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -1416,12 +1378,14 @@ GetOwnerAttribute(
pwPtr = TclpGetPwUid(statBuf.st_uid);
if (pwPtr == NULL) {
- TclNewIntObj(*attributePtrPtr, statBuf.st_uid);
+ *attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_uid);
} else {
Tcl_DString ds;
+ CONST char *utf;
- (void) Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, TCL_INDEX_NONE, &ds);
- *attributePtrPtr = Tcl_DStringToObj(&ds);
+ utf = Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, -1, &ds);
+ *attributePtrPtr = Tcl_NewStringObj(utf, Tcl_DStringLength(&ds));
+ Tcl_DStringFree(&ds);
}
return TCL_OK;
}
@@ -1446,7 +1410,7 @@ GetOwnerAttribute(
static int
GetPermissionsAttribute(
Tcl_Interp *interp, /* The interp we are using for errors. */
- TCL_UNUSED(int) /*objIndex*/,
+ 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. */
{
@@ -1457,15 +1421,15 @@ GetPermissionsAttribute(
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
*attributePtrPtr = Tcl_ObjPrintf(
- "%0#5o", ((int)statBuf.st_mode & 0x7FFF));
+ "%0#5lo", (long) (statBuf.st_mode & 0x00007FFF));
return TCL_OK;
}
@@ -1488,47 +1452,45 @@ GetPermissionsAttribute(
static int
SetGroupAttribute(
Tcl_Interp *interp, /* The interp for error reporting. */
- TCL_UNUSED(int) /*objIndex*/,
+ int objIndex, /* The index of the attribute. */
Tcl_Obj *fileName, /* The name of the file (UTF-8). */
Tcl_Obj *attributePtr) /* New group for file. */
{
- Tcl_WideInt gid;
+ long gid;
int result;
- const char *native;
+ CONST char *native;
- if (Tcl_GetWideIntFromObj(NULL, attributePtr, &gid) != TCL_OK) {
+ if (Tcl_GetLongFromObj(NULL, attributePtr, &gid) != TCL_OK) {
Tcl_DString ds;
struct group *groupPtr = NULL;
- const char *string;
+ CONST char *string;
+ int length;
- string = TclGetString(attributePtr);
+ string = Tcl_GetStringFromObj(attributePtr, &length);
- native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds);
+ native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
groupPtr = TclpGetGrNam(native); /* INTL: Native. */
Tcl_DStringFree(&ds);
if (groupPtr == NULL) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not set group for file \"%s\":"
- " group \"%s\" does not exist",
- TclGetString(fileName), string));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SETGRP",
- "NO_GROUP", (char *)NULL);
+ Tcl_AppendResult(interp, "could not set group for file \"",
+ TclGetString(fileName), "\": group \"", string,
+ "\" does not exist", NULL);
}
return TCL_ERROR;
}
gid = groupPtr->gr_gid;
}
- native = (const char *)Tcl_FSGetNativePath(fileName);
+ native = Tcl_FSGetNativePath(fileName);
result = chown(native, (uid_t) -1, (gid_t) gid); /* INTL: Native. */
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not set group for file \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not set group for file \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
}
return TCL_ERROR;
}
@@ -1554,47 +1516,45 @@ SetGroupAttribute(
static int
SetOwnerAttribute(
Tcl_Interp *interp, /* The interp for error reporting. */
- TCL_UNUSED(int) /*objIndex*/,
+ int objIndex, /* The index of the attribute. */
Tcl_Obj *fileName, /* The name of the file (UTF-8). */
Tcl_Obj *attributePtr) /* New owner for file. */
{
- Tcl_WideInt uid;
+ long uid;
int result;
- const char *native;
+ CONST char *native;
- if (Tcl_GetWideIntFromObj(NULL, attributePtr, &uid) != TCL_OK) {
+ if (Tcl_GetLongFromObj(NULL, attributePtr, &uid) != TCL_OK) {
Tcl_DString ds;
struct passwd *pwPtr = NULL;
- const char *string;
+ CONST char *string;
+ int length;
- string = TclGetString(attributePtr);
+ string = Tcl_GetStringFromObj(attributePtr, &length);
- native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds);
+ native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
pwPtr = TclpGetPwNam(native); /* INTL: Native. */
Tcl_DStringFree(&ds);
if (pwPtr == NULL) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not set owner for file \"%s\":"
- " user \"%s\" does not exist",
- TclGetString(fileName), string));
- Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SETOWN",
- "NO_USER", (char *)NULL);
+ Tcl_AppendResult(interp, "could not set owner for file \"",
+ TclGetString(fileName), "\": user \"", string,
+ "\" does not exist", NULL);
}
return TCL_ERROR;
}
uid = pwPtr->pw_uid;
}
- native = (const char *)Tcl_FSGetNativePath(fileName);
+ native = Tcl_FSGetNativePath(fileName);
result = chown(native, (uid_t) uid, (gid_t) -1); /* INTL: Native. */
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not set owner for file \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not set owner for file \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
}
return TCL_ERROR;
}
@@ -1620,15 +1580,15 @@ SetOwnerAttribute(
static int
SetPermissionsAttribute(
Tcl_Interp *interp, /* The interp we are using for errors. */
- TCL_UNUSED(int) /*objIndex*/,
+ int objIndex, /* The index of the attribute. */
Tcl_Obj *fileName, /* The name of the file (UTF-8). */
Tcl_Obj *attributePtr) /* The attribute to set. */
{
- Tcl_WideInt mode;
+ long mode;
mode_t newMode;
int result = TCL_ERROR;
- const char *native;
- const char *modeStringPtr = TclGetString(attributePtr);
+ CONST char *native;
+ char *modeStringPtr = TclGetString(attributePtr);
int scanned = TclParseAllWhiteSpace(modeStringPtr, -1);
/*
@@ -1643,11 +1603,11 @@ SetPermissionsAttribute(
TclNewLiteralStringObj(modeObj, "0o");
Tcl_AppendToObj(modeObj, modeStringPtr+scanned+1, -1);
- result = Tcl_GetWideIntFromObj(NULL, modeObj, &mode);
+ result = Tcl_GetLongFromObj(NULL, modeObj, &mode);
Tcl_DecrRefCount(modeObj);
}
if (result == TCL_OK
- || Tcl_GetWideIntFromObj(NULL, attributePtr, &mode) == TCL_OK) {
+ || Tcl_GetLongFromObj(NULL, attributePtr, &mode) == TCL_OK) {
newMode = (mode_t) (mode & 0x00007FFF);
} else {
Tcl_StatBuf buf;
@@ -1662,9 +1622,9 @@ SetPermissionsAttribute(
result = TclpObjStat(fileName, &buf);
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -1672,22 +1632,20 @@ SetPermissionsAttribute(
if (GetModeFromPermString(NULL, modeStringPtr, &newMode) != TCL_OK) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "unknown permission string format \"%s\"",
- modeStringPtr));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "PERMISSION", (char *)NULL);
+ Tcl_AppendResult(interp, "unknown permission string format \"",
+ modeStringPtr, "\"", NULL);
}
return TCL_ERROR;
}
}
- native = (const char *)Tcl_FSGetNativePath(fileName);
+ native = Tcl_FSGetNativePath(fileName);
result = chmod(native, newMode); /* INTL: Native. */
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not set permissions for file \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not set permissions for file \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -1714,8 +1672,7 @@ SetPermissionsAttribute(
Tcl_Obj *
TclpObjListVolumes(void)
{
- Tcl_Obj *resultPtr;
- TclNewLiteralStringObj(resultPtr, "/");
+ Tcl_Obj *resultPtr = Tcl_NewStringObj("/", 1);
Tcl_IncrRefCount(resultPtr);
return resultPtr;
@@ -1742,8 +1699,8 @@ TclpObjListVolumes(void)
static int
GetModeFromPermString(
- TCL_UNUSED(Tcl_Interp *),
- const char *modeStringPtr, /* Permissions string */
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ char *modeStringPtr, /* Permissions string */
mode_t *modePtr) /* pointer to the mode value */
{
mode_t newMode;
@@ -1762,7 +1719,7 @@ GetModeFromPermString(
newMode = 0;
for (i = 0; i < 9; i++) {
- switch (modeStringPtr[i]) {
+ switch (*(modeStringPtr+i)) {
case 'r':
if ((i%3) != 0) {
goto chmodStyleCheck;
@@ -1824,15 +1781,15 @@ GetModeFromPermString(
* We now check for an "ugoa+-=rwxst" style permissions string
*/
- for (n = 0 ; modeStringPtr[n] != '\0' ; n += i) {
+ for (n = 0 ; *(modeStringPtr+n) != '\0' ; n = n + i) {
oldMode = *modePtr;
who = op = what = op_found = who_found = 0;
- for (i = 0 ; modeStringPtr[n + i] != '\0' ; i++ ) {
+ for (i = 0 ; *(modeStringPtr+n+i) != '\0' ; i++ ) {
if (!who_found) {
/* who */
- switch (modeStringPtr[n + i]) {
+ switch (*(modeStringPtr+n+i)) {
case 'u':
- who |= 0x9C0;
+ who |= 0x9c0;
continue;
case 'g':
who |= 0x438;
@@ -1841,17 +1798,17 @@ GetModeFromPermString(
who |= 0x207;
continue;
case 'a':
- who |= 0xFFF;
+ who |= 0xfff;
continue;
}
}
who_found = 1;
if (who == 0) {
- who = 0xFFF;
+ who = 0xfff;
}
if (!op_found) {
/* op */
- switch (modeStringPtr[n + i]) {
+ switch (*(modeStringPtr+n+i)) {
case '+':
op = 1;
op_found = 1;
@@ -1869,7 +1826,7 @@ GetModeFromPermString(
}
}
/* what */
- switch (modeStringPtr[n + i]) {
+ switch (*(modeStringPtr+n+i)) {
case 'r':
what |= 0x124;
continue;
@@ -1880,7 +1837,7 @@ GetModeFromPermString(
what |= 0x49;
continue;
case 's':
- what |= 0xC00;
+ what |= 0xc00;
continue;
case 't':
what |= 0x200;
@@ -1890,7 +1847,7 @@ GetModeFromPermString(
default:
return TCL_ERROR;
}
- if (modeStringPtr[n + i] == ',') {
+ if (*(modeStringPtr+n+i) == ',') {
i++;
break;
}
@@ -1915,52 +1872,55 @@ GetModeFromPermString(
*
* TclpObjNormalizePath --
*
- * Replaces each component except that last one in a pathname that is a
- * symbolic link with the fully resolved target of that link.
+ * 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).
*
* Results:
- * Stores the resulting path in pathPtr and returns the offset of the last
- * byte processed to obtain the resulting path.
+ * The new 'nextCheckpoint' value, giving as far as we could understand
+ * in the path.
*
* Side effects:
+ * The pathPtr string, is modified.
*
*---------------------------------------------------------------------------
*/
int
TclpObjNormalizePath(
- TCL_UNUSED(Tcl_Interp *),
- 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. */
-
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr,
+ int nextCheckpoint)
{
- const char *currentPathEndPosition;
+ char *currentPathEndPosition;
+ int pathLen;
char cur;
- const char *path = TclGetString(pathPtr);
- size_t pathLen = pathPtr->length;
- Tcl_DString ds;
- const char *nativePath;
+ char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);
#ifndef NO_REALPATH
char normPath[MAXPATHLEN];
+ Tcl_DString ds;
+ CONST char *nativePath;
#endif
+ /*
+ * 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
- if (nextCheckpoint == 0 && haveRealpath) {
- /*
- * Try to get the entire path in one go
- */
+ /*
+ * For speed, try to get the entire path in one go.
+ */
- const char *lastDir = strrchr(currentPathEndPosition, '/');
+ if (nextCheckpoint == 0 && haveRealpath) {
+ char *lastDir = strrchr(currentPathEndPosition, '/');
if (lastDir != NULL) {
nativePath = Tcl_UtfToExternalDString(NULL, path,
@@ -1968,13 +1928,8 @@ TclpObjNormalizePath(
if (Realpath(nativePath, normPath) != NULL) {
if (*nativePath != '/' && *normPath == '/') {
/*
- * 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.
+ * realpath has transformed a relative path into an
+ * absolute path, we do not know how to handle this.
*/
} else {
nextCheckpoint = lastDir - path;
@@ -1997,6 +1952,8 @@ TclpObjNormalizePath(
* Reached directory separator.
*/
+ Tcl_DString ds;
+ CONST char *nativePath;
int accessOk;
nativePath = Tcl_UtfToExternalDString(NULL, path,
@@ -2013,13 +1970,13 @@ TclpObjNormalizePath(
}
/*
- * Assign the end of the current component to nextCheckpoint
+ * Update the acceptable point.
*/
nextCheckpoint = currentPathEndPosition - path;
} else if (cur == 0) {
/*
- * The end of the string.
+ * Reached end of string.
*/
break;
@@ -2028,23 +1985,26 @@ TclpObjNormalizePath(
}
/*
- * Call 'realpath' to obtain a canonical path.
+ * 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'.
*/
#ifndef NO_REALPATH
if (haveRealpath) {
- 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.
- */
+ /*
+ * 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) {
return 0;
}
- nativePath = Tcl_UtfToExternalDString(NULL, path,nextCheckpoint, &ds);
+ nativePath = Tcl_UtfToExternalDString(NULL, path, nextCheckpoint, &ds);
if (Realpath(nativePath, normPath) != NULL) {
int newNormLen;
@@ -2053,19 +2013,18 @@ TclpObjNormalizePath(
if ((newNormLen == Tcl_DStringLength(&ds))
&& (strcmp(normPath, nativePath) == 0)) {
/*
- * The original path is unchanged.
+ * String is unchanged.
*/
Tcl_DStringFree(&ds);
/*
- * 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.
+ * 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.
*
if (0 == access(normPath, F_OK)) {
return pathLen;
@@ -2076,7 +2035,8 @@ TclpObjNormalizePath(
}
/*
- * Free the original path and replace it with the normalized path.
+ * Free up the native path and put in its place the converted,
+ * normalized path.
*/
Tcl_DStringFree(&ds);
@@ -2084,7 +2044,7 @@ TclpObjNormalizePath(
if (path[nextCheckpoint] != '\0') {
/*
- * Append the remaining path components.
+ * Not at end, append remaining path.
*/
int normLen = Tcl_DStringLength(&ds);
@@ -2093,8 +2053,7 @@ TclpObjNormalizePath(
pathLen - nextCheckpoint);
/*
- * characters up to and including the directory separator have
- * been processed
+ * We recognise up to and including the directory separator.
*/
nextCheckpoint = normLen + 1;
@@ -2106,6 +2065,10 @@ TclpObjNormalizePath(
nextCheckpoint = Tcl_DStringLength(&ds);
}
+ /*
+ * Overwrite with the normalized path.
+ */
+
Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds),
Tcl_DStringLength(&ds));
}
@@ -2116,366 +2079,11 @@ TclpObjNormalizePath(
return nextCheckpoint;
}
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
/*
*----------------------------------------------------------------------
*
- * TclpOpenTemporaryFile, TclUnixOpenTemporaryFile --
- *
- * Creates a temporary file, possibly based on the supplied bits and
- * pieces of template supplied in the first three arguments. If the
- * fourth argument is non-NULL, it contains a Tcl_Obj to store the name
- * of the temporary file in (and it is caller's responsibility to clean
- * up). If the fourth argument is NULL, try to arrange for the temporary
- * file to go away once it is no longer needed.
- *
- * Results:
- * A read-write Tcl Channel open on the file for TclpOpenTemporaryFile,
- * or a file descriptor (or -1 on failure) for TclUnixOpenTemporaryFile.
- *
- * Side effects:
- * Accesses the filesystem. Will set the contents of the Tcl_Obj fourth
- * argument (if that is non-NULL).
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-TclpOpenTemporaryFile(
- Tcl_Obj *dirObj,
- Tcl_Obj *basenameObj,
- Tcl_Obj *extensionObj,
- Tcl_Obj *resultingNameObj)
-{
- int fd = TclUnixOpenTemporaryFile(dirObj, basenameObj, extensionObj,
- resultingNameObj);
-
- if (fd == -1) {
- return NULL;
- }
- return Tcl_MakeFileChannel(INT2PTR(fd), TCL_READABLE|TCL_WRITABLE);
-}
-
-int
-TclUnixOpenTemporaryFile(
- Tcl_Obj *dirObj,
- Tcl_Obj *basenameObj,
- Tcl_Obj *extensionObj,
- Tcl_Obj *resultingNameObj)
-{
- Tcl_DString templ, tmp;
- const char *string;
- int fd;
-
- /*
- * We should also check against making more then TMP_MAX of these.
- */
-
- if (dirObj) {
- string = TclGetString(dirObj);
- Tcl_UtfToExternalDString(NULL, string, dirObj->length, &templ);
- } else {
- Tcl_DStringInit(&templ);
- Tcl_DStringAppend(&templ, DefaultTempDir(), TCL_INDEX_NONE); /* INTL: native */
- }
-
- TclDStringAppendLiteral(&templ, "/");
-
- if (basenameObj) {
- string = TclGetString(basenameObj);
- Tcl_UtfToExternalDString(NULL, string, basenameObj->length, &tmp);
- TclDStringAppendDString(&templ, &tmp);
- Tcl_DStringFree(&tmp);
- } else {
- TclDStringAppendLiteral(&templ, "tcl");
- }
-
- TclDStringAppendLiteral(&templ, "_XXXXXX");
-
-#ifdef HAVE_MKSTEMPS
- if (extensionObj) {
- string = TclGetString(extensionObj);
- Tcl_UtfToExternalDString(NULL, string, extensionObj->length, &tmp);
- TclDStringAppendDString(&templ, &tmp);
- fd = mkstemps(Tcl_DStringValue(&templ), Tcl_DStringLength(&tmp));
- Tcl_DStringFree(&tmp);
- } else
-#endif
- {
- fd = mkstemp(Tcl_DStringValue(&templ));
- }
-
- if (fd == -1) {
- Tcl_DStringFree(&templ);
- return -1;
- }
-
- if (resultingNameObj) {
- Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&templ),
- Tcl_DStringLength(&templ), &tmp);
- Tcl_SetStringObj(resultingNameObj, Tcl_DStringValue(&tmp),
- Tcl_DStringLength(&tmp));
- Tcl_DStringFree(&tmp);
- } else {
- /*
- * Try to delete the file immediately since we're not reporting the
- * name to anyone. Note that we're *not* handling any errors from
- * this!
- */
-
- unlink(Tcl_DStringValue(&templ));
- errno = 0;
- }
- Tcl_DStringFree(&templ);
-
- return fd;
-}
-
-/*
- * Helper that does *part* of what tempnam() does.
- */
-
-static const char *
-DefaultTempDir(void)
-{
- const char *dir;
- Tcl_StatBuf buf;
-
- dir = getenv("TMPDIR");
- if (dir && dir[0] && TclOSstat(dir, &buf) == 0 && S_ISDIR(buf.st_mode)
- && access(dir, W_OK) == 0) {
- return dir;
- }
-
-#ifdef P_tmpdir
- dir = P_tmpdir;
- if (TclOSstat(dir, &buf)==0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)==0) {
- return dir;
- }
-#endif
-
- /*
- * Assume that the default location ("/tmp" if not overridden) is always
- * an existing writable directory; we've no recovery mechanism if it
- * isn't.
- */
-
- return TCL_TEMPORARY_FILE_DIRECTORY;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpCreateTemporaryDirectory --
- *
- * Creates a temporary directory, possibly based on the supplied bits and
- * pieces of template supplied in the arguments.
- *
- * Results:
- * An object (refcount 0) containing the name of the newly-created
- * directory, or NULL on failure.
- *
- * Side effects:
- * Accesses the native filesystem. Makes a directory.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-TclpCreateTemporaryDirectory(
- Tcl_Obj *dirObj,
- Tcl_Obj *basenameObj)
-{
- Tcl_DString templ, tmp;
- const char *string;
-
-#define DEFAULT_TEMP_DIR_PREFIX "tcl"
-
- /*
- * Build the template in writable memory from the user-supplied pieces and
- * some defaults.
- */
-
- if (dirObj) {
- string = TclGetString(dirObj);
- Tcl_UtfToExternalDString(NULL, string, dirObj->length, &templ);
- } else {
- Tcl_DStringInit(&templ);
- Tcl_DStringAppend(&templ, DefaultTempDir(), TCL_INDEX_NONE); /* INTL: native */
- }
-
- if (Tcl_DStringValue(&templ)[Tcl_DStringLength(&templ) - 1] != '/') {
- TclDStringAppendLiteral(&templ, "/");
- }
-
- if (basenameObj) {
- string = TclGetString(basenameObj);
- if (basenameObj->length) {
- Tcl_UtfToExternalDString(NULL, string, basenameObj->length, &tmp);
- TclDStringAppendDString(&templ, &tmp);
- Tcl_DStringFree(&tmp);
- } else {
- TclDStringAppendLiteral(&templ, DEFAULT_TEMP_DIR_PREFIX);
- }
- } else {
- TclDStringAppendLiteral(&templ, DEFAULT_TEMP_DIR_PREFIX);
- }
-
- TclDStringAppendLiteral(&templ, "_XXXXXX");
-
- /*
- * Make the temporary directory.
- */
-
- if (mkdtemp(Tcl_DStringValue(&templ)) == NULL) {
- Tcl_DStringFree(&templ);
- return NULL;
- }
-
- /*
- * The template has been updated. Tell the caller what it was.
- */
-
- Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&templ),
- Tcl_DStringLength(&templ), &tmp);
- Tcl_DStringFree(&templ);
- return Tcl_DStringToObj(&tmp);
-}
-
-#if defined(__CYGWIN__)
-
-static void
-StatError(
- Tcl_Interp *interp, /* The interp that has the error */
- Tcl_Obj *fileName) /* The name of the file which caused the
- * error. */
-{
- Tcl_WinConvertError(GetLastError());
- Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
-}
-
-static WCHAR *
-winPathFromObj(
- Tcl_Obj *fileName)
-{
- int size;
- const char *native = (const char *)Tcl_FSGetNativePath(fileName);
- WCHAR *winPath;
-
- size = cygwin_conv_path(1, native, NULL, 0);
- winPath = (WCHAR *)ckalloc(size);
- cygwin_conv_path(1, native, winPath, size);
-
- return winPath;
-}
-
-static const int attributeArray[] = {
- 0x20, 0, 2, 0, 0, 1, 4
-};
-
-/*
- *----------------------------------------------------------------------
- *
- * GetUnixFileAttributes
- *
- * Gets an attribute of a file.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * 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 to report errors to. */
- int objIndex, /* The index of the attribute. */
- Tcl_Obj *fileName, /* The pathname of the file (UTF-8). */
- Tcl_Obj **attributePtrPtr) /* Where to store the result. */
-{
- int fileAttributes;
- WCHAR *winPath = winPathFromObj(fileName);
-
- fileAttributes = GetFileAttributesW(winPath);
- ckfree(winPath);
-
- if (fileAttributes == -1) {
- StatError(interp, fileName);
- return TCL_ERROR;
- }
-
- TclNewIntObj(*attributePtrPtr,
- (fileAttributes & attributeArray[objIndex]) != 0);
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * SetUnixFileAttributes
- *
- * Sets the readonly attribute of a file.
- *
- * Results:
- * Standard TCL result.
- *
- * Side effects:
- * The readonly attribute of the file is changed.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-SetUnixFileAttributes(
- Tcl_Interp *interp, /* The interp we are using for errors. */
- int objIndex, /* The index of the attribute. */
- Tcl_Obj *fileName, /* The name of the file (UTF-8). */
- Tcl_Obj *attributePtr) /* The attribute to set. */
-{
- int yesNo, fileAttributes, old;
- WCHAR *winPath;
-
- if (Tcl_GetBooleanFromObj(interp, attributePtr, &yesNo) != TCL_OK) {
- return TCL_ERROR;
- }
-
- winPath = winPathFromObj(fileName);
-
- fileAttributes = old = GetFileAttributesW(winPath);
-
- if (fileAttributes == -1) {
- ckfree(winPath);
- StatError(interp, fileName);
- return TCL_ERROR;
- }
-
- if (yesNo) {
- fileAttributes |= attributeArray[objIndex];
- } else {
- fileAttributes &= ~attributeArray[objIndex];
- }
-
- if ((fileAttributes != old)
- && !SetFileAttributesW(winPath, fileAttributes)) {
- ckfree(winPath);
- StatError(interp, fileName);
- return TCL_ERROR;
- }
-
- ckfree(winPath);
- return TCL_OK;
-}
-#elif defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
-/*
- *----------------------------------------------------------------------
- *
- * GetUnixFileAttributes
+ * GetReadOnlyAttribute
*
* Gets the readonly attribute (user immutable flag) of a file.
*
@@ -2490,9 +2098,9 @@ SetUnixFileAttributes(
*/
static int
-GetUnixFileAttributes(
+GetReadOnlyAttribute(
Tcl_Interp *interp, /* The interp we are using for errors. */
- TCL_UNUSED(int) /*objIndex*/,
+ 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. */
{
@@ -2503,21 +2111,22 @@ GetUnixFileAttributes(
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
}
return TCL_ERROR;
}
- TclNewIntObj(*attributePtrPtr, (statBuf.st_flags & UF_IMMUTABLE) != 0);
+ *attributePtrPtr = Tcl_NewBooleanObj((statBuf.st_flags&UF_IMMUTABLE) != 0);
+
return TCL_OK;
}
/*
*---------------------------------------------------------------------------
*
- * SetUnixFileAttributes
+ * SetReadOnlyAttribute
*
* Sets the readonly attribute (user immutable flag) of a file.
*
@@ -2531,15 +2140,16 @@ GetUnixFileAttributes(
*/
static int
-SetUnixFileAttributes(
+SetReadOnlyAttribute(
Tcl_Interp *interp, /* The interp we are using for errors. */
- TCL_UNUSED(int) /*objIndex*/,
+ int objIndex, /* The index of the attribute. */
Tcl_Obj *fileName, /* The name of the file (UTF-8). */
Tcl_Obj *attributePtr) /* The attribute to set. */
{
Tcl_StatBuf statBuf;
- int result, readonly;
- const char *native;
+ int result;
+ int readonly;
+ CONST char *native;
if (Tcl_GetBooleanFromObj(interp, attributePtr, &readonly) != TCL_OK) {
return TCL_ERROR;
@@ -2549,9 +2159,9 @@ SetUnixFileAttributes(
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not read \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
}
return TCL_ERROR;
}
@@ -2562,13 +2172,13 @@ SetUnixFileAttributes(
statBuf.st_flags &= ~UF_IMMUTABLE;
}
- native = (const char *)Tcl_FSGetNativePath(fileName);
+ native = Tcl_FSGetNativePath(fileName);
result = chflags(native, statBuf.st_flags); /* INTL: Native. */
if (result != 0) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not set flags for file \"%s\": %s",
- TclGetString(fileName), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "could not set flags for file \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
}
return TCL_ERROR;
}