Raymond Toy pushed to branch issue-139-default-external-format-utf8 at cmucl / cmucl
Commits:
- 
4a7207b6
by Raymond Toy at 2022-10-17T18:58:45+00:00
 - 
ba5c5d2a
by Raymond Toy at 2022-10-17T18:58:45+00:00
 - 
ab9b27f9
by Raymond Toy at 2022-10-30T12:42:13-07:00
 
4 changed files:
Changes:
| ... | ... | @@ -1079,13 +1079,21 @@ optionally keeping some of the most recent old versions." | 
| 1079 | 1079 |  		 :pathname file
 | 
| 1080 | 1080 |  		 :format-control (intl:gettext "~S doesn't exist.")
 | 
| 1081 | 1081 |  		 :format-arguments (list file)))
 | 
| 1082 | -	(multiple-value-bind (winp dev ino mode nlink uid)
 | 
|
| 1083 | -			     (unix:unix-stat name)
 | 
|
| 1084 | -	  (declare (ignore dev ino mode nlink))
 | 
|
| 1085 | -	  (when winp
 | 
|
| 1086 | -            (let ((user-info (unix:unix-getpwuid uid)))
 | 
|
| 1087 | -              (when user-info
 | 
|
| 1088 | -                (unix:user-info-name user-info))))))))
 | 
|
| 1082 | +	;; unix-namestring converts "." to "".  Convert it back to
 | 
|
| 1083 | +	;; "." so we can stat the current directory.  (Perhaps
 | 
|
| 1084 | +	;; that's a bug in unix-namestring?)
 | 
|
| 1085 | +	(when (zerop (length name))
 | 
|
| 1086 | +	  (setf name "."))
 | 
|
| 1087 | +	(let (author)
 | 
|
| 1088 | +	  (unwind-protect
 | 
|
| 1089 | +	       (progn
 | 
|
| 1090 | +		 (setf author (alien:alien-funcall
 | 
|
| 1091 | +			       (alien:extern-alien "os_file_author"
 | 
|
| 1092 | +						   (function (alien:* c-call:c-string) c-call:c-string))
 | 
|
| 1093 | +			       (unix::%name->file name)))
 | 
|
| 1094 | +		 (unless (alien:null-alien author)
 | 
|
| 1095 | +		   (alien:cast author c-call:c-string)))
 | 
|
| 1096 | +	    (alien:free-alien author))))))
 | 
|
| 1089 | 1097 | |
| 1090 | 1098 | |
| 1091 | 1099 |  ;;;; DIRECTORY.
 | 
| ... | ... | @@ -5,12 +5,16 @@ | 
| 5 | 5 | |
| 6 | 6 |  */
 | 
| 7 | 7 | |
| 8 | +#include <assert.h>
 | 
|
| 8 | 9 |  #include <errno.h>
 | 
| 9 | 10 |  #include <math.h>
 | 
| 10 | 11 |  #include <netdb.h>
 | 
| 12 | +#include <pwd.h>
 | 
|
| 11 | 13 |  #include <stdio.h>
 | 
| 14 | +#include <stdlib.h>
 | 
|
| 12 | 15 |  #include <string.h>
 | 
| 13 | 16 |  #include <sys/stat.h>
 | 
| 17 | +#include <unistd.h>
 | 
|
| 14 | 18 |  #include <time.h>
 | 
| 15 | 19 | |
| 16 | 20 |  #include "os.h"
 | 
| ... | ... | @@ -715,3 +719,57 @@ os_lstat(const char* path, u_int64_t *dev, u_int64_t *ino, unsigned int *mode, u | 
| 715 | 719 | |
| 716 | 720 |      return rc;
 | 
| 717 | 721 |  }
 | 
| 722 | +  | 
|
| 723 | +/*
 | 
|
| 724 | + * Interface for file-author.  Given a pathname, returns a new string
 | 
|
| 725 | + * holding the author of the file or NULL if some error occurred.  The
 | 
|
| 726 | + * caller is responsible for freeing the memory used by the string.
 | 
|
| 727 | + */
 | 
|
| 728 | +char *
 | 
|
| 729 | +os_file_author(const char *path)
 | 
|
| 730 | +{
 | 
|
| 731 | +    struct stat sb;
 | 
|
| 732 | +    char initial[1024];
 | 
|
| 733 | +    char *buffer, *obuffer;
 | 
|
| 734 | +    size_t size;
 | 
|
| 735 | +    struct passwd pwd;
 | 
|
| 736 | +    struct passwd *ppwd;
 | 
|
| 737 | +    char *result;
 | 
|
| 738 | +  | 
|
| 739 | +    if (stat(path, &sb) != 0) {
 | 
|
| 740 | +        return NULL;
 | 
|
| 741 | +    }
 | 
|
| 742 | +  | 
|
| 743 | +    result = NULL;
 | 
|
| 744 | +    buffer = initial;
 | 
|
| 745 | +    obuffer = NULL;
 | 
|
| 746 | +    size = sizeof(initial) / sizeof(initial[0]);
 | 
|
| 747 | +  | 
|
| 748 | +    /*
 | 
|
| 749 | +     * Keep trying with larger buffers until a maximum is reached.  We
 | 
|
| 750 | +     * assume (1 << 20) is large enough for any OS.
 | 
|
| 751 | +     */
 | 
|
| 752 | +    while (size <= (1 << 20)) {
 | 
|
| 753 | +        switch (getpwuid_r(sb.st_uid, &pwd, buffer, size, &ppwd)) {
 | 
|
| 754 | +          case 0:
 | 
|
| 755 | +              /* Success, though we might not have a matching entry */
 | 
|
| 756 | +              result = (ppwd == NULL) ? NULL : strdup(pwd.pw_name);
 | 
|
| 757 | +              goto exit;
 | 
|
| 758 | +          case ERANGE:
 | 
|
| 759 | +              /* Buffer is too small, double its size and try again */
 | 
|
| 760 | +              size *= 2;
 | 
|
| 761 | +              obuffer = (buffer == initial) ? NULL : buffer;
 | 
|
| 762 | +              if ((buffer = realloc(obuffer, size)) == NULL) {
 | 
|
| 763 | +                  goto exit;
 | 
|
| 764 | +              }
 | 
|
| 765 | +              continue;
 | 
|
| 766 | +          default:
 | 
|
| 767 | +              /* All other errors */
 | 
|
| 768 | +              goto exit;
 | 
|
| 769 | +        }
 | 
|
| 770 | +    }
 | 
|
| 771 | +exit:
 | 
|
| 772 | +    free(obuffer);
 | 
|
| 773 | +    
 | 
|
| 774 | +    return result;
 | 
|
| 775 | +} | 
| ... | ... | @@ -676,6 +676,14 @@ | 
| 676 | 676 |  		 (err (relerr value answer)))
 | 
| 677 | 677 |  	    (assert-true (<= err eps) base err eps)))))))
 | 
| 678 | 678 | |
| 679 | +(define-test issue.130
 | 
|
| 680 | +    (:tag :issues)
 | 
|
| 681 | +  ;; Just verify that file-author works.  In particular "." should
 | 
|
| 682 | +  ;; work and not return NIL.
 | 
|
| 683 | +  (assert-true (file-author "."))
 | 
|
| 684 | +  (assert-true (file-author "bin/build.sh"))
 | 
|
| 685 | +  (assert-true (file-author "tests/안녕하십니까.txt")))
 | 
|
| 686 | +  | 
|
| 679 | 687 |  (define-test issue.139-default-external-format
 | 
| 680 | 688 |      (:tag :issues)
 | 
| 681 | 689 |    (assert-eq :utf-8 stream:*default-external-format*))
 | 
| 1 | +The file name of this file is "안녕하십니까.txt" ("Hello" in Korean.)
 | 
|
| 2 | +  | 
|
| 3 | +  |