Raymond Toy pushed to branch master at cmucl / cmucl
Commits:
-
459c91bc
by Raymond Toy at 2025-02-18T02:53:23+00:00
-
daf83c84
by Raymond Toy at 2025-02-18T02:53:23+00:00
3 changed files:
Changes:
... | ... | @@ -2907,28 +2907,71 @@ |
2907 | 2907 | (defun unix-mkstemp (template)
|
2908 | 2908 | _N"Generates a unique temporary file name from TEMPLATE, and creates
|
2909 | 2909 | and opens the file. On success, the corresponding file descriptor
|
2910 | - and name of the file is returned.
|
|
2911 | - |
|
2912 | - The last six characters of the template must be \"XXXXXX\"."
|
|
2913 | - ;; Hope this buffer is large enough!
|
|
2914 | - (let ((octets (%name->file template)))
|
|
2915 | - (syscall ("mkstemp" c-call:c-string)
|
|
2910 | + and name of the file is returned. Otherwise, NIL and the UNIX error
|
|
2911 | + code is returned."
|
|
2912 | + (let* ((format (if (eql *filename-encoding* :null)
|
|
2913 | + :iso8859-1
|
|
2914 | + *filename-encoding*))
|
|
2915 | + ;; Convert the string to octets using the
|
|
2916 | + ;; *FILENAME-ENCODING*. Should we signal an error if the
|
|
2917 | + ;; string can't be encoded?
|
|
2918 | + (octets (stream:string-to-octets template
|
|
2919 | + :external-format format))
|
|
2920 | + (length (length octets)))
|
|
2921 | + (with-alien ((buffer (* c-call:unsigned-char)))
|
|
2922 | + (setf buffer (make-alien c-call:unsigned-char (1+ length)))
|
|
2923 | + ;; Copy the octets from OCTETS to the null-terminated array BUFFER.
|
|
2924 | + (system:without-gcing
|
|
2925 | + (kernel:system-area-copy (vector-sap octets) 0
|
|
2926 | + (alien-sap buffer) 0
|
|
2927 | + (* length vm:byte-bits)))
|
|
2928 | + (setf (deref buffer length) 0)
|
|
2929 | + |
|
2930 | + (syscall ("mkstemp" (* c-call:char))
|
|
2916 | 2931 | (values result
|
2917 | - ;; Convert the file name back to a Lisp string.
|
|
2918 | - (%file->name octets))
|
|
2919 | - octets)))
|
|
2932 | + (progn
|
|
2933 | + ;; Copy out the alien bytes and convert back
|
|
2934 | + ;; to a lisp string.
|
|
2935 | + (system:without-gcing
|
|
2936 | + (kernel:system-area-copy (alien-sap buffer) 0
|
|
2937 | + (vector-sap octets) 0
|
|
2938 | + (* length vm:byte-bits)))
|
|
2939 | + (stream:octets-to-string octets
|
|
2940 | + :external-format format)))
|
|
2941 | + (cast buffer (* c-call:char))))))
|
|
2920 | 2942 | |
2921 | 2943 | (defun unix-mkdtemp (template)
|
2922 | - _N"Generate a uniquely named temporary directory from Template,
|
|
2923 | - which must have \"XXXXXX\" as the last six characters. The
|
|
2944 | + _N"Generate a uniquely named temporary directory from Template. The
|
|
2924 | 2945 | directory is created with permissions 0700. The name of the
|
2925 | - directory is returned."
|
|
2926 | - (let* ((octets (%name->file template))
|
|
2927 | - (result (alien-funcall
|
|
2928 | - (extern-alien "mkdtemp"
|
|
2929 | - (function (* char)
|
|
2930 | - c-call:c-string))
|
|
2931 | - octets)))
|
|
2932 | - (if (null-alien result)
|
|
2933 | - (values nil (unix-errno))
|
|
2934 | - (%file->name octets)))) |
|
2946 | + directory is returned.
|
|
2947 | + |
|
2948 | + If the directory cannot be created NIL and the UNIX error code is
|
|
2949 | + returned."
|
|
2950 | + (let* ((format (if (eql *filename-encoding* :null)
|
|
2951 | + :iso8859-1
|
|
2952 | + *filename-encoding*))
|
|
2953 | + ;; Encode the string using the appropriate
|
|
2954 | + ;; *filename-encoding*. Should we signal an error if the
|
|
2955 | + ;; string can't be encoded in that format?
|
|
2956 | + (octets (stream:string-to-octets template
|
|
2957 | + :external-format format))
|
|
2958 | + (length (length octets)))
|
|
2959 | + (with-alien ((buffer (* c-call:unsigned-char)))
|
|
2960 | + (setf buffer (make-alien c-call:unsigned-char (1+ length)))
|
|
2961 | + ;; Copy the octets from OCTETS to the null-terminated array BUFFER.
|
|
2962 | + (system:without-gcing
|
|
2963 | + (kernel:system-area-copy (vector-sap octets) 0
|
|
2964 | + (alien-sap buffer) 0
|
|
2965 | + (* length vm:byte-bits)))
|
|
2966 | + (setf (deref buffer length) 0)
|
|
2967 | + |
|
2968 | + (let ((result (alien-funcall
|
|
2969 | + (extern-alien "mkdtemp"
|
|
2970 | + (function (* char)
|
|
2971 | + (* char)))
|
|
2972 | + (cast buffer (* char)))))
|
|
2973 | + ;; If mkdtemp worked, a non-NIL value is returned, return the
|
|
2974 | + ;; resulting name. Otherwise, return NIL and the errno.
|
|
2975 | + (if (null-alien result)
|
|
2976 | + (values nil (unix-errno))
|
|
2977 | + (%file->name (cast result c-call:c-string))))))) |
... | ... | @@ -1440,16 +1440,17 @@ msgstr "" |
1440 | 1440 | msgid ""
|
1441 | 1441 | "Generates a unique temporary file name from TEMPLATE, and creates\n"
|
1442 | 1442 | " and opens the file. On success, the corresponding file descriptor\n"
|
1443 | -" and name of the file is returned.\n"
|
|
1444 | -"\n"
|
|
1445 | -" The last six characters of the template must be \"XXXXXX\"."
|
|
1443 | +" and name of the file is returned. Otherwise, NIL and the UNIX error\n"
|
|
1444 | +" code is returned."
|
|
1446 | 1445 | msgstr ""
|
1447 | 1446 | |
1448 | 1447 | #: src/code/unix.lisp
|
1449 | 1448 | msgid ""
|
1450 | -"Generate a uniquely named temporary directory from Template,\n"
|
|
1451 | -" which must have \"XXXXXX\" as the last six characters. The\n"
|
|
1449 | +"Generate a uniquely named temporary directory from Template. The\n"
|
|
1452 | 1450 | " directory is created with permissions 0700. The name of the\n"
|
1453 | -" directory is returned."
|
|
1451 | +" directory is returned.\n"
|
|
1452 | +"\n"
|
|
1453 | +" If the directory cannot be created NIL and the UNIX error code is\n"
|
|
1454 | +" returned."
|
|
1454 | 1455 | msgstr ""
|
1455 | 1456 |
1 | +;;; Tests for the unix interface
|
|
2 | + |
|
3 | +(defpackage :unix-tests
|
|
4 | + (:use :cl :lisp-unit))
|
|
5 | + |
|
6 | +(in-package "UNIX-TESTS")
|
|
7 | + |
|
8 | +(define-test mkstemp.name-returned
|
|
9 | + (:tag :issues)
|
|
10 | + (let (fd filename)
|
|
11 | + (unwind-protect
|
|
12 | + (progn
|
|
13 | + (let ((template "test-XXXXXX"))
|
|
14 | + (multiple-value-setq (fd filename)
|
|
15 | + (unix::unix-mkstemp (copy-seq template)))
|
|
16 | + (assert-true fd)
|
|
17 | + (assert-true (equalp (length filename) (length template)))
|
|
18 | + (assert-false (equalp filename template))
|
|
19 | + (assert-true (>= 5 (mismatch filename template))))))
|
|
20 | + (when fd
|
|
21 | + (unix:unix-unlink filename)))))
|
|
22 | + |
|
23 | +(define-test mkstemp.non-ascii-name-returned
|
|
24 | + (:tag :issues)
|
|
25 | + (let ((unix::*filename-encoding* :utf-8)
|
|
26 | + fd name)
|
|
27 | + (unwind-protect
|
|
28 | + (progn
|
|
29 | + ;; Temp name starts with a lower case alpha character.
|
|
30 | + (let* ((template (concatenate 'string (string #\u+3b1)
|
|
31 | + "test-XXXXXX"))
|
|
32 | + (x-posn (position #\X template)))
|
|
33 | + (multiple-value-setq (fd name)
|
|
34 | + (unix::unix-mkstemp template))
|
|
35 | + (assert-true fd)
|
|
36 | + (assert-false (search "XXXXXX" name)
|
|
37 | + name)
|
|
38 | + (assert-true (string= name template :end1 x-posn :end2 x-posn)
|
|
39 | + name)))
|
|
40 | + (when fd
|
|
41 | + (unix:unix-unlink name)))))
|
|
42 | + |
|
43 | +(define-test mkstemp.bad-path
|
|
44 | + (:tag :issues)
|
|
45 | + (multiple-value-bind (fd errno)
|
|
46 | + ;; Assumes that the directory "random-dir" doesn't exist
|
|
47 | + (unix::unix-mkstemp "random-dir/test-XXXXXX")
|
|
48 | + ;; Can't create and open the file so the FD should be NIL, and a
|
|
49 | + ;; positive Unix errno value should be returned.
|
|
50 | + (assert-false fd)
|
|
51 | + (assert-true (and (integerp errno) (plusp errno)))))
|
|
52 | + |
|
53 | +(define-test mkdtemp.name-returned
|
|
54 | + (:tag :issues)
|
|
55 | + (let (name)
|
|
56 | + (unwind-protect
|
|
57 | + (progn
|
|
58 | + (setf name (unix::unix-mkdtemp "dir-XXXXXX"))
|
|
59 | + ;; Verify that the dir name no longer has X's.
|
|
60 | + (assert-true (stringp name))
|
|
61 | + (assert-false (search "XXXXXX" name)))
|
|
62 | + (when name
|
|
63 | + (unix:unix-rmdir name)))))
|
|
64 | + |
|
65 | +(define-test mkdtemp.non-ascii-name-returned
|
|
66 | + (:tag :issues)
|
|
67 | + (let ((unix::*filename-encoding* :utf-8)
|
|
68 | + name)
|
|
69 | + (unwind-protect
|
|
70 | + (progn
|
|
71 | + ;; Temp name starts with a lower case alpha character.
|
|
72 | + (let* ((template (concatenate 'string (string #\u+3b1)
|
|
73 | + "dir-XXXXXX"))
|
|
74 | + (x-posn (position #\X template)))
|
|
75 | + (setf name (unix::unix-mkdtemp template))
|
|
76 | + ;; Verify that the dir name no longer has X's.
|
|
77 | + (assert-true (stringp name))
|
|
78 | + (assert-false (search "XXXXXX" name))
|
|
79 | + (assert-true (string= name template :end1 x-posn :end2 x-posn)
|
|
80 | + name x-posn)))
|
|
81 | + (when name
|
|
82 | + (unix:unix-rmdir name)))))
|
|
83 | + |
|
84 | +(define-test mkdtemp.bad-path
|
|
85 | + (:tag :issues)
|
|
86 | + (multiple-value-bind (result errno)
|
|
87 | + (unix::unix-mkdtemp "random-dir/dir-XXXXXX")
|
|
88 | + (assert-false result)
|
|
89 | + (assert-true (and (integerp errno) (plusp errno)))))
|
|
90 | + |
|
91 | + |