1/* See LICENSE file for copyright and license details. */
2
3#include <sys/stat.h>
4
5#include <errno.h>
6#include <fcntl.h>
7#include <stdio.h>
8
9#include "fs.h"
10#include "util.h"
11
12static int mv_status = 0;
13
14static int
15mv(const char *s1, const char *s2, int depth)
16{
17 struct recursor r = {.fn = rm, .follow = 'P', .flags = SILENT};
18
19 if (!rename(s1, s2))
20 return 0;
21 if (errno == EXDEV) {
22 cp_aflag = cp_rflag = cp_pflag = 1;
23 cp_follow = 'P';
24 cp_status = 0;
25 rm_status = 0;
26 cp(s1, s2, depth);
27 if (cp_status == 0)
28 recurse(AT_FDCWD, s1, NULL, &r);
29 if (cp_status || rm_status)
30 mv_status = 1;
31 } else {
32 weprintf("%s -> %s:", s1, s2);
33 mv_status = 1;
34 }
35
36 return 0;
37}
38
39static void
40usage(void)
41{
42 eprintf("usage: %s [-f] source ... dest\n", argv0);
43}
44
45// ?man mv: move or rename files
46// ?man arguments: source ... dest
47// ?man move or rename files and directories
48int
49main(int argc, char *argv[])
50{
51 struct stat st;
52
53 ARGBEGIN
54 {
55 // ?man -f: do not prompt before overwriting
56 case 'f':
57 break;
58 default:
59 usage();
60 }
61 ARGEND
62
63 if (argc < 2)
64 usage();
65
66 if (argc > 2) {
67 if (stat(argv[argc - 1], &st) < 0)
68 eprintf("stat %s:", argv[argc - 1]);
69 if (!S_ISDIR(st.st_mode))
70 eprintf("%s: not a directory\n", argv[argc - 1]);
71 }
72 enmasse(argc, argv, mv);
73
74 return mv_status;
75}