Question

When an application saves a file, a typical model is to save the file to a temporary location, then move the temporary file to the final location. In some cases that "move" becomes "replace". In pseudo code:

Save temp file;
if final file exists
   delete final file;
move temp file to final filename;

There's a window in there where the delete might succeed, but the move may not, so you can handle that by something like :

Save temp file;
if final file exists
   move final file to parking lot
move temp file to final filename;
if move succeeded       
   delete previous final file. 
else
   restore previous final file. 

Now to my questions:

  1. is it preferred to save the temporary file to a temporary directory, and then move it, as opposed to saving the temporary file to the final directory? (if so, why?)

  2. Is there a difference in attributes and permissions on a file that is first saved to a temp dir, then moved to the final file in a different directory, as compared to a file that is saved to a temp file in the final directory, and then renamed within the directory?

  3. If the answers to both are YES, then how can I do the preferred thing while getting the appropriate ACL on file which was first saved to a temporary directory and then moved to a final directory?

Was it helpful?

Solution

Create a temp file in the temp folder if it is just a temporary file. Otherwise, create it in its final destination.

Caveats:

1) This may not work if the final destination is a 'pickup' folder (unless the 'pickup' process checks for locked files (which it should))

2) The final destination has special permissions that have to be created in code and applied before being able to move to the final destination.

OTHER TIPS

Microsoft Word saves a temp file to the original directory starting with a tilde (~). I would just follow that convention.

If these are temp files that turn into permanent files, create them in the same location to avoid any risk of having to "move" files across disks/partitions, which will result in more I/O (as a copy followed by a delete).

If these are temp files that are truly temporary, create (and leave them) in the temp dir.

A reason why you might want to never write a file to one directory and move it to another is because those directories might be on different filesystems. Although this is less often a problem on windows, it is still reasonably possible so long as the parent filesystem is ntfs. In unix, it is a standard practice for /tmp to be a different filesystem.

The reason this could be a problem is because that means the file has to be copied from one place to another. This significantly impacts performance for files of substantial size, and will certainly require many more seeks, even if the file is small. Additionally, there are many more ways for this to fail when moving a file across filesystem boundaries. Of coursea access permissions could be different, but also the target filesystem could be full, or any number of other additional complications that you are now deferring until much later.

  1. It is preferable to create a temp file using the GetTempFile routines because this creates temp files in predefined locations (e.g. C:\temp) that utilities can delete if your app crashes or makes corrupt files in. If the same thing happens in your final directory, it is unrecoverable.

  2. Yes, attributes could be different if the target file's attributes or ACL has been edited. This could happen even if you create the temp file in the same folder.

  3. You fix this by using the File.Replace routine, which performs an atomic replacement of one file with another, replacing the new file's attributes and ACLs with the old file's.

A C# method that does this is an answer to Safe stream update of file.

I prefer saving the temporary file to the final directory:

  1. It avoids the potential permission problems that you've described.

  2. The final directory might be on a different volume, in which case the move (of the temporary to the final file) is really a copy + delete -- which incurs a lot of overhead if you do it often or if the file is big.

You can always rename the existing file to a second temporary file, rename the new temporary file to the existing file's name, and rollback on error. That seems to me to be the safest combination.

EDITED: I see that your "parking lot" already described my suggestion, so I'm not sure I've added much here.

1 . Yes, it is preferred to save to a temporary file first

Because the final file will never be in a corrupt state should the creation of the file fails for any reason. If you write directly to the final file and your program crashed mid-way... it will definitely leave the final file in an invalid state.

2 . Yes

The "inherited" attributes and permissions will of course, be different. But temporary directories on most systems usually are pre-configured for all applications to use. The "final file" directory might, however, need to be configured. Say the "Program Files" folder and Vista UAC, for example.

3 . Copy ACL from the final file to the temp file prior to replacing?

By default Android places .tmp as the suffix when the suffix param is set to null in File.createTempFile(). I would suggest you just use that.

File file = File.createTempFile(imageFileName, null, storageDir);

You should call file.delete() yourself as soon as you're done with your .tmp file in your app. You shouldn't depend on file.deleteOnExit() since there's absolutely no guarantee it'll be used by the Android system/VM.

Why not make it user configurable? Some users don't like temp files polluting their current directory.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top