2 Unix SMB/CIFS implementation.
4 Copyright (C) Ralph Boehme 2017
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
22 #include "popt_common.h"
25 static struct rename_xattr_state
{
34 static int rename_xattr(const char *path
,
35 const struct stat
*sb
,
42 if (typeflag
== FTW_SL
) {
43 d_printf("Ignoring symlink %s\n", path
);
48 d_printf("%s\n", path
);
51 len
= getxattr(path
, state
.xattr_from
, NULL
, 0);
53 if (errno
== ENOATTR
) {
56 d_printf("getxattr [%s] failed [%s]\n",
57 path
, strerror(errno
));
64 len
= getxattr(path
, state
.xattr_from
, &buf
[0], len
);
66 d_printf("getxattr [%s] failed [%s]\n",
67 path
, strerror(errno
));
71 ret
= setxattr(path
, state
.xattr_to
, &buf
[0], len
, XATTR_CREATE
);
73 if (errno
!= EEXIST
) {
74 d_printf("setxattr [%s] failed [%s]\n",
75 path
, strerror(errno
));
79 d_printf("destination [%s:%s] exists, use -f to force\n",
80 path
, state
.xattr_to
);
83 ret
= setxattr(path
, state
.xattr_to
, &buf
[0], len
, XATTR_REPLACE
);
85 d_printf("setxattr [%s:%s] failed [%s]\n",
86 path
, state
.xattr_to
, strerror(errno
));
91 ret
= removexattr(path
, state
.xattr_from
);
93 d_printf("removexattr [%s:%s] failed [%s]\n",
94 path
, state
.xattr_from
, strerror(errno
));
99 d_printf("Renamed %s to %s on %s\n",
100 state
.xattr_from
, state
.xattr_to
, path
);
107 int main(int argc
, const char *argv
[])
110 const char *path
= NULL
;
112 struct poptOption long_options
[] = {
114 {"from", 's', POPT_ARG_STRING
, &state
.xattr_from
, 's', "xattr source name" },
115 {"to", 'd', POPT_ARG_STRING
, &state
.xattr_to
, 'd', "xattr destination name" },
116 {"follow-symlinks", 'l', POPT_ARG_NONE
, &state
.follow_symlink
, 'l', "follow symlinks, the default is to ignore them" },
117 {"print", 'p', POPT_ARG_NONE
, &state
.print
, 'p', "print files where the xattr got renamed" },
118 {"verbose", 'v', POPT_ARG_NONE
, &state
.verbose
, 'v', "print files as they are checked" },
119 {"force", 'f', POPT_ARG_NONE
, &state
.force
, 'f', "force overwriting of destination xattr" },
122 TALLOC_CTX
*frame
= talloc_stackframe();
123 const char *s
= NULL
;
127 d_printf("%s only works as root!\n", argv
[0]);
132 pc
= poptGetContext(NULL
, argc
, argv
, long_options
, 0);
133 poptSetOtherOptionHelp(pc
, "-s STRING -d STRING PATH [PATH ...]");
135 while ((c
= poptGetNextOpt(pc
)) != -1) {
138 s
= poptGetOptArg(pc
);
139 state
.xattr_from
= talloc_strdup(frame
, s
);
140 if (state
.xattr_from
== NULL
) {
146 s
= poptGetOptArg(pc
);
147 state
.xattr_to
= talloc_strdup(frame
, s
);
148 if (state
.xattr_to
== NULL
) {
156 if (state
.xattr_from
== NULL
|| state
.xattr_to
== NULL
) {
157 poptPrintUsage(pc
, stderr
, 0);
162 if (poptPeekArg(pc
) == NULL
) {
163 poptPrintUsage(pc
, stderr
, 0);
168 while ((path
= poptGetArg(pc
)) != NULL
) {
169 ret
= nftw(path
, rename_xattr
, 256,
170 state
.follow_symlink
? 0 : FTW_PHYS
);