⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copy.c

📁 Linux下文件工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
	     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 = getdport (dst_path);    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 didn't create the destination.     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.  */  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;}static intvalid_options (const struct cp_options *co){  assert (co != NULL);  assert (VALID_BACKUP_TYPE (co->backup_type));  /* FIXME: for some reason this assertion always fails,     at least on Solaris2.5.1.  Just disable it for now.  */  /* assert (co->xstat == lstat || co->xstat == stat); */  /* Make sure xstat and dereference are consistent.  */  /* FIXME */  assert (VALID_SPARSE_MODE (co->sparse_mode));  return 1;}/* Copy the file SRC_PATH to the file DST_PATH.  The files may be of   any type.  NONEXISTENT_DST should be nonzero if the file DST_PATH   is known not to exist (e.g., because its parent directory was just   created);  NONEXISTENT_DST should be zero if DST_PATH might already   exist.  OPTIONS is ... FIXME-describe   Set *COPY_INTO_SELF to nonzero if SRC_PATH is a parent of (or the   same as) DST_PATH;  otherwise, set it to zero.   Return 0 if successful, 1 if an error occurs. */intcopy (const char *src_path, const char *dst_path,      int nonexistent_dst, const struct cp_options *options,      int *copy_into_self, int *rename_succeeded){  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 want 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, 1, copy_into_self, rename_succeeded);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -