common: add infrastructure for renameat2 syscall tests
[xfstests-dev.git] / src / renameat2.c
1 /*
2  * Copyright (c) 2014, Miklos Szeredi <mszeredi@suse.cz>
3  * This file is published under GPL2+.
4  *
5  * This is a trivial wrapper around the renameat2 syscall.
6  */
7
8 #include "global.h"
9
10 #ifndef HAVE_RENAMEAT2
11 #include <sys/syscall.h>
12
13 #if !defined(SYS_renameat2) && defined(__x86_64__)
14 #define SYS_renameat2 316
15 #endif
16
17 static int renameat2(int dfd1, const char *path1,
18                      int dfd2, const char *path2,
19                      unsigned int flags)
20 {
21 #ifdef SYS_renameat2
22         return syscall(SYS_renameat2, dfd1, path1, dfd2, path2, flags);
23 #else
24         errno = ENOSYS;
25         return -1;
26 #endif
27 }
28 #endif
29
30 #ifndef RENAME_NOREPLACE
31 #define RENAME_NOREPLACE        (1 << 0)        /* Don't overwrite target */
32 #endif
33 #ifndef RENAME_EXCHANGE
34 #define RENAME_EXCHANGE         (1 << 1)        /* Exchange source and dest */
35 #endif
36 #ifndef RENAME_WHITEOUT
37 #define RENAME_WHITEOUT         (1 << 2)        /* Whiteout source */
38 #endif
39
40 int main(int argc, char *argv[])
41 {
42         int ret;
43         int c;
44         const char *path1 = NULL;
45         const char *path2 = NULL;
46         unsigned int flags = 0;
47         int test = 0;
48
49         for (c = 1; c < argc; c++) {
50                 if (argv[c][0] == '-') {
51                         switch (argv[c][1]) {
52                         case 't':
53                                 test = 1;
54                                 break;
55                         case 'n':
56                                 flags |= RENAME_NOREPLACE;
57                                 break;
58                         case 'x':
59                                 flags |= RENAME_EXCHANGE;
60                                 break;
61                         case 'w':
62                                 flags |= RENAME_WHITEOUT;
63                                 break;
64                         default:
65                                 goto usage;
66                         }
67                 } else if (!path1) {
68                         path1 = argv[c];
69                 } else if (!path2) {
70                         path2 = argv[c];
71                 } else {
72                         goto usage;
73                 }
74         }
75
76         if (!test && (!path1 || !path2))
77                 goto usage;
78
79         ret = renameat2(AT_FDCWD, path1, AT_FDCWD, path2, flags);
80         if (ret == -1) {
81                 if (test) {
82                         if (errno == ENOSYS || errno == EINVAL)
83                                 return 1;
84                         else
85                                 return 0;
86                 }
87                 perror("");
88                 return 1;
89         }
90
91         return 0;
92
93 usage:
94         fprintf(stderr,
95                 "usage: %s [-t] [-n|-x|-w] path1 path2\n"
96                 "  -t  test\n"
97                 "  -n  noreplace\n"
98                 "  -x  exchange\n"
99                 "  -w  whiteout\n", argv[0]);
100
101         return 1;
102 }