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 | + |