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}