Raymond Toy pushed to branch issue-408-get-user-name-and-homedir at cmucl / cmucl

Commits:

3 changed files:

Changes:

  • src/code/unix.lisp
    ... ... @@ -2543,15 +2543,26 @@
    2543 2543
         (string-decode (cast result c-string) :default)))
    
    2544 2544
     
    
    2545 2545
     (defun unix-get-username (uid)
    
    2546
    -  (let (name)
    
    2547
    -    (unwind-protect
    
    2548
    -	 (progn
    
    2549
    -	   (setf name
    
    2550
    -		 (alien-funcall
    
    2551
    -		  (extern-alien "os_get_username"
    
    2552
    -				(function (* char) uid-t))
    
    2553
    -		  uid))
    
    2554
    -	   (unless (null-alien name)
    
    2555
    -	     (cast name c-call:c-string)))
    
    2556
    -      (unless (null-alien name)
    
    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_username"
    
    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))
    
    2557 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/os-common.c
    ... ... @@ -731,56 +731,37 @@ os_lstat(const char* path, uint64_t *dev, uint64_t *ino, unsigned int *mode, uin
    731 731
     }
    
    732 732
     
    
    733 733
     /*
    
    734
    - * From the given UID, find the corresponding user name and home
    
    735
    - * directory.
    
    736
    - *
    
    737
    - * NAME and DIR are set to the user name and home directory.  The
    
    738
    - * caller must free these.  If no such uid exists, NAME and DIR are
    
    739
    - * set to NULL.
    
    740
    - *
    
    741
    - * Returns the status of getpwuid.  Zero indicates success.  Otherwise
    
    742
    - * the errno is returned.
    
    734
    + * Basic interface to getpwuid, except we will automatically retry if
    
    735
    + * the given buffer is too small.  To support this |buffer| is a
    
    736
    + * pointer to a char buffer.  This will be updated with a new buffer
    
    737
    + * if we needed to retry getpwuid with a larger buffer.  The remaining
    
    738
    + * parameters are the same as for getpwuid.
    
    743 739
      */
    
    744 740
     int
    
    745
    -os_get_user_info(uid_t uid, char **name, char **dir)
    
    741
    +os_getpwuid(uid_t uid, struct passwd *pwd, char **buffer, size_t buflen, struct passwd **result)
    
    746 742
     {
    
    747
    -    char initial[1024];
    
    748
    -    char *buffer, *obuffer;
    
    749
    -    size_t size;
    
    750
    -    struct passwd pwd;
    
    751
    -    struct passwd *ppwd;
    
    752 743
         int status;
    
    753
    -
    
    754
    -    *name = NULL;
    
    755
    -    *dir = NULL;
    
    756
    -
    
    757
    -    buffer = initial;
    
    758
    -    obuffer = NULL;
    
    759
    -    size = sizeof(initial) / sizeof(initial[0]);
    
    744
    +    char *obuffer = NULL;
    
    760 745
     
    
    761 746
         /*
    
    762 747
          * Keep trying with larger buffers until a maximum is reached.  We
    
    763 748
          * assume (1 << 20) is large enough for any OS.
    
    764 749
          */
    
    765 750
     again:
    
    766
    -    switch (status = getpwuid_r(uid, &pwd, buffer, size, &ppwd)) {
    
    751
    +    switch (status = getpwuid_r(uid, pwd, *buffer, buflen, result)) {
    
    767 752
           case 0:
    
    768 753
     	  /* Success, though we might not have a matching entry */
    
    769
    -	  if (ppwd) {
    
    770
    -	      *name = strdup(pwd.pw_name);
    
    771
    -	      *dir = strdup(pwd.pw_dir);
    
    772
    -	  }
    
    773 754
     	  break;
    
    774 755
           case ERANGE:
    
    775 756
     	  /* Buffer is too small, double its size and try again */
    
    776
    -	  size *= 2;
    
    777
    -	  if (size > (1 << 20)) {
    
    757
    +	  buflen *= 2;
    
    758
    +	  if (buflen > (1 << 20)) {
    
    778 759
     	      break;
    
    779 760
     	  }
    
    780
    -	  if ((buffer = realloc(obuffer, size)) == NULL) {
    
    761
    +	  if ((*buffer = realloc(obuffer, buflen)) == NULL) {
    
    781 762
     	      break;
    
    782 763
     	  }
    
    783
    -	  obuffer = buffer;
    
    764
    +	  obuffer = *buffer;
    
    784 765
     	  goto again;
    
    785 766
           default:
    
    786 767
     	/* All other errors */
    
    ... ... @@ -791,23 +772,38 @@ again:
    791 772
         return status;
    
    792 773
     }
    
    793 774
     
    
    775
    +
    
    794 776
     /*
    
    795 777
      * Given the UID, return the user name.  If the uid does not exist,
    
    796 778
      * returns NULL.  The caller must call free on the string that is
    
    797 779
      * returned.
    
    798 780
      */
    
    799 781
     char *
    
    800
    -os_get_username(uid_t uid)
    
    782
    +os_get_username(uid_t uid, int *status)
    
    801 783
     {
    
    802
    -    int status;
    
    784
    +    char *buf;
    
    803 785
         char *name;
    
    804
    -    char *dir;
    
    786
    +    struct passwd pwd;
    
    787
    +    struct passwd *result;
    
    788
    +    char buffer[1024];
    
    805 789
     
    
    806
    -    status = os_get_user_info(uid, &name, &dir);
    
    790
    +    buf = buffer;
    
    807 791
     
    
    808
    -    free(dir);
    
    792
    +    *status = os_getpwuid(uid, &pwd, &buf, 1024, &result);
    
    809 793
     
    
    810
    -    return (status == 0) ? name : NULL;
    
    794
    +    if (*status != 0 || result == NULL || result->pw_name == NULL) {
    
    795
    +	name = NULL;
    
    796
    +    } else {
    
    797
    +	name = strdup(result->pw_name);
    
    798
    +	if (name == NULL) {
    
    799
    +	    *status = errno;
    
    800
    +	}
    
    801
    +	if (buf != buffer) {
    
    802
    +	    free(buf);
    
    803
    +	}
    
    804
    +    }
    
    805
    +
    
    806
    +    return name;
    
    811 807
     }
    
    812 808
     
    
    813 809
     /*
    
    ... ... @@ -818,13 +814,14 @@ os_get_username(uid_t uid)
    818 814
     char *
    
    819 815
     os_file_author(const char *path)
    
    820 816
     {
    
    817
    +    int status;
    
    821 818
         struct stat sb;
    
    822 819
     
    
    823 820
         if (stat(path, &sb) != 0) {
    
    824 821
             return NULL;
    
    825 822
         }
    
    826 823
     
    
    827
    -    return os_get_username(sb.st_uid);
    
    824
    +    return os_get_username(sb.st_uid, &status);
    
    828 825
     }
    
    829 826
     
    
    830 827
     int
    
    ... ... @@ -986,16 +983,29 @@ get_homedir_from_name(const char* name, int *status)
    986 983
     static char *
    
    987 984
     get_homedir_from_uid(uid_t uid, int *status)
    
    988 985
     {
    
    989
    -    char *name;
    
    986
    +    char buffer[1024];
    
    987
    +    char *buf;
    
    990 988
         char *dir;
    
    991
    -	
    
    992
    -    *status = os_get_user_info(uid, &name, &dir);
    
    989
    +    struct passwd pwd;
    
    990
    +    struct passwd *result;
    
    993 991
     
    
    994
    -    free(name);
    
    995
    -    
    
    996
    -    return (*status == 0) ? dir : NULL;
    
    997
    -}
    
    992
    +    buf = buffer;
    
    993
    +    dir = NULL;
    
    998 994
     
    
    995
    +    *status = os_getpwuid(uid, &pwd, &buf, 1024, &result);
    
    996
    +
    
    997
    +    if (*status == 0 && result != NULL && result->pw_dir != NULL) {
    
    998
    +	dir = strdup(result->pw_dir);
    
    999
    +	if (dir == NULL) {
    
    1000
    +	    *status = errno;
    
    1001
    +	}
    
    1002
    +	if (buf != buffer) {
    
    1003
    +	    free(buf);
    
    1004
    +	}
    
    1005
    +    }
    
    1006
    +
    
    1007
    +    return dir;
    
    1008
    +}
    
    999 1009
     
    
    1000 1010
     /*
    
    1001 1011
      * Return the home directory of the user named NAME.  If NAME is the