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