use scandir in folder_read
authorPhilipp Takacs <philipp@bureaucracy.de>
Thu, 19 Mar 2020 01:50:51 +0000 (02:50 +0100)
committerPhilipp Takacs <philipp@bureaucracy.de>
Tue, 31 Mar 2020 21:10:35 +0000 (23:10 +0200)
sbr/folder_read.c

index 011958f..6a8139a 100644 (file)
@@ -12,9 +12,6 @@
 #include <dirent.h>
 #include <sys/stat.h>
 
-/* We allocate the `mi' array 1024 elements at a time */
-#define NUMMSGS  1024
-
 /*
 ** 1) Create the folder/message structure
 ** 2) Read the directory (folder) and temporarily
 ** 4) Read and initialize the sequence information.
 */
 
+static int others;
+
+static int
+msgnumcmp(const struct dirent **d1, const struct dirent **d2)
+{
+       size_t l1, l2;
+
+       l1 = strlen((*d1)->d_name);
+       l2 = strlen((*d2)->d_name);
+       if (l1 < l2) {
+               return -1;
+       }
+       if (l1 > l2) {
+               return 1;
+       }
+       return strcmp((*d1)->d_name, (*d2)->d_name);
+}
+
+static int
+msgfilter(const struct dirent *e)
+{
+       int i;
+       /* For compatibility with nmh, ignore rmm backup files. */
+       if (e->d_name[0] == '.' || e->d_name[0] == ',' || e->d_name[0] == '#') {
+               return 0;
+       }
+       for (i = 0; e->d_name[i]; i++) {
+               if ((i == 0 && e->d_name[i] == '0') || e->d_name[i] < '0' || e->d_name[i] > '9') {
+                       others = 1;
+                       return 0;
+               }
+       }
+       return 1;
+}
+
 struct msgs *
 folder_read(char *name)
 {
-       int msgnum, len, *mi;
+       int i;
        struct msgs *mp;
        struct stat st;
-       struct dirent *dp;
-       DIR *dd;
+       struct dirent **dp;
 
+       others = 0;
        name = mh_xstrdup(toabsdir(name));
-       if (!(dd = opendir(name))) {
-               mh_free0(&name);
-               return NULL;
-       }
 
        if (stat(name, &st) == -1) {
                mh_free0(&name);
-               closedir(dd);
                return NULL;
        }
 
        /* Allocate the main structure for folder information */
        mp = mh_xcalloc(1, sizeof(*mp));
 
-       clear_folder_flags(mp);
        mp->foldpath = name;
-       mp->lowmsg = 0;
-       mp->hghmsg = 0;
-       mp->curmsg = 0;
-       mp->lowsel = 0;
-       mp->hghsel = 0;
-       mp->numsel = 0;
-       mp->nummsg = 0;
 
        if (access(name, W_OK) == -1)
                set_readonly(mp);
 
-       /*
-       ** Allocate a temporary place to record the
-       ** name of the messages in this folder.
-       */
-       len = NUMMSGS;
-       mi = mh_xcalloc(len, sizeof(*mi));
-
-       while ((dp = readdir(dd))) {
-               if ((msgnum = m_atoi(dp->d_name)) && msgnum > 0) {
-                       /*
-                       ** Check if we need to allocate more
-                       ** temporary elements for message names.
-                       */
-                       if (mp->nummsg >= len) {
-                               len += NUMMSGS;
-                               mi = mh_xrealloc(mi, len * sizeof(*mi));
-                       }
-
-                       /* Check if this is the first message we've seen */
-                       if (mp->nummsg == 0) {
-                               mp->lowmsg = msgnum;
-                               mp->hghmsg = msgnum;
-                       } else {
-                               /*
-                               ** Check if this is it the highest or
-                               ** lowest we've seen?
-                               */
-                               if (msgnum < mp->lowmsg)
-                                       mp->lowmsg = msgnum;
-                               if (msgnum > mp->hghmsg)
-                                       mp->hghmsg = msgnum;
-                       }
-
-                       /*
-                       ** Now increment count, and record message
-                       ** number in a temporary place for now.
-                       */
-                       mi[mp->nummsg++] = msgnum;
-
-               } else {
-                       switch (dp->d_name[0]) {
-                       case '.':
-                       case ',':
-                               continue;
-
-                       default:
-                               /*
-                               ** indicate that there are other
-                               ** files in folder
-                               */
-                               set_other_files(mp);
-                               continue;
-                       }
-               }
-       }
+       mp->nummsg = scandir(name, &dp, msgfilter, msgnumcmp);
 
-       closedir(dd);
-       mp->lowoff = max(mp->lowmsg, 1);
+       if (others)
+               set_other_files(mp);
 
-       /* Go ahead and allocate space for 100 additional messages. */
+       if (mp->nummsg < 0) {
+               mh_free0(&name);
+               mh_free0(&mp);
+               return NULL;
+       }
+       if (mp->nummsg > 0) {
+               mp->lowmsg = m_atoi(dp[0]->d_name);
+               mp->hghmsg = m_atoi(dp[mp->nummsg-1]->d_name);
+       }
+       mp->lowoff = max(mp->lowmsg, 1);
        mp->hghoff = mp->hghmsg + 100;
-
-       /* for testing, allocate minimal necessary space */
-       /* mp->hghoff = max(mp->hghmsg, 1); */
-
-       /* Allocate space for status of each message. */
-
        mp->msgstats = mh_xcalloc(MSGSTATSIZE(mp, mp->lowoff, mp->hghoff), 1);
-
-       /*
-       ** Scan through the array of messages we've seen and
-       ** setup the initial flags for those messages in the
-       ** newly allocated mp->msgstats area.
-       */
-       for (msgnum = 0; msgnum < mp->nummsg; msgnum++)
-               set_exists(mp, mi[msgnum]);
-
-       mh_free0(&mi);  /* We don't need this anymore */
+       for (i = 0; i < mp->nummsg; i++) {
+               set_exists(mp, m_atoi(dp[i]->d_name));
+               mh_free0(dp + i);
+       }
+       mh_free0(&dp);
 
        /*
        ** Read and initialize the sequence information.