Skip to content
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

mv deletes symlinked files when one is moved onto the other #40

Open
mwatts15 opened this issue Mar 2, 2015 · 2 comments
Open

mv deletes symlinked files when one is moved onto the other #40

mwatts15 opened this issue Mar 2, 2015 · 2 comments
Labels

Comments

@mwatts15
Copy link
Owner

mwatts15 commented Mar 2, 2015

The apparent source of this behavior is this block of code in coreutils' copy.c, called from mv.c:

          /* Here we have two symlinks that are hard-linked together,
             and we're not making backups.  In this unusual case, simply
             returning true would lead to mv calling "rename(A,B)",
             which would do nothing and return 0.  I.e., A would
             not be removed.  Hence, the solution is to tell the
             caller that all it must do is unlink A and return.  */
          if (same_link)
            {
              *unlink_src = true;
              *return_now = true;
              return true;
            }

and this block that actually does the unlink:

      if (x->move_mode)
        {
          if (abandon_move (x, dst_name, &dst_sb)
              || (unlink_src && unlink (src_name) == 0))
            {
              /* Pretend the rename succeeded, so the caller (mv)
                 doesn't end up removing the source file.  */
              if (rename_succeeded)
                *rename_succeeded = true;
              if (unlink_src && x->verbose)
                printf (_("removed %s\n"), quote (src_name));
              return true;
            }
          if (unlink_src)
            {
              error (0, errno, _("cannot remove %s"), quote (src_name));
              return false;
            }
        }

This behavior is appropriate in normal file systems, but in TagFS, the semantics of the i-number, when the use_ino option is active, don't align with the semantics of unlink as generally understood. Not enabling the the use_ino option can remove this problem, but it also makes it impossible for most utilities to identify a file as the same file at different locations which can cause problems when one attempts to copy a file onto itself at a distinct location.

@mwatts15 mwatts15 added the bug label Mar 2, 2015
@mwatts15
Copy link
Owner Author

mwatts15 commented Mar 9, 2015

The linking branch attempts to address this issue by causing the unlink operation to remove the tag corresponding to the last directory in the path for the unlink rather than completely deleting the file. Additionally, a file is not completely deleted until all tags are removed from the file and then the file is unlinked. Unfortunately, these semantics leave many files in the system which may have been intended for destruction.

@mwatts15
Copy link
Owner Author

My current solution is to add a check on the link count (st_nlink) in copy.c before returning true in same_file_ok:

          if (same_link)

becomes:

          if (same_link && src_sb->st_nlink > 1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant