emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

"Renaming: permission denied" file-error in Windows


From: LynX
Subject: "Renaming: permission denied" file-error in Windows
Date: Sun, 11 Dec 2011 02:16:45 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.8) Gecko/20100227 Thunderbird/3.0.3

Hello,

I found that dired in Windows does not provide you possibility to move a directory to a new location if this new location resides on a different logical disk.

For instance you have two opened dired buffers: `c:\dir1' and `f:\dir2'. To move some files from `dir1' to `dir2' you can use "R", but if you try to move some directory from `dir1' to `dir2' you will get `Renaming: permission denied' error message.

The problem occurs when dired calls Emacs function which delegates the call to native POSIX function `rename'.

In Windows `rename' operates a bit different than in other systems. According to MSDN [http://msdn.microsoft.com/en-us/library/zw5t957f.aspx]:

-- "You can use rename to move a file from one directory or device to another by giving a different path in the newname argument. However, you cannot use rename to move a directory." --

Whereas, in standard POSIX spec such constraint was not found.

Following code workarounds this problem by wrapping dired function
`dired-rename-file'. So when `Renaming: permission denied' error occurs, it tries to move the directory again by moving each of it files recursively to a new destination, recreating the source directory with its subdirectory structure.

If it also fails to do this due to real permission problems then it sends original error message.

Regards,
LX


(defadvice dired-rename-file
  (around my-dired-rename-file
    (file newname ok-if-already-exists))
  "This advice definition helps to deal with
`Renaming: permission denied' error message when moving
directories between different logical disks in dired.
This is a Windows specific problem."
  (condition-case err
    ad-do-it
    (file-error
      (and
        (string-starts-with
          (error-message-string err)
          "Renaming: permission denied")
        (file-directory-p file)
        (move-directory-recursively file newname)))))
(ad-activate 'dired-rename-file t)


(defun move-directory-recursively (dir-src dir-dst)
  "Moves directory DIR-SRC to the DIR-DST recursively.
To move directory dir1 into the directory dir2 you should
call this function like as follows:
  (move-directory-recursively `dir1' `dir2/dir1')
To move content of the directory dir1 into the directory
dir2:
  (move-directory-recursively `dir1' `dir2')
If dir2 does not exist it will be created."
  (let ((queue (list (cons dir-src dir-dst)))
        dir-dst dir-src remove-later)
    (while queue
      (let ((dir-src-dst (car queue)))
        (setq dir-src (car dir-src-dst))
        (setq dir-dst (cdr dir-src-dst)))
      (setq queue (cdr queue))
      ;; if dir-dst is a file signal an error
      (and
        (file-exists-p dir-dst)
        (not (file-directory-p dir-dst))
        (signal 'file-error
          (format "Error: file %s exist" dir-dst)))
      ;; if dir-dst does not exist - create it
      (if (not (file-exists-p dir-dst))
        (make-directory dir-dst))
      (dolist (file (directory-files dir-src))
        (and
          (not (string= file "."))
          (not (string= file ".."))
          (let ((path (concat dir-src "/" file)))
            (if (file-directory-p path)
              ;; it is a directory
              (progn
                ;; place it to the queue
                (setq queue
                  (cons
                    (cons path (concat dir-dst "/" file))
                    queue))
                ;; and store it path to remove it later
                (push path remove-later))
              ;; not a dir
              (progn
                (message
                  (format "Moving %s to %s" path dir-dst))
                (rename-file path dir-dst)))))))
  ;; after we moved all content we can remove the
  ;; empty directories in dir-src
  (dolist (dir remove-later)
    (condition-case err
      (dired-delete-file dir 'always)
      (error ;; catch errors from failed deletions
        (dired-log "%s\n" err)))))
  (dired-delete-file dir-src 'always))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]