Avoid shelling out for chown lookups

ober

8645f1e3f4c9c55e1fc3804bf20f5047c43e32e5

diff --git a/lib/jerboa-coreutils/chown.sls b/lib/jerboa-coreutils/chown.sls
index aef87bd..59bbdef 100644
--- a/lib/jerboa-coreutils/chown.sls
+++ b/lib/jerboa-coreutils/chown.sls
@@ -19,44 +19,19 @@
     (foreign-procedure "chown" (string int int) int))
   (define ffi-lchown
     (foreign-procedure "lchown" (string int int) int))
+  (define ffi-getpwnam-uid-c
+    (foreign-procedure "coreutils_getpwnam_uid" (string) int))
+  (define ffi-getgrnam-gid-c
+    (foreign-procedure "coreutils_getgrnam_gid" (string) int))
   (def (ffi-stat-isdir path) (if (file-directory? path) 1 0))
   (def (ffi-getpwnam-uid name)
        (with-catch
          (lambda (e) -1)
-         (lambda ()
-           (let-values ([(to-stdin from-stdout from-stderr pid)
-                         (open-process-ports
-                           (string-append "id -u " name " 2>/dev/null")
-                           (buffer-mode block)
-                           (native-transcoder))])
-             (close-port to-stdin)
-             (let ([result (get-line from-stdout)])
-               (close-port from-stdout)
-               (close-port from-stderr)
-               (if (and result (not (eof-object? result)))
-                   (let ([n (string->number result)])
-                     (if n (inexact->exact n) -1))
-                   -1))))))
+         (lambda () (ffi-getpwnam-uid-c name))))
   (def (ffi-getgrnam-gid name)
        (with-catch
          (lambda (e) -1)
-         (lambda ()
-           (let-values ([(to-stdin from-stdout from-stderr pid)
-                         (open-process-ports
-                           (string-append
-                             "getent group "
-                             name
-                             " 2>/dev/null | cut -d: -f3")
-                           (buffer-mode block)
-                           (native-transcoder))])
-             (close-port to-stdin)
-             (let ([result (get-line from-stdout)])
-               (close-port from-stdout)
-               (close-port from-stderr)
-               (if (and result (not (eof-object? result)))
-                   (let ([n (string->number result)])
-                     (if n (inexact->exact n) -1))
-                   -1))))))
+         (lambda () (ffi-getgrnam-gid-c name))))
   (def (string-find-char str ch)
        (let loop ([i 0])
          (cond
diff --git a/src/jerboa-coreutils/chown.ss b/src/jerboa-coreutils/chown.ss
index 6d69b4f..9d64ea5 100644
--- a/src/jerboa-coreutils/chown.ss
+++ b/src/jerboa-coreutils/chown.ss
@@ -16,6 +16,8 @@
 
 (define ffi-chown (foreign-procedure "chown" (string int int) int))
 (define ffi-lchown (foreign-procedure "lchown" (string int int) int))
+(define ffi-getpwnam-uid-c (foreign-procedure "coreutils_getpwnam_uid" (string) int))
+(define ffi-getgrnam-gid-c (foreign-procedure "coreutils_getgrnam_gid" (string) int))
 
 (def (ffi-stat-isdir path)
   (if (file-directory? path) 1 0))
@@ -23,38 +25,12 @@
 (def (ffi-getpwnam-uid name)
   (with-catch
     (lambda (e) -1)
-    (lambda ()
-      (let-values (((to-stdin from-stdout from-stderr pid)
-                    (open-process-ports
-                      (string-append "id -u " name " 2>/dev/null")
-                      (buffer-mode block)
-                      (native-transcoder))))
-        (close-port to-stdin)
-        (let ((result (get-line from-stdout)))
-          (close-port from-stdout)
-          (close-port from-stderr)
-          (if (and result (not (eof-object? result)))
-            (let ((n (string->number result)))
-              (if n (inexact->exact n) -1))
-            -1))))))
+    (lambda () (ffi-getpwnam-uid-c name))))
 
 (def (ffi-getgrnam-gid name)
   (with-catch
     (lambda (e) -1)
-    (lambda ()
-      (let-values (((to-stdin from-stdout from-stderr pid)
-                    (open-process-ports
-                      (string-append "getent group " name " 2>/dev/null | cut -d: -f3")
-                      (buffer-mode block)
-                      (native-transcoder))))
-        (close-port to-stdin)
-        (let ((result (get-line from-stdout)))
-          (close-port from-stdout)
-          (close-port from-stderr)
-          (if (and result (not (eof-object? result)))
-            (let ((n (string->number result)))
-              (if n (inexact->exact n) -1))
-            -1))))))
+    (lambda () (ffi-getgrnam-gid-c name))))
 
 (def (string-find-char str ch)
   (let loop ((i 0))
diff --git a/support/libcoreutils.c b/support/libcoreutils.c
index 8b09722..287b00c 100644
--- a/support/libcoreutils.c
+++ b/support/libcoreutils.c
@@ -62,7 +62,7 @@ int coreutils_getgrnam_gid(const char *name) {
 
 /* ========== stat helpers ========== */
 
-static struct stat stat_result_buf;
+static __thread struct stat stat_result_buf;
 
 int coreutils_stat_call(const char *path, int follow) {
     int rc = follow ? stat(path, &stat_result_buf) : lstat(path, &stat_result_buf);
@@ -117,7 +117,7 @@ long coreutils_du_stat(const char *path, int field) {
 
 /* ========== df / statvfs helpers ========== */
 
-static struct statvfs statvfs_result_buf;
+static __thread struct statvfs statvfs_result_buf;
 
 int coreutils_statvfs(const char *path) {
     if (statvfs(path, &statvfs_result_buf) < 0) return -1;