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

📄 cp.c

📁 Linux下文件工具。
💻 C
📖 第 1 页 / 共 2 页
字号:
      /* If `dest' is not a symlink to a nonexistent file, use	 the results of stat instead of lstat, so we can copy files	 into symlinks to directories. */      if (stat (dest, &sbx) == 0)	sb = sbx;      dest_is_dir = S_ISDIR (sb.st_mode);    }  if (!dest_is_dir)    {      if (target_directory)	{	  error (0, 0, _("%s: specified target is not a directory"),		 quote (dest));	  usage (1);	}      if (n_files > 1)	{	  error (0, 0,	 _("copying multiple files, but last argument %s is not a directory"),	     quote (dest));	  usage (1);	}    }  if (dest_is_dir)    {      /* cp file1...filen edir	 Copy the files `file1' through `filen'	 to the existing directory `edir'. */      int i;      for (i = 0; i < n_files; i++)	{	  char *dst_path;	  int parent_exists = 1; /* True if dir_name (dst_path) exists. */	  struct dir_attr *attr_list;	  char *arg_in_concat = NULL;	  char *arg = file[i];	  /* Trailing slashes are meaningful (i.e., maybe worth preserving)	     only in the source file names.  */	  if (remove_trailing_slashes)	    strip_trailing_slashes (arg);	  if (flag_path)	    {	      char *arg_no_trailing_slash;	      /* Use `arg' without trailing slashes in constructing destination		 file names.  Otherwise, we can end up trying to create a		 directory via `mkdir ("dst/foo/"...', which is not portable.		 It fails, due to the trailing slash, on at least		 NetBSD 1.[34] systems.  */	      ASSIGN_STRDUPA (arg_no_trailing_slash, arg);	      strip_trailing_slashes (arg_no_trailing_slash);	      /* Append all of `arg' (minus any trailing slash) to `dest'.  */	      dst_path = path_concat (dest, arg_no_trailing_slash,				      &arg_in_concat);	      if (dst_path == NULL)		xalloc_die ();	      /* For --parents, we have to make sure that the directory	         dir_name (dst_path) exists.  We may have to create a few	         leading directories. */	      parent_exists = !make_path_private (dst_path,						  arg_in_concat - dst_path,						  S_IRWXU,						  (x->verbose						   ? "%s -> %s\n" : NULL),						  &attr_list, &new_dst,						  x->xstat);	    }  	  else  	    {	      char *arg_base;	      /* Append the last component of `arg' to `dest'.  */	      ASSIGN_BASENAME_STRDUPA (arg_base, arg);	      /* For `cp -R source/.. dest', don't copy into `dest/..'. */	      dst_path = (STREQ (arg_base, "..")			  ? xstrdup (dest)			  : path_concat (dest, arg_base, NULL));	    }	  if (!parent_exists)	    {	      /* make_path_private failed, so don't even attempt the copy. */	      ret = 1;  	    }	  else	    {	      int copy_into_self;	      ret |= copy (arg, dst_path, new_dst, x, &copy_into_self, NULL);	      if (flag_path)		{		  ret |= re_protect (dst_path, arg_in_concat - dst_path,				     attr_list, x);		}	    }	  free (dst_path);	}      return ret;    }  else /* if (n_files == 1) */    {      char *new_dest;      char *source;      int unused;      struct stat source_stats;      if (flag_path)	{	  error (0, 0,	       _("when preserving paths, the destination must be a directory"));	  usage (1);	}      source = file[0];      /* When the force and backup options have been specified and	 the source and destination are the same name for an existing	 regular file, convert the user's command, e.g.,	 `cp --force --backup foo foo' to `cp --force foo fooSUFFIX'	 where SUFFIX is determined by any version control options used.  */      if (x->unlink_dest_after_failed_open	  && x->backup_type != none	  && STREQ (source, dest)	  && !new_dst && S_ISREG (sb.st_mode))	{	  static struct cp_options x_tmp;	  new_dest = find_backup_file_name (dest, x->backup_type);	  /* Set x->backup_type to `none' so that the normal backup	     mechanism is not used when performing the actual copy.	     backup_type must be set to `none' only *after* the above	     call to find_backup_file_name -- that function uses	     backup_type to determine the suffix it applies.  */	  x_tmp = *x;	  x_tmp.backup_type = none;	  x = &x_tmp;	  if (new_dest == NULL)	    xalloc_die ();	}      /* When the destination is specified with a trailing slash and the	 source exists but is not a directory, convert the user's command	 `cp source dest/' to `cp source dest/basename(source)'.  Doing	 this ensures that the command `cp non-directory file/' will now	 fail rather than performing the copy.  COPY diagnoses the case of	 `cp directory non-directory'.  */      else if (dest[strlen (dest) - 1] == '/'	  && lstat (source, &source_stats) == 0	  && !S_ISDIR (source_stats.st_mode))	{	  char *source_base;	  ASSIGN_BASENAME_STRDUPA (source_base, source);	  new_dest = (char *) alloca (strlen (dest)				      + strlen (source_base) + 1);	  stpcpy (stpcpy (new_dest, dest), source_base);	}      else	{	  new_dest = (char *) dest;	}      return copy (source, new_dest, new_dst, x, &unused, NULL);    }  /* unreachable */}static voidcp_option_init (struct cp_options *x){  x->copy_as_regular = 1;  x->dereference = DEREF_UNDEFINED;  x->unlink_dest_before_opening = 0;  x->unlink_dest_after_failed_open = 0;  x->hard_link = 0;  x->interactive = I_UNSPECIFIED;  x->myeuid = geteuid ();  x->move_mode = 0;  x->one_file_system = 0;  x->preserve_ownership = 0;  x->preserve_links = 0;  x->preserve_mode = 0;  x->preserve_timestamps = 0;  x->require_preserve = 0;  x->recursive = 0;  x->sparse_mode = SPARSE_AUTO;  x->symbolic_link = 0;  x->set_mode = 0;  x->mode = 0;  /* Not used.  */  x->stdin_tty = 0;  /* Find out the current file creation mask, to knock the right bits     when using chmod.  The creation mask is set to be liberal, so     that created directories can be written, even if it would not     have been allowed with the mask this process was started with.  */  x->umask_kill = ~ umask (0);  x->update = 0;  x->verbose = 0;  x->dest_info = NULL;  x->src_info = NULL;}/* Given a string, ARG, containing a comma-separated list of arguments   to the --preserve option, set the appropriate fields of X to ON_OFF.  */static voiddecode_preserve_arg (char const *arg, struct cp_options *x, int on_off){  enum File_attribute    {      PRESERVE_MODE,      PRESERVE_TIMESTAMPS,      PRESERVE_OWNERSHIP,      PRESERVE_LINK,      PRESERVE_ALL    };  static enum File_attribute const preserve_vals[] =    {      PRESERVE_MODE, PRESERVE_TIMESTAMPS,      PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL    };  /* Valid arguments to the `--reply' option. */  static char const* const preserve_args[] =    {      "mode", "timestamps",      "ownership", "links", "all", 0    };  char *arg_writable = xstrdup (arg);  char *s = arg_writable;  do    {      /* find next comma */      char *comma = strchr (s, ',');      enum File_attribute val;      /* put a NUL in its place */      if (comma)	*comma = 0;      /* process S.  */      val = XARGMATCH ("--preserve", s, preserve_args, preserve_vals);      switch (val)	{	case PRESERVE_MODE:	  x->preserve_mode = on_off;	  break;	case PRESERVE_TIMESTAMPS:	  x->preserve_timestamps = on_off;	  break;	case PRESERVE_OWNERSHIP:	  x->preserve_ownership = on_off;	  break;	case PRESERVE_LINK:	  x->preserve_links = on_off;	  break;	case PRESERVE_ALL:	  x->preserve_mode = on_off;	  x->preserve_timestamps = on_off;	  x->preserve_ownership = on_off;	  x->preserve_links = on_off;	  break;	default:	  abort ();	}      s = comma;    }  while (s);  free (arg_writable);}intmain (int argc, char **argv){  int c;  int make_backups = 0;  char *backup_suffix_string;  char *version_control_string = NULL;  struct cp_options x;  int copy_contents = 0;  char *target_directory = NULL;  program_name = argv[0];  setlocale (LC_ALL, "");  bindtextdomain (PACKAGE, LOCALEDIR);  textdomain (PACKAGE);  atexit (close_stdout);  cp_option_init (&x);  /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless     we'll actually use backup_suffix_string.  */  backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");  while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL))	 != -1)    {      switch (c)	{	case 0:	  break;	case SPARSE_OPTION:	  x.sparse_mode = XARGMATCH ("--sparse", optarg,				     sparse_type_string, sparse_type);	  break;	case 'a':		/* Like -dpPR. */	  x.dereference = DEREF_NEVER;	  x.preserve_links = 1;	  x.preserve_ownership = 1;	  x.preserve_mode = 1;	  x.preserve_timestamps = 1;	  x.require_preserve = 1;	  x.recursive = 1;	  break;	case 'V':  /* FIXME: this is deprecated.  Remove it in 2001.  */	  error (0, 0,		 _("warning: --version-control (-V) is obsolete;  support for\ it\nwill be removed in some future release.  Use --backup=%s instead."		   ), optarg);	  /* Fall through.  */	case 'b':	  make_backups = 1;	  if (optarg)	    version_control_string = optarg;	  break;	case COPY_CONTENTS_OPTION:	  copy_contents = 1;	  break;	case 'd':	  x.preserve_links = 1;	  x.dereference = DEREF_NEVER;	  break;	case 'f':	  x.unlink_dest_after_failed_open = 1;	  break;	case 'H':	  x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;	  break;	case 'i':	  x.interactive = I_ASK_USER;	  break;	case 'l':	  x.hard_link = 1;	  break;	case 'L':	  x.dereference = DEREF_ALWAYS;	  break;	case 'P':	  x.dereference = DEREF_NEVER;	  break;	case NO_PRESERVE_ATTRIBUTES_OPTION:	  decode_preserve_arg (optarg, &x, 0);	  break;	case PRESERVE_ATTRIBUTES_OPTION:	  if (optarg == NULL)	    {	      /* Fall through to the case for `p' below.  */	    }	  else	    {	      decode_preserve_arg (optarg, &x, 1);	      x.require_preserve = 1;	      break;	    }	case 'p':	  x.preserve_ownership = 1;	  x.preserve_mode = 1;	  x.preserve_timestamps = 1;	  x.require_preserve = 1;	  break;	case PARENTS_OPTION:	  flag_path = 1;	  break;	case 'r':	case 'R':	  x.recursive = 1;	  break;	case REPLY_OPTION:	  x.interactive = XARGMATCH ("--reply", optarg,				     reply_args, reply_vals);	  break;	case UNLINK_DEST_BEFORE_OPENING:	  x.unlink_dest_before_opening = 1;	  break;	case STRIP_TRAILING_SLASHES_OPTION:	  remove_trailing_slashes = 1;	  break;	case 's':#ifdef S_ISLNK	  x.symbolic_link = 1;#else	  error (1, 0, _("symbolic links are not supported on this system"));#endif	  break;	case TARGET_DIRECTORY_OPTION:	  target_directory = optarg;	  break;	case 'u':	  x.update = 1;	  break;	case 'v':	  x.verbose = 1;	  break;	case 'x':	  x.one_file_system = 1;	  break;	case 'S':	  make_backups = 1;	  backup_suffix_string = optarg;	  break;	case_GETOPT_HELP_CHAR;	case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);	default:	  usage (1);	}    }  if (x.hard_link && x.symbolic_link)    {      error (0, 0, _("cannot make both hard and symbolic links"));      usage (1);    }  if (backup_suffix_string)    simple_backup_suffix = xstrdup (backup_suffix_string);  x.backup_type = (make_backups		   ? xget_version (_("backup type"),				   version_control_string)		   : none);  if (x.preserve_mode == 1)    x.umask_kill = ~ (mode_t) 0;  if (x.dereference == DEREF_UNDEFINED)    {      if (x.recursive)	/* This is compatible with FreeBSD.  */	x.dereference = DEREF_NEVER;      else	x.dereference = DEREF_ALWAYS;    }  /* The key difference between -d (--no-dereference) and not is the version     of `stat' to call.  */  if (x.dereference == DEREF_NEVER)    x.xstat = lstat;  else    {      /* For DEREF_COMMAND_LINE_ARGUMENTS, x.xstat must be stat for	 each command line argument, but must later be `lstat' for	 any symlinks that are found via recursive traversal.  */      x.xstat = stat;    }  if (x.recursive)    x.copy_as_regular = copy_contents;  /* If --force (-f) was specified and we're in link-creation mode,     first remove any existing destination file.  */  if (x.unlink_dest_after_failed_open && (x.hard_link || x.symbolic_link))    x.unlink_dest_before_opening = 1;  /* Allocate space for remembering copied and created files.  */  hash_init ();  exit_status |= do_copy (argc - optind, argv + optind, target_directory, &x);  forget_all ();  exit (exit_status);}

⌨️ 快捷键说明

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