Raymond Toy pushed to branch issue-269-unix-get-user-homedir at cmucl / cmucl
Commits:
-
2f767eed
by Raymond Toy at 2023-11-27T11:04:00-08:00
-
3d955819
by Raymond Toy at 2023-11-27T11:04:59-08:00
-
c6a9f865
by Raymond Toy at 2023-11-27T11:06:34-08:00
-
637a5d78
by Raymond Toy at 2023-11-27T11:08:51-08:00
-
d7a3d533
by Raymond Toy at 2023-11-27T11:09:46-08:00
9 changed files:
- .gitlab-ci.yml
- src/code/exports.lisp
- src/code/filesys.lisp
- src/code/unix.lisp
- src/i18n/locale/cmucl-unix.pot
- src/i18n/locale/cmucl.pot
- src/lisp/os-common.c
- tests/filesys.lisp
- − tests/os.lisp
Changes:
... | ... | @@ -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:
|
... | ... | @@ -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")
|
... | ... | @@ -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))))) |
... | ... | @@ -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 | - |
... | ... | @@ -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 | - |
... | ... | @@ -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 ""
|
... | ... | @@ -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 | }
|
... | ... | @@ -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 | |
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))) |