[PATCH 2/4] dirent->d_type not available on Soalris

Austin Clements amdragon at MIT.EDU
Wed Apr 11 12:36:09 PDT 2012


Correct me if I'm mistaken, but d_name will only be a basename, so
your calls to stat will fail for files that are not in the current
directory.  I think in all of the situations you had to call stat, we
already construct the absolute path of the file (sometimes a little
later in the code, but it can easily be moved), so this should be easy
to fix.

Rather than sprinkling portability code throughout notmuch-new, it
seems like it would be simpler if this logic were wrapped in a
separate function.  For example, something along the (completely
untested) lines of,

static mode_t
dirent_type (const struct *entry, const char *abspath)
{
    struct stat statbuf;
#ifdef _DIRENT_HAVE_D_TYPE
    static const mode_t modes[] = {
	[DT_BLK]  = S_IFBLK,
	[DT_CHR]  = S_IFCHR,
	[DT_DIR]  = S_IFDIR,
	[DT_FIFO] = S_IFIFO,
	[DT_LNK]  = S_IFLNK,
	[DT_REG]  = S_IFREG,
	[DT_SOCK] = S_IFSOCK
    };
    if (entry->d_type >= 0 && entry->d_type < sizeof(modes)/sizeof(modes[0]) &&
	modes[entry->d_type])
	return modes[entry->d_type];
#endif

    if (stat(abspath, &statbuf) == -1)
	return -1;
    return statbuf.st_mode & S_IFMT;
}

This has the added benefit of correctly handling DT_UNKNOWN, which we
currently don't.

Instead of taking the absolute path of the file, this could take the
absolute path of the containing directory and construct the full path
from that and d_name; that would probably be a nicer interface, but it
would be redundant computation.

Quoth Vladimir.Marek at oracle.com on Apr 09 at  6:32 pm:
> From: Vladimir Marek <vlmarek at volny.cz>
> 
> The inspiration was taken from similar issue in mutt:
> http://does-not-exist.org/mail-archives/mutt-dev/msg11290.html
> 
> Signed-off-by: Vladimir Marek <vlmarek at volny.cz>
> ---
>  notmuch-new.c |   28 ++++++++++++++++++++++++++++
>  1 files changed, 28 insertions(+), 0 deletions(-)
> 
> diff --git a/notmuch-new.c b/notmuch-new.c
> index 4f13535..3d265bd 100644
> --- a/notmuch-new.c
> +++ b/notmuch-new.c
> @@ -21,6 +21,9 @@
>  #include "notmuch-client.h"
>  
>  #include <unistd.h>
> +#ifndef _DIRENT_HAVE_D_TYPE
> +#include <sys/types.h>
> +#endif
>  
>  typedef struct _filename_node {
>      char *filename;
> @@ -167,7 +170,14 @@ _entries_resemble_maildir (struct dirent **entries, int count)
>      int i, found = 0;
>  
>      for (i = 0; i < count; i++) {
> +#ifdef _DIRENT_HAVE_D_TYPE
>  	if (entries[i]->d_type != DT_DIR && entries[i]->d_type != DT_UNKNOWN)
> +#else
> +	struct stat statbuf;
> +	if (stat(entries[i]->d_name, &statbuf) == -1)
> +		continue;
> +	if (! S_ISDIR(statbuf.st_mode))
> +#endif
>  	    continue;
>  
>  	if (strcmp(entries[i]->d_name, "new") == 0 ||
> @@ -258,6 +268,9 @@ add_files_recursive (notmuch_database_t *notmuch,
>      struct stat st;
>      notmuch_bool_t is_maildir, new_directory;
>      const char **tag;
> +#ifndef _DIRENT_HAVE_D_TYPE
> +    struct stat statbuf;
> +#endif
>  
>      if (stat (path, &st)) {
>  	fprintf (stderr, "Error reading directory %s: %s\n",
> @@ -328,9 +341,16 @@ 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). */
> +#ifdef _DIRENT_HAVE_D_TYPE
>  	if (entry->d_type != DT_DIR &&
>  	    entry->d_type != DT_LNK &&
>  	    entry->d_type != DT_UNKNOWN)
> +#else
> +	if (stat(entry->d_name, &statbuf) == -1)
> +		continue;
> +	if (!(statbuf.st_mode & S_IFDIR) &&
> +	    !(statbuf.st_mode & S_IFLNK))
> +#endif
>  	{
>  	    continue;
>  	}
> @@ -427,7 +447,11 @@ add_files_recursive (notmuch_database_t *notmuch,
>  	 *
>  	 * In either case, a stat does the trick.
>  	 */
> +#ifdef _DIRENT_HAVE_D_TYPE
>  	if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) {
> +#else
> +	if (stat(entry->d_name, &statbuf) == -1 || statbuf.st_mode & S_IFLNK) {
> +#endif
>  	    int err;
>  
>  	    next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
> @@ -443,7 +467,11 @@ add_files_recursive (notmuch_database_t *notmuch,
>  
>  	    if (! S_ISREG (st.st_mode))
>  		continue;
> +#ifdef _DIRENT_HAVE_D_TYPE
>  	} else if (entry->d_type != DT_REG) {
> +#else
> +	} else if (statbuf.st_mode & S_IFREG) {
> +#endif
>  	    continue;
>  	}
>  


More information about the notmuch mailing list