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