Raymond Toy pushed to branch issue-269-unix-get-user-homedir at cmucl / cmucl

Commits:

9 changed files:

Changes:

  • .gitlab-ci.yml
    ... ... @@ -62,7 +62,6 @@ linux:test:
    62 62
         - job: linux:build
    
    63 63
           artifacts: true
    
    64 64
       script:
    
    65
    -    - printenv
    
    66 65
         - bin/run-unit-tests.sh -l dist/bin/lisp 2>&1 | tee test.log
    
    67 66
     
    
    68 67
     linux:ansi-test:
    
    ... ... @@ -147,7 +146,6 @@ osx:test:
    147 146
           artifacts: true
    
    148 147
       script:
    
    149 148
         - echo LANG = $LANG
    
    150
    -    - printenv
    
    151 149
         - bin/run-unit-tests.sh -l dist/bin/lisp 2>&1 | tee test.log
    
    152 150
     
    
    153 151
     osx:ansi-test:
    

  • src/code/exports.lisp
    ... ... @@ -227,7 +227,6 @@
    227 227
     	   "UNIX-MKDIR"
    
    228 228
     	   "UNIX-RMDIR"
    
    229 229
     	   "UNIX-UNLINK"
    
    230
    -           "UNIX-GET-USER-HOMEDIR"
    
    231 230
     	   "TIMEZONE"
    
    232 231
     	   "TIMEVAL"
    
    233 232
     	   "SIZE-T"
    
    ... ... @@ -1713,7 +1712,9 @@
    1713 1712
     	   "DESCRIBE-EXTERNAL-FORMAT"
    
    1714 1713
     	   "LIST-ALL-EXTERNAL-FORMATS"
    
    1715 1714
     	   "STRING-ENCODE" "STRING-DECODE"
    
    1716
    -	   "SET-SYSTEM-EXTERNAL-FORMAT"))
    
    1715
    +	   "SET-SYSTEM-EXTERNAL-FORMAT")
    
    1716
    +  ;; File sys items
    
    1717
    +  (:export "GET-USER-HOMEDIR-PATHNAME"))
    
    1717 1718
     
    
    1718 1719
     (defpackage "STREAM"
    
    1719 1720
       (:import-from "SYSTEM" "LISP-STREAM")
    

  • src/code/filesys.lisp
    ... ... @@ -27,7 +27,8 @@
    27 27
     
    
    28 28
     (in-package "EXTENSIONS")
    
    29 29
     (export '(print-directory complete-file ambiguous-files default-directory
    
    30
    -	  purge-backup-files file-writable unix-namestring))
    
    30
    +	  purge-backup-files file-writable unix-namestring
    
    31
    +          get-user-homedir-pathname))
    
    31 32
     (in-package "LISP")
    
    32 33
     
    
    33 34
     
    
    ... ... @@ -1483,3 +1484,28 @@ optionally keeping some of the most recent old versions."
    1483 1484
     				(go retry))))))
    
    1484 1485
     	 ;; Only the first path in a search-list is considered.
    
    1485 1486
     	 (return (values pathspec created-p))))))
    
    1487
    +
    
    1488
    +;;; GET-USER-HOMEDIR-PATHNAME  -- Public
    
    1489
    +;;;
    
    1490
    +(defun get-user-homedir-pathname (name)
    
    1491
    +  _N"Get the user home directory for user named NAME.  Two values are
    
    1492
    +  returned: the pathname of the home directory and a status code.  If
    
    1493
    +  the home directory does not exist NIL is returned.  The status is 0
    
    1494
    +  if no errors occurred.  Otherwise a non-zero value is returned.
    
    1495
    +  Examining errno may give information about what failed."
    
    1496
    +  (alien:with-alien ((status c-call:int))
    
    1497
    +    (let ((result
    
    1498
    +            (alien:alien-funcall
    
    1499
    +             (alien:extern-alien "os_get_user_homedir"
    
    1500
    +                                 (function c-call:c-string
    
    1501
    +                                           c-call:c-string
    
    1502
    +                                           (* c-call:int)))
    
    1503
    +             name
    
    1504
    +             (alien:addr status))))
    
    1505
    +      (if (and (zerop status) result)
    
    1506
    +          (values (pathname
    
    1507
    +                   (concatenate 'string
    
    1508
    +                                result
    
    1509
    +                                "/"))
    
    1510
    +                  status)
    
    1511
    +          (values result status)))))

  • src/code/unix.lisp
    ... ... @@ -2900,27 +2900,3 @@
    2900 2900
     	    (extern-alien "os_get_locale_codeset"
    
    2901 2901
     			  (function (* char))))
    
    2902 2902
     	c-string))
    2903
    -
    
    2904
    -(defun unix-get-user-homedir (name)
    
    2905
    -  _N"Get the user home directory for user named NAME.  Two values are
    
    2906
    -  returned: the pathname of the home directory and a status code.  If
    
    2907
    -  the home directory does not exist NIL is returned.  The status is 0
    
    2908
    -  if no errors occurred.  Otherwise a non-zero value is returned.
    
    2909
    -  Examining errno may give information about what failed."
    
    2910
    -  (with-alien ((status c-call:int))
    
    2911
    -    (let ((result
    
    2912
    -            (alien-funcall
    
    2913
    -             (extern-alien "os_get_user_homedir"
    
    2914
    -                           (function c-call:c-string
    
    2915
    -                                     c-call:c-string
    
    2916
    -                                     (* c-call:int)))
    
    2917
    -             name
    
    2918
    -             (addr status))))
    
    2919
    -      (if (and (zerop status) result)
    
    2920
    -          (values (pathname
    
    2921
    -                   (concatenate 'string
    
    2922
    -                                result
    
    2923
    -                                "/"))
    
    2924
    -                  status)
    
    2925
    -          (values result status)))))
    
    2926
    -  

  • src/i18n/locale/cmucl-unix.pot
    ... ... @@ -1432,12 +1432,3 @@ msgstr ""
    1432 1432
     msgid "Get the codeset from the locale"
    
    1433 1433
     msgstr ""
    
    1434 1434
     
    1435
    -#: src/code/unix.lisp
    
    1436
    -msgid ""
    
    1437
    -"Get the user home directory for user named NAME.  Two values are\n"
    
    1438
    -"  returned: the pathname of the home directory and a status code.  If\n"
    
    1439
    -"  the home directory does not exist NIL is returned.  The status is 0\n"
    
    1440
    -"  if no errors occurred.  Otherwise a non-zero value is returned.\n"
    
    1441
    -"  Examining errno may give information about what failed."
    
    1442
    -msgstr ""
    
    1443
    -

  • src/i18n/locale/cmucl.pot
    ... ... @@ -10207,6 +10207,15 @@ msgstr ""
    10207 10207
     msgid "Can't create directory ~A."
    
    10208 10208
     msgstr ""
    
    10209 10209
     
    
    10210
    +#: src/code/filesys.lisp
    
    10211
    +msgid ""
    
    10212
    +"Get the user home directory for user named NAME.  Two values are\n"
    
    10213
    +"  returned: the pathname of the home directory and a status code.  If\n"
    
    10214
    +"  the home directory does not exist NIL is returned.  The status is 0\n"
    
    10215
    +"  if no errors occurred.  Otherwise a non-zero value is returned.\n"
    
    10216
    +"  Examining errno may give information about what failed."
    
    10217
    +msgstr ""
    
    10218
    +
    
    10210 10219
     #: src/code/load.lisp
    
    10211 10220
     msgid "The default for the :IF-SOURCE-NEWER argument to load."
    
    10212 10221
     msgstr ""
    

  • src/lisp/os-common.c
    ... ... @@ -864,17 +864,24 @@ os_software_version(void)
    864 864
         return result;
    
    865 865
     }
    
    866 866
     
    
    867
    +/*
    
    868
    + * Return the home directory of the user named NAME.  If the user does
    
    869
    + * not exist, returns NULL.  Also returns NULL if the home directory
    
    870
    + * cannot be determined for any reason.  The parameter STATUS is 0 if
    
    871
    + * getpwnam_r was successful.  Otherwise it is the return value from
    
    872
    + * getpwnam_r or -1 if we ran out of memory for the buffer.
    
    873
    + */
    
    867 874
     char *
    
    868 875
     os_get_user_homedir(const char* name, int *status)
    
    869 876
     {
    
    870 877
         int buflen;
    
    871
    -    char * buf;
    
    878
    +    char *buf = NULL;
    
    872 879
         struct passwd pwd;
    
    873 880
         struct passwd *result;
    
    874 881
     
    
    875 882
         buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
    
    876 883
         /*
    
    877
    -     * If sysconf failed, just try some possibly large enough value
    
    884
    +     * If sysconf failed, just try some possibly large enough value.
    
    878 885
          */
    
    879 886
         if (buflen == -1) {
    
    880 887
             buflen = 1024;
    
    ... ... @@ -886,8 +893,7 @@ os_get_user_homedir(const char* name, int *status)
    886 893
          * upper limit and give up.
    
    887 894
          */
    
    888 895
         while (buflen <= (1 << 20)) {
    
    889
    -        errno = 0;
    
    890
    -        buf = malloc(buflen);
    
    896
    +        buf = realloc(buf, buflen);
    
    891 897
     
    
    892 898
             if (buf == NULL) {
    
    893 899
                 *status = -1;
    
    ... ... @@ -898,23 +904,24 @@ os_get_user_homedir(const char* name, int *status)
    898 904
     
    
    899 905
             if (*status == 0) {
    
    900 906
                 /*
    
    901
    -             * Success, or entry was not found.  If found the result
    
    907
    +             * Success, or entry was not found.  If found, the result
    
    902 908
                  * is not NULL.  Return the result or NULL
    
    903 909
                  */
    
    904
    -            fprintf(stderr, "dir = %s\n", pwd.pw_dir);
    
    905
    -            return result ? strdup(pwd.pw_dir) : NULL;
    
    910
    +            char* path = result ? strdup(pwd.pw_dir) : NULL;
    
    911
    +            free(buf);
    
    912
    +            return path;
    
    906 913
             }
    
    907 914
     
    
    908 915
             /*
    
    909 916
              * Check errno for ERANGE.  If so, the buffer was too small, so grow it.
    
    910 917
              */
    
    911 918
             if (errno == ERANGE) {
    
    912
    -            free(buf);
    
    913 919
                 buflen *= 2;
    
    914 920
             } else {
    
    915 921
                 /*
    
    916 922
                  * Some other error.  Just return NULL
    
    917 923
                  */
    
    924
    +            free(buf);
    
    918 925
                 return NULL;
    
    919 926
             }
    
    920 927
         }
    
    ... ... @@ -922,6 +929,7 @@ os_get_user_homedir(const char* name, int *status)
    922 929
         /*
    
    923 930
          * Ran out of space.  Just return NULL and set status to -1.
    
    924 931
          */
    
    932
    +    free(buf);
    
    925 933
         *status = -1;
    
    926 934
         return NULL;
    
    927 935
     }
    

  • tests/filesys.lisp
    ... ... @@ -55,6 +55,36 @@
    55 55
     		       (ext:unix-namestring "/tmp/foo/bar/symlink" nil)))
    
    56 56
         (unix:unix-unlink "/tmp/foo/bar/symlink")))
    
    57 57
     
    
    58
    -	 
    
    59
    -    
    
    58
    +(define-test user-homedir.1
    
    59
    +  "Test user-homedir"
    
    60
    +  (:tag :issues)
    
    61
    +  ;; Simple test to see if get-user-homedir-pathname returns the
    
    62
    +  ;; expected value.  Use getuid and getpwuid to figure out what the
    
    63
    +  ;; name and home directory should be.
    
    64
    +  (let* ((uid (unix:unix-getuid))
    
    65
    +         (user-info (unix:unix-getpwuid uid)))
    
    66
    +    (assert-true uid)
    
    67
    +    (assert-true user-info)
    
    68
    +    (let* ((info-dir (unix:user-info-dir user-info))
    
    69
    +           (info-name (unix:user-info-name user-info))
    
    70
    +           (expected-home-pathname (pathname
    
    71
    +                                    (concatenate 'string info-dir "/"))))
    
    72
    +      (multiple-value-bind (home-pathname status)
    
    73
    +          (ext:get-user-homedir-pathname info-name)
    
    74
    +        (assert-true info-dir)
    
    75
    +        (assert-true info-name)
    
    76
    +
    
    77
    +        (assert-equal home-pathname expected-home-pathname)
    
    78
    +        (assert-eql status 0)))))
    
    79
    +
    
    80
    +(define-test user-homedir.2
    
    81
    +  "Test user-homedir"
    
    82
    +  (:tag :issues)
    
    83
    +  ;; Simple test to see if get-user-homedir-pathname returns the expected
    
    84
    +  ;; value for a user that does not exist.  Well, we assume such a
    
    85
    +  ;; user doesn't exist.
    
    86
    +      (multiple-value-bind (home-pathname status)
    
    87
    +          (ext:get-user-homedir-pathname "zotuserunknown")
    
    88
    +        (assert-eql home-pathname nil)
    
    89
    +        (assert-eql status 0)))    
    
    60 90
       

  • tests/os.lisp deleted
    1
    -(defpackage :os-tests
    
    2
    -  (:use :cl :lisp-unit))
    
    3
    -
    
    4
    -(in-package "OS-TESTS")
    
    5
    -
    
    6
    -(define-test user-homedir.1
    
    7
    -  "Test user-homedir"
    
    8
    -  (:tag :issues)
    
    9
    -  ;; Simple test to see if unix-get-user-homedir returns the expected
    
    10
    -  ;; value.  Use getuid and getpwuid to figure out what the name and
    
    11
    -  ;; home directory should be.
    
    12
    -  (let* ((uid (unix:unix-getuid))
    
    13
    -         (user-info (unix:unix-getpwuid uid)))
    
    14
    -    (assert-true uid)
    
    15
    -    (assert-true user-info)
    
    16
    -    (let* ((info-dir (unix:user-info-dir user-info))
    
    17
    -           (info-name (unix:user-info-name user-info))
    
    18
    -           (expected-home-pathname (pathname
    
    19
    -                                    (concatenate 'string info-dir "/"))))
    
    20
    -      (multiple-value-bind (home-pathname status)
    
    21
    -          (unix:unix-get-user-homedir info-name)
    
    22
    -        (assert-true info-dir)
    
    23
    -        (assert-true info-name)
    
    24
    -
    
    25
    -        (assert-equal home-pathname expected-home-pathname)
    
    26
    -        (assert-eql status 0)))))
    
    27
    -
    
    28
    -(define-test user-homedir.2
    
    29
    -  "Test user-homedir"
    
    30
    -  (:tag :issues)
    
    31
    -  ;; Simple test to see if unix-get-user-homedir returns the expected
    
    32
    -  ;; value for a user that does not exist.  Well, we assume such a
    
    33
    -  ;; user doesn't exist.
    
    34
    -      (multiple-value-bind (home-pathname status)
    
    35
    -          (unix:unix-get-user-homedir "zotuserunknown")
    
    36
    -        (assert-eql home-pathname nil)
    
    37
    -        (assert-eql status 0)))