master xplshn/aruu / cmd / posix / cp.c
 1/* See LICENSE file for copyright and license details. */
 2
 3#include <sys/stat.h>
 4
 5#include "fs.h"
 6#include "util.h"
 7
 8static void
 9usage(void)
10{
11  eprintf("usage: %s [-afipv] [-R [-H | -L | -P]] source ... dest\n", argv0);
12}
13
14// ?man cp: copy files and directories
15// ?man arguments: source ... dest
16// ?man copy files and directories to a destination
17int
18main(int argc, char *argv[])
19{
20  struct stat st;
21
22  ARGBEGIN
23  {
24    // ?man -i: prompt before overwriting existing files
25    case 'i':
26      cp_iflag = 1;
27      break;
28    // ?man -a: archive mode; equivalent to -dpR
29    case 'a':
30      cp_follow = 'P';
31      cp_aflag = cp_pflag = cp_rflag = 1;
32      break;
33    // ?man -f: force copy by removing existing destination files
34    case 'f':
35      cp_fflag = 1;
36      break;
37    // ?man -p: preserve file attributes
38    case 'p':
39      cp_pflag = 1;
40      break;
41    // ?man -r: copy directories recursively
42    case 'r':
43    // ?man -R: copy directories recursively
44    case 'R':
45      cp_rflag = 1;
46      break;
47    // ?man -v: verbose mode; show progress
48    case 'v':
49      cp_vflag = 1;
50      break;
51    // ?man -H: specify option flag
52    case 'H':
53    // ?man -L: specify option flag
54    case 'L':
55    // ?man -P: specify option flag
56    case 'P':
57      cp_follow = ARGC();
58      break;
59    default:
60      usage();
61  }
62  ARGEND
63
64  if (argc < 2)
65    usage();
66
67  if (!cp_follow)
68    cp_follow = cp_rflag ? 'P' : 'L';
69
70  if (argc > 2) {
71    if (stat(argv[argc - 1], &st) < 0)
72      eprintf("stat %s:", argv[argc - 1]);
73    if (!S_ISDIR(st.st_mode))
74      eprintf("%s: not a directory\n", argv[argc - 1]);
75  }
76  enmasse(argc, argv, cp);
77
78  return fshut(stdout, "<stdout>") || cp_status;
79}