diff options
author | dgp <dgp@users.sourceforge.net> | 2005-12-05 15:10:31 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2005-12-05 15:10:31 (GMT) |
commit | e424d1746c959678c7f353e1ccc1aef32317b0e4 (patch) | |
tree | 850538a1bd6cfbe2b8664c5b2d4de08daa22ea2e /unix | |
parent | 6d30b8c11fa8b57fff54beea68c7c8394ee305d6 (diff) | |
download | tcl-e424d1746c959678c7f353e1ccc1aef32317b0e4.zip tcl-e424d1746c959678c7f353e1ccc1aef32317b0e4.tar.gz tcl-e424d1746c959678c7f353e1ccc1aef32317b0e4.tar.bz2 |
2005-12-05 Don Porter <dgp@users.sourceforge.net>
*** 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
Diffstat (limited to 'unix')
-rwxr-xr-x | unix/configure | 60 | ||||
-rw-r--r-- | unix/configure.in | 20 | ||||
-rw-r--r-- | unix/tclUnixFCmd.c | 130 |
3 files changed, 178 insertions, 32 deletions
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 <<EOF +#line 7508 "configure" +#include "confdefs.h" +#include <sys/param.h> + #include <sys/stat.h> + #include <fts.h> +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 -#line 7513 "configure" +#line 7557 "configure" #include "confdefs.h" #include <$ac_hdr> 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 -#line 7553 "configure" +#line 7597 "configure" #include "confdefs.h" #include <$ac_hdr> 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 <sys/param.h> + #include <sys/stat.h> + #include <fts.h>], + [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 <sys/statfs.h> #endif #endif +#ifdef HAVE_FTS +#include <fts.h> +#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; |