master xplshn/aruu / cmd / posix / cp.c
 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}