Commit Diff


commit - b38936bbf89f342bc53320ba9f16f0854cdfbc63
commit + 1396fea0b2bcd64a9ce0209971ed4f1eade8d28e
blob - 146194c4142774a611adc3ce8fbff389c45ad55b
blob + a91c6ebf9951e77e06952f816d8ae6ce25b19524
--- wp.rs
+++ wp.rs
@@ -609,39 +609,58 @@ fn html_escape(s: &str) -> String {
     out
 }
 
+fn local_date() -> String {
+    use std::os::raw::{c_int, c_long};
+
+    // struct tm layout per POSIX, with BSD extensions.
+    // over-sized _pad absorbs any platform-specific trailing
+    // fields so localtime_r never writes out of bounds.
+    #[repr(C)]
+    struct Tm {
+        tm_sec: c_int,
+        tm_min: c_int,
+        tm_hour: c_int,
+        tm_mday: c_int,
+        tm_mon: c_int,
+        tm_year: c_int,
+        tm_wday: c_int,
+        tm_yday: c_int,
+        tm_isdst: c_int,
+        _pad: [u8; 64],
+    }
+
+    extern "C" {
+        fn time(t: *mut c_long) -> c_long;
+        fn localtime_r(t: *const c_long, result: *mut Tm) -> *mut Tm;
+    }
+
+    unsafe {
+        let mut t: c_long = 0;
+        time(&mut t);
+        let mut tm = std::mem::zeroed::<Tm>();
+        let ret = localtime_r(&t, &mut tm);
+        if ret.is_null() {
+            return String::from("unknown");
+        }
+        format!(
+            "{:04}-{:02}-{:02}",
+            tm.tm_year + 1900,
+            tm.tm_mon + 1,
+            tm.tm_mday
+        )
+    }
+}
+
 fn footer(total: usize) -> String {
-    let date = {
-        let now = std::time::SystemTime::now();
-        let dur = now
-            .duration_since(std::time::UNIX_EPOCH)
-            .unwrap_or_default();
-        let secs = dur.as_secs() as i64;
-        let days = secs / 86400;
-        // days since 1970-01-01, convert to y-m-d
-        let (y, m, d) = days_to_ymd(days);
-        format!("{:04}-{:02}-{:02}", y, m, d)
-    };
     format!(
         "<hr>\n<footer>{} {} | {} ports | {}</footer>\n",
-        NAME, VERSION, total, date
+        NAME,
+        VERSION,
+        total,
+        local_date()
     )
 }
 
-fn days_to_ymd(days: i64) -> (i64, u32, u32) {
-    // algorithm from http://howardhinnant.github.io/date_algorithms.html
-    let z = days + 719468;
-    let era = if z >= 0 { z } else { z - 146096 } / 146097;
-    let doe = (z - era * 146097) as u32;
-    let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
-    let y = (yoe as i64) + era * 400;
-    let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
-    let mp = (5 * doy + 2) / 153;
-    let d = doy - (153 * mp + 2) / 5 + 1;
-    let m = if mp < 10 { mp + 3 } else { mp - 9 };
-    let y = if m <= 2 { y + 1 } else { y };
-    (y, m, d)
-}
-
 fn dep_link(dep: &str) -> String {
     // dependency format: "category/port" or "pkg:category/port"
     // or "category/port,subpkg" or "category/port>=version"