1 /*
2 Copyright (C) 2009 Andreas Gruenbacher <agruen@suse.de>
3
4 This program is free software: you can redistribute it and/or modify it
5 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
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * Example how to preserve Extended Attributes in file manager style
20 * applications. This does NOT also copy Access Control Lists!
21 *
22 * Andreas Gruenbacher, SuSE Labs, SuSE Linux AG
23 * 23 January 2003
24 */
25
26 #include "config.h"
27
28 #include <sys/stat.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <stdarg.h>
34 #include <locale.h>
35 /* #include <libintl.h> */
36 #ifdef HAVE_ATTR_ERROR_CONTEXT_H
37 # include <attr/error_context.h>
38 #endif
39 #ifdef HAVE_ATTR_LIBATTR_H
40 # include <attr/libattr.h>
41 #endif
42
43 /*
44 * We don't fully internationalize this example!
45 */
46 #define _(msg) (msg)
47
48 /*
49 * Optional error handler for attr_copy_file(). CTX is the error
50 * context passed to attr_copy_file(), ERR is the errno value
51 * that occurred. FMT and the rest are printf style arguments.
52 */
53 static void
54 error(struct error_context *ctx, const char *fmt, ...)
55 {
56 va_list ap;
57
58 va_start(ap, fmt);
59 if (vfprintf(stderr, fmt, ap))
60 fprintf(stderr, ": ");
61 fprintf(stderr, "%s\n", strerror(errno));
62 va_end(ap);
63 }
64
65 /*
66 * Optional handler for quoting path names in error messages.
67 * (This is a very stupid example!)
68 */
69 static const char *
70 quote(struct error_context *ctx, const char *pathname)
71 {
72 char *pn = strdup(pathname), *p;
73 pathname = strdup(pathname);
74 for (p = pn; *p != '\0'; p++)
75 if (*p & 0x80)
76 *p='?';
77 return pn;
78 }
79
80 static void
81 quote_free(struct error_context *ctx, const char *name)
82 {
83 free((void *)name);
84 }
85
86 /*
87 * The error context we pass to attr_copy_file().
88 */
89 struct error_context ctx = { error, quote, quote_free };
90
91 /*
92 * Optional attribute filter for attr_copy_file(). This example
93 * excludes all attributes other than extended user attributes.
94 */
95 static int is_user_attr(const char *name, struct error_context *ctx)
96 {
97 return strcmp(name, "user.") == 0;
98 }
99
100 int
101 main(int argc, char *argv[])
102 {
103 int ret;
104
105 /*
106 * Set the locale to enable message translation
107 */
108 setlocale(LC_MESSAGES, "");
109 setlocale(LC_CTYPE, "");
110
111 if (argc != 3) {
112 fprintf(stderr, _("Usage: %s from to\n"), argv[0]);
113 exit(1);
114 }
115
116 #if defined(HAVE_ATTR_COPY_FILE)
117 /*
118 * If the third parameter is NULL, all extended attributes
119 * except those that define Access Control Lists are copied.
120 * ACLs are excluded by default because copying them between
121 * file systems with and without ACL support needs some
122 * additional logic so that no unexpected permissions result.
123 *
124 * For copying ACLs, please use perm_copy_file() from libacl.
125 *
126 * The CTX parameter could also be NULL, in which case attr_copy_file
127 * would print no error messages.
128 */
129 ret = attr_copy_file(argv[1], argv[2], is_user_attr, &ctx);
130 #else
131 fprintf(stderr, _("No support for copying extended attributes\n"));
132 ret = -1;
133 #endif
134
135 if (ret != 0)
136 return EXIT_FAILURE;
137 return EXIT_SUCCESS;
138 }
139