-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: provide ioutil.SafeWriteFile writing to a tmp file before overwriting an existing file #17869
Comments
This seems like a good idea. I would prefer it to have a |
Using an adverb would clarify what part is safe (the writing or the file): But maybe better to just replace the verb: |
In light of #17873, we also need to decide whether the proposed
function should:
1. avoid rewrite the destination if it's readonly
2. preserve the destination's permission bits and other file system
properties like ACL, xattr and the like.
Solve the latter point is notoriously non-trivial, and it's something
to think about. I think it's probably one of the reason there is no
CopyFile function in the std.
|
I think the temporary file prefer on same disk-partition, same filesytem. How about to put the temporary file into same directory? ex: |
Sorry, already mentioned by grieseme. |
In addition to what @minux mentioned, the proposed function should also preserve owner and group information. |
Ahh, preserving ownership and group is hard.
I'm almost thinking that this is too big a problem to fix in std and gofmt
needs to choose another fix for ENOSPC problem, namely, make a backup of
the original file and then write to the original file unconditionally, and
if the write succeed, remove the backup.
|
@minux Yes, that's the other approach I was thinking of. It will make updates much slower if there's a lot of files to change. What I have now preserves permissions, but that is only half the story. |
CL https://golang.org/cl/33098 mentions this issue. |
This reverts the changes from https://golang.org/cl/33018: Instead of writing the result of gofmt to a tmp file and then rename that to the original (which doesn't preserve the original file's perm bits, uid, gid, and possibly other properties because it is hard to do in a platform-independent way - see #17869), use the original code that simply overwrites the processed file if gofmt was able to create a backup first. Upon success, the backup is removed, otherwise it remains. Fixes #17873. For #8984. Change-Id: Ifcf2bf1f84f730e6060f3517d63b45eb16215ae1 Reviewed-on: https://go-review.googlesource.com/33098 Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
I wonder if the "Safe" name prefix will raise crash safety expectations that won't be fulfilled by the function as proposed. Brad's ReplaceFile nicely avoids this connotation. |
Maybe AtomicWrite or AtomicWriteFile. |
The word Replace here still doesn't make it clear whether it replaces the
content only (i.e. preserving ownership/permission/etc.) or the file as a
whole (which might not preserve ownership, permission, etc.)
|
It seems that we're heading into the area of bikeshedding, but any name with the words 'Safe' or 'Atomic' in them seems to imply to me heavier guarantees of data persistence than the current proposed implementation gives. I would expect |
Probably relevant commentary around atomic writing in #8868 and https://go-review.googlesource.com/c/1591/. |
I haven't seen this mentioned before, but I've used: https://godoc.org/github.com/dchest/safefile before. |
This seems very hard and maybe beyond the scope of the library. |
We don't see how to do a 100% safe implementation of this on most systems. Gofmt changed to copy the old file to a temp file, then overwrite the old file, and then if the overwrite fails, attempt to rename the tempfile into the old file's place, which is actually different from the initial proposal. You can have the one that clears permission bits / ACLs on success. If the community converges on a particular semantics that is the "right" one, we can certainly revisit this. But right now we don't know what this should do, especially well enough to put in the standard library. Objections to declining this proposal? |
Would it be sensible for the standard library to include one or many of these functions that compromise in one way or another? From what I understand, you'd want the "right" one (as in not many at once) or at least for most people to agree on which is the better one. |
I would rather see a third party package provide a set of functions that emphasis different design priorities rather than seeing the standard library provide a hodgepodge of different implementations. |
If ioutil.WriteFile fails for some reason during writing/closing, it may destroy an existing file with the same name before reporting an error.
It's not hard to handle this on a case-by-case basis, but I suspect this is a common scenario for which to protect against and perhaps should be supported by ioutil.
See #8984 for a use case.
Implementation:
Better func name welcome.
The text was updated successfully, but these errors were encountered: