[RFC] Add support for the Solaris platform
Like on Mac OS X, the linker doesn't automatically resolve dependencies. Signed-off-by: Tomas Carnecky --- Makefile.local |2 +- configure | 28 ++-- lib/Makefile.local |2 +- notmuch-new.c | 70 ++-- 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/Makefile.local b/Makefile.local index 5bb570b..5bc872b 100644 --- a/Makefile.local +++ b/Makefile.local @@ -255,7 +255,7 @@ notmuch_client_srcs = \ notmuch_client_modules = $(notmuch_client_srcs:.c=.o) notmuch: $(notmuch_client_modules) lib/libnotmuch.a - $(call quiet,CXX $(CFLAGS)) $^ $(FINAL_LIBNOTMUCH_LDFLAGS) -o $@ + $(call quiet,CXX $(CFLAGS)) $^ $(FINAL_NOTMUCH_LDFLAGS) -o $@ notmuch-shared: $(notmuch_client_modules) lib/$(LINKER_NAME) $(call quiet,$(FINAL_NOTMUCH_LINKER) $(CFLAGS)) $(notmuch_client_modules) $(FINAL_NOTMUCH_LDFLAGS) -o $@ diff --git a/configure b/configure index c522ad8..91e08dd 100755 --- a/configure +++ b/configure @@ -257,15 +257,26 @@ else have_emacs=0 fi -printf "Checking for Mac OS X (for shared library)... " +printf "Checking which platform we are on... " if [ `uname` = "Darwin" ] ; then -printf "Yes.\n" -mac_os_x=1 +printf "Mac OS X.\n" +platform=MACOSX linker_resolves_library_dependencies=0 -else -printf "No.\n" -mac_os_x=0 +elif [ `uname` = "SunOS" ] ; then +printf "Solaris.\n" +platform=SOLARIS +linker_resolves_library_dependencies=0 +elif [ `uname` = "Linux" ] ; then +printf "Linux\n" +platform=LINUX linker_resolves_library_dependencies=1 +else +printf "Unknown.\n" +cat <d_name, (*b)->d_name); } +/* Helper functions to test if a given dirent is of a certain type + */ +static int +_is_reg(const char *path, struct dirent *entry) +{ +#ifdef DT_REG +if (entry->d_type == DT_REG) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); + +struct stat sbuf; +if (!stat(buffer, )) +return S_ISREG(sbuf.st_mode); + +return 0; +} + +static int +_is_dir(const char *path, struct dirent *entry) +{ +#ifdef DT_DIR +if (entry->d_type == DT_DIR) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); + +struct stat sbuf; +if (!stat(buffer, )) +return S_ISDIR(sbuf.st_mode); + +return 0; +} + +static int +_is_lnk(const char *path, struct dirent *entry) +{ +#ifdef DT_LNK +if (entry->d_type == DT_LNK) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); + +struct stat sbuf; +if (!stat(buffer, )) +return S_ISLNK(sbuf.st_mode); + +return 0; +} + /* Test if the directory looks like a Maildir directory. * * Search through the array of directory entries to see if we can find all @@ -143,12 +199,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) * Return 1 if the directory looks like a Maildir and 0 otherwise. */ static int -_entries_resemble_maildir (struct dirent **entries, int count) +_entries_resemble_maildir (const char *path, struct dirent **entries, int count) { int i, found = 0; for (i = 0; i < count; i++) { - if (entries[i]->d_type != DT_DIR && entries[i]->d_type != DT_UNKNOWN) + if (!_is_dir(path, entries[i])) continue; if (strcmp(entries[i]->d_name, "new") == 0 || @@ -261,7 +317,7 @@ add_files_recursive (notmuch_database_t *notmuch, } /* Pass 1: Recurse into all sub-directories. */ -is_maildir = _entries_resemble_maildir (fs_entries, num_fs_entries); +is_maildir = _entries_resemble_maildir (path, fs_entries, num_fs_entries); for (i = 0; i < num_fs_entries; i++) { if (interrupted) @@ -276,9 +332,7 @@ add_files_recursive (notmuch_database_t *notmuch, * scandir results, then it might be a directory (and if not, * then we'll stat and return immediately in the next level of * recursion). */ - if (entry->d_type != DT_DIR && - entry->d_type != DT_LNK && - entry->d_type != DT_UNKNOWN) + if (!_is_dir(path, entry) && !_is_lnk(path, entry)) { continue; } @@ -356,7 +410,7 @@ add_files_recursive (notmuch_database_t *notmuch, * * In either case, a stat does the trick. */ - if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) { + if (_is_lnk(path, entry)) { int err; next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name); @@ -372,7 +426,7 @@ add_files_recursive (notmuch_database_t *notmuch, if (! S_ISREG (st.st_mode)) continue; - } else if (entry->d_type != DT_REG) { + } else if (!_is_reg(path, entry)) { continue; } -- 1.7.1
[PATCH] Actually respect LDFLAGS as we say in the ./configure help
Signed-off-by: Tomas Carnecky --- configure |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/configure b/configure index 91e08dd..0153655 100755 --- a/configure +++ b/configure @@ -400,6 +400,9 @@ CFLAGS = ${CFLAGS} # Default FLAGS for C++ compiler (can be overridden by user such as "make CXXFLAGS=-g") CXXFLAGS = ${CXXFLAGS} +# Default FLAGS for the linker (can be overridden by user such as "make LDFLAGS=-uhm,whatever") +LDFLAGS = ${LDFLAGS} + # Flags to enable warnings when using the C++ compiler WARN_CXXFLAGS=-Wall -Wextra -Wwrite-strings -Wswitch-enum -- 1.7.1
[PATCH] Actually respect LDFLAGS as we say in the ./configure help
Signed-off-by: Tomas Carnecky t...@dbservice.com --- configure |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/configure b/configure index 91e08dd..0153655 100755 --- a/configure +++ b/configure @@ -400,6 +400,9 @@ CFLAGS = ${CFLAGS} # Default FLAGS for C++ compiler (can be overridden by user such as make CXXFLAGS=-g) CXXFLAGS = ${CXXFLAGS} +# Default FLAGS for the linker (can be overridden by user such as make LDFLAGS=-uhm,whatever) +LDFLAGS = ${LDFLAGS} + # Flags to enable warnings when using the C++ compiler WARN_CXXFLAGS=-Wall -Wextra -Wwrite-strings -Wswitch-enum -- 1.7.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[RFC] Add support for the Solaris platform
Like on Mac OS X, the linker doesn't automatically resolve dependencies. Signed-off-by: Tomas Carnecky t...@dbservice.com --- Makefile.local |2 +- configure | 28 ++-- lib/Makefile.local |2 +- notmuch-new.c | 70 ++-- 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/Makefile.local b/Makefile.local index 5bb570b..5bc872b 100644 --- a/Makefile.local +++ b/Makefile.local @@ -255,7 +255,7 @@ notmuch_client_srcs = \ notmuch_client_modules = $(notmuch_client_srcs:.c=.o) notmuch: $(notmuch_client_modules) lib/libnotmuch.a - $(call quiet,CXX $(CFLAGS)) $^ $(FINAL_LIBNOTMUCH_LDFLAGS) -o $@ + $(call quiet,CXX $(CFLAGS)) $^ $(FINAL_NOTMUCH_LDFLAGS) -o $@ notmuch-shared: $(notmuch_client_modules) lib/$(LINKER_NAME) $(call quiet,$(FINAL_NOTMUCH_LINKER) $(CFLAGS)) $(notmuch_client_modules) $(FINAL_NOTMUCH_LDFLAGS) -o $@ diff --git a/configure b/configure index c522ad8..91e08dd 100755 --- a/configure +++ b/configure @@ -257,15 +257,26 @@ else have_emacs=0 fi -printf Checking for Mac OS X (for shared library)... +printf Checking which platform we are on... if [ `uname` = Darwin ] ; then -printf Yes.\n -mac_os_x=1 +printf Mac OS X.\n +platform=MACOSX linker_resolves_library_dependencies=0 -else -printf No.\n -mac_os_x=0 +elif [ `uname` = SunOS ] ; then +printf Solaris.\n +platform=SOLARIS +linker_resolves_library_dependencies=0 +elif [ `uname` = Linux ] ; then +printf Linux\n +platform=LINUX linker_resolves_library_dependencies=1 +else +printf Unknown.\n +cat EOF + +*** Warning: Unknown platform. Notmuch might or might not build correctly. + +EOF fi if [ $errors -gt 0 ]; then @@ -433,9 +444,8 @@ HAVE_GETLINE = ${have_getline} # build its own version) HAVE_STRCASESTR = ${have_strcasestr} -# Whether we are building on OS X. This will affect how we build the -# shared library. -MAC_OS_X = ${mac_os_x} +# Supported platforms (so far) are: LINUX, MACOSX, SOLARIS +PLATFORM = ${platform} # Whether the linker will automatically resolve the dependency of one # library on another (if not, then linking a binary requires linking diff --git a/lib/Makefile.local b/lib/Makefile.local index 0cc1d39..62f2316 100644 --- a/lib/Makefile.local +++ b/lib/Makefile.local @@ -22,7 +22,7 @@ LIBNOTMUCH_VERSION_MINOR = 1 # simply compatible changes to the implementation). LIBNOTMUCH_VERSION_RELEASE = 0 -ifeq ($(MAC_OS_X),1) +ifeq ($(PLATFORM),MACOSX) LIBRARY_SUFFIX = dylib # On OS X, library version numbers go before suffix. LINKER_NAME = libnotmuch.$(LIBRARY_SUFFIX) diff --git a/notmuch-new.c b/notmuch-new.c index 8818728..aacb5a6 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -135,6 +135,62 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) return strcmp ((*a)-d_name, (*b)-d_name); } +/* Helper functions to test if a given dirent is of a certain type + */ +static int +_is_reg(const char *path, struct dirent *entry) +{ +#ifdef DT_REG +if (entry-d_type == DT_REG) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, %s/%s, path, entry-d_name); + +struct stat sbuf; +if (!stat(buffer, sbuf)) +return S_ISREG(sbuf.st_mode); + +return 0; +} + +static int +_is_dir(const char *path, struct dirent *entry) +{ +#ifdef DT_DIR +if (entry-d_type == DT_DIR) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, %s/%s, path, entry-d_name); + +struct stat sbuf; +if (!stat(buffer, sbuf)) +return S_ISDIR(sbuf.st_mode); + +return 0; +} + +static int +_is_lnk(const char *path, struct dirent *entry) +{ +#ifdef DT_LNK +if (entry-d_type == DT_LNK) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, %s/%s, path, entry-d_name); + +struct stat sbuf; +if (!stat(buffer, sbuf)) +return S_ISLNK(sbuf.st_mode); + +return 0; +} + /* Test if the directory looks like a Maildir directory. * * Search through the array of directory entries to see if we can find all @@ -143,12 +199,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) * Return 1 if the directory looks like a Maildir and 0 otherwise. */ static int -_entries_resemble_maildir (struct dirent **entries, int count) +_entries_resemble_maildir (const char *path, struct dirent **entries, int count) { int i, found = 0; for (i = 0; i count; i++) { - if (entries[i]-d_type != DT_DIR entries[i]-d_type != DT_UNKNOWN) + if (!_is_dir(path, entries[i])) continue; if (strcmp(entries[i]-d_name, new) == 0 || @@ -261,7 +317,7 @@ add_files_recursive (notmuch_database_t *notmuch, } /* Pass 1: Recurse into all sub-directories. */ -is_maildir = _entries_resemble_maildir (fs_entries
[PATCH] Wrap the compat header in extern "C" { } when compiling C++ sources
This fixes a build error on OpenSolaris where the final liking of notmuch fails because the linker can't find strcasestr() referenced from thread.cc. --- Is it safe to use NOTMUCH_BEGIN/END_DECLS in the compat header? The sha1 header also uses ifdef __cplusplus instead of that define.. compat/compat.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/compat/compat.h b/compat/compat.h index 173ef68..7767fe8 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -26,6 +26,10 @@ #ifndef NOTMUCH_COMPAT_H #define NOTMUCH_COMPAT_H +#ifdef __cplusplus +extern "C" { +#endif + #if !HAVE_GETLINE #include #include @@ -42,4 +46,8 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp); char* strcasestr(const char *haystack, const char *needle); #endif /* !HAVE_STRCASESTR */ +#ifdef __cplusplus +} +#endif + #endif /* NOTMUCH_COMPAT_H */ -- 1.7.0.5
[PATCH] Wrap the compat header in extern C { } when compiling C++ sources
This fixes a build error on OpenSolaris where the final liking of notmuch fails because the linker can't find strcasestr() referenced from thread.cc. --- Is it safe to use NOTMUCH_BEGIN/END_DECLS in the compat header? The sha1 header also uses ifdef __cplusplus instead of that define.. compat/compat.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/compat/compat.h b/compat/compat.h index 173ef68..7767fe8 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -26,6 +26,10 @@ #ifndef NOTMUCH_COMPAT_H #define NOTMUCH_COMPAT_H +#ifdef __cplusplus +extern C { +#endif + #if !HAVE_GETLINE #include stdio.h #include unistd.h @@ -42,4 +46,8 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp); char* strcasestr(const char *haystack, const char *needle); #endif /* !HAVE_STRCASESTR */ +#ifdef __cplusplus +} +#endif + #endif /* NOTMUCH_COMPAT_H */ -- 1.7.0.5 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] Use wrapper functions to find the type of struct dirent
Some platforms don't provide DT_REG/DT_LNK/DT_DIR. Create wrapper functions which test the presence of those symbols and fall back to stat(2). --- Not sure if I got the handling of DT_UNKNOWN correct in all cases. Someone please double-check that. notmuch-new.c | 70 ++-- 1 files changed, 62 insertions(+), 8 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index 44b50aa..95b 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -140,6 +140,62 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) return strcmp ((*a)->d_name, (*b)->d_name); } +/* Helper functions to test if a given dirent is of a certain type + */ +static int +_is_reg(const char *path, struct dirent *entry) +{ +#ifdef DT_REG +if (entry->d_type == DT_REG) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); + +struct stat sbuf; +if (!stat(buffer, )) +return S_ISREG(sbuf.st_mode); + +return 0; +} + +static int +_is_dir(const char *path, struct dirent *entry) +{ +#ifdef DT_DIR +if (entry->d_type == DT_DIR) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); + +struct stat sbuf; +if (!stat(buffer, )) +return S_ISDIR(sbuf.st_mode); + +return 0; +} + +static int +_is_lnk(const char *path, struct dirent *entry) +{ +#ifdef DT_LNK +if (entry->d_type == DT_LNK) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); + +struct stat sbuf; +if (!stat(buffer, )) +return S_ISLNK(sbuf.st_mode); + +return 0; +} + /* Test if the directory looks like a Maildir directory. * * Search through the array of directory entries to see if we can find all @@ -148,12 +204,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) * Return 1 if the directory looks like a Maildir and 0 otherwise. */ static int -_entries_resemble_maildir (struct dirent **entries, int count) +_entries_resemble_maildir (const char *path, struct dirent **entries, int count) { int i, found = 0; for (i = 0; i < count; i++) { - if (entries[i]->d_type != DT_DIR && entries[i]->d_type != DT_UNKNOWN) + if (!_is_dir(path, entries[i])) continue; if (strcmp(entries[i]->d_name, "new") == 0 || @@ -265,7 +321,7 @@ add_files_recursive (notmuch_database_t *notmuch, } /* Pass 1: Recurse into all sub-directories. */ -is_maildir = _entries_resemble_maildir (fs_entries, num_fs_entries); +is_maildir = _entries_resemble_maildir (path, fs_entries, num_fs_entries); for (i = 0; i < num_fs_entries; i++) { if (interrupted) @@ -280,9 +336,7 @@ add_files_recursive (notmuch_database_t *notmuch, * scandir results, then it might be a directory (and if not, * then we'll stat and return immediately in the next level of * recursion). */ - if (entry->d_type != DT_DIR && - entry->d_type != DT_LNK && - entry->d_type != DT_UNKNOWN) + if (!_is_dir(path, entry) && !_is_lnk(path, entry)) { continue; } @@ -360,7 +414,7 @@ add_files_recursive (notmuch_database_t *notmuch, * * In either case, a stat does the trick. */ - if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) { + if (_is_lnk(path, entry)) { int err; next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name); @@ -376,7 +430,7 @@ add_files_recursive (notmuch_database_t *notmuch, if (! S_ISREG (st.st_mode)) continue; - } else if (entry->d_type != DT_REG) { + } else if (!_is_reg(path, entry)) { continue; } -- 1.7.0.5
[PATCH] Add strcasestr v.3 - add compat implementation of strcasestr
On 4/13/10 6:47 PM, Dirk Hohndel wrote: > > v.3 of this patch, now with the changes to makefiles, configure script > compat.h and all new files that I need > Please test on platforms lacking strcasestr > > Signed-off-by: Dirk Hohndel Tested-by: Tomas Carnecky (on OpenSolaris snv_134) tom
[PATCH] Add simplistic reimplementation of strcasestr to compat library
On 4/13/10 6:10 AM, Dirk Hohndel wrote: > > While all systems that I have access to support strcasestr, it is > in fact not part of POSIX. So here's a fallback reimplementation > based on POSIX functions. Your patch is missing the part where it adds -DHAVE_STRCASESTR=.. to CONFIGURE_C{XX,}FLAGS. And I still have to figure out the licencing of my patch (need to wait for the original author to respond). So maybe your patch, with the missing parts added, is better. tom
[PATCH] Add compat version of strcasestr
strcasestr is not part of any standard (unlike for example strcasecmp) and thus not available on all platforms (in my case Solaris). --- compat/Makefile.local|4 compat/compat.h |4 compat/have_strcasestr.c |8 compat/strcasestr.c | 15 +++ configure| 19 +-- 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 compat/have_strcasestr.c create mode 100644 compat/strcasestr.c diff --git a/compat/Makefile.local b/compat/Makefile.local index 81e6c70..328eca2 100644 --- a/compat/Makefile.local +++ b/compat/Makefile.local @@ -8,3 +8,7 @@ notmuch_compat_srcs = ifneq ($(HAVE_GETLINE),1) notmuch_compat_srcs += $(dir)/getline.c $(dir)/getdelim.c endif + +ifneq ($(HAVE_STRCASESTR),1) +notmuch_compat_srcs += $(dir)/strcasestr.c +endif diff --git a/compat/compat.h b/compat/compat.h index d639e0f..be70bd8 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -38,4 +38,8 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp); #endif /* !HAVE_GETLINE */ +#if !HAVE_STRCASESTR +char *strcasestr(char *a, char *b); +#endif /* !HAVE_STRCASESTR */ + #endif /* NOTMUCH_COMPAT_H */ diff --git a/compat/have_strcasestr.c b/compat/have_strcasestr.c new file mode 100644 index 000..36e760d --- /dev/null +++ b/compat/have_strcasestr.c @@ -0,0 +1,8 @@ + +#include +#include + +int main() +{ + return strcasestr("",""); +} diff --git a/compat/strcasestr.c b/compat/strcasestr.c new file mode 100644 index 000..a4188b9 --- /dev/null +++ b/compat/strcasestr.c @@ -0,0 +1,15 @@ + +#include +#include + +char *strcasestr(char *a, char *b) +{ + size_t l; + char f[3]; + + snprintf(f, sizeof(f), "%c%c", tolower(*b), toupper(*b)); + for (l = strcspn(a, f); l != strlen(a); l += strcspn(a + l + 1, f) + 1) +if (strncasecmp(a + l, b, strlen(b)) == 0) + return a + l; + return NULL; +} diff --git a/configure b/configure index 5af7852..add2da6 100755 --- a/configure +++ b/configure @@ -310,6 +310,17 @@ else fi rm -f compat/have_getline +printf "Checking for strcasestr... " +if ${CC} -o compat/have_strcasestr compat/have_strcasestr.c > /dev/null 2>&1 +then +printf "Yes.\n" +have_strcasestr=1 +else +printf "No (will use our own instead).\n" +have_strcasestr=0 +fi +rm -f compat/have_strcasestr + cat <
Use of strcasestr
On 4/12/10 10:18 PM, Mikhail Gusarov wrote: > > Twas brillig at 15:58:10 12.04.2010 UTC+02 when tom at dbservice.com did gyre > and gimble: > > TC> In 4fd9ea0 (guess From address from Received headers, 2010-04-06) you > introduced > TC> strcasestr, which is not portable, see 82e47ec (notmuch reply: Use > strstr > TC> instead of strcasestr for portability., 2010-02-04). > > TC> Is strcasestr really necessary there or can it be replaced with strstr? > > strcasecmp is POSIX.1-2001. Indeed it is, but the code uses strcasestr and I couldn't find any indication which standard that function is part of. Adding that function to compat/ probably is the way to go, but the whole compat mechanism doesn't work here. It's like if compat/Makefile.local was not included in the top-level makefile, notmuch_compat_srcs is empty there. Any ideas how to debug that? tom
Re: [PATCH] Add strcasestr v.3 - add compat implementation of strcasestr
On 4/13/10 6:47 PM, Dirk Hohndel wrote: v.3 of this patch, now with the changes to makefiles, configure script compat.h and all new files that I need Please test on platforms lacking strcasestr Signed-off-by: Dirk Hohndelhohn...@infradead.org Tested-by: Tomas Carnecky t...@dbservice.com (on OpenSolaris snv_134) tom ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] Use wrapper functions to find the type of struct dirent
Some platforms don't provide DT_REG/DT_LNK/DT_DIR. Create wrapper functions which test the presence of those symbols and fall back to stat(2). --- Not sure if I got the handling of DT_UNKNOWN correct in all cases. Someone please double-check that. notmuch-new.c | 70 ++-- 1 files changed, 62 insertions(+), 8 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index 44b50aa..95b 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -140,6 +140,62 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) return strcmp ((*a)-d_name, (*b)-d_name); } +/* Helper functions to test if a given dirent is of a certain type + */ +static int +_is_reg(const char *path, struct dirent *entry) +{ +#ifdef DT_REG +if (entry-d_type == DT_REG) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, %s/%s, path, entry-d_name); + +struct stat sbuf; +if (!stat(buffer, sbuf)) +return S_ISREG(sbuf.st_mode); + +return 0; +} + +static int +_is_dir(const char *path, struct dirent *entry) +{ +#ifdef DT_DIR +if (entry-d_type == DT_DIR) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, %s/%s, path, entry-d_name); + +struct stat sbuf; +if (!stat(buffer, sbuf)) +return S_ISDIR(sbuf.st_mode); + +return 0; +} + +static int +_is_lnk(const char *path, struct dirent *entry) +{ +#ifdef DT_LNK +if (entry-d_type == DT_LNK) +return 1; +#endif + +char buffer[PATH_MAX]; +snprintf(buffer, PATH_MAX, %s/%s, path, entry-d_name); + +struct stat sbuf; +if (!stat(buffer, sbuf)) +return S_ISLNK(sbuf.st_mode); + +return 0; +} + /* Test if the directory looks like a Maildir directory. * * Search through the array of directory entries to see if we can find all @@ -148,12 +204,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) * Return 1 if the directory looks like a Maildir and 0 otherwise. */ static int -_entries_resemble_maildir (struct dirent **entries, int count) +_entries_resemble_maildir (const char *path, struct dirent **entries, int count) { int i, found = 0; for (i = 0; i count; i++) { - if (entries[i]-d_type != DT_DIR entries[i]-d_type != DT_UNKNOWN) + if (!_is_dir(path, entries[i])) continue; if (strcmp(entries[i]-d_name, new) == 0 || @@ -265,7 +321,7 @@ add_files_recursive (notmuch_database_t *notmuch, } /* Pass 1: Recurse into all sub-directories. */ -is_maildir = _entries_resemble_maildir (fs_entries, num_fs_entries); +is_maildir = _entries_resemble_maildir (path, fs_entries, num_fs_entries); for (i = 0; i num_fs_entries; i++) { if (interrupted) @@ -280,9 +336,7 @@ add_files_recursive (notmuch_database_t *notmuch, * scandir results, then it might be a directory (and if not, * then we'll stat and return immediately in the next level of * recursion). */ - if (entry-d_type != DT_DIR - entry-d_type != DT_LNK - entry-d_type != DT_UNKNOWN) + if (!_is_dir(path, entry) !_is_lnk(path, entry)) { continue; } @@ -360,7 +414,7 @@ add_files_recursive (notmuch_database_t *notmuch, * * In either case, a stat does the trick. */ - if (entry-d_type == DT_LNK || entry-d_type == DT_UNKNOWN) { + if (_is_lnk(path, entry)) { int err; next = talloc_asprintf (notmuch, %s/%s, path, entry-d_name); @@ -376,7 +430,7 @@ add_files_recursive (notmuch_database_t *notmuch, if (! S_ISREG (st.st_mode)) continue; - } else if (entry-d_type != DT_REG) { + } else if (!_is_reg(path, entry)) { continue; } -- 1.7.0.5 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Use of strcasestr
In 4fd9ea0 (guess From address from Received headers, 2010-04-06) you introduced strcasestr, which is not portable, see 82e47ec (notmuch reply: Use strstr instead of strcasestr for portability., 2010-02-04). Is strcasestr really necessary there or can it be replaced with strstr? tom
[PATCH] notmuch new --new-tags=tags...
On 4/12/10 1:59 PM, Jameson Rollins wrote: > On Mon, 12 Apr 2010 10:00:37 +0200, "Sebastian Spaeth" SSpaeth.de> wrote: >> On 2010-04-10, Anthony Towns wrote: >>> The attached patch makes "notmuch new --new-tags=unread,new" set the >>> "unread" and "new" tags on any new mail it finds rather than "unread" >>> and "inbox". Or whatever other tags you happen to specify. >> >> Thanks for the patch. I can't comment on the code quality, but rather >> than having to specify the set of new tags on the command line every >> time, I think it would make more sense to put them in the notmuch config >> file as this patch does: >> id:1268432006-24333-2-git-send-email-bgamari.foss at gmail.com > > I was thinking about this, and it seems to me that we really need is a > way to just specify which tags should be applied to new messages based > on search terms. It's becoming pretty clear that most people are doing > some sort of post-notmuch-new tag processing to modify the tags of new > messages to suite their needs. Why not just integrate this directly > into the notmuch-new processing itself? It seems like if this was > integrated into notmuch-new directly, the entire processing of new > messages could be sped up considerably, so that one wouldn't have to > call multiple notmuch-new processes in succession. > > I'm not sure exactly what the best way to handle it would be, but I can > imagine something like this: > > [new-tags] > +sent -new -- from:jrollins at finestructure.net > +drafts -new -- folder:draft > +notmuch -- from:notmuch at notmuchmail.org > +unread +inbox -new -- tag:new > > These are all just commands for "notmuch tag" that would be run on all > the new messages as they're processed. Each new message would be given > "new" tag by default, and then the new tag commands would be run. So it > would be the equivalent of running the following commands: > > notmuch new --new-tags=new > notmuch tag +sent -new -- from:jrollins at finestructure.net > notmuch tag +drafts -new -- folder:draft > notmuch tag +notmuch -- from:notmuch at notmuchmail.org > notmuch tag +unread +inbox -- tag:new > > This would make things much easier for everyone who is doing post-new > tag processing, which I think is probably most people. And I'm sure it > could be made much more efficient (if coded properly) than running all > these notmuch commands in succession, especially for people who have a > lot of post-new tag processing to do. Keeping the syntax identical to > the notmuch-tag command syntax would keep things simple as well. > > Do people who do a lot of post-notmuch-new tag processing think > something like this would suite their needs? I have a patch which adds support for hooks which are run when tags are added, removed or new messages added to notmuch. But perhaps the fork/exec overhead of running the hooks would slow the processing down too much. See http://caurea.org/2009/12/22/a-different-approach-to-email-tagging/, though that didn't work out quite how I expected. Classifying spam/ham is easy (that's what dspam was written for), but patch/not-patch resulted in a lot false-positives, especially when people quote emails which included patches. Same with the 'notmuch' and 'xorg' tags: dspam had trouble figuring out to which mailing list Carl sent the email (he sends emails to both lists). tom
Re: [PATCH] notmuch new --new-tags=tags...
On 4/12/10 1:59 PM, Jameson Rollins wrote: On Mon, 12 Apr 2010 10:00:37 +0200, Sebastian Spaethsebast...@sspaeth.de wrote: On 2010-04-10, Anthony Towns wrote: The attached patch makes notmuch new --new-tags=unread,new set the unread and new tags on any new mail it finds rather than unread and inbox. Or whatever other tags you happen to specify. Thanks for the patch. I can't comment on the code quality, but rather than having to specify the set of new tags on the command line every time, I think it would make more sense to put them in the notmuch config file as this patch does: id:1268432006-24333-2-git-send-email-bgamari.f...@gmail.com I was thinking about this, and it seems to me that we really need is a way to just specify which tags should be applied to new messages based on search terms. It's becoming pretty clear that most people are doing some sort of post-notmuch-new tag processing to modify the tags of new messages to suite their needs. Why not just integrate this directly into the notmuch-new processing itself? It seems like if this was integrated into notmuch-new directly, the entire processing of new messages could be sped up considerably, so that one wouldn't have to call multiple notmuch-new processes in succession. I'm not sure exactly what the best way to handle it would be, but I can imagine something like this: [new-tags] +sent -new -- from:jroll...@finestructure.net +drafts -new -- folder:draft +notmuch -- from:notmuch@notmuchmail.org +unread +inbox -new -- tag:new These are all just commands for notmuch tag that would be run on all the new messages as they're processed. Each new message would be given new tag by default, and then the new tag commands would be run. So it would be the equivalent of running the following commands: notmuch new --new-tags=new notmuch tag +sent -new -- from:jroll...@finestructure.net notmuch tag +drafts -new -- folder:draft notmuch tag +notmuch -- from:notmuch@notmuchmail.org notmuch tag +unread +inbox -- tag:new This would make things much easier for everyone who is doing post-new tag processing, which I think is probably most people. And I'm sure it could be made much more efficient (if coded properly) than running all these notmuch commands in succession, especially for people who have a lot of post-new tag processing to do. Keeping the syntax identical to the notmuch-tag command syntax would keep things simple as well. Do people who do a lot of post-notmuch-new tag processing think something like this would suite their needs? I have a patch which adds support for hooks which are run when tags are added, removed or new messages added to notmuch. But perhaps the fork/exec overhead of running the hooks would slow the processing down too much. See http://caurea.org/2009/12/22/a-different-approach-to-email-tagging/, though that didn't work out quite how I expected. Classifying spam/ham is easy (that's what dspam was written for), but patch/not-patch resulted in a lot false-positives, especially when people quote emails which included patches. Same with the 'notmuch' and 'xorg' tags: dspam had trouble figuring out to which mailing list Carl sent the email (he sends emails to both lists). tom ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Use of strcasestr
In 4fd9ea0 (guess From address from Received headers, 2010-04-06) you introduced strcasestr, which is not portable, see 82e47ec (notmuch reply: Use strstr instead of strcasestr for portability., 2010-02-04). Is strcasestr really necessary there or can it be replaced with strstr? tom ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Use of strcasestr
On 4/12/10 10:18 PM, Mikhail Gusarov wrote: Twas brillig at 15:58:10 12.04.2010 UTC+02 when t...@dbservice.com did gyre and gimble: TC In 4fd9ea0 (guess From address from Received headers, 2010-04-06) you introduced TC strcasestr, which is not portable, see 82e47ec (notmuch reply: Use strstr TC instead of strcasestr for portability., 2010-02-04). TC Is strcasestr really necessary there or can it be replaced with strstr? strcasecmp is POSIX.1-2001. Indeed it is, but the code uses strcasestr and I couldn't find any indication which standard that function is part of. Adding that function to compat/ probably is the way to go, but the whole compat mechanism doesn't work here. It's like if compat/Makefile.local was not included in the top-level makefile, notmuch_compat_srcs is empty there. Any ideas how to debug that? tom ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] Add compat version of strcasestr
strcasestr is not part of any standard (unlike for example strcasecmp) and thus not available on all platforms (in my case Solaris). --- compat/Makefile.local|4 compat/compat.h |4 compat/have_strcasestr.c |8 compat/strcasestr.c | 15 +++ configure| 19 +-- 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 compat/have_strcasestr.c create mode 100644 compat/strcasestr.c diff --git a/compat/Makefile.local b/compat/Makefile.local index 81e6c70..328eca2 100644 --- a/compat/Makefile.local +++ b/compat/Makefile.local @@ -8,3 +8,7 @@ notmuch_compat_srcs = ifneq ($(HAVE_GETLINE),1) notmuch_compat_srcs += $(dir)/getline.c $(dir)/getdelim.c endif + +ifneq ($(HAVE_STRCASESTR),1) +notmuch_compat_srcs += $(dir)/strcasestr.c +endif diff --git a/compat/compat.h b/compat/compat.h index d639e0f..be70bd8 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -38,4 +38,8 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp); #endif /* !HAVE_GETLINE */ +#if !HAVE_STRCASESTR +char *strcasestr(char *a, char *b); +#endif /* !HAVE_STRCASESTR */ + #endif /* NOTMUCH_COMPAT_H */ diff --git a/compat/have_strcasestr.c b/compat/have_strcasestr.c new file mode 100644 index 000..36e760d --- /dev/null +++ b/compat/have_strcasestr.c @@ -0,0 +1,8 @@ + +#include string.h +#include strings.h + +int main() +{ + return strcasestr(,); +} diff --git a/compat/strcasestr.c b/compat/strcasestr.c new file mode 100644 index 000..a4188b9 --- /dev/null +++ b/compat/strcasestr.c @@ -0,0 +1,15 @@ + +#include string.h +#include strings.h + +char *strcasestr(char *a, char *b) +{ + size_t l; + char f[3]; + + snprintf(f, sizeof(f), %c%c, tolower(*b), toupper(*b)); + for (l = strcspn(a, f); l != strlen(a); l += strcspn(a + l + 1, f) + 1) +if (strncasecmp(a + l, b, strlen(b)) == 0) + return a + l; + return NULL; +} diff --git a/configure b/configure index 5af7852..add2da6 100755 --- a/configure +++ b/configure @@ -310,6 +310,17 @@ else fi rm -f compat/have_getline +printf Checking for strcasestr... +if ${CC} -o compat/have_strcasestr compat/have_strcasestr.c /dev/null 21 +then +printf Yes.\n +have_strcasestr=1 +else +printf No (will use our own instead).\n +have_strcasestr=0 +fi +rm -f compat/have_strcasestr + cat EOF All required packages were found. You may now run the following @@ -384,6 +395,10 @@ zsh_completion_dir = \$(prefix)/share/zsh/functions/Completion/Unix # build its own version) HAVE_GETLINE = ${have_getline} +# Whether the strcasestr function is available (if not, then notmuch will +# build its own version) +HAVE_STRCASESTR = ${have_strcasestr} + # Flags needed to compile and link against Xapian XAPIAN_CXXFLAGS = ${xapian_cxxflags} XAPIAN_LDFLAGS = ${xapian_ldflags} @@ -405,9 +420,9 @@ VALGRIND_CFLAGS = ${valgrind_cflags} # Combined flags for compiling and linking against all of the above CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\ - \$(VALGRIND_CFLAGS) + \$(VALGRIND_CFLAGS) -DHAVE_STRCASESTR=\$(HAVE_STRCASESTR) CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)\\ \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\ -\$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS) +\$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS) -DHAVE_STRCASESTR=\$(HAVE_STRCASESTR) CONFIGURE_LDFLAGS = \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS) EOF -- 1.7.0.2 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] Add simplistic reimplementation of strcasestr to compat library
On 4/13/10 6:10 AM, Dirk Hohndel wrote: While all systems that I have access to support strcasestr, it is in fact not part of POSIX. So here's a fallback reimplementation based on POSIX functions. Your patch is missing the part where it adds -DHAVE_STRCASESTR=.. to CONFIGURE_C{XX,}FLAGS. And I still have to figure out the licencing of my patch (need to wait for the original author to respond). So maybe your patch, with the missing parts added, is better. tom ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[notmuch] [PATCH] Add post-add and post-tag hooks
On 12/23/09 12:02 AM, Olly Betts wrote: > Tomas Carnecky writes: >> #if defined(__sun__) >> ... sprintf, stat etc >> #else >> (void) path; >> return dirent->d_type == DT_DIR; >> #endif > > Rather than a platform-specific check, it would be better to check if DT_DIR > is defined. > > Beware that even on Linux (where the d_type field is present), it may always > contain DT_UNKNOWN for some filesystems, so you really should check for that > case and fall back to using stat() instead. Currently configure is a simple shell script and not some autoconf magic. And I don't know how eager Carl is to use autoconf, scons, cmake or similar. tom
[notmuch] [PATCH] Add post-add and post-tag hooks
On 12/22/09 3:56 AM, Tomas Carnecky wrote: > The post-add hook is run by 'notmuch new' after each new message is added, > post-tag is run after a tag has been added or removed. The hooks are stored > in the users home directory (~/.notmuch/hooks/). > > Since post-tag is run unconditionally every time a new tag is added or removed, > that means it is also invoked when 'notmuch new' adds the two implicit > tags (inbox, unread). So make sure your scripts don't choke on that and can > be both executed in parallel. What are these good for? I (try to) use these two hooks to automatically tag messages. But not in the usual way, I don't use static scripts, I use a spam filter. I hope to be able to teach it to classify the messages, not only spam/ham but also add tags such as patch (does that message contain a patch?), tag messages based on which mailing lists the messages belong etc. I use dspam as the spam filter. Each tag is actually a virtual user that exists in dspam. When adding new messages dspam classifies the mails and I assign the tags based on the result. If dspam deemed the message Spam then I set the tag. To train dspam I use the post-tag hook: whenever I change a tag (for example add 'spam' to a falsely unrecognized spam), the post-tag hook retrains dspam. Since the post-add hook is running synchronously with 'notmuch new', this adds quite a bit overhead. Depending on how fast the spam filter is, it adds more or less time to do the import of new messages. It also depends on how many tags you want to assign - dspam has to run once for each tag to see if the tag should be assigned or not. tom --- >8 --- post-add #!/bin/bash # This is so that the post-tag doesn't trigger retraining! export NOTMUCH_POST_ADD=1 MESSAGEID=$1 FILENAME=$2 # Array of tags. tags=( spam ) for tag in "${tags[@]}"; do RESULT="$(/opt/dspam/bin/dspam --user $tag --deliver=summary < $FILENAME)" if echo $RESULT | grep -q 'result="Spam";'; then echo $tag fi done # I remove the inbox flag from all new messages and keep only 'unread' echo "-inbox" --- >8 --- --- >8 --- post-tag #!/bin/sh if [ "$NOTMUCH_POST_ADD" ]; then echo "Exiting due to running in post-add" exit fi MESSAGEID=$1 FILENAME=$2 TAG=$3 ADDREMOVE=$4 if [ "x$ADDREMOVE" = "xadded" ]; then CLASS="spam" else CLASS="innocent" fi /opt/dspam/bin/dspam --user $TAG --source=error --class=$CLASS < $FILENAME --- >8 ---
[notmuch] [PATCH] Add post-add and post-tag hooks
The post-add hook is run by 'notmuch new' after each new message is added, post-tag is run after a tag has been added or removed. The hooks are stored in the users home directory (~/.notmuch/hooks/). Since post-tag is run unconditionally every time a new tag is added or removed, that means it is also invoked when 'notmuch new' adds the two implicit tags (inbox, unread). So make sure your scripts don't choke on that and can be both executed in parallel. Signed-off-by: Tomas Carnecky --- lib/message.cc | 45 ++ notmuch-new.c | 66 2 files changed, 111 insertions(+), 0 deletions(-) diff --git a/lib/message.cc b/lib/message.cc index 49519f1..bcd8abb 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -664,6 +664,47 @@ _notmuch_message_remove_term (notmuch_message_t *message, return NOTMUCH_PRIVATE_STATUS_SUCCESS; } +/* Run the post-tag hook */ +static void +post_tag_hook (notmuch_message_t *message, const char *tag, int added) +{ +/* Skip tags that notmuch itself assigns to new messages */ +const char *skip[] = { +"inbox", "unread" +}; + +for (int i = 0; i < sizeof (skip) / sizeof (skip[0]); ++i) { +if (strcmp(skip[i], tag) == 0) +return; +} + +char proc[PATH_MAX]; +snprintf (proc, PATH_MAX, "%s/.notmuch/hooks/post-tag", getenv("HOME")); +if (access (proc, X_OK)) +return; + +int pid = fork (); +if (pid == -1) +return; + +/* Wait for the hook to finish. This behaviour might be changed in the + * future, but for now I think it's better to take the safe route. */ +if (pid > 0) { +waitpid (0, NULL, 0); +return; +} + +const char *filename = notmuch_message_get_filename (message); +const char *message_id = notmuch_message_get_message_id (message); + +const char *args[] = { +proc, message_id, filename, tag, added ? "added" : "removed", NULL +}; + +execv (proc, (char *const *) ); +exit (0); +} + notmuch_status_t notmuch_message_add_tag (notmuch_message_t *message, const char *tag) { @@ -684,6 +725,8 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag) if (! message->frozen) _notmuch_message_sync (message); +post_tag_hook (message, tag, 1); + return NOTMUCH_STATUS_SUCCESS; } @@ -707,6 +750,8 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag) if (! message->frozen) _notmuch_message_sync (message); +post_tag_hook (message, tag, 0); + return NOTMUCH_STATUS_SUCCESS; } diff --git a/notmuch-new.c b/notmuch-new.c index 837ae4f..d984aae 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -42,6 +42,71 @@ handle_sigint (unused (int sig)) interrupted = 1; } +/* Run the post-add hook. The hook is given the chance to specify additional tags + * that should be added to the message. The hook writes the tags to its stdout, + * separated by a newline. The script's stdout is redirected to a pipe so that + * notmuch can process its output. The tags can be prefixed with '+' or '-' to + * indicate if the tag should be added or removed. Absence of one of these prefixes + * means that the tag will be added. */ +static void +post_add_hook (notmuch_message_t *message) +{ +char proc[PATH_MAX]; +snprintf (proc, PATH_MAX, "%s/.notmuch/hooks/post-add", getenv ("HOME")); +if (access (proc, X_OK)) +return; + +/* The pipe between the hook and the notmuch process. The script writes + * into fds[0], notmuch reads from fds[1]. */ +int fds[2]; +if (pipe (fds)) + return; + +int pid = fork (); +if (pid == -1) { + close (fds[0]); + close (fds[1]); + return; +} else if (pid > 0) { + close (fds[0]); + waitpid (0, NULL, 0); + + char buffer[256] = { 0, }; + read (fds[1], buffer, sizeof (buffer)); + + char *tag; + for (tag = buffer; tag && *tag; ) { + char *end = strchr (tag, '\n'); + if (end) + *end = 0; + + if (tag[0] == '+') + notmuch_message_add_tag (message, tag + 1); + else if (tag[0] == '-') + notmuch_message_remove_tag (message, tag + 1); + else + notmuch_message_add_tag (message, tag); + + tag = end ? end + 1 : end; + } + + return; +} + +/* This is the child process (where the hook runs) */ +close (fds[1]); +dup2 (fds[0], 1); + +const char *filename = notmuch_message_get_filename (message); +const char *message_id = notmuch_message_get_message_id (message); +const char *args[] = { + proc, message_id, filename, NULL +}; + +execv (proc, (char *const *) ); +exit (0); +} + static void tag_inbox_and_unre
[notmuch] [PATCH] Solaris doesn't have 'struct dirent::d_type'
On 12/20/09 7:02 PM, James Westby wrote: > From: Tomas Carnecky > > Use stat(2) instead. > > Signed-off-by: Tomas Carnecky > Signed-off-by: James Westby<jw+debian at jameswestby.net> > --- > >The original patch duplicated asprintf and stat calls, rearraging >the code means we don't need to. > >I have a concern about the duplicated stats in is_maildir, but they >are not so easy to save. I ran a quick timing test (3931 files), dropping >caches before each set: > > master: >real 2m3.545s >real 1m34.571s >real 1m36.005s > > original patch: >real 2m18.114s >real 1m34.843s >real 1m36.317s > > revised patch: >real 2m5.890s >real 1m36.387s >real 1m36.453s > >This shoes there is little impact of the code, but given that it is >around one percent we may want to make it conditional on platform >and save the extra stat calls. If performance regression is an issue, something like this could be used to keep the current code paths in linux and stat() on other platforms: static bool is_dir(const char *path, struct dirent *dirent) { #if defined(__sun__) ... sprintf, stat etc #else (void) path; return dirent->d_type == DT_DIR; #endif } tom
[notmuch] [PATCH] Solaris doesn't have 'struct dirent::d_type'
Use stat(2) instead. Signed-off-by: Tomas Carnecky --- There is a second issue that prevents notmuch from working on Solaris: the getpwuid_r() prototype doesn't have the last argument. But that can be easily worked around by setting -D_POSIX_PTHREAD_SEMANTICS on the compiler commandline. Do you want to use uname to detect the platform and define platform-specific code or can I unconditionally add that define to CFLAGS? notmuch-new.c | 22 +- 1 files changed, 17 insertions(+), 5 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index 9d20616..837ae4f 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -90,12 +90,18 @@ static int ino_cmp(const struct dirent **a, const struct dirent **b) * Return 1 if the directory looks like a Maildir and 0 otherwise. */ static int -is_maildir (struct dirent **entries, int count) +is_maildir (const char *path, struct dirent **entries, int count) { int i, found = 0; for (i = 0; i < count; i++) { - if (entries[i]->d_type != DT_DIR) continue; + char pbuf[PATH_MAX]; +snprintf(pbuf, PATH_MAX, "%s/%s", path, entries[i]->d_name); + + struct stat buf; + if (stat(pbuf, ) == -1 || !S_ISDIR(buf.st_mode)) + continue; + if (strcmp(entries[i]->d_name, "new") == 0 || strcmp(entries[i]->d_name, "cur") == 0 || strcmp(entries[i]->d_name, "tmp") == 0) @@ -178,7 +184,13 @@ add_files_recursive (notmuch_database_t *notmuch, /* If this directory hasn't been modified since the last * add_files, then we only need to look further for * sub-directories. */ - if (path_mtime <= path_dbtime && entry->d_type == DT_REG) + struct stat buf; + char pbuf[PATH_MAX]; + snprintf(pbuf, PATH_MAX, "%s/%s", path, entry->d_name); + if (stat(pbuf, ) == -1) + continue; + + if (path_mtime <= path_dbtime && S_ISREG(buf.st_mode)) continue; /* Ignore special directories to avoid infinite recursion. @@ -188,9 +200,9 @@ add_files_recursive (notmuch_database_t *notmuch, * user specify files to be ignored. */ if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0 || - (entry->d_type == DT_DIR && + (S_ISDIR(buf.st_mode) && (strcmp (entry->d_name, "tmp") == 0) && -is_maildir (namelist, num_entries)) || +is_maildir (path, namelist, num_entries)) || strcmp (entry->d_name, ".notmuch") ==0) { continue; -- 1.6.6.rc1.39.g9a42