Finer Last-Modified times in lighttpd

For various reasons I won't go in to here I needed finer granularity in the Last-Modified and If-Modified-Since HTTPD headers for a project I am working on. Since Linux 2.5.48 the file modification time has a granularity of nanoseconds - here is the quote from the man page: Since kernel 2.5.48, the stat structure supports nanosecond resolution for the three file timestamp fields. Glibc exposes the nanosecond component of each field using names either of the form st_atim.tv_nsec, if the _BSD_SOURCE or _SVID_SOURCE feature test macro is defined, or of the form st_atimensec, if neither of these macros is defined. Originally I made changes for Apache to achieve this (and I can supply them if anyone is really interested) but we are using lighttpd now. The following diff against lighttpd 1.4.26 provides microsecond granularity on Last-Modified and If-Modified-Since. I've not tested all possible lighttpd modules as we are only using the expires one but I believe it is correct - certainly works in our scenario and verified with wget and curl.
diff -ru lighttpd-1.4.26/src/base.h lighttpd-1.4.26.hacked/src/base.h
--- lighttpd-1.4.26/src/base.h  2010-02-01 23:28:20.000000000 +0000
+++ lighttpd-1.4.26.hacked/src/base.h   2010-03-15 16:42:40.198607918 +0000
@@ -468,7 +468,7 @@
 } realpath_cache_type;

 typedef struct {
-       time_t  mtime;  /* the key */
+       struct timespec  mtime;  /* the key */
        buffer *str;    /* a buffer for the string represenation */
 } mtime_cache_type;

diff -ru lighttpd-1.4.26/src/http-header-glue.c
lighttpd-1.4.26.hacked/src/http-header-glue.c
--- lighttpd-1.4.26/src/http-header-glue.c      2010-02-01 23:28:20.000000000
+0000
+++ lighttpd-1.4.26.hacked/src/http-header-glue.c       2010-03-19
17:26:45.424258304 +0000
@@ -216,16 +216,20 @@
        return 0;
 }

-buffer * strftime_cache_get(server *srv, time_t last_mod) {
+buffer * strftime_cache_get(server *srv, struct timespec last_mod) {
        struct tm *tm;
-       size_t i;
+       size_t  i;
+        char nsec[10];
+        char format[50];

        for (i = 0; i < FILE_CACHE_MAX; i++) {
                /* found cache-entry */
-               if (srv->mtime_cache[i].mtime == last_mod) return
srv->mtime_cache[i].str;
+            if ((srv->mtime_cache[i].mtime.tv_nsec == last_mod.tv_nsec) &&
+                (srv->mtime_cache[i].mtime.tv_sec == last_mod.tv_sec))
+                return srv->mtime_cache[i].str;

                /* found empty slot */
-               if (srv->mtime_cache[i].mtime == 0) break;
+               if (srv->mtime_cache[i].mtime.tv_sec == 0) break;
        }

        if (i == FILE_CACHE_MAX) {
@@ -234,10 +238,16 @@

        srv->mtime_cache[i].mtime = last_mod;
        buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
-       tm = gmtime(&(srv->mtime_cache[i].mtime));
+       tm = gmtime(&(srv->mtime_cache[i].mtime.tv_sec));
+        sprintf(nsec, "%ld", last_mod.tv_nsec);
+        nsec[6] = '\0';
+        strcpy(format, "%a, %d %b %Y %H:%M:%S.");
+        strcat(format, nsec);
+
        srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
                                                 srv->mtime_cache[i].str->size
- 1,
-                                                "%a, %d %b %Y %H:%M:%S GMT",
tm);
+                                                format, tm);
        srv->mtime_cache[i].str->used++;

        return srv->mtime_cache[i].str;

diff -ru lighttpd-1.4.26/src/mod_compress.c
lighttpd-1.4.26.hacked/src/mod_compress.c
--- lighttpd-1.4.26/src/mod_compress.c  2010-02-01 23:28:20.000000000 +0000
+++ lighttpd-1.4.26.hacked/src/mod_compress.c   2010-03-15 16:38:43.622608346
+0000
@@ -767,7 +767,7 @@
                                        const char *compression_name = NULL;
                                        int compression_type = 0;

-                                       mtime = strftime_cache_get(srv,
sce->st.st_mtime);
+                                       mtime = strftime_cache_get(srv,
sce->st.st_mtim);

                                        /* try matching original etag of
uncompressed version */

                                        etag_mutate(con->physical.etag,
sce->etag);

diff -ru lighttpd-1.4.26/src/mod_ssi.c lighttpd-1.4.26.hacked/src/mod_ssi.c
--- lighttpd-1.4.26/src/mod_ssi.c       2010-02-01 23:28:20.000000000 +0000
+++ lighttpd-1.4.26.hacked/src/mod_ssi.c        2010-03-19 17:34:47.790610148
+0000
@@ -1084,6 +1084,7 @@
                stat_cache_entry *sce = NULL;
                time_t lm_time = 0;
                buffer *mtime = NULL;
+                struct timespec ts;

                stat_cache_get_entry(srv, con, con->physical.path, &sce);

@@ -1095,7 +1096,10 @@
                else
                        lm_time = include_file_last_mtime;

-               mtime = strftime_cache_get(srv, lm_time);
+                ts.tv_sec = lm_time;
+                ts.tv_nsec = 0;
+
+               mtime = strftime_cache_get(srv, ts);
                response_header_overwrite(srv, con,
CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
        }

diff -ru lighttpd-1.4.26/src/mod_staticfile.c
lighttpd-1.4.26.hacked/src/mod_staticfile.c
--- lighttpd-1.4.26/src/mod_staticfile.c        2010-02-01 23:28:20.000000000
+0000
+++ lighttpd-1.4.26.hacked/src/mod_staticfile.c 2010-03-19 17:35:25.150607097
+0000
@@ -466,7 +466,8 @@

                /* prepare header */
                if (NULL == (ds = (data_string
*)array_get_element(con->response.headers, "Last-Modified"))) {
-                       mtime = strftime_cache_get(srv, sce->st.st_mtime);
+                       mtime = strftime_cache_get(srv, sce->st.st_mtim);
+
                        response_header_overwrite(srv, con,
CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
                } else {
                        mtime = ds->value;

diff -ru lighttpd-1.4.26/src/response.h lighttpd-1.4.26.hacked/src/response.h
--- lighttpd-1.4.26/src/response.h      2010-02-01 23:28:20.000000000 +0000
+++ lighttpd-1.4.26.hacked/src/response.h       2010-03-15 16:34:48.294609510
+0000
@@ -16,5 +16,5 @@
 int http_response_redirect_to_directory(server *srv, connection *con);
 int http_response_handle_cachable(server *srv, connection *con, buffer *
mtime);

-buffer * strftime_cache_get(server *srv, time_t last_mod);
+buffer * strftime_cache_get(server *srv, struct timespec last_mod);
 #endif

diff -ru lighttpd-1.4.26/src/server.c lighttpd-1.4.26.hacked/src/server.c
--- lighttpd-1.4.26/src/server.c        2010-02-01 23:28:20.000000000 +0000
+++ lighttpd-1.4.26.hacked/src/server.c 2010-03-15 16:45:07.851315667 +0000
@@ -207,7 +207,8 @@
 #undef CLEAN

        for (i = 0; i < FILE_CACHE_MAX; i++) {
-               srv->mtime_cache[i].mtime = (time_t)-1;
+               srv->mtime_cache[i].mtime.tv_sec = (time_t)-1;
+                srv->mtime_cache[i].mtime.tv_nsec = (time_t)-1;
                srv->mtime_cache[i].str = buffer_init();
        }