[Dovecot] LIST problem with Dovecot1.1beta10

Dean Brooks dean at iglou.com
Tue Dec 4 21:47:18 EET 2007


On Tue, Dec 04, 2007 at 07:34:37PM +0200, Timo Sirainen wrote:
> On Tue, 2007-12-04 at 12:12 -0500, Dean Brooks wrote:
> > However, no matter what configuration changes I make, Dovecot refuses
> > to list a filesystem mailbox unless you specify a wildcard:
> > 
> > x list "" Sent
> > x OK List completed.
> > 
> > x list "" Sent*
> > * LIST (\NoInferiors \UnMarked) "/" "Sent"
> > x OK List completed.
> > 
> > Were there any changes to the filesystem listing code?  We're on NFS
> > filesystem if it makes any difference.
> 
> That might explain it, but I can't think of any change that could have
> broken this.

Found it.

It affects anyone under Solaris 8 , and probably all other versions of Solaris.

In src/list/mailbox-list-fs-iter.c, in the function fs_list_dir_next(),
the following code near the end of the function is the culprit:

                if (i_strocpy(dir->dirent.d_name, fname,
                          sizeof(dir->dirent.d_name)) < 0) {
                        /* name too large.. shouldn't happen. */
                        continue;
                }

To fix it, I changed it to:

                if (i_strocpy(dir->dirent.d_name, fname, MAXNAMLEN) < 0) {
                        /* name too large.. shouldn't happen. */
                        continue;
                }

It appears that sizeof(dir->dirent.d_name) always returns "1" under
Solaris.  Indeed, when I do a "man dirent", I see this:

     The  dirent structure is defined:

     struct  dirent {
             ino_t           d_ino;
             off_t           d_off;
             unsigned short  d_reclen;
             char            d_name[1];
     };

     The  field  d_name
     is  the  beginning of the character array giving the name of
     the directory entry. This name is null  terminated  and  may
     have  at  most   MAXNAMLEN  characters. This results in file
     system independent directory entries being  variable  length
     entities.

Turns out this is a common dirent portability issue that affects a
few operating systems, including Solaris.  I googled around and
found other authors who have done crazy stuff like this:

#ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
 strcpy(dirent->d_name, filename, MAXPATHLEN);
#else
 strcpy(dirent->d_name, filename, sizeof(dirent->d_name));
#endif

There is probably a cleaner way to deal with this though.  Anyway, it
something that needs to be dealt with.  From what I can tell, this is
the only place in Dovecot where a sizeof() is done on d_name.

--
Dean Brooks
dean at iglou.com


More information about the dovecot mailing list