Opened 9 years ago

Last modified 5 years ago

#667 new defect

open :if-exists :rename doesn't rename

Reported by: stassats Owned by: gb
Priority: normal Milestone:
Component: Runtime (threads, GC) Version: trunk
Keywords: Cc:


(open "foo" :if-exists :rename :direction :output) doesn't actually rename the old file.

Change History (3)

comment:1 Changed 5 years ago by rme

I think it's important to ensure that renaming the old file doesn't cause any existing file to be deleted.

On Unix systems, there's a well-known race involved when a program checks to see if a file name exists (via access(2) or probe-file or whatever) and then tries to create a file with that name. The race is that some other process could have come along between the access(2) and the open(2) and created a file with the name in question.

I don't know what the Windows situation is in this case.

I wonder if we need to be careful about that here.

Doing something like

  (let ((new-name (make-derived-name original-name)))
    (unless (probe-file new-name)
      (rename-file original-name new-name)

has the race I'm worrying about. In fact, rename-file is subject to the race I'm taking about (thanks to our :if-exists extension).

Is it too much to make our rename-file safe from the race condition? We could then handle the file error that would be signaled when rename-file tries to rename to an existing name, and loop as needed until we found an available name.

On Unix, we could presumably use mkstemp(3) or at least open with O_EXCL to ensure that the new filename doesn't exist. I'm not sure what the equivalent is on Windows.

Or is this race condition not worth worrying about?

comment:2 Changed 5 years ago by loic

On SBCL, if foo and foo.bak exist, it seem throw an error, I think it cannot rename because the backup for the foo exist.

On Windows for race condition I found this :

LockFile? function (shared access)

LockFileEx? function (exclusive access)

With CreateFile? used for an exclusive access (third parameter - dwShareMode=0x0)

both avoid the case of race condition, and maybe can be used in our case.

But it complicate our case.

Note: See TracTickets for help on using tickets.