-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
fs::copy: Cannot copy special/device files (ex: /dev/null) into a file #79390
Comments
Well, this is documented behavior:
|
In the light of "everything is a file" perhaps the documentation could be improved to say "regular file" . |
@sylvestre Not sure if #79399 is the kind of fix you are looking for, it fixes it from a documentation perspective. I wonder if it is possible to allow copying from |
@pickfire At least, the doc should be improved but yeah, I think this function should allow copy. There are cases when /dev/null is used as a regular file like: |
It would be good to know why the check explicitly rejecting it has been added in the first place. It has been there since the module was introduced in 2015 And understanding the use-case would be good too. If you want to create an empty file (copying |
I guess the folks who implemented it didn't know that it wasn't uncommon to do |
* fix(install): workaround the /dev/null bug Caused by a limitation of fs::copy in rust. see: rust-lang/rust#79390
Check should be removed in my opinion. Don't understand what it's checking against. As noted here, it is common in UNIX to copy from all kinds of special files. In addition to Yes, you have to be careful what you copy from and to. That's true in any case. |
Hrm, I just read the docs for |
If you need custom behavior deviating from |
I don't see why it can't copy the permissions from a device file? I think that may have been a poor design choice, but I don't think it gets in the way of fixing this issue. |
I don't think the requested behavior deviates from the specification for Curious if anyone can give an example where allowing |
I was responding to the post directly above mine, not the general topic as I already covered that earlier. |
I think this is rather stretched nterpretation of the text "the from path is not a file". A reader familiar with Unix will read that as "not a plain file". But I think it's fine to change the spec here. The issue with the permissions is more awkward (see below).
A backup program would definitely need to check the metadata for other reasons. But some kind of rudimentary version control system might not need to. Note that such a system would probably do something unhelpful with symlinks. (I haven't checked but I assume that
Copying the permissions from a device file is definitely wrong. For example, Stepping back, ISTM that we should (i) decide what the best behaviour would be (ii) consider whether that behaviour would be a breaking change (iii) make sure to document the behaviour unambiguously. So best behaviour for a basic file-copying functionOn Unix, copying the execute bit is sensible. Copying read restrictions is sensible. I think copying the other permissions is not usually sensible for a simple file copying function. Or to put it another way the behaviour should be as if we used Symlinks should be dereferenced at both ends. If the source is not a plain file, the destination mode should be IMO if the destination file does not exist it should not have its permissions changed. Ie, we is this a breaking changeWell, it clearly this would change the behaviour. Would it be a breaking change? I think though that programs which need particular behaviour for the file mode will already need to have taken control of that themselves. For programs that didn't do anything special it's quite possible that if we change this behaviour we may fix bugs in those programs. The existing spec says it copies permissions and it is not clear whether that includes acls or the immutable bit. A reader familiar with Unix would probably assume tht it meant just the file mode, but a reader not familiar with Unix terminology would perhaps think all permission-like things are included. I don't imagine the current implementation copies acls (I haven't checked) because that is very complicated (and not always even possible). The unix mode permission bits are interpreted in the context of the file's ownership. What copying the group permissions means depends on what the group ownership of the new file is. On systems with universal personal groups and a umask of So arguably this is a bugfix. I think this is not clear-cut. |
@ijackson Great comment! I agree with pretty much all of it. The only quibble I might have is with "A reader familiar with Unix will read that as 'not a plain file'." I just assumed they were talking about directories, which would be a perfectly normal restriction for a file copy program. The permissions thing is, as you say, a big bag of worms. If I had spec'ed this, I probably would have said that new target files would be created 0777 modified by the umask (which is pretty much the normal behavior for UNIX things) and existing target files would keep their existing permissions. The situation is made worse when you start thinking about what should happen under Windows and other non-standard OS targets. Again, I'm not sure there's anything "special" about device special files here. It's probably a mistake to preserve the permissions on any world-writeable file when creating a new copy: the umask should always be applied by default. This would definitely be a change in the specification, but I'm for it. |
I think part of the question here is whether we expect I think it's worth noting that on Windows, this calls I think it may have made sense for this function to copy file contents even if the file is a device file or other special file, and then we may want a different function that does the equivalent of That said, since not handling device/special files is a specifically documented property of this function, I'd be somewhat concerned that people wrote code that relies on this behavior. (That doesn't mean we can't change it, as it may fall under platform-specific behavior, but it may be imprudent for us to change it.) Given that, the safest option might be to add a |
@joshtriplett Yeah, it seems like we're well into the "explore behavior in the wild" stage. Does anybody use this function in non-toy programs at all? Would the best course to be to deprecate and kill it, offering no replacement? It seems like this innocent-looking thing can lead to quite a hornet's nest of considerations. |
Just to throw another option in (i am actually just at the beginning of my rust journey), can't there be an |
@cheriimoya Welcome to Rust! Yes, there absolutely could be an alternate API, which is one of the options being considered. Sadly, you wouldn't want to use global state for setting options, for a whole bunch of really excellent reasons, so it really would have to be an entirely new API, exposing new functions. The danger here is that, as the old saying goes, "now you have two problems." It would be much better to preserve the existing API if we can agree on how to make it safe and palatable for everyone involved. It's all especially frustrating because the simplest and arguably most common use case, just copying a plain file to another plain file, is almost right. Even there, though, the permissions spec might need to be changed to avoid really surprising behaviors — I had no idea until this thread that |
thanks @BartMassey! oh, yeah, i thought that even after skimming through the code i still don't fully get it.. would it somehow be possible to move |
Any change to the existing API is breaking, and will probably never happen. Part of what makes the discussion of |
Includes suggestion from the8472 rust-lang#79390 (comment) More detail error explanation in fs doc
Use detailed and shorter fs error explaination Includes suggestion from `@the8472` rust-lang#79390 (comment)
I tried this code:
I expected to see this happen:
I agree that the use case isn't super useful. But I would expect this to work and create an empty file.
Instead, this happened:
the source path is not an existing regular file
Don't hesitate to wontfix this bug...
The text was updated successfully, but these errors were encountered: