rem: return 1; }  dst_backup = (char *) alloca (strlen (tmp_backup) + 1); strcpy (dst_backup, tmp_backup);
add: return false; }   ASSIGN_STRDUPA (dst_backup, tmp_backup);
context: copy_internal (const char *src_path, const char *dst_path,	       int new_dst,	       dev_t device,	       struct dir_list *ancestors,	       const struct cp_options *x,	       int command_line_arg,	       int *copy_into_self,	       int *rename_succeeded){  struct stat src_sb;  struct stat dst_sb;  mode_t src_mode;  mode_t src_type;  char *earlier_file = NULL;  char *dst_backup = NULL;  int backup_succeeded = 0;  int delayed_fail;  int copied_as_regular = 0;  int ran_chown = 0;  int preserve_metadata;  if (x->move_mode && rename_succeeded)    *rename_succeeded = 0;  *copy_into_self = 0;  if ((*(x->xstat)) (src_path, &src_sb))    {      error (0, errno, _("cannot stat %s"), quote (src_path));      return 1;    }  src_type = src_sb.st_mode;  src_mode = src_sb.st_mode;  if (S_ISDIR (src_type) && !x->recursive)    {      error (0, 0, _("omitting directory %s"), quote (src_path));      return 1;    }  /* Detect the case in which the same source file appears more than     once on the command line and no backup option has been selected.     If so, simply warn and don't copy it the second time.     This check is enabled only if x->src_info is non-NULL.  */  if (command_line_arg)    {      if ( ! S_ISDIR (src_sb.st_mode)	   && x->backup_type == none	   && seen_file (x->src_info, src_path, &src_sb))	{	  error (0, 0, _("warning: source file %s specified more than once"),		 quote (src_path));	  return 0;	}      record_file (x->src_info, src_path, &src_sb);    }  if (!new_dst)    {      if ((*(x->xstat)) (dst_path, &dst_sb))	{	  if (errno != ENOENT)	    {	      error (0, errno, _("cannot stat %s"), quote (dst_path));	      return 1;	    }	  else	    {	      new_dst = 1;	    }	}      else	{	  int return_now;	  int ok = same_file_ok (src_path, &src_sb, dst_path, &dst_sb,				 x, &return_now);	  if (return_now)	    return 0;	  if (! ok)	    {	      error (0, 0, _("%s and %s are the same file"),		     quote_n (0, src_path), quote_n (1, dst_path));	      return 1;	    }	  if (!S_ISDIR (dst_sb.st_mode))	    {	      if (S_ISDIR (src_type))		{		  error (0, 0,		     _("cannot overwrite non-directory %s with directory %s"),			 quote_n (0, dst_path), quote_n (1, src_path));		  return 1;		}	      /* Don't let the user destroy their data, even if they try hard:		 This mv command must fail (likewise for cp):		   rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c		 Otherwise, the contents of b/f would be lost.		 In the case of `cp', b/f would be lost if the user simulated		 a move using cp and rm.		 Note that it works fine if you use --backup=numbered.  */	      if (command_line_arg		  && x->backup_type != numbered		  && seen_file (x->dest_info, dst_path, &dst_sb))		{		  error (0, 0,			 _("will not overwrite just-created %s with %s"),			 quote_n (0, dst_path), quote_n (1, src_path));		  return 1;		}	    }	  if (!S_ISDIR (src_type))	    {	      if (S_ISDIR (dst_sb.st_mode))		{		  error (0, 0,		       _("cannot overwrite directory %s with non-directory"),			 quote (dst_path));		  return 1;		}	      if (x->update && MTIME_CMP (src_sb, dst_sb) <= 0)		{		  /* We're using --update and the source file is older		     than the destination file, so there is no need to		     copy or move.  */		  /* Pretend the rename succeeded, so the caller (mv)		     doesn't end up removing the source file.  */		  if (rename_succeeded)		    *rename_succeeded = 1;		  return 0;		}	    }	  /* When there is an existing destination file, we may end up	     returning early, and hence not copying/moving the file.	     This may be due to an interactive `negative' reply to the	     prompt about the existing file.  It may also be due to the	     use of the --reply=no option.  */	  if (!S_ISDIR (src_type))	    {	      /* cp and mv treat -i and -f differently.  */	      if (x->move_mode)		{		  if ((x->interactive == I_ALWAYS_NO		       && UNWRITABLE (dst_path, dst_sb.st_mode))		      || ((x->interactive == I_ASK_USER			   || (x->interactive == I_UNSPECIFIED			       && x->stdin_tty			       && UNWRITABLE (dst_path, dst_sb.st_mode)))			  && (overwrite_prompt (dst_path, &dst_sb), 1)			  && ! yesno ()))		    {		      /* Pretend the rename succeeded, so the caller (mv)			 doesn't end up removing the source file.  */		      if (rename_succeeded)			*rename_succeeded = 1;		      return 0;		    }		}	      else		{		  if (x->interactive == I_ALWAYS_NO		      || (x->interactive == I_ASK_USER			  && (overwrite_prompt (dst_path, &dst_sb), 1)			  && ! yesno ()))		    {		      return 0;		    }		}	    }	  if (x->move_mode)	    {	      /* In move_mode, DEST may not be an existing directory.  */	      if (S_ISDIR (dst_sb.st_mode))		{		  error (0, 0, _("cannot overwrite directory %s"),			 quote (dst_path));		  return 1;		}	      /* Don't allow user to move a directory onto a non-directory.  */	      if (S_ISDIR (src_sb.st_mode) && !S_ISDIR (dst_sb.st_mode))		{		  error (0, 0,		       _("cannot move directory onto non-directory: %s -> %s"),			 quote_n (0, src_path), quote_n (0, dst_path));		  return 1;		}	    }	  if (x->backup_type != none && !S_ISDIR (dst_sb.st_mode))	    {	      char *tmp_backup = find_backup_file_name (dst_path,							x->backup_type);	      if (tmp_backup == NULL)		xalloc_die ();	      /* Detect (and fail) when creating the backup file would		 destroy the source file.  Before, running the commands		 cd /tmp; rm -f a a~; : > a; echo A > a~; cp --b=simple a~ a		 would leave two zero-length files: a and a~.  */	      /* FIXME: but simply change e.g., the final a~ to `./a~'		 and the source will still be destroyed.  */	      if (STREQ (tmp_backup, src_path))		{		  const char *fmt;		  fmt = (x->move_mode		 ? _("backing up %s would destroy source;  %s not moved")		 : _("backing up %s would destroy source;  %s not copied"));		  error (0, 0, fmt,			 quote_n (0, dst_path),			 quote_n (1, src_path));		  free (tmp_backup);		  return 1;		}	      dst_backup = (char *) alloca (strlen (tmp_backup) + 1);	      strcpy (dst_backup, tmp_backup);	      free (tmp_backup);	      if (rename (dst_path, dst_backup))		{		  if (errno != ENOENT)		    {		      error (0, errno, _("cannot backup %s"), quote (dst_path));		      return 1;		    }		  else		    {		      dst_backup = NULL;		    }		}	      else		{		  backup_succeeded = 1;		}	      new_dst = 1;	    }	  else if (! S_ISDIR (dst_sb.st_mode)		   && (x->unlink_dest_before_opening		       || (x->xstat == lstat			   && ! S_ISREG (src_sb.st_mode))))	    {	      if (unlink (dst_path) && errno != ENOENT)		{		  error (0, errno, _("cannot remove %s"), quote (dst_path));		  return 1;		}	      new_dst = 1;	    }	}    }  /* If the source is a directory, we don't always create the destination     directory.  So --verbose should not announce anything until we're     sure we'll create a directory. */  if (x->verbose && !S_ISDIR (src_type))    {      printf ("%s -> %s", quote_n (0, src_path), quote_n (1, dst_path));      if (backup_succeeded)	printf (_(" (backup: %s)"), quote (dst_backup));      putchar ('\n');    }  /* Associate the destination path with the source device and inode     so that if we encounter a matching dev/ino pair in the source tree     we can arrange to create a hard link between the corresponding names     in the destination tree.     Sometimes, when preserving links, we have to record dev/ino even     though st_nlink == 1:     - when using -H and processing a command line argument;	that command line argument could be a symlink pointing to another	command line argument.  With `cp -H --preserve=link', we hard-link	those two destination files.     - likewise for -L except that it applies to all files, not just	command line arguments.     Also record directory dev/ino when using --recursive.  We'll use that     info to detect this problem: cp -R dir dir.  FIXME-maybe: ideally,     directory info would be recorded in a separate hash table, since     such entries are useful only while a single command line hierarchy     is being copied -- so that separate table could be cleared between     command line args.  Using the same hash table to preserve hard     links means that it may not be cleared.  */  if ((x->preserve_links       && (1 < src_sb.st_nlink	   || (command_line_arg	       && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)	   || x->dereference == DEREF_ALWAYS))      || (x->recursive && S_ISDIR (src_type)))    {      earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);    }  /* Did we copy this inode somewhere else (in this command line argument)     and therefore this is a second hard link to the inode?  */  if (earlier_file)    {      /* Avoid damaging the destination filesystem by refusing to preserve	 hard-linked directories (which are found at least in Netapp snapshot	 directories).  */      if (S_ISDIR (src_type))	{	  /* If src_path and earlier_file refer to the same directory entry,	     then warn about copying a directory into itself.  */	  if (same_name (src_path, earlier_file))	    {	      error (0, 0, _("cannot copy a directory, %s, into itself, %s"),		     quote_n (0, top_level_src_path),		     quote_n (1, top_level_dst_path));	      *copy_into_self = 1;	    }	  else	    {	      error (0, 0, _("will not create hard link %s to directory %s"),		     quote_n (0, dst_path), quote_n (1, earlier_file));	    }	  goto un_backup;	}      {	int link_failed;	link_failed = link (earlier_file, dst_path);	/* If the link failed because of an existing destination,	   remove that file and then call link again.  */	if (link_failed && errno == EEXIST)	  {	    if (unlink (dst_path))	      {		error (0, errno, _("cannot remove %s"), quote (dst_path));		goto un_backup;	      }	    link_failed = link (earlier_file, dst_path);	  }	if (link_failed)	  {	    error (0, errno, _("cannot create hard link %s to %s"),		   quote_n (0, dst_path), quote_n (1, earlier_file));	    goto un_backup;	  }	else	  {	    if (x->ignore_attributes == 0	    	&& copy_attributes_by_name(earlier_file, dst_path, false) != 0)		fprintf(stderr, "%s: could not copy attributes\n", earlier_file);	  }	return 0;      }    }  if (x->move_mode)    {      if (rename (src_path, dst_path) == 0)	{	  if (x->verbose && S_ISDIR (src_type))	    printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));	  if (rename_succeeded)	    *rename_succeeded = 1;	  if (command_line_arg)	    {	      /* Record destination dev/ino/filename, so that if we are asked		 to overwrite that file again, we can detect it and fail.  */	      /* It's fine to use the _source_ stat buffer (src_sb) to get the	         _destination_ dev/ino, since the rename above can't have		 changed those, and `mv' always uses lstat.		 We could limit it further by operating		 only on non-directories.  */	      record_file (x->dest_info, dst_path, &src_sb);	    }	  return 0;	}      /* FIXME: someday, consider what to do when moving a directory into	 itself but when source and destination are on different devices.  */      /* This happens when attempting to rename a directory to a	 subdirectory of itself.  */      if (errno == EINVAL	  /* When src_path is on an NFS file system, some types of	     clients, e.g., SunOS4.1.4 and IRIX-5.3, set errno to EIO	     instead.  Testing for this here risks misinterpreting a real	     I/O error as an attempt to move a directory into itself, so	     FIXME: consider not doing this.  */	  || errno == EIO	  /* And with SunOS-4.1.4 client and OpenBSD-2.3 server,	     we get ENOTEMPTY.  */	  || errno == ENOTEMPTY)	{	  /* FIXME: this is a little fragile in that it relies on rename(2)	     failing with a specific errno value.  Expect problems on	     non-POSIX systems.  */	  error (0, 0, _("cannot move %s to a subdirectory of itself, %s"),		 quote_n (0, top_level_src_path),		 quote_n (1, top_level_dst_path));	  /* Note that there is no need to call forget_created here,	     (compare with the other calls in this file) since the	     destination directory didn't exist before.  */	  *copy_into_self = 1;	  /* FIXME-cleanup: Don't return zero here; adjust mv.c accordingly.	     The only caller that uses this code (mv.c) ends up setting its	     exit status to nonzero when copy_into_self is nonzero.  */	  return 0;	}      /* WARNING: there probably exist systems for which an inter-device	 rename fails with a value of errno not handled here.	 If/as those are reported, add them to the condition below.	 If this happens to you, please do the following and send the output	 to the bug-reporting address (e.g., in the output of cp --help):	   touch k; perl -e 'rename "k","/tmp/k" or print "$!(",$!+0,")\n"'	 where your current directory is on one partion and /tmp is the other.	 Also, please try to find the E* errno macro name corresponding to	 the diagnostic and parenthesized integer, and include that in your	 e-mail.  One way to do that is to run a command like this	   find /usr/include/. -type f \	     | xargs grep 'define.*\<E[A-Z]*\>.*\<18\>' /dev/null	 where you'd replace `18' with the integer in parentheses that	 was output from the perl one-liner above.	 If necessary, of course, change `/tmp' to some other directory.  */      if (errno != EXDEV)	{	  /* There are many ways this can happen due to a race condition.	     When something happens between the initial xstat and the	     subsequent rename, we can get many different types of errors.	     For example, if the destination is initially a non-directory	     or non-existent, but it is created as a directory, the rename	     fails.  If two `mv' commands try to rename the same file at	     about the same time, one will succeed and the other will fail.	     If the permissions on the directory containing the source or	     destination file are made too restrictive, the rename will	     fail.  Etc.  */	  error (0, errno,		 _("cannot move %s to %s"),		 quote_n (0, src_path), quote_n (1, dst_path));	  forget_created (src_sb.st_ino, src_sb.st_dev);	  return 1;	}      /* The rename attempt has failed.  Remove any existing destination	 file so that a cross-device `mv' acts as if it were really using	 the rename syscall.  */      if (unlink (dst_path) && errno != ENOENT)	{	  error (0, errno,	     _("inter-device move failed: %s to %s; unable to remove target"),		 quote_n (0, src_path), quote_n (1, dst_path));	  forget_created (src_sb.st_ino, src_sb.st_dev);	  return 1;	}      new_dst = 1;    }  delayed_fail = 0;  /* In certain modes (cp's --symbolic-link), and for certain file types     (symlinks and hard links) it doesn't make sense to preserve metadata,     or it's possible to preserve only some of it.     In such cases, set this variable to zero.  */  preserve_metadata = 1;  if (S_ISDIR (src_type))    {      struct dir_list *dir;      /* If this directory has been copied before during the         recursion, there is a symbolic link to an ancestor         directory of the symbolic link.  It is impossible to         continue to copy this, unless we've got an infinite disk.  */      if (is_ancestor (&src_sb, ancestors))	{	  error (0, 0, _("cannot copy cyclic symbolic link %s"),		 quote (src_path));	  goto un_backup;	}      /* Insert the current directory in the list of parents.  */      dir = (struct dir_list *) alloca (sizeof (struct dir_list));      dir->parent = ancestors;      dir->ino = src_sb.st_ino;      dir->dev = src_sb.st_dev;      if (new_dst || !S_ISDIR (dst_sb.st_mode))	{	  /* Create the new directory writable and searchable, so             we can create new entries in it.  */	  if (mkdir (dst_path, (src_mode & x->umask_kill) | S_IRWXU))	    {	      error (0, errno, _("cannot create directory %s"),		     quote (dst_path));	      goto un_backup;	    }	  /* Insert the created directory's inode and device             numbers into the search structure, so that we can             avoid copying it again.  */	  if (remember_created (dst_path))	    goto un_backup;	  if (x->verbose)	    printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));	}      /* Are we crossing a file system boundary?  */      if (x->one_file_system && device != 0 && device != src_sb.st_dev)	return 0;      /* Copy the contents of the directory.  */      if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir, x,		    copy_into_self))	{	  /* Don't just return here -- otherwise, the failure to read a	     single file in a source directory would cause the containing	     destination directory not to have owner/perms set properly.  */	  delayed_fail = 1;	}    }#ifdef S_ISLNK  else if (x->symbolic_link)    {      preserve_metadata = 0;      if (*src_path != '/')	{	  /* Check that DST_PATH denotes a file in the current directory.  */	  struct stat dot_sb;	  struct stat dst_parent_sb;	  char *dst_parent;	  int in_current_dir;	  dst_parent = dir_name (dst_path);	  in_current_dir = (STREQ (".", dst_parent)			    /* If either stat call fails, it's ok not to report			       the failure and say dst_path is in the current			       directory.  Other things will fail later.  */			    || stat (".", &dot_sb)			    || stat (dst_parent, &dst_parent_sb)			    || SAME_INODE (dot_sb, dst_parent_sb));	  free (dst_parent);	  if (! in_current_dir)	    {	      error (0, 0,	   _("%s: can make relative symbolic links only in current directory"),		     quote (dst_path));	      goto un_backup;	    }	}      if (symlink (src_path, dst_path))	{	  error (0, errno, _("cannot create symbolic link %s to %s"),		 quote_n (0, dst_path), quote_n (1, src_path));	  goto un_backup;	}    }#endif  else if (x->hard_link)    {      preserve_metadata = 0;      if (link (src_path, dst_path))	{	  error (0, errno, _("cannot create link %s"), quote (dst_path));	  goto un_backup;	}    }  else if (S_ISREG (src_type)	   || (x->copy_as_regular && !S_ISDIR (src_type)#ifdef S_ISLNK	       && !S_ISLNK (src_type)#endif	       ))    {      copied_as_regular = 1;      /* POSIX says the permission bits of the source file must be	 used as the 3rd argument in the open call, but that's not consistent	 with historical practice.  */      if (copy_reg (src_path, dst_path, x,		    get_dest_mode (x, src_mode), &new_dst, &src_sb))	goto un_backup;    }  else#ifdef S_ISFIFO  if (S_ISFIFO (src_type))    {      if (mkfifo (dst_path, get_dest_mode (x, src_mode)))	{	  error (0, errno, _("cannot create fifo %s"), quote (dst_path));	  goto un_backup;	}    }  else#endif    if (S_ISBLK (src_type) || S_ISCHR (src_type)#ifdef S_ISSOCK	|| S_ISSOCK (src_type)#endif	)    {      if (mknod (dst_path, get_dest_mode (x, src_mode), src_sb.st_rdev))	{	  error (0, errno, _("cannot create special file %s"),		 quote (dst_path));	  goto un_backup;	}    }  else#ifdef S_ISLNK  if (S_ISLNK (src_type))    {      char *src_link_val = xreadlink (src_path);      if (src_link_val == NULL)	{	  error (0, errno, _("cannot read symbolic link %s"), quote (src_path));	  goto un_backup;	}      if (!symlink (src_link_val, dst_path))	free (src_link_val);      else	{	  int saved_errno = errno;	  int same_link = 0;	  if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode))	    {	      /* See if the destination is already the desired symlink.  */	      size_t src_link_len = strlen (src_link_val);	      char *dest_link_val = (char *) alloca (src_link_len + 1);	      int dest_link_len = readlink (dst_path, dest_link_val,					    src_link_len + 1);	      if ((size_t) dest_link_len == src_link_len		  && strncmp (dest_link_val, src_link_val, src_link_len) == 0)		same_link = 1;	    }	  free (src_link_val);	  if (! same_link)	    {	      error (0, saved_errno, _("cannot create symbolic link %s"),		     quote (dst_path));	      goto un_backup;	    }	}      /* There's no need to preserve timestamps or permissions.  */      preserve_metadata = 0;      if (x->preserve_ownership)	{	  /* Preserve the owner and group of the just-`copied'	     symbolic link, if possible.  */# if HAVE_LCHOWN	  if (DO_CHOWN (lchown, dst_path, src_sb.st_uid, src_sb.st_gid))	    {	      error (0, errno, _("failed to preserve ownership for %s"),		     dst_path);	      goto un_backup;	    }# else	  /* Can't preserve ownership of symlinks.	     FIXME: maybe give a warning or even error for symlinks	     in directories with the sticky bit set -- there, not	     preserving owner/group is a potential security problem.  */# endif	}    }  else#endif    {      error (0, 0, _("%s has unknown file type"), quote (src_path));      goto un_backup;    }  if (command_line_arg)    record_file (x->dest_info, dst_path, NULL);  if ( ! preserve_metadata)    return 0;  /* POSIX says that `cp -p' must restore the following:     - permission bits     - setuid, setgid bits     - owner and group     If it fails to restore any of those, we may give a warning but     the destination must not be removed.     FIXME: implement the above. */  /* Adjust the times (and if possible, ownership) for the copy.     chown turns off set[ug]id bits for non-root,     so do the chmod last.  */  if (x->preserve_timestamps)    {      struct utimbuf utb;      /* There's currently no interface to set file timestamps with	 better than 1-second resolution, so discard any fractional	 part of the source timestamp.  */      utb.actime = src_sb.st_atime;      utb.modtime = src_sb.st_mtime;      if (utime (dst_path, &utb))	{	  error (0, errno, _("preserving times for %s"), quote (dst_path));	  if (x->require_preserve)	    return 1;	}    }  /* Avoid calling chown if we know it's not necessary.  */  if (x->preserve_ownership      && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))    {      ran_chown = 1;      if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid))	{	  error (0, errno, _("failed to preserve ownership for %s"),		 quote (dst_path));	  if (x->require_preserve)	    return 1;	}    }#if HAVE_STRUCT_STAT_ST_AUTHOR  /* Preserve the st_author field.  */  {    file_t file = file_name_lookup (dst_path, 0, 0);    if (file_chauthor (file, src_sb.st_author))      error (0, errno, _("failed to preserve authorship for %s"),	     quote (dst_path));    mach_port_deallocate (mach_task_self (), file);  }#endif  /* Permissions of newly-created regular files were set upon `open' in     copy_reg.  But don't return early if there were any special bits and     we had to run chown, because the chown must have reset those bits.  */  if ((new_dst && copied_as_regular)      && !(ran_chown && (src_mode & ~S_IRWXUGO)))    return delayed_fail;  if ((x->preserve_mode || new_dst)      && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type)))    {      if (chmod (dst_path, get_dest_mode (x, src_mode)))	{	  error (0, errno, _("setting permissions for %s"), quote (dst_path));	  if (x->set_mode || x->require_preserve)	    return 1;	}    }  return delayed_fail;un_backup:  /* We have failed to create the destination file.     If we've just added a dev/ino entry via the remember_copied     call above (i.e., unless we've just failed to create a hard link),     remove the entry associating the source dev/ino with the     destination file name, so we don't try to `preserve' a link     to a file we didn't create.  */  if (earlier_file == NULL)    forget_created (src_sb.st_ino, src_sb.st_dev);  if (dst_backup)    {      if (rename (dst_backup, dst_path))	error (0, errno, _("cannot un-backup %s"), quote (dst_path));      else	{	  if (x->verbose)	    printf (_("%s -> %s (unbackup)\n"),		    quote_n (0, dst_backup), quote_n (1, dst_path));	}    }  return 1;}