diff options
author | Xin Ouyang <Xin.Ouyang@windriver.com> | 2012-06-12 10:18:39 +0800 |
---|---|---|
committer | Xin Ouyang <Xin.Ouyang@windriver.com> | 2012-06-12 10:22:47 +0800 |
commit | 8d203e6ff285c08e55a9b3f26fa85334f537379c (patch) | |
tree | 8902b4dd4945402925588abf6556b6661f1dbdc1 | |
parent | 72d7f55772e72ac18ff9fe4e77fb196a95e0c4a4 (diff) | |
download | meta-selinux-8d203e6ff285c08e55a9b3f26fa85334f537379c.tar.gz |
tar: Build with selinux support.
Also add a patch to support xattrs and selinux.
Signed-off-by: Xin Ouyang <Xin.Ouyang@windriver.com>
-rw-r--r-- | recipes-extended/tar/tar/tar-1.24-xattrs.patch | 1636 | ||||
-rw-r--r-- | recipes-extended/tar/tar_1.26.bbappend | 9 |
2 files changed, 1645 insertions, 0 deletions
diff --git a/recipes-extended/tar/tar/tar-1.24-xattrs.patch b/recipes-extended/tar/tar/tar-1.24-xattrs.patch new file mode 100644 index 0000000..e91baa7 --- /dev/null +++ b/recipes-extended/tar/tar/tar-1.24-xattrs.patch | |||
@@ -0,0 +1,1636 @@ | |||
1 | configure.ac | 20 ++- | ||
2 | doc/tar.texi | 75 +++++++++ | ||
3 | src/Makefile.am | 7 +- | ||
4 | src/common.h | 18 ++ | ||
5 | src/create.c | 54 ++++++- | ||
6 | src/extract.c | 123 ++++++++++++++ | ||
7 | src/list.c | 7 + | ||
8 | src/tar.c | 80 +++++++++- | ||
9 | src/tar.h | 20 +++ | ||
10 | src/xattrs.c | 489 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
11 | src/xattrs.h | 14 ++ | ||
12 | src/xheader.c | 237 +++++++++++++++++++++++---- | ||
13 | 12 files changed, 1103 insertions(+), 41 deletions(-) | ||
14 | |||
15 | diff -urNp tar-1.24-orig/configure.ac tar-1.24/configure.ac | ||
16 | --- tar-1.24-orig/configure.ac 2010-10-24 23:35:35.000000000 +0200 | ||
17 | +++ tar-1.24/configure.ac 2010-10-25 10:24:52.548214037 +0200 | ||
18 | @@ -44,7 +44,7 @@ AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h | ||
19 | sys/param.h sys/device.h sys/gentape.h \ | ||
20 | sys/inet.h sys/io/trioctl.h \ | ||
21 | sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \ | ||
22 | - unistd.h locale.h) | ||
23 | + unistd.h locale.h attr/xattr.h sys/acl.h) | ||
24 | |||
25 | AC_CHECK_HEADERS([sys/buf.h], [], [], | ||
26 | [#if HAVE_SYS_PARAM_H | ||
27 | @@ -91,6 +91,12 @@ gl_INIT | ||
28 | tar_PAXUTILS | ||
29 | |||
30 | AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink]) | ||
31 | +AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \ | ||
32 | + setxattr fsetxattr lsetxattr \ | ||
33 | + listxattr flistxattr llistxattr, | ||
34 | + AC_DEFINE(HAVE_XATTRS,,[Define if we have a working extended attributes]),) | ||
35 | +AC_CHECK_LIB(acl, acl_get_fd) | ||
36 | + | ||
37 | AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>]) | ||
38 | AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>]) | ||
39 | AC_CHECK_DECLS([time],,, [#include <time.h>]) | ||
40 | @@ -214,6 +220,7 @@ AC_DEFINE_UNQUOTED(DEFAULT_QUOTING_STYLE | ||
41 | # Iconv | ||
42 | AM_ICONV | ||
43 | AC_CHECK_HEADERS(iconv.h) | ||
44 | +AC_CHECK_HEADERS(attr/xattr.h) | ||
45 | AC_CHECK_TYPE(iconv_t,:, | ||
46 | AC_DEFINE(iconv_t, int, | ||
47 | [Conversion descriptor type]), | ||
48 | @@ -223,6 +230,17 @@ AC_CHECK_TYPE(iconv_t,:, | ||
49 | #endif | ||
50 | ]) | ||
51 | |||
52 | +AC_ARG_ENABLE(selinux, | ||
53 | + AC_HELP_STRING([--enable-selinux], | ||
54 | + [enable SELinux support (disabled by default)]), | ||
55 | + [selinux_enabled=$enableval], | ||
56 | + [selinux_enabled=no]) | ||
57 | + | ||
58 | +if test "x$selinux_enabled" = xyes; then | ||
59 | + AC_CHECK_LIB(selinux, getfilecon) | ||
60 | + AC_CHECK_HEADERS(selinux/selinux.h) | ||
61 | +fi | ||
62 | + | ||
63 | # Gettext. | ||
64 | AM_GNU_GETTEXT([external], [need-formatstring-macros]) | ||
65 | AM_GNU_GETTEXT_VERSION([0.16]) | ||
66 | diff -urNp tar-1.24-orig/doc/tar.texi tar-1.24/doc/tar.texi | ||
67 | --- tar-1.24-orig/doc/tar.texi 2010-10-24 20:07:54.000000000 +0200 | ||
68 | +++ tar-1.24/doc/tar.texi 2010-10-25 10:24:52.554213688 +0200 | ||
69 | @@ -2370,6 +2370,10 @@ Normally when creating an archive, @comm | ||
70 | @samp{/} from member names. This option disables that behavior. | ||
71 | @xref{absolute}. | ||
72 | |||
73 | +@opsummary{acl} | ||
74 | +@item --acls | ||
75 | +Causes @command{tar} to store ACL's. @xref{Attributes}. | ||
76 | + | ||
77 | @opsummary{after-date} | ||
78 | @item --after-date | ||
79 | |||
80 | @@ -2914,6 +2918,10 @@ contents have changed (as opposed to just @option{--newer}, which will | ||
81 | also back up files for which any status information has | ||
82 | changed). @xref{after}. | ||
83 | |||
84 | +@opsummary{no-acl} | ||
85 | +@item --no-acls | ||
86 | +Causes @command{tar} not to store and not to extract ACL's. @xref{Attributes}. | ||
87 | + | ||
88 | @opsummary{no-anchored} | ||
89 | @item --no-anchored | ||
90 | An exclude pattern can match any subsequence of the name's components. | ||
91 | @@ -2997,11 +3005,21 @@ locations. Usually @command{tar} determines automatically whether | ||
92 | the archive can be seeked or not. Use this option to disable this | ||
93 | mechanism. | ||
94 | |||
95 | +@opsummary{no-selinux} | ||
96 | +@item --no-selinux | ||
97 | +Causes @command{tar} not to store and not to extract SELinux security context. | ||
98 | +@xref{Attributes}. | ||
99 | + | ||
100 | @opsummary{no-unquote} | ||
101 | @item --no-unquote | ||
102 | Treat all input file or member names literally, do not interpret | ||
103 | escape sequences. @xref{input name quoting}. | ||
104 | |||
105 | +@opsummary{no-xattrs} | ||
106 | +@item --no-xattrs | ||
107 | +Causes @command{tar} not to store and not to extract xattrs. This option also | ||
108 | +enables @option{--no-selinux} and @option{--no-acls}. @xref{Attributes}. | ||
109 | + | ||
110 | @opsummary{no-wildcards} | ||
111 | @item --no-wildcards | ||
112 | Do not use wildcards. | ||
113 | @@ -3234,6 +3252,11 @@ in cases when such recognition fails. It takes effect only if the | ||
114 | archive is open for reading (e.g. with @option{--list} or | ||
115 | @option{--extract} options). | ||
116 | |||
117 | +@opsummary{selinux} | ||
118 | +@item --selinux | ||
119 | +Causes @command{tar} to store SElinux security context. @xref{Attributes}. | ||
120 | + | ||
121 | + | ||
122 | @opsummary{show-defaults} | ||
123 | @item --show-defaults | ||
124 | |||
125 | @@ -3447,6 +3470,11 @@ Enable or disable warning messages identified by @var{keyword}. The | ||
126 | messages are suppressed if @var{keyword} is prefixed with @samp{no-}. | ||
127 | @xref{warnings}. | ||
128 | |||
129 | +@opsummary{xattrs} | ||
130 | +@item --xattrs | ||
131 | +Causes @command{tar} to store xattrs. This option also enables | ||
132 | +@option{--selinux} and @option{--acls}. @xref{Attributes}. | ||
133 | + | ||
134 | @opsummary{wildcards} | ||
135 | @item --wildcards | ||
136 | Use wildcards when matching member names with patterns. | ||
137 | @@ -8659,6 +8687,8 @@ implementation able to read @samp{ustar} archives will be able to read | ||
138 | most @samp{posix} archives as well, with the only exception that any | ||
139 | additional information (such as long file names etc.) will in such | ||
140 | case be extracted as plain text files along with the files it refers to. | ||
141 | +This is the only format that can store ACLs, SELinux context and extended | ||
142 | +attributes. | ||
143 | |||
144 | This archive format will be the default format for future versions | ||
145 | of @GNUTAR{}. | ||
146 | @@ -9293,6 +9323,51 @@ Same as both @option{--same-permissions} and @option{--same-order}. | ||
147 | |||
148 | This option is deprecated, and will be removed in @GNUTAR{} version 1.23. | ||
149 | |||
150 | +@opindex acls | ||
151 | +@item --acls | ||
152 | +This option causes @command{tar} to store the current ACL in the archive. | ||
153 | + | ||
154 | +The @option{--acls} option has no equivalent short option name. | ||
155 | + | ||
156 | +@opindex selinux | ||
157 | +@item --selinux | ||
158 | +This option causes @command{tar} to store the current SELinux security context | ||
159 | +information in the archive. | ||
160 | + | ||
161 | +The @option{--selinux} option has no equivalent short option name. | ||
162 | + | ||
163 | +@opindex xattrs | ||
164 | +@item --xattrs | ||
165 | +This option causes @command{tar} to store the current extended attributes in | ||
166 | +the archive. This option also enables @option{--acls} and @option{--selinux} if | ||
167 | +they haven't been set already. | ||
168 | + | ||
169 | +The @option{--xattrs} option has no equivalent short option name. | ||
170 | + | ||
171 | +@opindex no-acls | ||
172 | +@item --no-acls | ||
173 | +This option causes @command{tar} not to store the current ACL in the archive | ||
174 | +and not to extract any ACL information in an archive. | ||
175 | + | ||
176 | +The @option{--no-acls} option has no equivalent short option name. | ||
177 | + | ||
178 | +@opindex no-selinux | ||
179 | +@item --no-selinux | ||
180 | +This option causes @command{tar} not to store the current SELinux security | ||
181 | +context information in the archive and not to extract any SELinux information in | ||
182 | +an archive. | ||
183 | + | ||
184 | +The @option{--no-selinux} option has no equivalent short option name. | ||
185 | + | ||
186 | +@opindex no-xattrs | ||
187 | +@item --no-xattrs | ||
188 | +This option causes @command{tar} not to store the current extended attributes in | ||
189 | +the archive and not to extract any extended attributes in an archive. This | ||
190 | +option also enables @option{--no-acls} and @option{--no-selinux} if | ||
191 | +they haven't been set already. | ||
192 | + | ||
193 | +The @option{--no-xattrs} option has no equivalent short option name. | ||
194 | + | ||
195 | @end table | ||
196 | |||
197 | @node Portability | ||
198 | diff -urNp tar-1.24-orig/src/common.h tar-1.24/src/common.h | ||
199 | --- tar-1.24-orig/src/common.h 2010-10-24 20:07:54.000000000 +0200 | ||
200 | +++ tar-1.24/src/common.h 2010-10-25 10:24:52.558475456 +0200 | ||
201 | @@ -253,6 +253,15 @@ GLOBAL int same_owner_option; | ||
202 | /* If positive, preserve permissions when extracting. */ | ||
203 | GLOBAL int same_permissions_option; | ||
204 | |||
205 | +/* If positive, save the SELinux context. */ | ||
206 | +GLOBAL int selinux_context_option; | ||
207 | + | ||
208 | +/* If positive, save the ACLs. */ | ||
209 | +GLOBAL int acls_option; | ||
210 | + | ||
211 | +/* If positive, save the user and root xattrs. */ | ||
212 | +GLOBAL int xattrs_option; | ||
213 | + | ||
214 | /* When set, strip the given number of file name components from the file name | ||
215 | before extracting */ | ||
216 | GLOBAL size_t strip_name_components; | ||
217 | @@ -707,6 +716,9 @@ extern char *output_start; | ||
218 | |||
219 | void update_archive (void); | ||
220 | |||
221 | +/* Module attrs.c. */ | ||
222 | +#include "xattrs.h" | ||
223 | + | ||
224 | /* Module xheader.c. */ | ||
225 | |||
226 | void xheader_decode (struct tar_stat_info *stat); | ||
227 | @@ -727,6 +739,12 @@ bool xheader_string_end (struct xheader *xhdr, char const *keyword); | ||
228 | bool xheader_keyword_deleted_p (const char *kw); | ||
229 | char *xheader_format_name (struct tar_stat_info *st, const char *fmt, | ||
230 | size_t n); | ||
231 | +void xheader_xattr_init(struct tar_stat_info *st); | ||
232 | +void xheader_xattr_free(struct xattr_array *vals, size_t sz); | ||
233 | +void xheader_xattr_copy(const struct tar_stat_info *st, | ||
234 | + struct xattr_array **vals, size_t *sz); | ||
235 | +void xheader_xattr_add(struct tar_stat_info *st, | ||
236 | + const char *key, const char *val, size_t len); | ||
237 | |||
238 | /* Module system.c */ | ||
239 | |||
240 | diff -urNp tar-1.24-orig/src/create.c tar-1.24/src/create.c | ||
241 | --- tar-1.24-orig/src/create.c 2010-10-24 20:07:54.000000000 +0200 | ||
242 | +++ tar-1.24/src/create.c 2010-10-25 10:24:52.560213618 +0200 | ||
243 | @@ -24,6 +24,7 @@ | ||
244 | #include <quotearg.h> | ||
245 | |||
246 | #include "common.h" | ||
247 | + | ||
248 | #include <hash.h> | ||
249 | |||
250 | /* Error number to use when an impostor is discovered. | ||
251 | @@ -936,6 +937,30 @@ start_header (struct tar_stat_info *st) | ||
252 | GNAME_TO_CHARS (st->gname, header->header.gname); | ||
253 | } | ||
254 | |||
255 | + if (archive_format == POSIX_FORMAT) | ||
256 | + { | ||
257 | + if (acls_option > 0) | ||
258 | + { | ||
259 | + if (st->acls_a_ptr) | ||
260 | + xheader_store ("SCHILY.acl.access", st, NULL); | ||
261 | + if (st->acls_d_ptr) | ||
262 | + xheader_store ("SCHILY.acl.default", st, NULL); | ||
263 | + } | ||
264 | + if ((selinux_context_option > 0) && st->cntx_name) | ||
265 | + xheader_store ("RHT.security.selinux", st, NULL); | ||
266 | + if (xattrs_option > 0) | ||
267 | + { | ||
268 | + size_t scan_xattr = 0; | ||
269 | + struct xattr_array *xattr_map = st->xattr_map; | ||
270 | + | ||
271 | + while (scan_xattr < st->xattr_map_size) | ||
272 | + { | ||
273 | + xheader_store (xattr_map[scan_xattr].xkey, st, &scan_xattr); | ||
274 | + ++scan_xattr; | ||
275 | + } | ||
276 | + } | ||
277 | + } | ||
278 | + | ||
279 | return header; | ||
280 | } | ||
281 | |||
282 | @@ -1710,6 +1735,14 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p) | ||
283 | { | ||
284 | bool ok; | ||
285 | struct stat final_stat; | ||
286 | + int fd_xattr = fd; | ||
287 | + if (!fd_xattr) | ||
288 | + // upstream tar now uses zero fd as "no fd" | ||
289 | + fd_xattr = -1; | ||
290 | + | ||
291 | + xattrs_acls_get(st, p, fd_xattr, !is_dir); | ||
292 | + xattrs_selinux_get(st, p, fd_xattr); | ||
293 | + xattrs_xattrs_get(st, p, fd_xattr); | ||
294 | |||
295 | if (is_dir) | ||
296 | { | ||
297 | @@ -1829,6 +1862,9 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p) | ||
298 | if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size) | ||
299 | write_long_link (st); | ||
300 | |||
301 | + xattrs_selinux_get(st, p, -1); | ||
302 | + xattrs_xattrs_get(st, p, -1); | ||
303 | + | ||
304 | block_ordinal = current_block_ordinal (); | ||
305 | st->stat.st_size = 0; /* force 0 size on symlink */ | ||
306 | header = start_header (st); | ||
307 | @@ -1847,11 +1883,23 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p) | ||
308 | } | ||
309 | #endif | ||
310 | else if (S_ISCHR (st->stat.st_mode)) | ||
311 | - type = CHRTYPE; | ||
312 | + { | ||
313 | + type = CHRTYPE; | ||
314 | + xattrs_selinux_get(st, p, -1); | ||
315 | + xattrs_xattrs_get(st, p, -1); | ||
316 | + } | ||
317 | else if (S_ISBLK (st->stat.st_mode)) | ||
318 | - type = BLKTYPE; | ||
319 | + { | ||
320 | + type = BLKTYPE; | ||
321 | + xattrs_selinux_get(st, p, -1); | ||
322 | + xattrs_xattrs_get(st, p, -1); | ||
323 | + } | ||
324 | else if (S_ISFIFO (st->stat.st_mode)) | ||
325 | - type = FIFOTYPE; | ||
326 | + { | ||
327 | + type = FIFOTYPE; | ||
328 | + xattrs_selinux_get(st, p, -1); | ||
329 | + xattrs_xattrs_get(st, p, -1); | ||
330 | + } | ||
331 | else if (S_ISSOCK (st->stat.st_mode)) | ||
332 | { | ||
333 | WARNOPT (WARN_FILE_IGNORED, | ||
334 | diff -urNp tar-1.24-orig/src/extract.c tar-1.24/src/extract.c | ||
335 | --- tar-1.24-orig/src/extract.c 2010-10-24 20:07:54.000000000 +0200 | ||
336 | +++ tar-1.24/src/extract.c 2010-10-25 10:35:10.903214037 +0200 | ||
337 | @@ -97,6 +97,14 @@ struct delayed_set_stat | ||
338 | /* Directory that the name is relative to. */ | ||
339 | int change_dir; | ||
340 | |||
341 | + /* extended attributes*/ | ||
342 | + char *cntx_name; | ||
343 | + char *acls_a_ptr; | ||
344 | + size_t acls_a_len; | ||
345 | + char *acls_d_ptr; | ||
346 | + size_t acls_d_len; | ||
347 | + size_t xattr_map_size; /* Size of the xattr map */ | ||
348 | + struct xattr_array *xattr_map; | ||
349 | /* Length and contents of name. */ | ||
350 | size_t file_name_len; | ||
351 | char file_name[1]; | ||
352 | @@ -134,6 +142,18 @@ struct delayed_link | ||
353 | hard-linked together. */ | ||
354 | struct string_list *sources; | ||
355 | |||
356 | + /* SELinux context */ | ||
357 | + char *cntx_name; | ||
358 | + | ||
359 | + /* ACLs */ | ||
360 | + char *acls_a_ptr; | ||
361 | + size_t acls_a_len; | ||
362 | + char *acls_d_ptr; | ||
363 | + size_t acls_d_len; | ||
364 | + | ||
365 | + size_t xattr_map_size; /* Size of the xattr map */ | ||
366 | + struct xattr_array *xattr_map; | ||
367 | + | ||
368 | /* The desired target of the desired link. */ | ||
369 | char target[1]; | ||
370 | }; | ||
371 | @@ -335,6 +355,10 @@ set_stat (char const *file_name, | ||
372 | utime_error (file_name); | ||
373 | } | ||
374 | |||
375 | + xattrs_acls_set(st, file_name, typeflag); | ||
376 | + xattrs_selinux_set(st, file_name, typeflag); | ||
377 | + xattrs_xattrs_set(st, file_name, typeflag); | ||
378 | + | ||
379 | if (0 < same_owner_option && ! interdir) | ||
380 | { | ||
381 | /* Some systems allow non-root users to give files away. Once this | ||
382 | @@ -431,6 +455,36 @@ delay_set_stat (char const *file_name, s | ||
383 | data->atflag = atflag; | ||
384 | data->after_links = 0; | ||
385 | data->change_dir = chdir_current; | ||
386 | + data->cntx_name = NULL; | ||
387 | + if (st) | ||
388 | + assign_string (&data->cntx_name, st->cntx_name); | ||
389 | + if (st && st->acls_a_ptr) | ||
390 | + { | ||
391 | + data->acls_a_ptr = xmemdup(st->acls_a_ptr, st->acls_a_len + 1); | ||
392 | + data->acls_a_len = st->acls_a_len; | ||
393 | + } | ||
394 | + else | ||
395 | + { | ||
396 | + data->acls_a_ptr = NULL; | ||
397 | + data->acls_a_len = 0; | ||
398 | + } | ||
399 | + if (st && st->acls_d_ptr) | ||
400 | + { | ||
401 | + data->acls_d_ptr = xmemdup(st->acls_d_ptr, st->acls_d_len + 1); | ||
402 | + data->acls_d_len = st->acls_d_len; | ||
403 | + } | ||
404 | + else | ||
405 | + { | ||
406 | + data->acls_d_ptr = NULL; | ||
407 | + data->acls_d_len = 0; | ||
408 | + } | ||
409 | + if (st) | ||
410 | + xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size); | ||
411 | + else | ||
412 | + { | ||
413 | + data->xattr_map = NULL; | ||
414 | + data->xattr_map_size = 0; | ||
415 | + } | ||
416 | strcpy (data->file_name, file_name); | ||
417 | delayed_set_stat_head = data; | ||
418 | if (must_be_dot_or_slash (file_name)) | ||
419 | @@ -673,6 +727,31 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made) | ||
420 | return RECOVER_NO; | ||
421 | } | ||
422 | |||
423 | +/* Restore stat extended attributes (xattr) for FILE_NAME, using information | ||
424 | + given in *ST. Restore before extraction because they may affect layout. | ||
425 | + If not restoring permissions, invert the | ||
426 | + INVERT_PERMISSIONS bits from the file's current permissions. | ||
427 | + TYPEFLAG specifies the type of the file. | ||
428 | + FILE_CREATED indicates set_xattr has created the file */ | ||
429 | +static int | ||
430 | +set_xattr (char const *file_name, struct tar_stat_info const *st, | ||
431 | + mode_t invert_permissions, char typeflag, int *file_created) | ||
432 | +{ | ||
433 | + int status = 0; | ||
434 | + bool interdir_made = false; | ||
435 | + | ||
436 | + if ((xattrs_option >= 0) && st->xattr_map_size) { | ||
437 | + mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask; | ||
438 | + | ||
439 | + do | ||
440 | + status = mknod (file_name, mode ^ invert_permissions, 0); | ||
441 | + while (status && maybe_recoverable ((char *)file_name, false, &interdir_made)); | ||
442 | + xattrs_xattrs_set(st, file_name, typeflag); | ||
443 | + *file_created = 1; | ||
444 | + } | ||
445 | + return(status); | ||
446 | +} | ||
447 | + | ||
448 | /* Fix the statuses of all directories whose statuses need fixing, and | ||
449 | which are not ancestors of FILE_NAME. If AFTER_LINKS is | ||
450 | nonzero, do this for all such directories; otherwise, stop at the | ||
451 | @@ -733,12 +812,23 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links) | ||
452 | sb.stat.st_gid = data->gid; | ||
453 | sb.atime = data->atime; | ||
454 | sb.mtime = data->mtime; | ||
455 | + sb.cntx_name = data->cntx_name; | ||
456 | + sb.acls_a_ptr = data->acls_a_ptr; | ||
457 | + sb.acls_a_len = data->acls_a_len; | ||
458 | + sb.acls_d_ptr = data->acls_d_ptr; | ||
459 | + sb.acls_d_len = data->acls_d_len; | ||
460 | + sb.xattr_map = data->xattr_map; | ||
461 | + sb.xattr_map_size = data->xattr_map_size; | ||
462 | set_stat (data->file_name, &sb, | ||
463 | -1, current_mode, current_mode_mask, | ||
464 | DIRTYPE, data->interdir, data->atflag); | ||
465 | } | ||
466 | |||
467 | delayed_set_stat_head = data->next; | ||
468 | + xheader_xattr_free (data->xattr_map, data->xattr_map_size); | ||
469 | + free (data->cntx_name); | ||
470 | + free (data->acls_a_ptr); | ||
471 | + free (data->acls_d_ptr); | ||
472 | free (data); | ||
473 | } | ||
474 | } | ||
475 | @@ -854,6 +944,7 @@ extract_dir (char *file_name, int typeflag) | ||
476 | |||
477 | static int | ||
478 | open_output_file (char const *file_name, int typeflag, mode_t mode, | ||
479 | + int file_created, | ||
480 | mode_t *current_mode, mode_t *current_mode_mask) | ||
481 | { | ||
482 | int fd; | ||
483 | @@ -864,6 +955,10 @@ open_output_file (char const *file_name, int typeflag, mode_t mode, | ||
484 | ? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW) | ||
485 | : O_EXCL)); | ||
486 | |||
487 | + /* File might be created in set_xattr. So clear O_EXCL to avoid open() failure */ | ||
488 | + if (file_created) | ||
489 | + openflag = openflag & ~O_EXCL; | ||
490 | + | ||
491 | if (typeflag == CONTTYPE) | ||
492 | { | ||
493 | static int conttype_diagnosed; | ||
494 | @@ -934,6 +1029,7 @@ extract_file (char *file_name, int typeflag) | ||
495 | bool interdir_made = false; | ||
496 | mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX | ||
497 | & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0)); | ||
498 | + mode_t invert_permissions = 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0; | ||
499 | mode_t current_mode = 0; | ||
500 | mode_t current_mode_mask = 0; | ||
501 | |||
502 | @@ -950,7 +1046,17 @@ extract_file (char *file_name, int typeflag) | ||
503 | } | ||
504 | else | ||
505 | { | ||
506 | + int file_created = 0; | ||
507 | + if (set_xattr (file_name, ¤t_stat_info, invert_permissions, | ||
508 | + typeflag, &file_created)) | ||
509 | + { | ||
510 | + skip_member (); | ||
511 | + open_error (file_name); | ||
512 | + return 1; | ||
513 | + } | ||
514 | + | ||
515 | while ((fd = open_output_file (file_name, typeflag, mode, | ||
516 | + file_created, | ||
517 | ¤t_mode, ¤t_mode_mask)) | ||
518 | < 0) | ||
519 | { | ||
520 | @@ -1091,6 +1197,13 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made) | ||
521 | + strlen (file_name) + 1); | ||
522 | p->sources->next = 0; | ||
523 | strcpy (p->sources->string, file_name); | ||
524 | + p->cntx_name = NULL; | ||
525 | + assign_string (&p->cntx_name, current_stat_info.cntx_name); | ||
526 | + p->acls_a_ptr = NULL; | ||
527 | + p->acls_a_len = 0; | ||
528 | + p->acls_d_ptr = NULL; | ||
529 | + p->acls_d_len = 0; | ||
530 | + xheader_xattr_copy (¤t_stat_info, &p->xattr_map, &p->xattr_map_size); | ||
531 | strcpy (p->target, current_stat_info.link_name); | ||
532 | |||
533 | h = delayed_set_stat_head; | ||
534 | @@ -1525,6 +1638,13 @@ apply_delayed_links (void) | ||
535 | st1.stat.st_gid = ds->gid; | ||
536 | st1.atime = ds->atime; | ||
537 | st1.mtime = ds->mtime; | ||
538 | + st1.cntx_name = ds->cntx_name; | ||
539 | + st1.acls_a_ptr = ds->acls_a_ptr; | ||
540 | + st1.acls_a_len = ds->acls_a_len; | ||
541 | + st1.acls_d_ptr = ds->acls_d_ptr; | ||
542 | + st1.acls_d_len = ds->acls_d_len; | ||
543 | + st1.xattr_map = ds->xattr_map; | ||
544 | + st1.xattr_map_size = ds->xattr_map_size; | ||
545 | set_stat (source, &st1, -1, 0, 0, SYMTYPE, | ||
546 | false, AT_SYMLINK_NOFOLLOW); | ||
547 | valid_source = source; | ||
548 | @@ -1539,6 +1659,9 @@ apply_delayed_links (void) | ||
549 | sources = next; | ||
550 | } | ||
551 | |||
552 | + xheader_xattr_free (ds->xattr_map, ds->xattr_map_size); | ||
553 | + free (ds->cntx_name); | ||
554 | + | ||
555 | { | ||
556 | struct delayed_link *next = ds->next; | ||
557 | free (ds); | ||
558 | diff -urNp tar-1.24-orig/src/list.c tar-1.24/src/list.c | ||
559 | --- tar-1.24-orig/src/list.c 2010-10-25 09:15:14.216463863 +0200 | ||
560 | +++ tar-1.24/src/list.c 2010-10-25 10:24:52.563213968 +0200 | ||
561 | @@ -615,6 +615,13 @@ decode_header (union block *header, struct tar_stat_info *stat_info, | ||
562 | assign_string (&stat_info->gname, | ||
563 | header->header.gname[0] ? header->header.gname : NULL); | ||
564 | |||
565 | + stat_info->acls_a_ptr = NULL; | ||
566 | + stat_info->acls_a_len = 0; | ||
567 | + stat_info->acls_d_ptr = NULL; | ||
568 | + stat_info->acls_d_len = 0; | ||
569 | + stat_info->cntx_name = NULL; | ||
570 | + xheader_xattr_init(stat_info); | ||
571 | + | ||
572 | if (format == OLDGNU_FORMAT && incremental_option) | ||
573 | { | ||
574 | stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime); | ||
575 | diff -urNp tar-1.24-orig/src/Makefile.am tar-1.24/src/Makefile.am | ||
576 | --- tar-1.24-orig/src/Makefile.am 2010-10-24 20:07:54.000000000 +0200 | ||
577 | +++ tar-1.24/src/Makefile.am 2010-10-25 10:24:52.564214456 +0200 | ||
578 | @@ -20,7 +20,7 @@ | ||
579 | |||
580 | bin_PROGRAMS = tar | ||
581 | |||
582 | -noinst_HEADERS = arith.h common.h tar.h | ||
583 | +noinst_HEADERS = arith.h common.h tar.h xattrs.h | ||
584 | tar_SOURCES = \ | ||
585 | buffer.c\ | ||
586 | checkpoint.c\ | ||
587 | @@ -42,10 +42,11 @@ tar_SOURCES = \ | ||
588 | unlink.c\ | ||
589 | update.c\ | ||
590 | utf8.c\ | ||
591 | - warning.c | ||
592 | + warning.c\ | ||
593 | + xattrs.c | ||
594 | |||
595 | INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib | ||
596 | |||
597 | LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV) | ||
598 | |||
599 | -tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) | ||
600 | +tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) | ||
601 | diff -urNp tar-1.24-orig/src/tar.c tar-1.24/src/tar.c | ||
602 | --- tar-1.24-orig/src/tar.c 2010-10-24 20:07:55.000000000 +0200 | ||
603 | +++ tar-1.24/src/tar.c 2010-10-25 10:24:52.565223676 +0200 | ||
604 | @@ -255,7 +255,8 @@ tar_set_quoting_style (char *arg) | ||
605 | |||
606 | enum | ||
607 | { | ||
608 | - ANCHORED_OPTION = CHAR_MAX + 1, | ||
609 | + ACLS_OPTION = CHAR_MAX + 1, | ||
610 | + ANCHORED_OPTION, | ||
611 | ATIME_PRESERVE_OPTION, | ||
612 | BACKUP_OPTION, | ||
613 | CHECK_DEVICE_OPTION, | ||
614 | @@ -288,6 +289,7 @@ enum | ||
615 | MODE_OPTION, | ||
616 | MTIME_OPTION, | ||
617 | NEWER_MTIME_OPTION, | ||
618 | + NO_ACLS_OPTION, | ||
619 | NO_ANCHORED_OPTION, | ||
620 | NO_AUTO_COMPRESS_OPTION, | ||
621 | NO_CHECK_DEVICE_OPTION, | ||
622 | @@ -301,9 +303,11 @@ enum | ||
623 | NO_SAME_OWNER_OPTION, | ||
624 | NO_SAME_PERMISSIONS_OPTION, | ||
625 | NO_SEEK_OPTION, | ||
626 | + NO_SELINUX_CONTEXT_OPTION, | ||
627 | NO_UNQUOTE_OPTION, | ||
628 | NO_WILDCARDS_MATCH_SLASH_OPTION, | ||
629 | NO_WILDCARDS_OPTION, | ||
630 | + NO_XATTR_OPTION, | ||
631 | NULL_OPTION, | ||
632 | NUMERIC_OWNER_OPTION, | ||
633 | OCCURRENCE_OPTION, | ||
634 | @@ -325,6 +329,7 @@ enum | ||
635 | RMT_COMMAND_OPTION, | ||
636 | RSH_COMMAND_OPTION, | ||
637 | SAME_OWNER_OPTION, | ||
638 | + SELINUX_CONTEXT_OPTION, | ||
639 | SHOW_DEFAULTS_OPTION, | ||
640 | SHOW_OMITTED_DIRS_OPTION, | ||
641 | SHOW_TRANSFORMED_NAMES_OPTION, | ||
642 | @@ -340,7 +345,8 @@ enum | ||
643 | VOLNO_FILE_OPTION, | ||
644 | WARNING_OPTION, | ||
645 | WILDCARDS_MATCH_SLASH_OPTION, | ||
646 | - WILDCARDS_OPTION | ||
647 | + WILDCARDS_OPTION, | ||
648 | + XATTR_OPTION | ||
649 | }; | ||
650 | |||
651 | const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION; | ||
652 | @@ -486,6 +492,10 @@ static struct argp_option options[] = { | ||
653 | {NULL, 0, NULL, 0, | ||
654 | N_("Handling of file attributes:"), GRID }, | ||
655 | |||
656 | + {"acls", ACLS_OPTION, 0, 0, | ||
657 | + N_("Save the ACLs to the archive"), GRID+1 }, | ||
658 | + {"no-acls", NO_ACLS_OPTION, 0, 0, | ||
659 | + N_("Don't extract the ACLs from the archive"), GRID+1 }, | ||
660 | {"owner", OWNER_OPTION, N_("NAME"), 0, | ||
661 | N_("force NAME as owner for added files"), GRID+1 }, | ||
662 | {"group", GROUP_OPTION, N_("NAME"), 0, | ||
663 | @@ -516,6 +526,14 @@ static struct argp_option options[] = { | ||
664 | {"preserve-order", 's', 0, 0, | ||
665 | N_("sort names to extract to match archive"), GRID+1 }, | ||
666 | {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, | ||
667 | + {"selinux", SELINUX_CONTEXT_OPTION, 0, 0, | ||
668 | + N_("Save the SELinux context to the archive"), GRID+1 }, | ||
669 | + {"no-selinux", NO_SELINUX_CONTEXT_OPTION, 0, 0, | ||
670 | + N_("Don't extract the SELinux context from the archive"), GRID+1 }, | ||
671 | + {"xattrs", XATTR_OPTION, 0, 0, | ||
672 | + N_("Save the user/root xattrs to the archive"), GRID+1 }, | ||
673 | + {"no-xattrs", NO_XATTR_OPTION, 0, 0, | ||
674 | + N_("Don't extract the user/root xattrs from the archive"), GRID+1 }, | ||
675 | {"preserve", PRESERVE_OPTION, 0, 0, | ||
676 | N_("same as both -p and -s"), GRID+1 }, | ||
677 | {"delay-directory-restore", DELAY_DIRECTORY_RESTORE_OPTION, 0, 0, | ||
678 | @@ -2079,6 +2097,37 @@ parse_opt (int key, char *arg, struct ar | ||
679 | same_permissions_option = -1; | ||
680 | break; | ||
681 | |||
682 | + case ACLS_OPTION: | ||
683 | + set_archive_format ("posix"); | ||
684 | + acls_option = 1; | ||
685 | + break; | ||
686 | + | ||
687 | + case NO_ACLS_OPTION: | ||
688 | + acls_option = -1; | ||
689 | + break; | ||
690 | + | ||
691 | + case SELINUX_CONTEXT_OPTION: | ||
692 | + set_archive_format ("posix"); | ||
693 | + selinux_context_option = 1; | ||
694 | + break; | ||
695 | + | ||
696 | + case NO_SELINUX_CONTEXT_OPTION: | ||
697 | + selinux_context_option = -1; | ||
698 | + break; | ||
699 | + | ||
700 | + case XATTR_OPTION: | ||
701 | + set_archive_format ("posix"); | ||
702 | + if (!acls_option) acls_option = 1; | ||
703 | + if (!selinux_context_option) selinux_context_option = 1; | ||
704 | + xattrs_option = 1; | ||
705 | + break; | ||
706 | + | ||
707 | + case NO_XATTR_OPTION: | ||
708 | + if (!acls_option) acls_option = -1; | ||
709 | + if (!selinux_context_option) selinux_context_option = -1; | ||
710 | + xattrs_option = -1; | ||
711 | + break; | ||
712 | + | ||
713 | case RECURSION_OPTION: | ||
714 | recursion_option = FNM_LEADING_DIR; | ||
715 | break; | ||
716 | @@ -2461,6 +2510,29 @@ decode_options (int argc, char **argv) | ||
717 | || subcommand_option != LIST_SUBCOMMAND)) | ||
718 | USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives"))); | ||
719 | |||
720 | + /* star create's non-POSIX typed archives with xattr support, so allow the | ||
721 | + extra headers */ | ||
722 | + if ((acls_option > 0) | ||
723 | + && archive_format != POSIX_FORMAT | ||
724 | + && (subcommand_option != EXTRACT_SUBCOMMAND | ||
725 | + || subcommand_option != DIFF_SUBCOMMAND | ||
726 | + || subcommand_option != LIST_SUBCOMMAND)) | ||
727 | + USAGE_ERROR ((0, 0, _("--acls can be used only on POSIX archives"))); | ||
728 | + | ||
729 | + if ((selinux_context_option > 0) | ||
730 | + && archive_format != POSIX_FORMAT | ||
731 | + && (subcommand_option != EXTRACT_SUBCOMMAND | ||
732 | + || subcommand_option != DIFF_SUBCOMMAND | ||
733 | + || subcommand_option != LIST_SUBCOMMAND)) | ||
734 | + USAGE_ERROR ((0, 0, _("--selinux can be used only on POSIX archives"))); | ||
735 | + | ||
736 | + if ((xattrs_option > 0) | ||
737 | + && archive_format != POSIX_FORMAT | ||
738 | + && (subcommand_option != EXTRACT_SUBCOMMAND | ||
739 | + || subcommand_option != DIFF_SUBCOMMAND | ||
740 | + || subcommand_option != LIST_SUBCOMMAND)) | ||
741 | + USAGE_ERROR ((0, 0, _("--xattrs can be used only on POSIX archives"))); | ||
742 | + | ||
743 | /* If ready to unlink hierarchies, so we are for simpler files. */ | ||
744 | if (recursive_unlink_option) | ||
745 | old_files_option = UNLINK_FIRST_OLD_FILES; | ||
746 | @@ -2713,11 +2785,15 @@ void | ||
747 | tar_stat_destroy (struct tar_stat_info *st) | ||
748 | { | ||
749 | tar_stat_close (st); | ||
750 | + xheader_xattr_free (st->xattr_map, st->xattr_map_size); | ||
751 | free (st->orig_file_name); | ||
752 | free (st->file_name); | ||
753 | free (st->link_name); | ||
754 | free (st->uname); | ||
755 | free (st->gname); | ||
756 | + free (st->cntx_name); | ||
757 | + free (st->acls_a_ptr); | ||
758 | + free (st->acls_d_ptr); | ||
759 | free (st->sparse_map); | ||
760 | free (st->dumpdir); | ||
761 | xheader_destroy (&st->xhdr); | ||
762 | diff -urNp tar-1.24-orig/src/tar.h tar-1.24/src/tar.h | ||
763 | --- tar-1.24-orig/src/tar.h 2010-10-24 20:07:46.000000000 +0200 | ||
764 | +++ tar-1.24/src/tar.h 2010-10-25 10:24:52.567223606 +0200 | ||
765 | @@ -276,6 +276,14 @@ struct xheader | ||
766 | uintmax_t string_length; | ||
767 | }; | ||
768 | |||
769 | +/* Information about xattrs for a file. */ | ||
770 | +struct xattr_array | ||
771 | + { | ||
772 | + char *xkey; | ||
773 | + char *xval_ptr; | ||
774 | + size_t xval_len; | ||
775 | + }; | ||
776 | + | ||
777 | struct tar_stat_info | ||
778 | { | ||
779 | char *orig_file_name; /* name of file read from the archive header */ | ||
780 | @@ -287,6 +295,15 @@ struct tar_stat_info | ||
781 | |||
782 | char *uname; /* user name of owner */ | ||
783 | char *gname; /* group name of owner */ | ||
784 | + | ||
785 | + char *cntx_name; /* SELinux context for the current archive entry. */ | ||
786 | + | ||
787 | + char *acls_a_ptr; /* Access ACLs for the current archive entry. */ | ||
788 | + size_t acls_a_len; /* Access ACLs for the current archive entry. */ | ||
789 | + | ||
790 | + char *acls_d_ptr; /* Default ACLs for the current archive entry. */ | ||
791 | + size_t acls_d_len; /* Default ACLs for the current archive entry. */ | ||
792 | + | ||
793 | struct stat stat; /* regular filesystem stat */ | ||
794 | |||
795 | /* STAT doesn't always have access, data modification, and status | ||
796 | @@ -309,6 +326,9 @@ struct tar_stat_info | ||
797 | size_t sparse_map_size; /* Size of the sparse map */ | ||
798 | struct sp_array *sparse_map; | ||
799 | |||
800 | + size_t xattr_map_size; /* Size of the xattr map */ | ||
801 | + struct xattr_array *xattr_map; | ||
802 | + | ||
803 | /* Extended headers */ | ||
804 | struct xheader xhdr; | ||
805 | |||
806 | diff -urNp tar-1.24-orig/src/xattrs.c tar-1.24/src/xattrs.c | ||
807 | --- tar-1.24-orig/src/xattrs.c 1970-01-01 01:00:00.000000000 +0100 | ||
808 | +++ tar-1.24/src/xattrs.c 2010-10-25 10:24:52.568214736 +0200 | ||
809 | @@ -0,0 +1,489 @@ | ||
810 | +/* Create a tar archive. | ||
811 | + | ||
812 | + Copyright (C) 2006 Free Software Foundation, Inc. | ||
813 | + | ||
814 | + Written by James Antill, on 2006-07-27. | ||
815 | + | ||
816 | + This program is free software; you can redistribute it and/or modify it | ||
817 | + under the terms of the GNU General Public License as published by the | ||
818 | + Free Software Foundation; either version 2, or (at your option) any later | ||
819 | + version. | ||
820 | + | ||
821 | + This program is distributed in the hope that it will be useful, but | ||
822 | + WITHOUT ANY WARRANTY; without even the implied warranty of | ||
823 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||
824 | + Public License for more details. | ||
825 | + | ||
826 | + You should have received a copy of the GNU General Public License along | ||
827 | + with this program; if not, write to the Free Software Foundation, Inc., | ||
828 | + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
829 | + | ||
830 | +#include <system.h> | ||
831 | + | ||
832 | +#include <quotearg.h> | ||
833 | + | ||
834 | +#include "common.h" | ||
835 | + | ||
836 | + | ||
837 | +#ifndef HAVE_SELINUX_SELINUX_H | ||
838 | +# undef HAVE_LIBSELINUX | ||
839 | +#endif | ||
840 | + | ||
841 | +#ifndef HAVE_ATTR_XATTR_H | ||
842 | +# undef HAVE_XATTRS | ||
843 | +#endif | ||
844 | + | ||
845 | +#ifndef HAVE_SYS_ACL_H | ||
846 | +# undef HAVE_LIBACL | ||
847 | +#endif | ||
848 | + | ||
849 | +#ifdef HAVE_SELINUX_SELINUX_H | ||
850 | +# include <selinux/selinux.h> | ||
851 | +#endif | ||
852 | + | ||
853 | +#ifdef HAVE_ATTR_XATTR_H | ||
854 | +# include <attr/xattr.h> | ||
855 | +#endif | ||
856 | + | ||
857 | +#ifdef HAVE_SYS_ACL_H | ||
858 | +# include <sys/acl.h> | ||
859 | +#endif | ||
860 | + | ||
861 | + | ||
862 | +#if 0 /* unused by xattr's atm. */ | ||
863 | +static void xattrs__fd_get(struct tar_stat_info *st, | ||
864 | + char const *file_name, int fd, const char *attr, | ||
865 | + char **ret_ptr, size_t *ret_len) | ||
866 | +{ | ||
867 | +#ifdef HAVE_XATTRS | ||
868 | + static ssize_t asz = 1024; | ||
869 | + ssize_t ret = 0; | ||
870 | + static char *val = NULL; | ||
871 | + | ||
872 | + if (!val) val = xmalloc (asz); | ||
873 | + | ||
874 | + while (((ret = fgetxattr (fd, attr, val, asz)) == -1) && | ||
875 | + (errno == ERANGE)) | ||
876 | + { | ||
877 | + asz <<= 1; | ||
878 | + val = xrealloc (val, asz); | ||
879 | + } | ||
880 | + | ||
881 | + if (ret != -1) | ||
882 | + { | ||
883 | + *ret_ptr = xmemdup (val, ret + 1); | ||
884 | + *ret_len = ret; | ||
885 | + } | ||
886 | + else if (errno != ENOATTR) | ||
887 | + call_arg_warn ("fgetxattr", file_name); | ||
888 | +#endif | ||
889 | +} | ||
890 | +#endif | ||
891 | + | ||
892 | +static void xattrs__acls_get_a(struct tar_stat_info *st, | ||
893 | + char const *file_name, int fd, | ||
894 | + char **ret_ptr, size_t *ret_len) | ||
895 | +{ /* "system.posix_acl_access" */ | ||
896 | +#ifdef HAVE_LIBACL | ||
897 | + char *val = NULL; | ||
898 | + ssize_t len; | ||
899 | + acl_t acl; | ||
900 | + | ||
901 | + if (fd != -1) | ||
902 | + { | ||
903 | + if ((acl = acl_get_fd (fd)) == (acl_t)NULL) | ||
904 | + { | ||
905 | + if (errno != ENOTSUP) | ||
906 | + call_arg_warn ("acl_get_fd", file_name); | ||
907 | + return; | ||
908 | + } | ||
909 | + } | ||
910 | + else if ((acl = acl_get_file (file_name, ACL_TYPE_ACCESS)) == (acl_t)NULL) | ||
911 | + { | ||
912 | + if (errno != ENOTSUP) | ||
913 | + call_arg_warn ("acl_get_file", file_name); | ||
914 | + return; | ||
915 | + } | ||
916 | + | ||
917 | + | ||
918 | + val = acl_to_text(acl, &len); | ||
919 | + acl_free (acl); | ||
920 | + | ||
921 | + if (val == NULL) | ||
922 | + { | ||
923 | + call_arg_warn ("acl_to_text", file_name); | ||
924 | + return; | ||
925 | + } | ||
926 | + | ||
927 | + *ret_ptr = xstrdup (val); | ||
928 | + *ret_len = len; | ||
929 | + | ||
930 | + acl_free (val); | ||
931 | +#endif | ||
932 | +} | ||
933 | + | ||
934 | +static void xattrs__acls_get_d(struct tar_stat_info *st, | ||
935 | + char const *file_name, | ||
936 | + char **ret_ptr, size_t *ret_len) | ||
937 | +{ /* "system.posix_acl_default" */ | ||
938 | +#ifdef HAVE_LIBACL | ||
939 | + char *val = NULL; | ||
940 | + ssize_t len; | ||
941 | + acl_t acl; | ||
942 | + | ||
943 | + if ((acl = acl_get_file (file_name, ACL_TYPE_DEFAULT)) == (acl_t)NULL) | ||
944 | + { | ||
945 | + if (errno != ENOTSUP) | ||
946 | + call_arg_warn ("acl_get_file", file_name); | ||
947 | + return; | ||
948 | + } | ||
949 | + | ||
950 | + val = acl_to_text(acl, &len); | ||
951 | + acl_free (acl); | ||
952 | + | ||
953 | + if (val == NULL) | ||
954 | + { | ||
955 | + call_arg_warn ("acl_to_text", file_name); | ||
956 | + return; | ||
957 | + } | ||
958 | + | ||
959 | + *ret_ptr = xstrdup (val); | ||
960 | + *ret_len = len; | ||
961 | + | ||
962 | + acl_free (val); | ||
963 | +#endif | ||
964 | +} | ||
965 | + | ||
966 | +void xattrs_acls_get(struct tar_stat_info *st, char const *file_name, int fd, | ||
967 | + int xisfile) | ||
968 | +{ | ||
969 | + if (acls_option > 0) | ||
970 | + { | ||
971 | +#ifndef HAVE_LIBACL | ||
972 | + static int done = 0; | ||
973 | + if (!done) | ||
974 | + WARN ((0, 0, _("ACL support requested, but not available"))); | ||
975 | + done = 1; | ||
976 | +#endif | ||
977 | + xattrs__acls_get_a (st, file_name, fd, | ||
978 | + &st->acls_a_ptr, &st->acls_a_len); | ||
979 | + if (!xisfile) | ||
980 | + xattrs__acls_get_d (st, file_name, | ||
981 | + &st->acls_d_ptr, &st->acls_d_len); | ||
982 | + } | ||
983 | +} | ||
984 | + | ||
985 | +void xattrs_selinux_get(struct tar_stat_info *st, char const *file_name, int fd) | ||
986 | +{ | ||
987 | + if (selinux_context_option > 0) | ||
988 | + { | ||
989 | +#ifndef HAVE_LIBSELINUX | ||
990 | + static int done = 0; | ||
991 | + if (!done) | ||
992 | + WARN ((0, 0, _("SELinux support requested, but not available"))); | ||
993 | + done = 1; | ||
994 | +#else | ||
995 | + if (fd == -1) | ||
996 | + { | ||
997 | + if ((lgetfilecon (file_name, &st->cntx_name) == -1) && (errno != ENOTSUP) && (errno != ENODATA)) | ||
998 | + call_arg_warn ("lgetfilecon", file_name); | ||
999 | + } | ||
1000 | + else if ((fgetfilecon (fd, &st->cntx_name) == -1) && (errno != ENOTSUP) && (errno != ENODATA)) | ||
1001 | + call_arg_warn ("fgetfilecon", file_name); | ||
1002 | +#endif | ||
1003 | + } | ||
1004 | +} | ||
1005 | + | ||
1006 | +void xattrs_xattrs_get(struct tar_stat_info *st, char const *file_name, int fd) | ||
1007 | +{ | ||
1008 | + if (xattrs_option > 0) | ||
1009 | + { /* get all xattrs ... this include security.* and system.* if | ||
1010 | + available. We filter them here, but we have to filter them | ||
1011 | + in xattrs_xattrs_set() anyway. | ||
1012 | + */ | ||
1013 | + static ssize_t xsz = 1024; | ||
1014 | + static char *xatrs = NULL; | ||
1015 | + ssize_t xret = -1; | ||
1016 | + | ||
1017 | +#ifndef HAVE_XATTRS | ||
1018 | + static int done = 0; | ||
1019 | + if ((xattrs_option > 0) && !done) | ||
1020 | + WARN ((0, 0, _("Xattr support requested, but not available"))); | ||
1021 | + done = 1; | ||
1022 | +#else | ||
1023 | + | ||
1024 | + if (!xatrs) xatrs = xmalloc (xsz); | ||
1025 | + | ||
1026 | + while (((fd == -1) ? | ||
1027 | + ((xret = llistxattr (file_name, xatrs, xsz)) == -1) : | ||
1028 | + ((xret = flistxattr (fd, xatrs, xsz)) == -1)) && | ||
1029 | + (errno == ERANGE)) | ||
1030 | + { | ||
1031 | + xsz <<= 1; | ||
1032 | + xatrs = xrealloc (xatrs, xsz); | ||
1033 | + } | ||
1034 | + | ||
1035 | + if (xret == -1) | ||
1036 | + call_arg_warn ((fd == -1) ? "llistxattrs" : "flistxattrs", file_name); | ||
1037 | + else | ||
1038 | + { | ||
1039 | + const char *attr = xatrs; | ||
1040 | + static ssize_t asz = 1024; | ||
1041 | + static char *val = NULL; | ||
1042 | + | ||
1043 | + if (!val) val = xmalloc (asz); | ||
1044 | + | ||
1045 | + while (xret > 0) | ||
1046 | + { | ||
1047 | + size_t len = strlen (attr); | ||
1048 | + ssize_t aret = 0; | ||
1049 | + | ||
1050 | + /* Archive all xattrs during creation, decide at extraction time | ||
1051 | + * which ones are of interest/use for the target filesystem. */ | ||
1052 | + while (((fd == -1) ? | ||
1053 | + ((aret = lgetxattr (file_name, attr, val, asz)) == -1) : | ||
1054 | + ((aret = fgetxattr (fd, attr, val, asz)) == -1)) && | ||
1055 | + (errno == ERANGE)) | ||
1056 | + { | ||
1057 | + asz <<= 1; | ||
1058 | + val = xrealloc (val, asz); | ||
1059 | + } | ||
1060 | + | ||
1061 | + if (aret != -1) | ||
1062 | + xheader_xattr_add (st, attr, val, aret); | ||
1063 | + else if (errno != ENOATTR) | ||
1064 | + call_arg_warn ((fd==-1) ? "lgetxattr" : "fgetxattr", file_name); | ||
1065 | + | ||
1066 | + attr += len + 1; | ||
1067 | + xret -= len + 1; | ||
1068 | + } | ||
1069 | + } | ||
1070 | +#endif | ||
1071 | + } | ||
1072 | +} | ||
1073 | + | ||
1074 | +static void xattrs__fd_set(struct tar_stat_info const *st, | ||
1075 | + char const *file_name, char typeflag, | ||
1076 | + const char *attr, | ||
1077 | + const char *ptr, size_t len) | ||
1078 | +{ | ||
1079 | +#ifdef HAVE_XATTRS | ||
1080 | + if (ptr) | ||
1081 | + { | ||
1082 | + const char *sysname = "setxattr"; | ||
1083 | + int ret = -1; | ||
1084 | + | ||
1085 | + if (typeflag != SYMTYPE) | ||
1086 | + ret = setxattr (file_name, attr, ptr, len, 0); | ||
1087 | + else | ||
1088 | + { | ||
1089 | + sysname = "lsetxattr"; | ||
1090 | + ret = lsetxattr (file_name, attr, ptr, len, 0); | ||
1091 | + } | ||
1092 | + | ||
1093 | + /* do not print warnings when SELinux is disabled */ | ||
1094 | + if ((ret == -1) && (errno != EPERM) && (errno != ENOTSUP)) | ||
1095 | + call_arg_error(sysname, file_name); | ||
1096 | + } | ||
1097 | +#endif | ||
1098 | +} | ||
1099 | + | ||
1100 | +/* convert unix permissions into an ACL ... needed due to "default" ACLs */ | ||
1101 | +#ifdef HAVE_LIBACL | ||
1102 | +static acl_t perms2acl(int perms) | ||
1103 | +{ | ||
1104 | + char val[] = "user::---,group::---,other::---"; | ||
1105 | + /* 0123456789 123456789 123456789 123456789 */ | ||
1106 | + | ||
1107 | + /* user */ | ||
1108 | + if (perms & 0400) val[ 6] = 'r'; | ||
1109 | + if (perms & 0200) val[ 7] = 'w'; | ||
1110 | + if (perms & 0100) val[ 8] = 'x'; | ||
1111 | + | ||
1112 | + /* group */ | ||
1113 | + if (perms & 0040) val[17] = 'r'; | ||
1114 | + if (perms & 0020) val[18] = 'w'; | ||
1115 | + if (perms & 0010) val[19] = 'x'; | ||
1116 | + | ||
1117 | + /* other */ | ||
1118 | + if (perms & 0004) val[28] = 'r'; | ||
1119 | + if (perms & 0002) val[29] = 'w'; | ||
1120 | + if (perms & 0001) val[30] = 'x'; | ||
1121 | + | ||
1122 | + return (acl_from_text (val)); | ||
1123 | +} | ||
1124 | +#endif | ||
1125 | + | ||
1126 | +static char *skip_to_ext_fields(char *ptr) | ||
1127 | +{ | ||
1128 | + ptr += strcspn(ptr, ":,\n"); /* skip tag name. Ie. user/group/default/mask */ | ||
1129 | + | ||
1130 | + if (*ptr != ':') | ||
1131 | + return (ptr); /* error? no user/group field */ | ||
1132 | + ++ptr; | ||
1133 | + | ||
1134 | + ptr += strcspn(ptr, ":,\n"); /* skip user/group name */ | ||
1135 | + | ||
1136 | + if (*ptr != ':') | ||
1137 | + return (ptr); /* error? no perms field */ | ||
1138 | + ++ptr; | ||
1139 | + | ||
1140 | + ptr += strcspn(ptr, ":,\n"); /* skip perms */ | ||
1141 | + | ||
1142 | + if (*ptr != ':') | ||
1143 | + return (ptr); /* no extra fields */ | ||
1144 | + | ||
1145 | + return (ptr); | ||
1146 | +} | ||
1147 | + | ||
1148 | +/* The POSIX draft allows extra fields after the three main ones. Star | ||
1149 | + uses this to add a fourth field for user/group which is the numeric ID. | ||
1150 | + We just skip all extra fields atm. */ | ||
1151 | +static const char *fixup_extra_acl_fields(const char *ptr) | ||
1152 | +{ | ||
1153 | + char *src = (char *)ptr; | ||
1154 | + char *dst = (char *)ptr; | ||
1155 | + | ||
1156 | + while (*src) | ||
1157 | + { | ||
1158 | + const char *old = src; | ||
1159 | + size_t len = 0; | ||
1160 | + | ||
1161 | + src = skip_to_ext_fields(src); | ||
1162 | + len = src - old; | ||
1163 | + if (old != dst) memmove(dst, old, len); | ||
1164 | + dst += len; | ||
1165 | + | ||
1166 | + if (*src == ':') /* We have extra fields, skip them all */ | ||
1167 | + src += strcspn(src, "\n,"); | ||
1168 | + | ||
1169 | + if ((*src == '\n') || (*src == ',')) | ||
1170 | + *dst++ = *src++; /* also done when dst == src, but that's ok */ | ||
1171 | + } | ||
1172 | + if (src != dst) | ||
1173 | + *dst = 0; | ||
1174 | + | ||
1175 | + return ptr; | ||
1176 | +} | ||
1177 | + | ||
1178 | +static void xattrs__acls_set(struct tar_stat_info const *st, | ||
1179 | + char const *file_name, int type, | ||
1180 | + const char *ptr, size_t len) | ||
1181 | +{ /* "system.posix_acl_access" */ | ||
1182 | +#ifdef HAVE_LIBACL | ||
1183 | + acl_t acl; | ||
1184 | + | ||
1185 | + if (ptr) | ||
1186 | + { | ||
1187 | + /* assert (strlen (ptr) == len); */ | ||
1188 | + ptr = fixup_extra_acl_fields(ptr); | ||
1189 | + | ||
1190 | + acl = acl_from_text (ptr); | ||
1191 | + acls_option = 1; | ||
1192 | + } | ||
1193 | + else if (acls_option > 0) | ||
1194 | + acl = perms2acl (st->stat.st_mode); | ||
1195 | + else | ||
1196 | + return; /* don't call acl functions unless we first hit an ACL, or | ||
1197 | + --acls was passed explicitly */ | ||
1198 | + | ||
1199 | + if (acl == (acl_t)NULL) | ||
1200 | + { | ||
1201 | + call_arg_warn ("acl_from_text", file_name); | ||
1202 | + return; | ||
1203 | + } | ||
1204 | + | ||
1205 | + if (acl_set_file (file_name, type, acl) == -1) | ||
1206 | + { | ||
1207 | + if (errno != ENOTSUP) | ||
1208 | + call_arg_warn ("acl_set_file", file_name); | ||
1209 | + } | ||
1210 | + acl_free (acl); | ||
1211 | +#endif | ||
1212 | +} | ||
1213 | + | ||
1214 | +void xattrs_acls_set(struct tar_stat_info const *st, | ||
1215 | + char const *file_name, char typeflag) | ||
1216 | +{ | ||
1217 | + if ((acls_option >= 0) && (typeflag != SYMTYPE)) | ||
1218 | + { | ||
1219 | +#ifndef HAVE_LIBACL | ||
1220 | + static int done = 0; | ||
1221 | + if (!done) | ||
1222 | + WARN ((0, 0, _("ACL support requested, but not available"))); | ||
1223 | + done = 1; | ||
1224 | +#else | ||
1225 | + xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS, | ||
1226 | + st->acls_a_ptr, st->acls_a_len); | ||
1227 | + if ((typeflag == DIRTYPE) || (typeflag == GNUTYPE_DUMPDIR)) | ||
1228 | + xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT, | ||
1229 | + st->acls_d_ptr, st->acls_d_len); | ||
1230 | +#endif | ||
1231 | + } | ||
1232 | +} | ||
1233 | + | ||
1234 | +void xattrs_selinux_set(struct tar_stat_info const *st, | ||
1235 | + char const *file_name, char typeflag) | ||
1236 | +{ | ||
1237 | + if ((selinux_context_option >= 0) && st->cntx_name) | ||
1238 | + { | ||
1239 | + const char *sysname = "setfilecon"; | ||
1240 | + int ret = -1; | ||
1241 | + | ||
1242 | +#ifndef HAVE_LIBSELINUX | ||
1243 | + static int done = 0; | ||
1244 | + if (!done) | ||
1245 | + WARN ((0, 0, _("SELinux support requested, but not available"))); | ||
1246 | + done = 1; | ||
1247 | +#else | ||
1248 | + if (typeflag != SYMTYPE) | ||
1249 | + ret = setfilecon (file_name, st->cntx_name); | ||
1250 | + else | ||
1251 | + { | ||
1252 | + sysname = "lsetfilecon"; | ||
1253 | + ret = lsetfilecon (file_name, st->cntx_name); | ||
1254 | + } | ||
1255 | + | ||
1256 | + if ((ret == -1) && (errno == EPERM)) | ||
1257 | + call_arg_warn(sysname, file_name); | ||
1258 | + else if ((ret == -1) && (errno != EOPNOTSUPP)) | ||
1259 | + call_arg_error(sysname, file_name); | ||
1260 | +#endif | ||
1261 | + } | ||
1262 | +} | ||
1263 | + | ||
1264 | +void xattrs_xattrs_set(struct tar_stat_info const *st, | ||
1265 | + char const *file_name, char typeflag) | ||
1266 | +{ | ||
1267 | + if ((xattrs_option >= 0) && st->xattr_map_size) | ||
1268 | + { | ||
1269 | + size_t scan = 0; | ||
1270 | + | ||
1271 | +#ifndef HAVE_XATTRS | ||
1272 | + static int done = 0; | ||
1273 | + if (!done) | ||
1274 | + WARN ((0, 0, _("Xattr support requested, but not available"))); | ||
1275 | + done = 1; | ||
1276 | +#else | ||
1277 | + while (scan < st->xattr_map_size) | ||
1278 | + { | ||
1279 | + char *keyword = st->xattr_map[scan].xkey; | ||
1280 | + | ||
1281 | + /* assert (!memcpy (keyword, "SCHILY.xattr.", strlen("SCHILY.xattr."))); */ | ||
1282 | + keyword += strlen("SCHILY.xattr."); | ||
1283 | + | ||
1284 | + if (strncmp (keyword, "user.", strlen("user.")) && | ||
1285 | + strncmp (keyword, "lustre.", strlen("lustre.")) && | ||
1286 | + strncmp (keyword, "trusted.", strlen("trusted.")) && | ||
1287 | + strncmp (keyword, "security.NTACL", strlen("security.NTACL"))) | ||
1288 | + continue; /* don't try and set anything but normal xattrs */ | ||
1289 | + | ||
1290 | + xattrs__fd_set (st, file_name, typeflag, keyword, | ||
1291 | + st->xattr_map[scan].xval_ptr, | ||
1292 | + st->xattr_map[scan].xval_len); | ||
1293 | + | ||
1294 | + ++scan; | ||
1295 | + } | ||
1296 | +#endif | ||
1297 | + } | ||
1298 | +} | ||
1299 | diff -urNp tar-1.24-orig/src/xattrs.h tar-1.24/src/xattrs.h | ||
1300 | --- tar-1.24-orig/src/xattrs.h 1970-01-01 01:00:00.000000000 +0100 | ||
1301 | +++ tar-1.24/src/xattrs.h 2010-10-25 10:24:52.569214526 +0200 | ||
1302 | @@ -0,0 +1,14 @@ | ||
1303 | + | ||
1304 | +extern void xattrs_acls_get(struct tar_stat_info *st, | ||
1305 | + char const *file_name, int fd, int xisfile); | ||
1306 | +extern void xattrs_selinux_get(struct tar_stat_info *st, | ||
1307 | + char const *file_name, int fd); | ||
1308 | +extern void xattrs_xattrs_get(struct tar_stat_info *st, | ||
1309 | + char const *file_name, int fd); | ||
1310 | + | ||
1311 | +extern void xattrs_acls_set(struct tar_stat_info const *st, | ||
1312 | + char const *file_name, char typeflag); | ||
1313 | +extern void xattrs_selinux_set(struct tar_stat_info const *st, | ||
1314 | + char const *file_name, char typeflag); | ||
1315 | +extern void xattrs_xattrs_set(struct tar_stat_info const *st, | ||
1316 | + char const *file_name, char typeflag); | ||
1317 | diff -urNp tar-1.24-orig/src/xheader.c tar-1.24/src/xheader.c | ||
1318 | --- tar-1.24-orig/src/xheader.c 2010-10-24 20:07:46.000000000 +0200 | ||
1319 | +++ tar-1.24/src/xheader.c 2010-10-25 10:24:52.570223396 +0200 | ||
1320 | @@ -460,6 +460,74 @@ xheader_write_global (struct xheader *xh | ||
1321 | } | ||
1322 | } | ||
1323 | |||
1324 | +void xheader_xattr_init(struct tar_stat_info *st) | ||
1325 | +{ | ||
1326 | + st->xattr_map = NULL; | ||
1327 | + st->xattr_map_size = 0; | ||
1328 | +} | ||
1329 | + | ||
1330 | +void xheader_xattr_free(struct xattr_array *xattr_map, size_t xattr_map_size) | ||
1331 | +{ | ||
1332 | + size_t scan = 0; | ||
1333 | + | ||
1334 | + while (scan < xattr_map_size) | ||
1335 | + { | ||
1336 | + free (xattr_map[scan].xkey); | ||
1337 | + free (xattr_map[scan].xval_ptr); | ||
1338 | + | ||
1339 | + ++scan; | ||
1340 | + } | ||
1341 | + free (xattr_map); | ||
1342 | +} | ||
1343 | + | ||
1344 | +static void xheader_xattr__add(struct xattr_array **xattr_map, | ||
1345 | + size_t *xattr_map_size, | ||
1346 | + const char *key, const char *val, size_t len) | ||
1347 | +{ | ||
1348 | + size_t pos = (*xattr_map_size)++; | ||
1349 | + | ||
1350 | + *xattr_map = xrealloc (*xattr_map, | ||
1351 | + *xattr_map_size * sizeof(struct xattr_array)); | ||
1352 | + (*xattr_map)[pos].xkey = xstrdup (key); | ||
1353 | + (*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1); | ||
1354 | + (*xattr_map)[pos].xval_len = len; | ||
1355 | +} | ||
1356 | + | ||
1357 | +void xheader_xattr_add(struct tar_stat_info *st, | ||
1358 | + const char *key, const char *val, size_t len) | ||
1359 | +{ | ||
1360 | + size_t klen = strlen (key); | ||
1361 | + char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1); | ||
1362 | + char *tmp = xkey; | ||
1363 | + | ||
1364 | + tmp = stpcpy (tmp, "SCHILY.xattr."); | ||
1365 | + tmp = stpcpy (tmp, key); | ||
1366 | + | ||
1367 | + xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len); | ||
1368 | + | ||
1369 | + free (xkey); | ||
1370 | +} | ||
1371 | + | ||
1372 | +void xheader_xattr_copy(const struct tar_stat_info *st, | ||
1373 | + struct xattr_array **xattr_map, size_t *xattr_map_size) | ||
1374 | +{ | ||
1375 | + size_t scan = 0; | ||
1376 | + | ||
1377 | + *xattr_map = NULL; | ||
1378 | + *xattr_map_size = 0; | ||
1379 | + | ||
1380 | + while (scan < st->xattr_map_size) | ||
1381 | + { | ||
1382 | + char *key = st->xattr_map[scan].xkey; | ||
1383 | + char *val = st->xattr_map[scan].xval_ptr; | ||
1384 | + size_t len = st->xattr_map[scan].xval_len; | ||
1385 | + | ||
1386 | + xheader_xattr__add(xattr_map, xattr_map_size, key, val, len); | ||
1387 | + | ||
1388 | + ++scan; | ||
1389 | + } | ||
1390 | +} | ||
1391 | + | ||
1392 | |||
1393 | /* General Interface */ | ||
1394 | |||
1395 | @@ -473,6 +541,7 @@ struct xhdr_tab | ||
1396 | struct xheader *, void const *data); | ||
1397 | void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t); | ||
1398 | int flags; | ||
1399 | + bool prefix; | ||
1400 | }; | ||
1401 | |||
1402 | /* This declaration must be extern, because ISO C99 section 6.9.2 | ||
1403 | @@ -489,8 +558,17 @@ locate_handler (char const *keyword) | ||
1404 | struct xhdr_tab const *p; | ||
1405 | |||
1406 | for (p = xhdr_tab; p->keyword; p++) | ||
1407 | - if (strcmp (p->keyword, keyword) == 0) | ||
1408 | - return p; | ||
1409 | + if (p->prefix) | ||
1410 | + { | ||
1411 | + if (strncmp (p->keyword, keyword, strlen(p->keyword)) == 0) | ||
1412 | + return p; | ||
1413 | + } | ||
1414 | + else | ||
1415 | + { | ||
1416 | + if (strcmp (p->keyword, keyword) == 0) | ||
1417 | + return p; | ||
1418 | + } | ||
1419 | + | ||
1420 | return NULL; | ||
1421 | } | ||
1422 | |||
1423 | @@ -500,7 +578,7 @@ xheader_protected_pattern_p (const char | ||
1424 | struct xhdr_tab const *p; | ||
1425 | |||
1426 | for (p = xhdr_tab; p->keyword; p++) | ||
1427 | - if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0) | ||
1428 | + if (!p->prefix && (p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0) | ||
1429 | return true; | ||
1430 | return false; | ||
1431 | } | ||
1432 | @@ -511,7 +589,7 @@ xheader_protected_keyword_p (const char | ||
1433 | struct xhdr_tab const *p; | ||
1434 | |||
1435 | for (p = xhdr_tab; p->keyword; p++) | ||
1436 | - if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0) | ||
1437 | + if (!p->prefix && (p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0) | ||
1438 | return true; | ||
1439 | return false; | ||
1440 | } | ||
1441 | @@ -1470,6 +1548,71 @@ volume_filename_decoder (struct tar_stat | ||
1442 | } | ||
1443 | |||
1444 | static void | ||
1445 | +xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword, | ||
1446 | + struct xheader *xhdr, void const *data) | ||
1447 | +{ | ||
1448 | + code_string (st->cntx_name, keyword, xhdr); | ||
1449 | +} | ||
1450 | + | ||
1451 | +static void | ||
1452 | +xattr_selinux_decoder (struct tar_stat_info *st, | ||
1453 | + char const *keyword, char const *arg, size_t size) | ||
1454 | +{ | ||
1455 | + decode_string (&st->cntx_name, arg); | ||
1456 | +} | ||
1457 | + | ||
1458 | +static void | ||
1459 | +xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword, | ||
1460 | + struct xheader *xhdr, void const *data) | ||
1461 | +{ | ||
1462 | + xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len); | ||
1463 | +} | ||
1464 | + | ||
1465 | +static void | ||
1466 | +xattr_acls_a_decoder (struct tar_stat_info *st, | ||
1467 | + char const *keyword, char const *arg, size_t size) | ||
1468 | +{ | ||
1469 | + st->acls_a_ptr = xmemdup (arg, size + 1); | ||
1470 | + st->acls_a_len = size; | ||
1471 | +} | ||
1472 | + | ||
1473 | +static void | ||
1474 | +xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword, | ||
1475 | + struct xheader *xhdr, void const *data) | ||
1476 | +{ | ||
1477 | + xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len); | ||
1478 | +} | ||
1479 | + | ||
1480 | +static void | ||
1481 | +xattr_acls_d_decoder (struct tar_stat_info *st, | ||
1482 | + char const *keyword, char const *arg, size_t size) | ||
1483 | +{ | ||
1484 | + st->acls_d_ptr = xmemdup (arg, size + 1); | ||
1485 | + st->acls_d_len = size; | ||
1486 | +} | ||
1487 | + | ||
1488 | +static void | ||
1489 | +xattr_coder (struct tar_stat_info const *st , char const *keyword, | ||
1490 | + struct xheader *xhdr, void const *data) | ||
1491 | +{ | ||
1492 | + struct xattr_array *xattr_map = st->xattr_map; | ||
1493 | + const size_t *off = data; | ||
1494 | + xheader_print_n (xhdr, keyword, | ||
1495 | + xattr_map[*off].xval_ptr, xattr_map[*off].xval_len); | ||
1496 | +} | ||
1497 | + | ||
1498 | +static void | ||
1499 | +xattr_decoder (struct tar_stat_info *st, | ||
1500 | + char const *keyword, char const *arg, size_t size) | ||
1501 | +{ | ||
1502 | + char *xstr = NULL; | ||
1503 | + | ||
1504 | + xstr = xmemdup(arg, size + 1); | ||
1505 | + xheader_xattr_add(st, keyword + strlen("SCHILY.xattr."), xstr, size); | ||
1506 | + free(xstr); | ||
1507 | +} | ||
1508 | + | ||
1509 | +static void | ||
1510 | sparse_major_coder (struct tar_stat_info const *st, char const *keyword, | ||
1511 | struct xheader *xhdr, void const *data) | ||
1512 | { | ||
1513 | @@ -1506,53 +1649,53 @@ sparse_minor_decoder (struct tar_stat_in | ||
1514 | } | ||
1515 | |||
1516 | struct xhdr_tab const xhdr_tab[] = { | ||
1517 | - { "atime", atime_coder, atime_decoder, 0 }, | ||
1518 | - { "comment", dummy_coder, dummy_decoder, 0 }, | ||
1519 | - { "charset", dummy_coder, dummy_decoder, 0 }, | ||
1520 | - { "ctime", ctime_coder, ctime_decoder, 0 }, | ||
1521 | - { "gid", gid_coder, gid_decoder, 0 }, | ||
1522 | - { "gname", gname_coder, gname_decoder, 0 }, | ||
1523 | - { "linkpath", linkpath_coder, linkpath_decoder, 0 }, | ||
1524 | - { "mtime", mtime_coder, mtime_decoder, 0 }, | ||
1525 | - { "path", path_coder, path_decoder, 0 }, | ||
1526 | - { "size", size_coder, size_decoder, 0 }, | ||
1527 | - { "uid", uid_coder, uid_decoder, 0 }, | ||
1528 | - { "uname", uname_coder, uname_decoder, 0 }, | ||
1529 | + { "atime", atime_coder, atime_decoder, 0, false }, | ||
1530 | + { "comment", dummy_coder, dummy_decoder, 0, false }, | ||
1531 | + { "charset", dummy_coder, dummy_decoder, 0, false }, | ||
1532 | + { "ctime", ctime_coder, ctime_decoder, 0, false }, | ||
1533 | + { "gid", gid_coder, gid_decoder, 0, false }, | ||
1534 | + { "gname", gname_coder, gname_decoder, 0, false }, | ||
1535 | + { "linkpath", linkpath_coder, linkpath_decoder, 0, false }, | ||
1536 | + { "mtime", mtime_coder, mtime_decoder, 0, false }, | ||
1537 | + { "path", path_coder, path_decoder, 0, false }, | ||
1538 | + { "size", size_coder, size_decoder, 0, false }, | ||
1539 | + { "uid", uid_coder, uid_decoder, 0, false }, | ||
1540 | + { "uname", uname_coder, uname_decoder, 0, false }, | ||
1541 | |||
1542 | /* Sparse file handling */ | ||
1543 | { "GNU.sparse.name", path_coder, path_decoder, | ||
1544 | - XHDR_PROTECTED }, | ||
1545 | + XHDR_PROTECTED, false }, | ||
1546 | { "GNU.sparse.major", sparse_major_coder, sparse_major_decoder, | ||
1547 | - XHDR_PROTECTED }, | ||
1548 | + XHDR_PROTECTED, false }, | ||
1549 | { "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder, | ||
1550 | - XHDR_PROTECTED }, | ||
1551 | + XHDR_PROTECTED, false }, | ||
1552 | { "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder, | ||
1553 | - XHDR_PROTECTED }, | ||
1554 | + XHDR_PROTECTED, false }, | ||
1555 | { "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder, | ||
1556 | - XHDR_PROTECTED }, | ||
1557 | + XHDR_PROTECTED, false }, | ||
1558 | |||
1559 | /* tar 1.14 - 1.15.90 keywords. */ | ||
1560 | { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, | ||
1561 | - XHDR_PROTECTED }, | ||
1562 | + XHDR_PROTECTED, false }, | ||
1563 | /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x' | ||
1564 | headers, and each of them was meaningful. It confilcted with POSIX specs, | ||
1565 | which requires that "when extended header records conflict, the last one | ||
1566 | given in the header shall take precedence." */ | ||
1567 | { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder, | ||
1568 | - XHDR_PROTECTED }, | ||
1569 | + XHDR_PROTECTED, false }, | ||
1570 | { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder, | ||
1571 | - XHDR_PROTECTED }, | ||
1572 | + XHDR_PROTECTED, false }, | ||
1573 | /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */ | ||
1574 | { "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */, | ||
1575 | - sparse_map_decoder, 0 }, | ||
1576 | + sparse_map_decoder, 0, false }, | ||
1577 | |||
1578 | { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder, | ||
1579 | - XHDR_PROTECTED }, | ||
1580 | + XHDR_PROTECTED, false }, | ||
1581 | |||
1582 | /* Keeps the tape/volume label. May be present only in the global headers. | ||
1583 | Equivalent to GNUTYPE_VOLHDR. */ | ||
1584 | { "GNU.volume.label", volume_label_coder, volume_label_decoder, | ||
1585 | - XHDR_PROTECTED | XHDR_GLOBAL }, | ||
1586 | + XHDR_PROTECTED | XHDR_GLOBAL, false }, | ||
1587 | |||
1588 | /* These may be present in a first global header of the archive. | ||
1589 | They provide the same functionality as GNUTYPE_MULTIVOL header. | ||
1590 | @@ -1561,11 +1704,41 @@ struct xhdr_tab const xhdr_tab[] = { | ||
1591 | GNU.volume.offset keeps the offset of the start of this volume, | ||
1592 | otherwise kept in oldgnu_header.offset. */ | ||
1593 | { "GNU.volume.filename", volume_label_coder, volume_filename_decoder, | ||
1594 | - XHDR_PROTECTED | XHDR_GLOBAL }, | ||
1595 | + XHDR_PROTECTED | XHDR_GLOBAL, false }, | ||
1596 | { "GNU.volume.size", volume_size_coder, volume_size_decoder, | ||
1597 | - XHDR_PROTECTED | XHDR_GLOBAL }, | ||
1598 | + XHDR_PROTECTED | XHDR_GLOBAL, false }, | ||
1599 | { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, | ||
1600 | - XHDR_PROTECTED | XHDR_GLOBAL }, | ||
1601 | - | ||
1602 | - { NULL, NULL, NULL, 0 } | ||
1603 | + XHDR_PROTECTED | XHDR_GLOBAL, false }, | ||
1604 | + | ||
1605 | + /* We get the SELinux value from filecon, so add a namespace for SELinux | ||
1606 | + instead of storing it in SCHILY.xattr.* (which would be RAW). */ | ||
1607 | + { "RHT.security.selinux", | ||
1608 | + xattr_selinux_coder, xattr_selinux_decoder, 0, false }, | ||
1609 | + | ||
1610 | + /* ACLs, use the star format... */ | ||
1611 | + { "SCHILY.acl.access", | ||
1612 | + xattr_acls_a_coder, xattr_acls_a_decoder, 0, false }, | ||
1613 | + | ||
1614 | + { "SCHILY.acl.default", | ||
1615 | + xattr_acls_d_coder, xattr_acls_d_decoder, 0, false }, | ||
1616 | + | ||
1617 | + /* FIXME: These are compat. for FC-6 ... we shipped a tar using the generic | ||
1618 | + header names by accident. */ | ||
1619 | + { "SCHILY.xattr.security.selinux", | ||
1620 | + xattr_selinux_coder, xattr_selinux_decoder, 0, false }, | ||
1621 | + { "SCHILY.xattr.system.posix_acl_access", | ||
1622 | + xattr_acls_a_coder, xattr_acls_a_decoder, 0, false }, | ||
1623 | + { "SCHILY.xattr.system.posix_acl_default", | ||
1624 | + xattr_acls_d_coder, xattr_acls_d_decoder, 0, false }, | ||
1625 | + | ||
1626 | + /* xattrs use the star format. note we only save some variants... */ | ||
1627 | + { "SCHILY.xattr.user", xattr_coder, xattr_decoder, 0, true }, | ||
1628 | + { "SCHILY.xattr.trusted", xattr_coder, xattr_decoder, 0, true }, | ||
1629 | + { "SCHILY.xattr.lustre", xattr_coder, xattr_decoder, 0, true }, | ||
1630 | + { "SCHILY.xattr.security.NTACL", xattr_coder, xattr_decoder, 0, true }, | ||
1631 | + | ||
1632 | + /* ignore everything else in the xattr namespaces... */ | ||
1633 | + { "SCHILY.xattr", dummy_coder, dummy_decoder, 0, true }, | ||
1634 | + | ||
1635 | + { NULL, NULL, NULL, 0, false } | ||
1636 | }; | ||
diff --git a/recipes-extended/tar/tar_1.26.bbappend b/recipes-extended/tar/tar_1.26.bbappend new file mode 100644 index 0000000..2996853 --- /dev/null +++ b/recipes-extended/tar/tar_1.26.bbappend | |||
@@ -0,0 +1,9 @@ | |||
1 | PR .= ".1" | ||
2 | |||
3 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
4 | |||
5 | SRC_URI += "file://tar-1.24-xattrs.patch" | ||
6 | |||
7 | DEPENDS += "${@base_contains('DISTRO_FEATURES', 'selinux', 'libselinux', '', d)}" | ||
8 | |||
9 | EXTRA_OECONF += "${@base_contains('DISTRO_FEATURES', 'selinux', '--enable-selinux', '--disable-selinux', d)}" | ||