Skip to content

Do not remove dest file on File.cp error #3156

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

Closed
wants to merge 1 commit into from
Closed

Do not remove dest file on File.cp error #3156

wants to merge 1 commit into from

Conversation

shankardevy
Copy link
Contributor

Fixes #3155

Actually I have removed the 'rm' calls in do_cp_file and do_cp_link as I believe erlang takes care of not creating a file residue in case of failure. However, if that's not the case, either a bug report in erlang should be created or we have to delete the file conditionally only when the dest is not the same as src.

@@ -607,8 +607,6 @@ defmodule File do
[dest|acc]
{:error, :eexist} ->
if callback.(src, dest) do
# If rm/1 fails, copy/2 will fail
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your comment is true here, because the previous copy was ran with exclusive mode.

@shankardevy
Copy link
Contributor Author

@josevalim what is the purpose of trying low level copy/3 when cp/3 fails with {:error, :eexist} ?

The problem discussed here cannot be solved by simply removing the call the rm/2 because the subsequent call to copy/3 does not result in error but creates an empty file.

Summary:

  1. The problem reported initially:
    when the src file and dest file are same, calling File.cp/3 results in {:error, :enoent} but also deletes the src file which it shouldn't. Also the error should be {:error, :eexist} and NOT {:error, :enoent}.
  2. Trying to remove the call to rm/2 inside do_cp_file/4, the src file is now empty after cp/3 call and returns :ok

Next?

  1. Understand why there is call to copy/3 in first place and possibly remove it.
  2. If option1 above is not possible, then add a conditional before calling rm/2 to check if src and dest are same and throw error

@josevalim
Copy link
Member

So the bug is in Erlang copy implementation. :( I have no idea what to do next then. Maybe we should expand the paths ourselves and check if they are not equal.

@shankardevy
Copy link
Contributor Author

I have posted a question on erlang mailing list regarding this. https://groups.google.com/forum/#!topic/erlang-questions/q2BjcwC58j8 .

Can this wait until something is heard from erlang end or we go ahead and implement a condition checking src and dest? Also to keep in mind is that this issue with copying src to src is affecting all cp* functions including cp_r!/3 cp_r/3 etc, though the actual error is different in each of them.

@lexmag
Copy link
Member

lexmag commented May 19, 2015

Seems like nobody has responded in Erlang Questions group; it could not probably be a bug as :file.copy('LICENCE', 'LICENCE') makes blank LICENCE file correctly since destination will be opened with :write mode which truncates existing file before reads from source happen (that's why we have :exclusive option at first :file.copy/2 call).
I think we could fix #3155 by expanding paths and making equality check in default callback implementation. @josevalim what are your thoughts on it?
@shankardevy if you are not planing to proceed with this issue I'd gladly pick it up.

@josevalim
Copy link
Member

@lexmag checking the paths may be a better way to go indeed.

@shankardevy
Copy link
Contributor Author

@lexmag pls proceed. thank you.

@josevalim
Copy link
Member

CLosing, thank you.

@josevalim josevalim closed this May 22, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Copy a file to itself will remove the file
3 participants