Loading src/code/filesys.lisp +15 −7 Original line number Diff line number Diff line Loading @@ -1079,13 +1079,21 @@ optionally keeping some of the most recent old versions." :pathname file :format-control (intl:gettext "~S doesn't exist.") :format-arguments (list file))) (multiple-value-bind (winp dev ino mode nlink uid) (unix:unix-stat name) (declare (ignore dev ino mode nlink)) (when winp (let ((user-info (unix:unix-getpwuid uid))) (when user-info (unix:user-info-name user-info)))))))) ;; unix-namestring converts "." to "". Convert it back to ;; "." so we can stat the current directory. (Perhaps ;; that's a bug in unix-namestring?) (when (zerop (length name)) (setf name ".")) (let (author) (unwind-protect (progn (setf author (alien:alien-funcall (alien:extern-alien "os_file_author" (function (alien:* c-call:c-string) c-call:c-string)) (unix::%name->file name))) (unless (alien:null-alien author) (alien:cast author c-call:c-string))) (alien:free-alien author)))))) ;;;; DIRECTORY. Loading src/lisp/os-common.c +57 −1 Original line number Diff line number Diff line Loading @@ -5,13 +5,17 @@ */ #include <assert.h> #include <errno.h> #include <math.h> #include <netdb.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/utsname.h> #include <unistd.h> #include <time.h> #include "os.h" Loading Loading @@ -717,6 +721,59 @@ os_lstat(const char* path, u_int64_t *dev, u_int64_t *ino, unsigned int *mode, u return rc; } /* * Interface for file-author. Given a pathname, returns a new string * holding the author of the file or NULL if some error occurred. The * caller is responsible for freeing the memory used by the string. */ char * os_file_author(const char *path) { struct stat sb; char initial[1024]; char *buffer, *obuffer; size_t size; struct passwd pwd; struct passwd *ppwd; char *result; if (stat(path, &sb) != 0) { return NULL; } result = NULL; buffer = initial; obuffer = NULL; size = sizeof(initial) / sizeof(initial[0]); /* * Keep trying with larger buffers until a maximum is reached. We * assume (1 << 20) is large enough for any OS. */ while (size <= (1 << 20)) { switch (getpwuid_r(sb.st_uid, &pwd, buffer, size, &ppwd)) { case 0: /* Success, though we might not have a matching entry */ result = (ppwd == NULL) ? NULL : strdup(pwd.pw_name); goto exit; case ERANGE: /* Buffer is too small, double its size and try again */ size *= 2; obuffer = (buffer == initial) ? NULL : buffer; if ((buffer = realloc(obuffer, size)) == NULL) { goto exit; } continue; default: /* All other errors */ goto exit; } } exit: free(obuffer); return result; } /* * For Linux and solaris, software-version returns the concatenation * of the uname release and version fields. For BSD (including Loading Loading @@ -769,4 +826,3 @@ os_software_type() return os_name; } tests/issues.lisp +7 −0 Original line number Diff line number Diff line Loading @@ -670,3 +670,10 @@ (err (relerr value answer))) (assert-true (<= err eps) base err eps))))))) (define-test issue.130 (:tag :issues) ;; Just verify that file-author works. In particular "." should ;; work and not return NIL. (assert-true (file-author ".")) (assert-true (file-author "bin/build.sh")) (assert-true (file-author "tests/안녕하십니까.txt"))) tests/안녕하십니까.txt 0 → 100644 +3 −0 Original line number Diff line number Diff line The file name of this file is "안녕하십니까.txt" ("Hello" in Korean.) Loading
src/code/filesys.lisp +15 −7 Original line number Diff line number Diff line Loading @@ -1079,13 +1079,21 @@ optionally keeping some of the most recent old versions." :pathname file :format-control (intl:gettext "~S doesn't exist.") :format-arguments (list file))) (multiple-value-bind (winp dev ino mode nlink uid) (unix:unix-stat name) (declare (ignore dev ino mode nlink)) (when winp (let ((user-info (unix:unix-getpwuid uid))) (when user-info (unix:user-info-name user-info)))))))) ;; unix-namestring converts "." to "". Convert it back to ;; "." so we can stat the current directory. (Perhaps ;; that's a bug in unix-namestring?) (when (zerop (length name)) (setf name ".")) (let (author) (unwind-protect (progn (setf author (alien:alien-funcall (alien:extern-alien "os_file_author" (function (alien:* c-call:c-string) c-call:c-string)) (unix::%name->file name))) (unless (alien:null-alien author) (alien:cast author c-call:c-string))) (alien:free-alien author)))))) ;;;; DIRECTORY. Loading
src/lisp/os-common.c +57 −1 Original line number Diff line number Diff line Loading @@ -5,13 +5,17 @@ */ #include <assert.h> #include <errno.h> #include <math.h> #include <netdb.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/utsname.h> #include <unistd.h> #include <time.h> #include "os.h" Loading Loading @@ -717,6 +721,59 @@ os_lstat(const char* path, u_int64_t *dev, u_int64_t *ino, unsigned int *mode, u return rc; } /* * Interface for file-author. Given a pathname, returns a new string * holding the author of the file or NULL if some error occurred. The * caller is responsible for freeing the memory used by the string. */ char * os_file_author(const char *path) { struct stat sb; char initial[1024]; char *buffer, *obuffer; size_t size; struct passwd pwd; struct passwd *ppwd; char *result; if (stat(path, &sb) != 0) { return NULL; } result = NULL; buffer = initial; obuffer = NULL; size = sizeof(initial) / sizeof(initial[0]); /* * Keep trying with larger buffers until a maximum is reached. We * assume (1 << 20) is large enough for any OS. */ while (size <= (1 << 20)) { switch (getpwuid_r(sb.st_uid, &pwd, buffer, size, &ppwd)) { case 0: /* Success, though we might not have a matching entry */ result = (ppwd == NULL) ? NULL : strdup(pwd.pw_name); goto exit; case ERANGE: /* Buffer is too small, double its size and try again */ size *= 2; obuffer = (buffer == initial) ? NULL : buffer; if ((buffer = realloc(obuffer, size)) == NULL) { goto exit; } continue; default: /* All other errors */ goto exit; } } exit: free(obuffer); return result; } /* * For Linux and solaris, software-version returns the concatenation * of the uname release and version fields. For BSD (including Loading Loading @@ -769,4 +826,3 @@ os_software_type() return os_name; }
tests/issues.lisp +7 −0 Original line number Diff line number Diff line Loading @@ -670,3 +670,10 @@ (err (relerr value answer))) (assert-true (<= err eps) base err eps))))))) (define-test issue.130 (:tag :issues) ;; Just verify that file-author works. In particular "." should ;; work and not return NIL. (assert-true (file-author ".")) (assert-true (file-author "bin/build.sh")) (assert-true (file-author "tests/안녕하십니까.txt")))
tests/안녕하십니까.txt 0 → 100644 +3 −0 Original line number Diff line number Diff line The file name of this file is "안녕하십니까.txt" ("Hello" in Korean.)