Raymond Toy pushed to branch master at cmucl / cmucl

Commits:

3 changed files:

Changes:

  • src/code/unix.lisp
    ... ... @@ -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)))))))

  • src/i18n/locale/cmucl-unix.pot
    ... ... @@ -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
     

  • tests/unix.lisp
    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
    +