bug-fileutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

mv does not behave like Solaris mv with respect to directory contents


From: Haynes, Tom
Subject: mv does not behave like Solaris mv with respect to directory contents
Date: Wed, 17 Apr 2002 11:54:40 -0700 (PDT)

I've looked at traces of both Solaris mv and the cut and paste GUI operation
on windows for behavior when a directory is moved.  In both cases, if
the rename of the directory failed, then it is copied and then the entries
are moved across one by one.  Both approaches try a move and not a copy.

In the GNU mv, if the directory rename fails, then the entries are all
copied and no attempt is made to move them across.  As an optimization,
I see why that would be there.  However, it does yield different behavior
than other platforms.

In NetApp's NFS file servers, we have the concept of a quota tree, qtree, which
is a combination of a logical partition and quotas on a rooted subtree
of a volume.  In the past, we disallowed moving files across qtrees. In
our next release, we are going to allow moving files, but not directories,
across qtrees.  With the typical client implementation of mv, the
rename of the directory fails, so it gets copied to the new qtree,
and then recursion tries to rename the files.  They get renamed and
finally the original directory gets deleted.

This will not work with the 4.1 version of fileutils.

If I look in the source, I see:
int
copy (const char *src_path, const char *dst_path,
      int nonexistent_dst, const struct cp_options *options,
      int *copy_into_self, int *rename_succeeded)
{
  /* move_mode is set to the value from the `options' parameter for the
     first copy_internal call.  For all subsequent calls (if any), it must
     be zero.  */
  int move_mode = options->move_mode;

  assert (valid_options (options));

  /* Record the file names: they're used in case of error, when copying
     a directory into itself.  I don't like to make these tools do *any*
     extra work in the common case when that work is solely to handle
     exceptional cases, but in this case, I don't see a way to derive the
     top level source and destination directory names where they're used.
     An alternative is to use COPY_INTO_SELF and print the diagnostic
     from every caller -- but I don't wan't to do that.  */
  top_level_src_path = src_path;
  top_level_dst_path = dst_path;

  return copy_internal (src_path, dst_path, nonexistent_dst, 0, NULL,
                        options, move_mode, copy_into_self, rename_succeeded);
}

Later, inside copy_dir:

      ret |= copy_internal (src_path, dst_path, new_dst, src_sb->st_dev,
                            ancestors, &non_command_line_options, 0,
                            &local_copy_into_self, NULL);

One solution is to pass move_mode to copy_dir and let it follow the
recursion.  The second is to change all references to move_mode to
be to options->move_mode and remove the move_mode parameter.

I can provide network trace files of the different client mvs.

--
Tom Haynes, cfb
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]