This is the mail archive of the cygwin-developers mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: New rename(2) function


Corinna Vinschen wrote:
On Aug 9 21:23, Eric Blake wrote:
According to Christian Franke on 8/9/2007 10:38 AM:
...

Btw., this looks weird in mv:


  $ mv -T Bar bar
  mv: cannot remove `Bar': Operation not permitted

Huh? Nobody asked for removing Bar, afaics...


The root of the problem is IMO the copy.c:same_file_ok() function, see attached code snippets (coreutils 6.9).


On -T, it treats the dest dir as a file and checks (1 < #links) which is always true for a directory. The same_name() function is case sensitive.

Therefore, same_file_ok() returns true and sets unlink_src=true.

Later, copy_internal() handles the source path as a hard link to destination and tries to unlink() the source. Fortunately, unlink() is unable to rmdir().

No problem if both names match:

$ mv -T bar bar
mv: `bar' and `bar' are the same file

$ mv -T ./BAR BAR
mv: `./BAR' and `BAR' are the same file


In the file case, the problem does not occur because #links usually are 1:


$ touch Foo

$ mv Foo foo
mv: `Foo' and `foo' are the same file


But be aware: If there are hard links, things get really worse:


$ touch Foo

$ ln Foo Fool

$ mv -v Foo foo
removed `Foo'

$ ls foo* Foo*
ls: cannot access foo*: No such file or directory
Fool


This is probably not POSIX compliant ;-)


Christian

   612	same_file_ok (...)
...
   734	  if (x->move_mode || x->unlink_dest_before_opening)
   735	    {
   736	      if (S_ISLNK (dst_sb_link->st_mode))
   737		return true;
   738	
   739	      if (same_link
   740		  && 1 < dst_sb_link->st_nlink
   741		  && ! same_name (src_name, dst_name))
   742		{
   743		  if (x->move_mode)
   744		    {
   745		      *unlink_src = true;
   746		      *return_now = true;
   747		    }
   748		  return true;
   749		}
   750	    }
...
  1014	copy_internal (...)
...
  1102		  bool return_now;
  1103		  bool unlink_src;
  1104	
  1105		  if (! same_file_ok (src_name, &src_sb, dst_name, &dst_sb,
  1106				      x, &return_now, &unlink_src))
  1107		    {
  1108		      error (0, 0, _("%s and %s are the same file"),
  1109			     quote_n (0, src_name), quote_n (1, dst_name));
  1110		      return false;
  1111		    }
...
  1120		  if (x->move_mode)
  1121		    {
  1122		      if (abandon_move (x, dst_name, &dst_sb)
  1123			  || (unlink_src && unlink (src_name) == 0))
  1124			{
  1125			  /* Pretend the rename succeeded, so the caller (mv)
  1126			     doesn't end up removing the source file.  */
  1127			  if (rename_succeeded)
  1128			    *rename_succeeded = true;
  1129			  if (unlink_src && x->verbose)
  1130			    printf (_("removed %s\n"), quote (src_name));
  1131			  return true;
  1132			}
  1133		      if (unlink_src)
  1134			{
  1135			  error (0, errno, _("cannot remove %s"), quote (src_name));
  1136			  return false;
  1137			}
  1138		    }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]