Raymond Toy pushed to branch master at cmucl / cmucl

Commits:

6 changed files:

Changes:

  • src/code/filesys.lisp
    ... ... @@ -1232,8 +1232,7 @@ optionally keeping some of the most recent old versions."
    1232 1232
     		   (declare (ignore sec min hour date month))
    
    1233 1233
     		   (format t "~2D ~8A ~8D ~12A ~A~@[/~]~%"
    
    1234 1234
     			   nlink
    
    1235
    -                           (let ((user-info (unix:unix-getpwuid uid)))
    
    1236
    -                             (if user-info (unix:user-info-name user-info) uid))
    
    1235
    +			   (or (unix::unix-get-username uid) uid)
    
    1237 1236
     			   size
    
    1238 1237
     			   (decode-universal-time-for-files mtime year)
    
    1239 1238
     			   tail
    

  • src/code/os.lisp
    ... ... @@ -69,29 +69,21 @@
    69 69
       The status is 0 if no errors occurred.  Otherwise a non-zero value
    
    70 70
       is returned. Examining errno may give information about what failed."
    
    71 71
       (declare (string name))
    
    72
    -  (cond
    
    73
    -    ((zerop (length name))
    
    74
    -     (multiple-value-bind (user-info status)
    
    75
    -         (unix:unix-getpwuid (unix:unix-getuid))
    
    76
    -       (values (when user-info
    
    77
    -                 (unix:user-info-dir user-info))
    
    78
    -               status)))
    
    79
    -    (t
    
    80
    -     (alien:with-alien ((status c-call:int))
    
    81
    -       (let (result)
    
    82
    -         (unwind-protect
    
    83
    -              (progn
    
    84
    -                (setf result
    
    85
    -                      (alien:alien-funcall
    
    86
    -                       (alien:extern-alien "os_get_user_homedir"
    
    87
    -                                           (function (alien:* c-call:c-string)
    
    88
    -                                                     c-call:c-string
    
    89
    -                                                     (* c-call:int)))
    
    90
    -                       name
    
    91
    -                       (alien:addr status)))
    
    92
    -                (if (and (zerop status)
    
    93
    -                         (not (alien:null-alien result)))
    
    94
    -                    (values (alien:cast result c-call:c-string)
    
    95
    -                            status)
    
    96
    -                    (values nil status)))
    
    97
    -           (alien:free-alien result)))))))
    72
    +  (alien:with-alien ((status c-call:int))
    
    73
    +    (let (result)
    
    74
    +      (unwind-protect
    
    75
    +           (progn
    
    76
    +             (setf result
    
    77
    +                   (alien:alien-funcall
    
    78
    +                    (alien:extern-alien "os_get_user_homedir"
    
    79
    +                                        (function (alien:* c-call:c-string)
    
    80
    +                                                  c-call:c-string
    
    81
    +                                                  (* c-call:int)))
    
    82
    +                    name
    
    83
    +                    (alien:addr status)))
    
    84
    +             (if (and (zerop status)
    
    85
    +                      (not (alien:null-alien result)))
    
    86
    +                 (values (alien:cast result c-call:c-string)
    
    87
    +                         status)
    
    88
    +                 (values nil status)))
    
    89
    +        (alien:free-alien result)))))

  • src/code/unix.lisp
    ... ... @@ -2541,3 +2541,28 @@
    2541 2541
         ;; Result from strerror can be localized so we need to decode
    
    2542 2542
         ;; those octets to get a proper Lisp string.
    
    2543 2543
         (string-decode (cast result c-string) :default)))
    
    2544
    +
    
    2545
    +(defun unix-get-username (uid)
    
    2546
    +  _N"Returns a string that is the user name corresponding to the given UID.
    
    2547
    +  If no such uid exists or if the user name does not exist, NIL is
    
    2548
    +  returned."
    
    2549
    +  (with-alien ((status c-call:int))
    
    2550
    +    (let (result)
    
    2551
    +      (unwind-protect
    
    2552
    +	   (progn
    
    2553
    +	     (setf result
    
    2554
    +		   (alien-funcall
    
    2555
    +		    (extern-alien "os_get_user_name"
    
    2556
    +				  (function (* c-call:c-string)
    
    2557
    +					    uid-t
    
    2558
    +					    (* c-call:int)))
    
    2559
    +		    uid
    
    2560
    +		    (addr status)))
    
    2561
    +	     (values 
    
    2562
    +	      (if (and (zerop status)
    
    2563
    +		       (not (null-alien result)))
    
    2564
    +		  (cast result c-call:c-string)
    
    2565
    +		  nil)
    
    2566
    +	      status))
    
    2567
    +	(free-alien name)))))
    
    2568
    +    

  • src/i18n/locale/cmucl-unix.pot
    ... ... @@ -810,3 +810,10 @@ msgstr ""
    810 810
     msgid "Returns a string that describes the error code Errno"
    
    811 811
     msgstr ""
    
    812 812
     
    
    813
    +#: src/code/unix.lisp
    
    814
    +msgid ""
    
    815
    +"Returns a string that is the user name corresponding to the given UID.\n"
    
    816
    +"  If no such uid exists or if the user name does not exist, NIL is\n"
    
    817
    +"  returned."
    
    818
    +msgstr ""
    
    819
    +

  • src/lisp/Darwin-os.c
    ... ... @@ -593,7 +593,7 @@ os_temporary_directory(void)
    593 593
     
    
    594 594
         len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, PATH_MAX);
    
    595 595
         if (len == 0 || len > PATH_MAX || (len == PATH_MAX && path[len - 1] != '/')) {
    
    596
    -	strlcpy(path, "/tmp/");
    
    596
    +	strcpy(path, "/tmp/");
    
    597 597
         } else if (path[len - 1] != '/') {
    
    598 598
     	strcat(path, "/");
    
    599 599
         }
    

  • src/lisp/os-common.c
    ... ... @@ -734,58 +734,97 @@ os_lstat(const char* path, uint64_t *dev, uint64_t *ino, unsigned int *mode, uin
    734 734
     }
    
    735 735
     
    
    736 736
     /*
    
    737
    - * Interface for file-author.  Given a pathname, returns a new string
    
    738
    - * holding the author of the file or NULL if some error occurred.  The
    
    739
    - * caller is responsible for freeing the memory used by the string.
    
    737
    + * Basic interface to getpwuid, except we will automatically retry if
    
    738
    + * the given buffer is too small.  To support this |buffer| is a
    
    739
    + * pointer to a char buffer.  This will be updated with a new buffer
    
    740
    + * if we needed to retry getpwuid with a larger buffer.  The remaining
    
    741
    + * parameters are the same as for getpwuid.
    
    740 742
      */
    
    741
    -char *
    
    742
    -os_file_author(const char *path)
    
    743
    +static int
    
    744
    +os_getpwuid(uid_t uid, struct passwd *pwd, char **buffer, size_t buflen, struct passwd **result)
    
    743 745
     {
    
    744
    -    struct stat sb;
    
    745
    -    char initial[1024];
    
    746
    -    char *buffer, *obuffer;
    
    747
    -    size_t size;
    
    748
    -    struct passwd pwd;
    
    749
    -    struct passwd *ppwd;
    
    750
    -    char *result;
    
    751
    -
    
    752
    -    if (stat(path, &sb) != 0) {
    
    753
    -        return NULL;
    
    754
    -    }
    
    755
    -
    
    756
    -    result = NULL;
    
    757
    -    buffer = initial;
    
    758
    -    obuffer = NULL;
    
    759
    -    size = sizeof(initial) / sizeof(initial[0]);
    
    746
    +    int status;
    
    747
    +    char *obuffer = NULL;
    
    760 748
     
    
    761 749
         /*
    
    762 750
          * Keep trying with larger buffers until a maximum is reached.  We
    
    763 751
          * assume (1 << 20) is large enough for any OS.
    
    764 752
          */
    
    765 753
     again:
    
    766
    -    switch (getpwuid_r(sb.st_uid, &pwd, buffer, size, &ppwd)) {
    
    754
    +    switch (status = getpwuid_r(uid, pwd, *buffer, buflen, result)) {
    
    767 755
           case 0:
    
    768 756
     	  /* Success, though we might not have a matching entry */
    
    769
    -	  result = (ppwd == NULL) ? NULL : strdup(pwd.pw_name);
    
    770 757
     	  break;
    
    771 758
           case ERANGE:
    
    772 759
     	  /* Buffer is too small, double its size and try again */
    
    773
    -	  size *= 2;
    
    774
    -	  if (size > (1 << 20)) {
    
    760
    +	  buflen *= 2;
    
    761
    +	  if (buflen > (1 << 20)) {
    
    775 762
     	      break;
    
    776 763
     	  }
    
    777
    -	  if ((buffer = realloc(obuffer, size)) == NULL) {
    
    764
    +	  if ((*buffer = realloc(obuffer, buflen)) == NULL) {
    
    778 765
     	      break;
    
    779 766
     	  }
    
    780
    -	  obuffer = buffer;
    
    767
    +	  obuffer = *buffer;
    
    781 768
     	  goto again;
    
    782 769
           default:
    
    783 770
     	/* All other errors */
    
    784 771
     	break;
    
    785 772
         }
    
    786 773
         free(obuffer);
    
    787
    -    
    
    788
    -    return result;
    
    774
    +
    
    775
    +    return status;
    
    776
    +}
    
    777
    +
    
    778
    +
    
    779
    +/*
    
    780
    + * Given the UID, return the user name.  If the uid does not exist,
    
    781
    + * returns NULL.  The caller must call free on the string that is
    
    782
    + * returned.
    
    783
    + */
    
    784
    +char *
    
    785
    +os_get_user_name(uid_t uid, int *status)
    
    786
    +{
    
    787
    +    char *buf;
    
    788
    +    char *name;
    
    789
    +    struct passwd pwd;
    
    790
    +    struct passwd *result;
    
    791
    +    char buffer[1024];
    
    792
    +
    
    793
    +    buf = buffer;
    
    794
    +
    
    795
    +    *status = os_getpwuid(uid, &pwd, &buf, sizeof(buffer), &result);
    
    796
    +
    
    797
    +    if (*status != 0 || result == NULL || result->pw_name == NULL) {
    
    798
    +	name = NULL;
    
    799
    +    } else {
    
    800
    +	name = strdup(result->pw_name);
    
    801
    +	if (name == NULL) {
    
    802
    +	    *status = errno;
    
    803
    +	}
    
    804
    +	if (buf != buffer) {
    
    805
    +	    free(buf);
    
    806
    +	}
    
    807
    +    }
    
    808
    +
    
    809
    +    return name;
    
    810
    +}
    
    811
    +
    
    812
    +/*
    
    813
    + * Interface for file-author.  Given a pathname, returns a new string
    
    814
    + * holding the author of the file or NULL if some error occurred.  The
    
    815
    + * caller is responsible for freeing the memory used by the string.
    
    816
    + */
    
    817
    +char *
    
    818
    +os_file_author(const char *path)
    
    819
    +{
    
    820
    +    int status;
    
    821
    +    struct stat sb;
    
    822
    +
    
    823
    +    if (stat(path, &sb) != 0) {
    
    824
    +        return NULL;
    
    825
    +    }
    
    826
    +
    
    827
    +    return os_get_user_name(sb.st_uid, &status);
    
    789 828
     }
    
    790 829
     
    
    791 830
     int
    
    ... ... @@ -874,15 +913,8 @@ os_software_version(void)
    874 913
         return result;
    
    875 914
     }
    
    876 915
     
    
    877
    -/*
    
    878
    - * Return the home directory of the user named NAME.  If the user does
    
    879
    - * not exist, returns NULL.  Also returns NULL if the home directory
    
    880
    - * cannot be determined for any reason.  The parameter STATUS is 0 if
    
    881
    - * getpwnam_r was successful.  Otherwise it is the return value from
    
    882
    - * getpwnam_r or -1 if we ran out of memory for the buffer.
    
    883
    - */
    
    884
    -char *
    
    885
    -os_get_user_homedir(const char* name, int *status)
    
    916
    +static char *
    
    917
    +get_homedir_by_user_name(const char* name, int *status)
    
    886 918
     {
    
    887 919
         int buflen;
    
    888 920
         char *buf = NULL;
    
    ... ... @@ -944,6 +976,60 @@ os_get_user_homedir(const char* name, int *status)
    944 976
         return NULL;
    
    945 977
     }
    
    946 978
     
    
    979
    +/*
    
    980
    + * Return the home directory for the given UID.  If the home directory
    
    981
    + * does not exist, NULL is returned.  STATUS is set to 0 if the home
    
    982
    + * directory could be found.  Otherwise, it is the errno.
    
    983
    + *
    
    984
    + * The caller must free the memory returned.
    
    985
    + */
    
    986
    +static char *
    
    987
    +get_homedir_by_uid(uid_t uid, int *status)
    
    988
    +{
    
    989
    +    char buffer[1024];
    
    990
    +    char *buf;
    
    991
    +    char *dir;
    
    992
    +    struct passwd pwd;
    
    993
    +    struct passwd *result;
    
    994
    +
    
    995
    +    buf = buffer;
    
    996
    +    dir = NULL;
    
    997
    +
    
    998
    +    *status = os_getpwuid(uid, &pwd, &buf, sizeof(buffer), &result);
    
    999
    +
    
    1000
    +    if (*status == 0 && result != NULL && result->pw_dir != NULL) {
    
    1001
    +	dir = strdup(result->pw_dir);
    
    1002
    +	if (dir == NULL) {
    
    1003
    +	    *status = errno;
    
    1004
    +	}
    
    1005
    +	if (buf != buffer) {
    
    1006
    +	    free(buf);
    
    1007
    +	}
    
    1008
    +    }
    
    1009
    +
    
    1010
    +    return dir;
    
    1011
    +}
    
    1012
    +
    
    1013
    +/*
    
    1014
    + * Return the home directory of the user named NAME.  If NAME is the
    
    1015
    + * empty string, returns the home directory of the current user.  If
    
    1016
    + * the user does not exist, returns NULL.  Also returns NULL if the
    
    1017
    + * home directory cannot be determined for any reason.  The parameter
    
    1018
    + * STATUS is 0 if the home directory could be determined.  Otherwise
    
    1019
    + * it is the errno value.
    
    1020
    + *
    
    1021
    + * The caller must free the memory returned for the result.
    
    1022
    + */
    
    1023
    +char *
    
    1024
    +os_get_user_homedir(const char* name, int *status)
    
    1025
    +{
    
    1026
    +    if (strlen(name) == 0) {
    
    1027
    +	return get_homedir_by_uid(getuid(), status);
    
    1028
    +    }
    
    1029
    +
    
    1030
    +    return get_homedir_by_user_name(name, status);
    
    1031
    +}
    
    1032
    +    
    
    947 1033
     /*
    
    948 1034
      * Return a new string (or NULL) for the current working directory.
    
    949 1035
      * The caller must free this space.