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"
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
;
111 poptContext pc
= NULL
;
112 struct poptOption long_options
[] = {
117 .argInfo
= POPT_ARG_STRING
,
118 .arg
= &state
.xattr_from
,
120 .descrip
= "xattr source name",
125 .argInfo
= POPT_ARG_STRING
,
126 .arg
= &state
.xattr_to
,
128 .descrip
= "xattr destination name",
131 .longName
= "follow-symlinks",
133 .argInfo
= POPT_ARG_NONE
,
134 .arg
= &state
.follow_symlink
,
136 .descrip
= "follow symlinks, the default is to "
142 .argInfo
= POPT_ARG_NONE
,
145 .descrip
= "print files where the xattr got "
149 .longName
= "verbose",
151 .argInfo
= POPT_ARG_NONE
,
152 .arg
= &state
.verbose
,
154 .descrip
= "print files as they are checked",
159 .argInfo
= POPT_ARG_NONE
,
162 .descrip
= "force overwriting of destination xattr",
166 TALLOC_CTX
*frame
= talloc_stackframe();
167 const char *s
= NULL
;
171 d_printf("%s only works as root!\n", argv
[0]);
176 pc
= poptGetContext(NULL
, argc
, argv
, long_options
, 0);
177 poptSetOtherOptionHelp(pc
, "-s STRING -d STRING PATH [PATH ...]");
179 while ((c
= poptGetNextOpt(pc
)) != -1) {
182 s
= poptGetOptArg(pc
);
183 state
.xattr_from
= talloc_strdup(frame
, s
);
184 if (state
.xattr_from
== NULL
) {
190 s
= poptGetOptArg(pc
);
191 state
.xattr_to
= talloc_strdup(frame
, s
);
192 if (state
.xattr_to
== NULL
) {
197 case POPT_ERROR_BADOPT
:
198 fprintf(stderr
, "\nInvalid option %s: %s\n\n",
199 poptBadOption(pc
, 0), poptStrerror(c
));
200 poptPrintUsage(pc
, stderr
, 0);
205 if (state
.xattr_from
== NULL
|| state
.xattr_to
== NULL
) {
206 poptPrintUsage(pc
, stderr
, 0);
211 if (poptPeekArg(pc
) == NULL
) {
212 poptPrintUsage(pc
, stderr
, 0);
217 while ((path
= poptGetArg(pc
)) != NULL
) {
218 ret
= nftw(path
, rename_xattr
, 256,
219 state
.follow_symlink
? 0 : FTW_PHYS
);