From: Mark Wooding Date: Sun, 17 Jul 2011 20:51:16 +0000 (+0100) Subject: safely.lisp: More on the CLisp RENAME-FILE mess. X-Git-Url: https://git.distorted.org.uk/~mdw/lisp/commitdiff_plain/9224720f63a3a3f810ce03dc4018e23a0c6d8492 safely.lisp: More on the CLisp RENAME-FILE mess. The :IF-EXISTS option is only in very new versions of CLisp. It turns out that the bizarre double-pathname-merging bug in POSIX:COPY-FILE doesn't cause trouble if the source is absolute (unsurprising, in retrospect) so I could use TRUENAME to dig my way out of this mess; but COPY-FILE will clobber the target file before looking to see whether the source succeeds (unless persuaded otherwise with :IF-EXISTS, which only works if RENAME-FILE understands that option). Give up, and use rename(2) through the FFI. --- diff --git a/safely.lisp b/safely.lisp index 9b4ab45..0674429 100644 --- a/safely.lisp +++ b/safely.lisp @@ -110,12 +110,25 @@ (safely-trail safe)) stream)) +#+clisp +(progn + (ffi:def-call-out %rename (:name "rename") + (:language :stdc) + (:arguments (from ffi:c-string) + (to ffi:c-string)) + (:return-type ffi:int))) + (declaim (inline rename)) (defun rename (old new) + #-clisp (let ((target (make-pathname :directory '(:relative) :defaults new))) - #-clisp (rename-file old target) - #+clisp (rename-file old target :if-exists :overwrite))) + (rename-file old target)) + + #+clisp + (let ((rc (%rename (namestring old) (namestring new)))) + (when (= rc -1) + (error "Failed to rename ~S to ~S: ~A" old new (posix:strerror))))) (defun delete-file-without-moaning (file) "Delete the FILE, ignoring errors."