From 9be69008c0dd066816b4a9b04d47fade2282664a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 5 Aug 2008 21:06:00 +0000 Subject: [PATCH] uip/folder.c: chdir(nmhdir) in main rather than in dodir, which is called many times. Drop the chdir in get_folder_info, which served no purpose at all. If struct stat has d_type (BSD), use that to skip processing (strcmp, stat, and so on) of message files, mostly undoing the slow-down from the last change. Plus autoconf machinery to detect d_type field. Patch from Eric Gillespie. --- ChangeLog | 13 +++++++++ aclocal.m4 | 52 ++++++++++++++++++++++++++++++++++++ configure.in | 2 ++ uip/folder.c | 84 ++++++++++++++++++++++++++++++++-------------------------- 4 files changed, 113 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f02b17..7dc5491 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-08-05 Eric Gillespie + + * uip/folder.c: chdir(nmhdir) in main rather than in dodir, which + is called many times. Drop the chdir in get_folder_info, which + served no purpose at all. If struct stat has d_type (BSD), use + that to skip processing (strcmp, stat, and so on) of message + files, mostly undoing the slow-down from the last change. + + * configure.in: Call CHECK_TYPE_STRUCT_DIRENT_D_TYPE. + + * aclocal.m4: Add CHECK_TYPE_STRUCT_DIRENT_D_TYPE from + GNU coreutils. + 2008-08-04 Eric Gillespie * uip/folder.c: Simplify dodir/addir/addfold. Dump hacky diff --git a/aclocal.m4 b/aclocal.m4 index c0d4fb8..6091daa 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -84,3 +84,55 @@ else : fi ])dnl + +dnl ---------------- +dnl CHECK FOR d_type +dnl ---------------- +dnl +dnl From Jim Meyering. +dnl +dnl Check whether struct dirent has a member named d_type. +dnl + +# Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +AC_DEFUN([CHECK_TYPE_STRUCT_DIRENT_D_TYPE], + [AC_REQUIRE([AC_HEADER_DIRENT])dnl + AC_CACHE_CHECK([for d_type member in directory struct], + jm_cv_struct_dirent_d_type, + [AC_TRY_LINK(dnl + [ +#include +#ifdef HAVE_DIRENT_H +# include +#else /* not HAVE_DIRENT_H */ +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif /* HAVE_SYS_NDIR_H */ +# ifdef HAVE_SYS_DIR_H +# include +# endif /* HAVE_SYS_DIR_H */ +# ifdef HAVE_NDIR_H +# include +# endif /* HAVE_NDIR_H */ +#endif /* HAVE_DIRENT_H */ + ], + [struct dirent dp; dp.d_type = 0;], + + jm_cv_struct_dirent_d_type=yes, + jm_cv_struct_dirent_d_type=no) + ] + ) + if test $jm_cv_struct_dirent_d_type = yes; then + AC_DEFINE(HAVE_STRUCT_DIRENT_D_TYPE, 1, + [Define if there is a member named d_type in the struct describing + directory headers.]) + fi + ] +) diff --git a/configure.in b/configure.in index 0b2a73c..ce9c4ba 100644 --- a/configure.in +++ b/configure.in @@ -950,6 +950,8 @@ if test "$nmh_cv_union_wait" = yes; then fi AC_MSG_RESULT($nmh_cv_union_wait) +CHECK_TYPE_STRUCT_DIRENT_D_TYPE() + dnl ------------- dnl CHECK SIGNALS dnl ------------- diff --git a/uip/folder.c b/uip/folder.c index d4d9868..a94f131 100644 --- a/uip/folder.c +++ b/uip/folder.c @@ -365,6 +365,9 @@ main (int argc, char **argv) /* * If no folder is given, do them all */ + /* change directory to base of nmh directory for dodir */ + if (chdir (nmhdir) == NOTOK) + adios (nmhdir, "unable to change directory to"); if (!argfolder) { if (msg) admonish (NULL, "no folder given for message %s", msg); @@ -422,10 +425,6 @@ dodir (char *dir) start = foldp; - /* change directory to base of nmh directory */ - if (chdir (nmhdir) == NOTOK) - adios (nmhdir, "unable to change directory to"); - addir (dir); for (i = start; i < foldp; i++) { @@ -441,7 +440,6 @@ static int get_folder_info (char *fold, char *msg) { int i, retval = 1; - char *mailfile; struct msgs *mp = NULL; i = total_folders++; @@ -463,42 +461,36 @@ get_folder_info (char *fold, char *msg) fi[i].others = 0; fi[i].error = 0; - mailfile = m_maildir (fold); - - if (!chdir (mailfile)) { - if ((ftotal > 0) || !fshort || msg || fpack) { - /* - * create message structure and get folder info - */ - if (!(mp = folder_read (fold))) { - admonish (NULL, "unable to read folder %s", fold); - return 0; - } + if ((ftotal > 0) || !fshort || msg || fpack) { + /* + * create message structure and get folder info + */ + if (!(mp = folder_read (fold))) { + admonish (NULL, "unable to read folder %s", fold); + return 0; + } - /* set the current message */ - if (msg && !sfold (mp, msg)) - retval = 0; + /* set the current message */ + if (msg && !sfold (mp, msg)) + retval = 0; - if (fpack) { - if (folder_pack (&mp, fverb) == -1) - done (1); - seq_save (mp); /* synchronize the sequences */ - context_save (); /* save the context file */ - } - - /* record info for this folder */ - if ((ftotal > 0) || !fshort) { - fi[i].nummsg = mp->nummsg; - fi[i].curmsg = mp->curmsg; - fi[i].lowmsg = mp->lowmsg; - fi[i].hghmsg = mp->hghmsg; - fi[i].others = other_files (mp); - } + if (fpack) { + if (folder_pack (&mp, fverb) == -1) + done (1); + seq_save (mp); /* synchronize the sequences */ + context_save (); /* save the context file */ + } - folder_free (mp); /* free folder/message structure */ + /* record info for this folder */ + if ((ftotal > 0) || !fshort) { + fi[i].nummsg = mp->nummsg; + fi[i].curmsg = mp->curmsg; + fi[i].lowmsg = mp->lowmsg; + fi[i].hghmsg = mp->hghmsg; + fi[i].others = other_files (mp); } - } else { - fi[i].error = 1; + + folder_free (mp); /* free folder/message structure */ } if (frecurse && (fshort || fi[i].others) && (fi[i].error == 0)) @@ -669,6 +661,7 @@ addir (char *name) struct stat st; struct dirent *dp; DIR * dd; + int child_is_folder; if (!(dd = opendir (name))) { admonish (name, "unable to read directory "); @@ -682,11 +675,26 @@ addir (char *name) } while ((dp = readdir (dd))) { + /* If the system supports it, try to skip processing of children we + * know are not directories or symlinks. */ + child_is_folder = -1; +#if defined(HAVE_STRUCT_DIRENT_D_TYPE) + if (dp->d_type == DT_DIR) { + child_is_folder = 1; + } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) { + continue; + } +#endif if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) { continue; } child = concat (prefix, dp->d_name, (void *)NULL); - if (stat (child, &st) != -1 && S_ISDIR(st.st_mode)) { + /* If we have no d_type or d_type is DT_LNK or DT_UNKNOWN, stat the + * child to see what it is. */ + if (child_is_folder == -1) { + child_is_folder = (stat (child, &st) != -1 && S_ISDIR(st.st_mode)); + } + if (child_is_folder) { /* addfold saves child in the list, don't free it */ addfold (child); } else { -- 1.7.10.4