]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/exch.c
Merge branch 'sed' of https://github.com/t-8ch/util-linux
[thirdparty/util-linux.git] / misc-utils / exch.c
CommitLineData
cd094a05 1/*
8380ce72 2 * SPDX-License-Identifier: GPL-2.0-or-later
cd094a05
MY
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
8380ce72
KZ
9 * Copyright (C) 2023 Red Hat, Inc. All rights reserved.
10 * Written by Masatake YAMATO <yamato@redhat.com>
cd094a05 11 *
8380ce72 12 * exch(1) - a command line interface for RENAME_EXCHANGE of renameat2(2).
cd094a05 13 */
cd094a05
MY
14#include "c.h"
15#include "nls.h"
16
17#include <fcntl.h>
18#include <getopt.h>
19
20#ifndef HAVE_RENAMEAT2
8380ce72
KZ
21# include <sys/syscall.h>
22# include <unistd.h>
23#endif
cd094a05
MY
24
25#ifndef RENAME_EXCHANGE
8380ce72 26# define RENAME_EXCHANGE (1 << 1)
cd094a05
MY
27#endif
28
8a7c8803 29#if !defined(HAVE_RENAMEAT2) && defined(SYS_renameat2)
cd094a05
MY
30static inline int renameat2(int olddirfd, const char *oldpath,
31 int newdirfd, const char *newpath, unsigned int flags)
32{
33 return syscall (SYS_renameat2, olddirfd, oldpath, newdirfd, newpath, flags);
34}
cd094a05
MY
35#endif
36
37static void __attribute__((__noreturn__)) usage(void)
38{
39 FILE *out = stdout;
40
41 fputs(USAGE_HEADER, out);
42 fprintf(out, _(" %s [options] oldpath newpath\n"), program_invocation_short_name);
8380ce72
KZ
43 fputs(USAGE_SEPARATOR, out);
44 fputs(_("Atomically exchanges paths between two files.\n"), out);
cd094a05
MY
45
46 fputs(USAGE_OPTIONS, out);
47 fprintf(out, USAGE_HELP_OPTIONS(30));
48
49 fprintf(out, USAGE_MAN_TAIL("exch(1)"));
50
51 exit(EXIT_SUCCESS);
52}
53
54int main(int argc, char **argv)
55{
56 int c;
57 int rc;
58
59 static const struct option longopts[] = {
60 { "version", no_argument, NULL, 'V' },
61 { "help", no_argument, NULL, 'h' },
75f4d809 62 { NULL }
cd094a05
MY
63 };
64
65 setlocale(LC_ALL, "");
66 bindtextdomain(PACKAGE, LOCALEDIR);
67 textdomain(PACKAGE);
68
69 while ((c = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) {
70 switch (c) {
71 case 'V':
72 print_version(EXIT_SUCCESS);
73 case 'h':
74 usage();
75 default:
76 errtryhelp(EXIT_FAILURE);
77 }
78 }
79
80 if (argc - optind < 2) {
81 warnx(_("too few arguments"));
82 errtryhelp(EXIT_FAILURE);
83 } else if (argc - optind > 2) {
84 warnx(_("too many arguments"));
85 errtryhelp(EXIT_FAILURE);
86 }
87
88 rc = renameat2(AT_FDCWD, argv[optind],
89 AT_FDCWD, argv[optind + 1], RENAME_EXCHANGE);
90 if (rc)
91 warn(_("failed to exchange \"%s\" and \"%s\""),
92 argv[optind], argv[optind + 1]);
93
94 return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
95}