From e424d1746c959678c7f353e1ccc1aef32317b0e4 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 5 Dec 2005 15:10:31 +0000 Subject: 2005-12-05 Don Porter *** 8.4.12 TAGGED FOR RELEASE *** * unix/configure.in: Revised fix for [Bug 1034337] from Daniel * unix/tclUnixFCmd.c: Steffen. Uses fts_*() routines. * unix/configure: autoconf-2.13 * changes: Update changes for 8.4.12 release --- ChangeLog | 9 +++- changes | 6 +-- unix/configure | 60 +++++++++++++++++++++---- unix/configure.in | 20 ++++++++- unix/tclUnixFCmd.c | 130 +++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 189 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 40528f9..290f823 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,14 @@ -2005-12-04 Daniel Steffen +2005-12-05 Don Porter *** 8.4.12 TAGGED FOR RELEASE *** + * unix/configure.in: Revised fix for [Bug 1034337] from Daniel + * unix/tclUnixFCmd.c: Steffen. Uses fts_*() routines. + * unix/configure: autoconf-2.13 + * changes: Update changes for 8.4.12 release + +2005-12-04 Daniel Steffen + * README: refer to macosx/README instead of mac/README. * mac/README: add note that mac classic port is no longer supported. diff --git a/changes b/changes index 017bb5b..f7178a3 100644 --- a/changes +++ b/changes @@ -1,6 +1,6 @@ Recent user-visible changes to Tcl: -RCS: @(#) $Id: changes,v 1.79.2.31 2005/12/03 21:55:24 hobbs Exp $ +RCS: @(#) $Id: changes,v 1.79.2.32 2005/12/05 15:10:32 dgp Exp $ 1. No more [command1] [command2] construct for grouping multiple commands on a single command line. @@ -6276,8 +6276,6 @@ Restores Tcl 8.4.9 behavior (porter) 2005-10-05 (bug fix)[979640] buffer overrun mixing putenv(), ::env (bold,hobbs) -2005-10-07 (Darwin bug fix)[1034337] recursive file delete, MacOSX, NFS (hobbs) - 2005-10-13 (bug fix)[1284178] [format] accept all integer values (porter) 2005-10-22 (bug fix)[1251791] optimization exposed wide/int difference(sofer) @@ -6321,4 +6319,6 @@ Restores Tcl 8.4.9 behavior (porter) 2005-11-29 (enhancement)[1369597] Win 64: --enable-64bit=amd64|ia64 (hobbs) +2005-12-05 (Darwin bug fix)[1034337] NFS recursive file delete (steffen) + --- Released 8.4.12, Decemeber 3, 2005 --- See ChangeLog for details --- diff --git a/unix/configure b/unix/configure index 44f82a0..d243def 100755 --- a/unix/configure +++ b/unix/configure @@ -7493,6 +7493,50 @@ EOF #-------------------------------------------------------------------- +# Check for support of fts functions on Darwin (readdir replacement) +#-------------------------------------------------------------------- + +if test "`uname -s`" = "Darwin" ; then + echo $ac_n "checking for fts""... $ac_c" 1>&6 +echo "configure:7502: checking for fts" >&5 +if eval "test \"`echo '$''{'tcl_cv_api_fts'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext < + #include + #include +int main() { +char*const p[2] = {"/", NULL}; + FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL); + FTSENT *e = fts_read(f); fts_close(f); +; return 0; } +EOF +if { (eval echo configure:7519: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + tcl_cv_api_fts=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + tcl_cv_api_fts=no +fi +rm -f conftest* +fi + +echo "$ac_t""$tcl_cv_api_fts" 1>&6 + if test $tcl_cv_api_fts = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_FTS 1 +EOF + + fi +fi + +#-------------------------------------------------------------------- # The statements below check for systems where POSIX-style # non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. # On these systems (mostly older ones), use the old BSD-style @@ -7504,17 +7548,17 @@ EOF do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:7508: checking for $ac_hdr" >&5 +echo "configure:7552: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7518: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7562: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7544,17 +7588,17 @@ done do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:7548: checking for $ac_hdr" >&5 +echo "configure:7592: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7558: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7602: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7581,7 +7625,7 @@ fi done echo $ac_n "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O""... $ac_c" 1>&6 -echo "configure:7585: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5 +echo "configure:7629: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5 if test -f /usr/lib/NextStep/software_version; then system=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` else @@ -7661,7 +7705,7 @@ HTML_DIR='$(DISTDIR)/html' if test "`uname -s`" = "Darwin" ; then echo $ac_n "checking how to package libraries""... $ac_c" 1>&6 -echo "configure:7665: checking how to package libraries" >&5 +echo "configure:7709: checking how to package libraries" >&5 # Check whether --enable-framework or --disable-framework was given. if test "${enable_framework+set}" = set; then enableval="$enable_framework" diff --git a/unix/configure.in b/unix/configure.in index 791497f..18079e9 100644 --- a/unix/configure.in +++ b/unix/configure.in @@ -3,7 +3,7 @@ dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. # -# RCS: @(#) $Id: configure.in,v 1.106.2.21 2005/11/27 02:34:42 das Exp $ +# RCS: @(#) $Id: configure.in,v 1.106.2.22 2005/12/05 15:10:33 dgp Exp $ AC_INIT(../generic/tcl.h) AC_PREREQ(2.13) @@ -436,6 +436,24 @@ fi SC_ENABLE_LANGINFO #-------------------------------------------------------------------- +# Check for support of fts functions on Darwin (readdir replacement) +#-------------------------------------------------------------------- + +if test "`uname -s`" = "Darwin" ; then + AC_CACHE_CHECK([for fts], tcl_cv_api_fts, [ + AC_TRY_LINK([#include + #include + #include ], + [char*const p[2] = {"/", NULL}; + FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL); + FTSENT *e = fts_read(f); fts_close(f);], + tcl_cv_api_fts=yes, tcl_cv_api_fts=no)]) + if test $tcl_cv_api_fts = yes; then + AC_DEFINE(HAVE_FTS) + fi +fi + +#-------------------------------------------------------------------- # The statements below check for systems where POSIX-style # non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. # On these systems (mostly older ones), use the old BSD-style diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index f5555b7..02bd513 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.28.2.7 2005/11/27 02:34:42 das Exp $ + * RCS: @(#) $Id: tclUnixFCmd.c,v 1.28.2.8 2005/12/05 15:10:33 dgp Exp $ * * Portions of this code were derived from NetBSD source code which has * the following copyright notice: @@ -56,6 +56,9 @@ #include #endif #endif +#ifdef HAVE_FTS +#include +#endif /* * The following constants specify the type of callback when @@ -147,7 +150,7 @@ static int CopyFile _ANSI_ARGS_((CONST char *src, static int CopyFileAtts _ANSI_ARGS_((CONST char *src, CONST char *dst, CONST Tcl_StatBuf *statBufPtr)); static int DoCopyFile _ANSI_ARGS_((CONST char *srcPtr, - CONST char *dstPtr)); + CONST char *dstPtr, CONST Tcl_StatBuf *statBufPtr)); static int DoCreateDirectory _ANSI_ARGS_((CONST char *pathPtr)); static int DoRemoveDirectory _ANSI_ARGS_((Tcl_DString *pathPtr, int recursive, Tcl_DString *errorPtr)); @@ -343,25 +346,26 @@ TclpObjCopyFile(srcPathPtr, destPathPtr) Tcl_Obj *srcPathPtr; Tcl_Obj *destPathPtr; { - return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr), - Tcl_FSGetNativePath(destPathPtr)); + CONST char *src = Tcl_FSGetNativePath(srcPathPtr); + Tcl_StatBuf srcStatBuf; + + if (TclOSlstat(src, &srcStatBuf) != 0) { /* INTL: Native. */ + return TCL_ERROR; + } + + return DoCopyFile(src, Tcl_FSGetNativePath(destPathPtr), &srcStatBuf); } static int -DoCopyFile(src, dst) +DoCopyFile(src, dst, 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 srcStatBuf, dstStatBuf; + Tcl_StatBuf dstStatBuf; - /* - * Have to do a stat() to determine the filetype. - */ - - if (TclOSlstat(src, &srcStatBuf) != 0) { /* INTL: Native. */ - return TCL_ERROR; - } - if (S_ISDIR(srcStatBuf.st_mode)) { + if (S_ISDIR(statBufPtr->st_mode)) { errno = EISDIR; return TCL_ERROR; } @@ -383,7 +387,7 @@ DoCopyFile(src, dst) } } - switch ((int) (srcStatBuf.st_mode & S_IFMT)) { + switch ((int) (statBufPtr->st_mode & S_IFMT)) { #ifndef DJGPP case S_IFLNK: { char link[MAXPATHLEN]; @@ -405,20 +409,20 @@ DoCopyFile(src, dst) #endif case S_IFBLK: case S_IFCHR: { - if (mknod(dst, srcStatBuf.st_mode, /* INTL: Native. */ - srcStatBuf.st_rdev) < 0) { + if (mknod(dst, statBufPtr->st_mode, /* INTL: Native. */ + statBufPtr->st_rdev) < 0) { return TCL_ERROR; } - return CopyFileAtts(src, dst, &srcStatBuf); + return CopyFileAtts(src, dst, statBufPtr); } case S_IFIFO: { - if (mkfifo(dst, srcStatBuf.st_mode) < 0) { /* INTL: Native. */ + if (mkfifo(dst, statBufPtr->st_mode) < 0) { /* INTL: Native. */ return TCL_ERROR; } - return CopyFileAtts(src, dst, &srcStatBuf); + return CopyFileAtts(src, dst, statBufPtr); } default: { - return CopyFile(src, dst, &srcStatBuf); + return CopyFile(src, dst, statBufPtr); } } return TCL_OK; @@ -832,9 +836,15 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind) CONST char *source, *errfile; int result, sourceLen; int targetLen; +#ifndef HAVE_FTS int numProcessed = 0; Tcl_DirEntry *dirEntPtr; DIR *dirPtr; +#else + CONST char *paths[2] = {NULL, NULL}; + FTS *fts = NULL; + FTSENT *ent; +#endif errfile = NULL; result = TCL_OK; @@ -853,6 +863,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind) return (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_F, errorPtr); } +#ifndef HAVE_FTS dirPtr = opendir(source); /* INTL: Native. */ if (dirPtr == NULL) { /* @@ -938,6 +949,74 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind) result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_POSTD, errorPtr); } +#else /* HAVE_FTS */ + paths[0] = source; + fts = fts_open((char**)paths, FTS_PHYSICAL|FTS_NOCHDIR| +#ifdef HAVE_STRUCT_STAT64 + FTS_NOSTAT, /* fts doesn't do stat64 */ +#else + (doRewind ? FTS_NOSTAT : 0), /* no need to stat for delete */ +#endif + NULL); + if (fts == NULL) { + errfile = source; + goto end; + } + + sourceLen = Tcl_DStringLength(sourcePtr); + if (targetPtr != NULL) { + targetLen = Tcl_DStringLength(targetPtr); + } + + while ((ent = fts_read(fts)) != NULL) { + unsigned short info = ent->fts_info; + char * path = ent->fts_path + sourceLen; + 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; + } + Tcl_DStringAppend(sourcePtr, path, pathlen); + if (targetPtr != NULL) { + Tcl_DStringAppend(targetPtr, path, pathlen); + } + switch (info) { + case FTS_D: + type = DOTREE_PRED; + break; + case FTS_DP: + type = DOTREE_POSTD; + break; + default: + type = DOTREE_F; + break; + } + if (!doRewind) { /* no need to stat for delete */ +#ifdef HAVE_STRUCT_STAT64 + statBufPtr = &statBuf; + if (TclOSlstat(ent->fts_path, statBufPtr) != 0) { + errfile = ent->fts_path; + break; + } +#else + statBufPtr = ent->fts_statp; +#endif + } + result = (*traverseProc)(sourcePtr, targetPtr, statBufPtr, type, + errorPtr); + if (result != TCL_OK) { + break; + } + Tcl_DStringSetLength(sourcePtr, sourceLen); + if (targetPtr != NULL) { + Tcl_DStringSetLength(targetPtr, targetLen); + } + } +#endif /* HAVE_FTS */ + end: if (errfile != NULL) { if (errorPtr != NULL) { @@ -945,6 +1024,11 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind) } result = TCL_ERROR; } +#ifdef HAVE_FTS + if (fts != NULL) { + fts_close(fts); + } +#endif /* HAVE_FTS */ return result; } @@ -980,8 +1064,8 @@ TraversalCopy(srcPtr, dstPtr, statBufPtr, type, errorPtr) { switch (type) { case DOTREE_F: - if (DoCopyFile(Tcl_DStringValue(srcPtr), - Tcl_DStringValue(dstPtr)) == TCL_OK) { + if (DoCopyFile(Tcl_DStringValue(srcPtr), Tcl_DStringValue(dstPtr), + statBufPtr) == TCL_OK) { return TCL_OK; } break; -- cgit v0.12