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

📄 cp.c

📁 《linux应用开发技术详解》的配套代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 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 void
cp_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;

  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 void
decode_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);
}

int
main (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.interactive = 0;
	  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 (EXIT_FAILURE, 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 (EXIT_FAILURE);
	}
    }

  if (x.hard_link && x.symbolic_link)
    {
      error (0, 0, _("cannot make both hard and symbolic links"));
      usage (EXIT_FAILURE);
    }

  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.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 + -