2 ;;; directly pullled from metatilities, sigh
5 ;(in-package #:metatilities)
7 (defcondition (source/target-file-error
9 "General condition for file errors that have a source and target."
12 (source-pathname target-pathname
)
13 "Copy of ~S to ~S failed"
14 source-pathname target-pathname
)
16 (defcondition (source/target-target-already-exists-error
18 "This error is signaled when the target pathname already exists."
20 :slot-names
(source-pathname target-pathname
))
21 (source/target-file-error
)
23 "File action failed because target ~S already exists"
26 (defcondition (source/target-source-does-not-exist-error
28 "This error is signaled when the source file does not exist."
30 :slot-names
(source-pathname target-pathname
))
31 (source/target-file-error
)
33 "File action failed because source ~S does not exist"
36 (defun copy-file (from to
&key
(if-does-not-exist :error
)
38 "Copies the file designated by the non-wild pathname designator FROM
39 to the file designated by the non-wild pathname designator TO. The following
40 keyword parameters are supported:
43 this can be either :supersede or :error (the default). If it is :error then
44 a source/target-target-already-exists-error will be signaled if the file designated
45 by the TO pathname already exists.
48 this can be either :ignore or :error (the default). If it is :error then
49 a source/target-source-does-not-exist-error will be signaled if the FROM pathname
50 designator does not exist.
52 (assert (member if-exists
'(:error
:supersede
))
54 "The if-exists keyword parameter must be one of :error or :supersede. It is currently set to ~S"
56 (assert (member if-does-not-exist
'(:error
:ignore
))
58 "The if-does-not-exist keyword parameter must be one of :error or :ignore. It is currently set to ~S"
60 (ensure-directories-exist to
)
61 (cond ((probe-file from
)
65 :overwrite
(if (eq if-exists
:supersede
) :ignore nil
))
67 (let ((element-type #-
:cormanlisp
'(unsigned-byte 8)
68 #+:cormanlisp
'unsigned-byte
))
69 (with-open-file (in from
:element-type element-type
)
70 (with-open-file (out to
:element-type element-type
74 (error (make-condition 'source
/target-target-already-exists
76 :target-pathname to
)))
77 (copy-stream in out
))))
81 (ecase if-does-not-exist
82 ((:error
) (error 'source
/target-source-does-not-exist-error
83 :pathname from
:target-pathname to
))
86 (defun move-file (from to
&rest args
&key
(if-does-not-exist :error
)
88 (declare (dynamic-extent args
)
89 (ignore if-exists if-does-not-exist
))
90 (when (apply #'copy-file from to args
)
93 ;;; borrowed from asdf-install -- how did this ever work ?!
94 ;; for non-SBCL we just steal this from SB-EXECUTABLE
96 (defvar *stream-buffer-size
* 8192)
98 (defun copy-stream (from to
)
99 "Copy into TO from FROM until end of the input stream, in blocks of
100 *stream-buffer-size*. The streams should have the same element type."
101 (unless (subtypep (stream-element-type to
) (stream-element-type from
))
102 (error "Incompatible streams ~A and ~A." from to
))
103 (let ((buf (make-array *stream-buffer-size
*
104 :element-type
(stream-element-type from
))))
106 (let ((pos #-
(or :clisp
:cmu
) (read-sequence buf from
)
107 #+:clisp
(ext:read-byte-sequence buf from
:no-hang nil
)
108 #+:cmu
(sys:read-n-bytes from buf
0 *stream-buffer-size
* nil
)))
109 (when (zerop pos
) (return))
110 (write-sequence buf to
:end pos
)))))
113 (defun copy-stream (from to
)
114 "Perform copy and map EOL mode."
115 (multiple-value-bind (reader reader-arg
) (ccl::stream-reader from
)
116 (multiple-value-bind (writer writer-arg
) (ccl::stream-writer to
)
118 (loop (unless (setf datum
(funcall reader reader-arg
))
120 (funcall writer writer-arg datum
))))))