summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixFCmd.c
diff options
context:
space:
mode:
authordas <das>2006-07-20 06:18:37 (GMT)
committerdas <das>2006-07-20 06:18:37 (GMT)
commit012ac88ab78de5f4b8f0e7b196e1746bb75bdf9b (patch)
treed0364276ac6c8c4168a1e2ff1c15ccf01d284585 /unix/tclUnixFCmd.c
parentf2a1ea5dbae4b3440723227e75a0c9da1d88ff93 (diff)
downloadtcl-012ac88ab78de5f4b8f0e7b196e1746bb75bdf9b.zip
tcl-012ac88ab78de5f4b8f0e7b196e1746bb75bdf9b.tar.gz
tcl-012ac88ab78de5f4b8f0e7b196e1746bb75bdf9b.tar.bz2
* macosx/tclMacOSXNotify.c (Tcl_InitNotifier, Tcl_WaitForEvent): create
notifier thread lazily upon first call to Tcl_WaitForEvent() rather than in Tcl_InitNotifier(). Allows calling exeve() in processes where the event loop has not yet been run (Darwin's execve() fails in processes with more than one thread), in particular allows embedders to call fork() followed by execve(), previously the pthread_atfork() child handler's call to Tcl_InitNotifier() would immediately recreate the notifier thread in the child after a fork. * macosx/tclMacOSXFCmd.c (TclMacOSXCopyFileAttributes): add support * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): for weakly * unix/tclUnixInit.c (Tcl_GetEncodingNameFromEnvironment): importing symbols not available on OSX 10.2 or 10.3, enables binaires built on later OSX versions to run on earlier ones. * macosx/Tcl.xcodeproj/project.pbxproj: enable weak-linking; turn on extra warnings. * macosx/README: document how to enable weak-linking; cleanup. * unix/tclUnixPort.h: add support for weak-linking; conditionalize AvailabilityMacros.h inclusion; only disable realpath on 10.2 or earlier when threads are enabled. * unix/tclLoadDyld.c (TclpLoadMemoryGetBuffer): change runtime Darwin * unix/tclUnixInit.c (TclpInitPlatform): release check to use global initialized once. * unix/tclUnixFCmd.c (DoRenameFile, TclpObjNormalizePath): add runtime Darwin release check to determine if realpath is threadsafe. * unix/configure.in: add check on Darwin for compiler support of weak * unix/tcl.m4: import and for AvailabilityMacros.h header; move Darwin specific checks & defines that are only relevant to the tcl build out of tcl.m4; restrict framework option to Darwin; cleanup quoting and help messages. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * unix/tclLoadDyld.c (TclpLoadMemory): fix signed-with-unsigned comparison and other warnings from gcc4 -Wextra.
Diffstat (limited to 'unix/tclUnixFCmd.c')
-rw-r--r--unix/tclUnixFCmd.c144
1 files changed, 81 insertions, 63 deletions
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c
index 1bba9ee..27b880e 100644
--- a/unix/tclUnixFCmd.c
+++ b/unix/tclUnixFCmd.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUnixFCmd.c,v 1.53 2006/03/28 10:45:25 das Exp $
+ * RCS: @(#) $Id: tclUnixFCmd.c,v 1.54 2006/07/20 06:18:38 das Exp $
*
* Portions of this code were derived from NetBSD source code which has the
* following copyright notice:
@@ -218,6 +218,22 @@ Realpath(
#else
#define Realpath realpath
#endif
+
+#ifndef NO_REALPATH
+#if defined(__APPLE__) && defined(TCL_THREADS) && \
+ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
+ MAC_OS_X_VERSION_MIN_REQUIRED < 1030
+/*
+ * prior to Darwin 7, realpath is not threadsafe, c.f. bug 711232;
+ * if we might potentially be running on pre-10.3 OSX,
+ * check Darwin release at runtime before using realpath.
+ */
+MODULE_SCOPE long tclMacOSXDarwinRelease;
+#define haveRealpath (tclMacOSXDarwinRelease >= 7)
+#else
+#define haveRealpath 1
+#endif
+#endif /* NO_REALPATH */
/*
*---------------------------------------------------------------------------
@@ -294,7 +310,7 @@ DoRenameFile(
* compiled because realpath() not defined on all systems.
*/
- if (errno == EINVAL) {
+ if (errno == EINVAL && haveRealpath) {
char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN];
DIR *dirPtr;
Tcl_DirEntry *dirEntPtr;
@@ -1877,7 +1893,7 @@ TclpObjNormalizePath(
* For speed, try to get the entire path in one go.
*/
- if (nextCheckpoint == 0) {
+ if (nextCheckpoint == 0 && haveRealpath) {
char *lastDir = strrchr(currentPathEndPosition, '/');
if (lastDir != NULL) {
@@ -1950,86 +1966,88 @@ TclpObjNormalizePath(
*/
#ifndef NO_REALPATH
- /*
- * 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 (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) {
- return 0;
- }
+ if (nextCheckpoint == 0) {
+ return 0;
+ }
- nativePath = Tcl_UtfToExternalDString(NULL, path, nextCheckpoint, &ds);
- if (Realpath(nativePath, normPath) != NULL) {
- int newNormLen;
+ nativePath = Tcl_UtfToExternalDString(NULL, path, nextCheckpoint, &ds);
+ if (Realpath(nativePath, normPath) != NULL) {
+ int newNormLen;
- wholeStringOk:
- newNormLen = strlen(normPath);
- if ((newNormLen == Tcl_DStringLength(&ds))
- && (strcmp(normPath, nativePath) == 0)) {
- /*
- * String is unchanged.
- */
+ wholeStringOk:
+ newNormLen = strlen(normPath);
+ if ((newNormLen == Tcl_DStringLength(&ds))
+ && (strcmp(normPath, nativePath) == 0)) {
+ /*
+ * String is unchanged.
+ */
- Tcl_DStringFree(&ds);
+ 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.
- *
- if (0 == access(normPath, F_OK)) {
- return pathLen;
+ /*
+ * 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;
+ }
+ */
+
+ return nextCheckpoint;
}
+
+ /*
+ * Free up the native path and put in its place the converted,
+ * normalized path.
*/
- return nextCheckpoint;
- }
+ Tcl_DStringFree(&ds);
+ Tcl_ExternalToUtfDString(NULL, normPath, (int) newNormLen, &ds);
- /*
- * Free up the native path and put in its place the converted,
- * normalized path.
- */
+ if (path[nextCheckpoint] != '\0') {
+ /*
+ * Not at end, append remaining path.
+ */
- Tcl_DStringFree(&ds);
- Tcl_ExternalToUtfDString(NULL, normPath, (int) newNormLen, &ds);
+ int normLen = Tcl_DStringLength(&ds);
- if (path[nextCheckpoint] != '\0') {
- /*
- * Not at end, append remaining path.
- */
+ Tcl_DStringAppend(&ds, path + nextCheckpoint,
+ pathLen - nextCheckpoint);
- int normLen = Tcl_DStringLength(&ds);
+ /*
+ * We recognise up to and including the directory separator.
+ */
- Tcl_DStringAppend(&ds, path + nextCheckpoint,
- pathLen - nextCheckpoint);
+ nextCheckpoint = normLen + 1;
+ } else {
+ /*
+ * We recognise the whole string.
+ */
- /*
- * We recognise up to and including the directory separator.
- */
+ nextCheckpoint = Tcl_DStringLength(&ds);
+ }
- nextCheckpoint = normLen + 1;
- } else {
/*
- * We recognise the whole string.
+ * Overwrite with the normalized path.
*/
- nextCheckpoint = Tcl_DStringLength(&ds);
+ Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds));
}
-
- /*
- * Overwrite with the normalized path.
- */
-
- Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
+ Tcl_DStringFree(&ds);
}
- Tcl_DStringFree(&ds);
#endif /* !NO_REALPATH */
return nextCheckpoint;