1/* See LICENSE file for copyright and license details. */
2
3
4#include <sys/stat.h>
5
6#include "fs.h"
7#include "util.h"
8
9static void
10usage(void)
11{
12 eprintf("usage: %s [-afipv] [-R [-H | -L | -P]] source ... dest\n", argv0);
13}
14
15// ?man cp: copy files and directories
16// ?man arguments: source ... dest
17// ?man copy files and directories to a destination
18int
19main(int argc, char *argv[])
20{
21 struct stat st;
22
23 ARGBEGIN {
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 } ARGEND
62
63 if (argc < 2)
64 usage();
65
66 if (!cp_follow)
67 cp_follow = cp_rflag ? 'P' : 'L';
68
69 if (argc > 2) {
70 if (stat(argv[argc - 1], &st) < 0)
71 eprintf("stat %s:", argv[argc - 1]);
72 if (!S_ISDIR(st.st_mode))
73 eprintf("%s: not a directory\n", argv[argc - 1]);
74 }
75 enmasse(argc, argv, cp);
76
77 return fshut(stdout, "<stdout>") || cp_status;
78}