I updated my patch a bit.

There was a problem with storing only mtime's seconds as mandb's last
changed time.  There's a chance that if mandb -p gets called twice
within a second that it won't know to crawl a directory on the second
run.  That didn't matter as much before, since the changed files would
be indexed on the next run, whenever that happened.  But with the
ctime patch, there's a risk that it could never catch some files if
this happened.  I made mandb store nanoseconds to avoid this.
Index: man-db-2.6.3/src/check_mandirs.c
===================================================================
--- man-db-2.6.3.orig/src/check_mandirs.c       2012-10-27 12:00:13.000000000 
+0300
+++ man-db-2.6.3/src/check_mandirs.c    2012-10-31 20:24:59.285914354 +0200
@@ -316,12 +316,15 @@
                free (lg.whatis);
 }
 
-static inline void add_dir_entries (const char *path, char *infile)
+static inline void add_dir_entries (const char *path, char *infile,
+                                   time_t last, time_t ulast)
 {
        char *manpage;
        int len;
        struct dirent *newdir;
        DIR *dir;
+       struct stat statbuf;
+       int fd, ret;
 
        manpage = appendstr (NULL, path, "/", infile, "/", NULL);
        len = strlen (manpage);
@@ -332,7 +335,17 @@
         */
 
        dir = opendir (infile);
-       if (!dir) {
+       if (dir) {
+#if _BSD_SOURCE
+               if ( (fd = dirfd (dir)) != -1)
+                       ret = fchdir (fd);
+               else
+                       ret = chdir (infile);
+#else
+               ret = chdir (infile);
+#endif
+       }
+       if (!dir || ret == -1) {
                error (0, errno, _("can't search directory %s"), manpage);
                free (manpage);
                 return;
@@ -343,12 +356,25 @@
        while ( (newdir = readdir (dir)) )
                if (!(*newdir->d_name == '.' && 
                      strlen (newdir->d_name) < (size_t) 3)) {
+#if _BSD_SOURCE
+                       if (last)
+                               lstat(newdir->d_name, &statbuf);
+                       if (!last || last < statbuf.st_ctime ||
+                           (last == statbuf.st_ctime
+                            && ulast < statbuf.st_ctim.tv_nsec)) {
+                               manpage = appendstr (manpage, newdir->d_name, 
NULL);
+                               test_manfile (manpage, path);
+                               *(manpage + len) = '\0';
+                       }
+#else
                        manpage = appendstr (manpage, newdir->d_name, NULL);
                        test_manfile (manpage, path);
                        *(manpage + len) = '\0';
+#endif
                }
                
        free (manpage);
+       chdir ("..");
        closedir (dir);
 }
 
@@ -425,13 +451,14 @@
  * scanned for new files, which are then added to the db.
  */
 static int testmandirs (const char *path, const char *catpath, time_t last,
-                       int create)
+                       time_t ulast, int create)
 {
        DIR *dir;
        struct dirent *mandir;
        struct stat stbuf;
        int amount = 0;
        int created = 0;
+       int fd;
 
        debug ("Testing %s for new files\n", path);
 
@@ -441,7 +468,14 @@
                return 0;
        }
 
+#ifdef _BSD_SOURCE
+       if ( (fd = dirfd (dir)) != -1)
+               fchdir (fd);
+       else
+               chdir (path);
+#else
        chdir (path);
+#endif
 
        while( (mandir = readdir (dir)) ) {
                if (strncmp (mandir->d_name, "man", 3) != 0)
@@ -453,13 +487,26 @@
                        continue;
                if (!S_ISDIR(stbuf.st_mode))            /* not a directory */
                        continue;
-               if (last && stbuf.st_mtime <= last) {
+#ifdef _BSD_SOURCE
+               if (last && (stbuf.st_mtime < last
+                            || (stbuf.st_mtime == last
+                                && stbuf.st_mtim.tv_nsec < ulast))) {
+                       /* scanned already */
+                       debug ("%s modified %ld.%09d, db modified %ld.%09d\n",
+                              mandir->d_name, (long) stbuf.st_mtime,
+                              (int) stbuf.st_mtim.tv_nsec,
+                              (long) last, (int) ulast);
+                       continue;
+               }
+#else
+               if (last && stbuf.st_mtime < last) {
                        /* scanned already */
                        debug ("%s modified %ld, db modified %ld\n",
                               mandir->d_name, (long) stbuf.st_mtime,
                               (long) last);
                        continue;
                }
+#endif
 
                debug ("\tsubdirectory %s has been 'modified'\n",
                       mandir->d_name);
@@ -508,7 +555,7 @@
                        if (!tty)
                                fprintf (stderr, "\n");
                }
-               add_dir_entries (path, mandir->d_name);
+               add_dir_entries (path, mandir->d_name, last, ulast);
                MYDBM_CLOSE (dbf);
                amount++;
        }
@@ -520,11 +567,14 @@
 /* update the time key stored within `database' */
 void update_db_time (void)
 {
+       struct timeval tv;
        datum key, content;
 #ifdef FAST_BTREE
        datum key1, content1;
 #endif /* FAST_BTREE */
 
+       gettimeofday (&tv, NULL);
+
        memset (&key, 0, sizeof key);
        memset (&content, 0, sizeof content);
 #ifdef FAST_BTREE
@@ -533,7 +583,8 @@
 #endif
 
        MYDBM_SET (key, xstrdup (KEY));
-       MYDBM_SET (content, xasprintf ("%ld", (long) time (NULL)));
+       MYDBM_SET (content, xasprintf ("%ld.%09d", (long) tv.tv_sec,
+                                      (int) tv.tv_usec));
 
        /* Open the db in RW to store the $mtime$ ID */
        /* we know that this should succeed because we just updated the db! */
@@ -595,7 +646,7 @@
        
        debug ("create_db(%s): %s\n", manpath, database);
 
-       amount = testmandirs (manpath, catpath, (time_t) 0, 1);
+       amount = testmandirs (manpath, catpath, (time_t) 0, (time_t) 0, 1);
 
        if (amount) {
                update_db_time ();
@@ -646,6 +697,8 @@
        if (dbf) {
                datum key, content;
                int new;
+               long sec;
+               int usec;
 
                memset (&key, 0, sizeof key);
                memset (&content, 0, sizeof content);
@@ -654,16 +707,23 @@
                content = MYDBM_FETCH (dbf, key);
                MYDBM_CLOSE (dbf);
                free (MYDBM_DPTR (key));
+               if (MYDBM_DPTR (content)) {
+                       char *end;
+
+                       sec = strtol (MYDBM_DPTR (content), &end, 10);
+                       usec = *end == '.' ? strtol (end+1, NULL, 10) : 0;
+               } else
+                       sec = usec = 0;
 
-               debug ("update_db(): %ld\n",
-                      MYDBM_DPTR (content) ? atol (MYDBM_DPTR (content)) : 0L);
+               debug ("update_db(): %ld.%09d\n", sec, usec);
                if (MYDBM_DPTR (content)) {
                        new = testmandirs (
                                manpath, catpath,
-                               (time_t) atol (MYDBM_DPTR (content)), 0);
+                               (time_t) sec, (time_t) usec, 0);
                        MYDBM_FREE (MYDBM_DPTR (content));
                } else
-                       new = testmandirs (manpath, catpath, (time_t) 0, 0);
+                       new = testmandirs (manpath, catpath,
+                                          (time_t) 0, (time_t) 0, 0);
 
                if (new) {
                        update_db_time ();

Reply via email to