]> wimlib.net Git - wimlib/blob - src/unix_apply.c
unix_apply.c: support extracting xattrs
[wimlib] / src / unix_apply.c
1 /*
2  * unix_apply.c - Code to apply files from a WIM image on UNIX.
3  */
4
5 /*
6  * Copyright (C) 2012-2016 Eric Biggers
7  *
8  * This file is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the Free
10  * Software Foundation; either version 3 of the License, or (at your option) any
11  * later version.
12  *
13  * This file is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this file; if not, see http://www.gnu.org/licenses/.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #ifdef HAVE_SYS_XATTR_H
33 #  include <sys/xattr.h>
34 #endif
35 #include <unistd.h>
36
37 #include "wimlib/apply.h"
38 #include "wimlib/assert.h"
39 #include "wimlib/blob_table.h"
40 #include "wimlib/dentry.h"
41 #include "wimlib/error.h"
42 #include "wimlib/file_io.h"
43 #include "wimlib/reparse.h"
44 #include "wimlib/timestamp.h"
45 #include "wimlib/unix_data.h"
46 #include "wimlib/xattr.h"
47
48 /* We don't require O_NOFOLLOW, but the advantage of having it is that if we
49  * need to extract a file to a location at which there exists a symbolic link,
50  * open(..., O_NOFOLLOW | ...) recognizes the symbolic link rather than
51  * following it and creating the file somewhere else.  (Equivalent to
52  * FILE_OPEN_REPARSE_POINT on Windows.)  */
53 #ifndef O_NOFOLLOW
54 #  define O_NOFOLLOW 0
55 #endif
56
57 static int
58 unix_get_supported_features(const char *target,
59                             struct wim_features *supported_features)
60 {
61         supported_features->sparse_files = 1;
62         supported_features->hard_links = 1;
63         supported_features->symlink_reparse_points = 1;
64         supported_features->unix_data = 1;
65         supported_features->timestamps = 1;
66         supported_features->case_sensitive_filenames = 1;
67 #ifdef HAVE_XATTR_SUPPORT
68         supported_features->linux_xattrs = 1;
69 #endif
70         return 0;
71 }
72
73 #define NUM_PATHBUFS 2  /* We need 2 when creating hard links  */
74
75 struct unix_apply_ctx {
76         /* Extract flags, the pointer to the WIMStruct, etc.  */
77         struct apply_ctx common;
78
79         /* Buffers for building extraction paths (allocated).  */
80         char *pathbufs[NUM_PATHBUFS];
81
82         /* Index of next pathbuf to use  */
83         unsigned which_pathbuf;
84
85         /* Currently open file descriptors for extraction  */
86         struct filedes open_fds[MAX_OPEN_FILES];
87
88         /* Number of currently open file descriptors in open_fds, starting from
89          * the beginning of the array.  */
90         unsigned num_open_fds;
91
92         /* For each currently open file, whether we're writing to it in "sparse"
93          * mode or not.  */
94         bool is_sparse_file[MAX_OPEN_FILES];
95
96         /* Whether is_sparse_file[] is true for any currently open file  */
97         bool any_sparse_files;
98
99         /* Allocated buffer for reading blob data when it cannot be extracted
100          * directly  */
101         u8 *data_buffer;
102
103         /* Pointer to the next byte in @data_buffer to fill  */
104         u8 *data_buffer_ptr;
105
106         /* Size allocated in @data_buffer  */
107         size_t data_buffer_size;
108
109         /* Absolute path to the target directory (allocated buffer).  Only set
110          * if needed for absolute symbolic link fixups.  */
111         char *target_abspath;
112
113         /* Number of characters in target_abspath.  */
114         size_t target_abspath_nchars;
115
116         /* Number of special files we couldn't create due to EPERM  */
117         unsigned long num_special_files_ignored;
118
119 #ifdef HAVE_XATTR_SUPPORT
120         /* Delayed xattrs saved in memory (deduplicated)  */
121         struct blob_table *delayed_xattrs;
122 #endif
123 };
124
125 /* Returns the number of characters needed to represent the path to the
126  * specified @dentry when extracted, not including the null terminator or the
127  * path to the target directory itself.  */
128 static size_t
129 unix_dentry_path_length(const struct wim_dentry *dentry)
130 {
131         size_t len = 0;
132         const struct wim_dentry *d;
133
134         d = dentry;
135         do {
136                 len += d->d_extraction_name_nchars + 1;
137                 d = d->d_parent;
138         } while (!dentry_is_root(d) && will_extract_dentry(d));
139
140         return len;
141 }
142
143 /* Returns the maximum number of characters needed to represent the path to any
144  * dentry in @dentry_list when extracted, including the null terminator and the
145  * path to the target directory itself.  */
146 static size_t
147 unix_compute_path_max(const struct list_head *dentry_list,
148                       const struct unix_apply_ctx *ctx)
149 {
150         size_t max = 0;
151         size_t len;
152         const struct wim_dentry *dentry;
153
154         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
155                 len = unix_dentry_path_length(dentry);
156                 if (len > max)
157                         max = len;
158         }
159
160         /* Account for target and null terminator.  */
161         return ctx->common.target_nchars + max + 1;
162 }
163
164 /* Prepare to read the next blob, which has size @blob_size, into an in-memory
165  * buffer.  */
166 static bool
167 prepare_data_buffer(struct unix_apply_ctx *ctx, u64 blob_size)
168 {
169         if (blob_size > ctx->data_buffer_size) {
170                 /* Larger buffer needed.  */
171                 void *new_buffer;
172                 if ((size_t)blob_size != blob_size)
173                         return false;
174                 new_buffer = REALLOC(ctx->data_buffer, blob_size);
175                 if (!new_buffer)
176                         return false;
177                 ctx->data_buffer = new_buffer;
178                 ctx->data_buffer_size = blob_size;
179         }
180         /* On the first call this changes data_buffer_ptr from NULL, which tells
181          * unix_extract_chunk() that the data buffer needs to be filled while
182          * reading the stream data.  */
183         ctx->data_buffer_ptr = ctx->data_buffer;
184         return true;
185 }
186
187 /* Builds and returns the filesystem path to which to extract @dentry.
188  * This cycles through NUM_PATHBUFS different buffers.  */
189 static const char *
190 unix_build_extraction_path(const struct wim_dentry *dentry,
191                            struct unix_apply_ctx *ctx)
192 {
193         char *pathbuf;
194         char *p;
195         const struct wim_dentry *d;
196
197         pathbuf = ctx->pathbufs[ctx->which_pathbuf];
198         ctx->which_pathbuf = (ctx->which_pathbuf + 1) % NUM_PATHBUFS;
199
200         p = &pathbuf[ctx->common.target_nchars +
201                      unix_dentry_path_length(dentry)];
202         *p = '\0';
203         d = dentry;
204         do {
205                 p -= d->d_extraction_name_nchars;
206                 if (d->d_extraction_name_nchars)
207                         memcpy(p, d->d_extraction_name,
208                                d->d_extraction_name_nchars);
209                 *--p = '/';
210                 d = d->d_parent;
211         } while (!dentry_is_root(d) && will_extract_dentry(d));
212
213         return pathbuf;
214 }
215
216 /* This causes the next call to unix_build_extraction_path() to use the same
217  * path buffer as the previous call.  */
218 static void
219 unix_reuse_pathbuf(struct unix_apply_ctx *ctx)
220 {
221         ctx->which_pathbuf = (ctx->which_pathbuf - 1) % NUM_PATHBUFS;
222 }
223
224 /* Builds and returns the filesystem path to which to extract an unspecified
225  * alias of the @inode.  This cycles through NUM_PATHBUFS different buffers.  */
226 static const char *
227 unix_build_inode_extraction_path(const struct wim_inode *inode,
228                                  struct unix_apply_ctx *ctx)
229 {
230         return unix_build_extraction_path(inode_first_extraction_dentry(inode), ctx);
231 }
232
233 /* Should the specified file be extracted as a directory on UNIX?  We extract
234  * the file as a directory if FILE_ATTRIBUTE_DIRECTORY is set and the file does
235  * not have a symlink or junction reparse point.  It *may* have a different type
236  * of reparse point.  */
237 static inline bool
238 should_extract_as_directory(const struct wim_inode *inode)
239 {
240         return (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) &&
241                 !inode_is_symlink(inode);
242 }
243
244 /* Sets the timestamps on a file being extracted. */
245 static int
246 unix_set_timestamps(const char *path, u64 atime, u64 mtime)
247 {
248 #ifdef HAVE_UTIMENSAT
249         {
250                 struct timespec times[2];
251
252                 times[0] = wim_timestamp_to_timespec(atime);
253                 times[1] = wim_timestamp_to_timespec(mtime);
254
255                 if (utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW) == 0)
256                         return 0;
257                 if (errno != ENOSYS)
258                         return -1;
259         }
260 #endif
261         {
262                 struct timeval times[2];
263
264                 times[0] = wim_timestamp_to_timeval(atime);
265                 times[1] = wim_timestamp_to_timeval(mtime);
266
267                 return lutimes(path, times);
268         }
269 }
270
271 /* Set metadata on an extracted file. */
272 static int
273 unix_set_metadata(const struct wim_inode *inode, struct unix_apply_ctx *ctx)
274 {
275         const char *path = unix_build_inode_extraction_path(inode, ctx);
276         struct wimlib_unix_data unix_data;
277
278         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA)
279             && inode_get_unix_data(inode, &unix_data))
280         {
281                 u32 uid = unix_data.uid;
282                 u32 gid = unix_data.gid;
283                 u32 mode = unix_data.mode;
284
285                 if (lchown(path, uid, gid) != 0) {
286                         if (ctx->common.extract_flags &
287                             WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
288                         {
289                                 ERROR_WITH_ERRNO("Can't set uid=%"PRIu32" and "
290                                                  "gid=%"PRIu32" on \"%s\"",
291                                                  uid, gid, path);
292                                 return WIMLIB_ERR_SET_SECURITY;
293                         }
294                         WARNING_WITH_ERRNO("Can't set uid=%"PRIu32" and "
295                                            "gid=%"PRIu32" on \"%s\"",
296                                            uid, gid, path);
297                 }
298
299                 if (!inode_is_symlink(inode) && chmod(path, mode) != 0) {
300                         if (ctx->common.extract_flags &
301                             WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
302                         {
303                                 ERROR_WITH_ERRNO("Can't set mode=0%"PRIo32" "
304                                                  "on \"%s\"", mode, path);
305                                 return WIMLIB_ERR_SET_SECURITY;
306                         }
307                         WARNING_WITH_ERRNO("Can't set mode=0%"PRIo32" "
308                                            "on \"%s\"", mode, path);
309                 }
310         }
311
312         if (unix_set_timestamps(path, inode->i_last_access_time,
313                                 inode->i_last_write_time) != 0)
314         {
315                 if (ctx->common.extract_flags &
316                     WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS)
317                 {
318                         ERROR_WITH_ERRNO("Can't set timestamps on \"%s\"", path);
319                         return WIMLIB_ERR_SET_TIMESTAMPS;
320                 }
321                 WARNING_WITH_ERRNO("Can't set timestamps on \"%s\"", path);
322         }
323         return 0;
324 }
325
326 /*
327  * Extract all needed aliases of the specified @inode, where the first alias has
328  * already been extracted to @first_path.
329  */
330 static int
331 unix_create_hardlinks(const struct wim_inode *inode,
332                       const char *first_path, struct unix_apply_ctx *ctx)
333 {
334         const struct wim_dentry *dentry;
335         const char *newpath;
336
337         inode_for_each_extraction_alias(dentry, inode) {
338                 if (dentry == inode_first_extraction_dentry(inode))
339                         continue;
340                 newpath = unix_build_extraction_path(dentry, ctx);
341         retry_link:
342                 if (link(first_path, newpath)) {
343                         if (errno == EEXIST && !unlink(newpath))
344                                 goto retry_link;
345                         ERROR_WITH_ERRNO("Can't create hard link "
346                                          "\"%s\" => \"%s\"", newpath, first_path);
347                         return WIMLIB_ERR_LINK;
348                 }
349                 unix_reuse_pathbuf(ctx);
350         }
351         return 0;
352 }
353
354 static int
355 unix_create_directory(const struct wim_dentry *dentry,
356                       struct unix_apply_ctx *ctx)
357 {
358         const char *path = unix_build_extraction_path(dentry, ctx);
359         struct stat stbuf;
360
361         if (mkdir(path, 0755) &&
362             /* It's okay if the path already exists, as long as it's a
363              * directory.  */
364             !(errno == EEXIST && !lstat(path, &stbuf) && S_ISDIR(stbuf.st_mode)))
365         {
366                 ERROR_WITH_ERRNO("Can't create directory \"%s\"", path);
367                 return WIMLIB_ERR_MKDIR;
368         }
369
370         return 0;
371 }
372
373 static int
374 unix_create_nondirectory(const struct wim_inode *inode,
375                          struct unix_apply_ctx *ctx)
376 {
377         const char *path = unix_build_inode_extraction_path(inode, ctx);
378         struct wimlib_unix_data unix_data;
379
380         /* Recognize special files in UNIX_DATA mode  */
381         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) &&
382             inode_get_unix_data(inode, &unix_data) &&
383             !S_ISREG(unix_data.mode))
384         {
385         retry_mknod:
386                 if (mknod(path, unix_data.mode, unix_data.rdev)) {
387                         if (errno == EPERM) {
388                                 WARNING_WITH_ERRNO("Can't create special "
389                                                    "file \"%s\"", path);
390                                 ctx->num_special_files_ignored++;
391                                 return 0;
392                         }
393                         if (errno == EEXIST && !unlink(path))
394                                 goto retry_mknod;
395                         ERROR_WITH_ERRNO("Can't create special file \"%s\"",
396                                          path);
397                         return WIMLIB_ERR_MKNOD;
398                 }
399         } else {
400                 int fd;
401
402         retry_create:
403                 fd = open(path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
404                 if (fd < 0) {
405                         if (errno == EEXIST && !unlink(path))
406                                 goto retry_create;
407                         ERROR_WITH_ERRNO("Can't create regular file \"%s\"", path);
408                         return WIMLIB_ERR_OPEN;
409                 }
410                 if (close(fd)) {
411                         ERROR_WITH_ERRNO("Error closing \"%s\"", path);
412                         return WIMLIB_ERR_WRITE;
413                 }
414         }
415
416         return unix_create_hardlinks(inode, path, ctx);
417 }
418
419 /* Create all files (and directories) except for symlinks. */
420 static int
421 unix_create_file_structure(const struct list_head *dentry_list,
422                            struct unix_apply_ctx *ctx)
423 {
424         const struct wim_dentry *dentry;
425         const struct wim_inode *inode;
426         int ret;
427
428         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
429                 inode = dentry->d_inode;
430                 if (!should_extract_as_directory(inode))
431                         continue;
432                 ret = unix_create_directory(dentry, ctx);
433                 if (!ret)
434                         ret = report_file_created(&ctx->common);
435                 if (ret)
436                         return ret;
437         }
438         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
439                 inode = dentry->d_inode;
440                 if (should_extract_as_directory(inode) ||
441                     inode_is_symlink(inode) ||
442                     dentry != inode_first_extraction_dentry(inode))
443                         continue;
444                 ret = unix_create_nondirectory(inode, ctx);
445                 if (!ret)
446                         ret = report_file_created(&ctx->common);
447                 if (ret)
448                         return ret;
449         }
450         return 0;
451 }
452
453 static void
454 unix_count_inodes(const struct list_head *dentry_list,
455                   u64 *full_count, u64 *symlink_count)
456 {
457         const struct wim_dentry *dentry;
458
459         *full_count = 0;
460         *symlink_count = 0;
461
462         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
463                 if (dentry != inode_first_extraction_dentry(dentry->d_inode))
464                         continue;
465                 ++*full_count;
466                 if (inode_is_symlink(dentry->d_inode))
467                         ++*symlink_count;
468         }
469 }
470
471 #ifdef HAVE_XATTR_SUPPORT
472
473 static int
474 apply_xattrs(struct wim_inode *inode, const void *entries,
475              size_t entries_size, struct unix_apply_ctx *ctx)
476 {
477         const void * const entries_end = entries + entries_size;
478         const char *path = unix_build_inode_extraction_path(inode, ctx);
479         char name[XATTR_NAME_MAX + 1];
480
481         for (const struct wimlib_xattr_entry *entry = entries;
482              (void *)entry < entries_end; entry = xattr_entry_next(entry))
483         {
484                 u16 name_len;
485                 const void *value;
486                 u32 value_len;
487
488                 if (!valid_xattr_entry(entry, entries_end - (void *)entry)) {
489                         ERROR("\"%s\": extended attribute stream is corrupt",
490                                 path);
491                         return WIMLIB_ERR_INVALID_EXTENDED_ATTRIBUTE;
492                 }
493                 name_len = le16_to_cpu(entry->name_len);
494                 memcpy(name, entry->name, name_len);
495                 name[name_len] = '\0';
496
497                 value = entry->name + name_len;
498                 value_len = le32_to_cpu(entry->value_len);
499
500                 if (lsetxattr(path, name, value, value_len, 0) != 0) {
501                         if (ctx->common.extract_flags &
502                             WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
503                         {
504                                 ERROR_WITH_ERRNO("\"%s\": unable to set "
505                                                  "extended attribute %s",
506                                                  path, name);
507                                 return WIMLIB_ERR_SET_SECURITY;
508                         }
509                         WARNING_WITH_ERRNO("\"%s\": unable to set extended "
510                                            "attribute %s", path, name);
511                 }
512         }
513         return 0;
514 }
515
516 static int
517 apply_delayed_xattrs(struct list_head *dentry_list, struct unix_apply_ctx *ctx)
518 {
519         struct wim_dentry *dentry;
520
521         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
522                 struct wim_inode *inode = dentry->d_inode;
523                 const struct blob_descriptor *blob;
524                 const struct wim_inode_stream *strm;
525                 int ret;
526
527                 if (!inode_is_symlink(inode))
528                         continue;
529                 if (dentry != inode_first_extraction_dentry(inode))
530                         continue;
531                 strm = inode_get_stream(inode, STREAM_TYPE_LINUX_XATTR,
532                                         NO_STREAM_NAME);
533                 if (!strm)
534                         continue;
535                 blob = lookup_blob(ctx->delayed_xattrs, stream_hash(strm));
536                 if (!blob)
537                         continue;
538                 wimlib_assert(blob->blob_location == BLOB_IN_ATTACHED_BUFFER);
539                 ret = apply_xattrs(inode, blob->attached_buffer, blob->size,
540                                    ctx);
541                 if (ret)
542                         return ret;
543         }
544         return 0;
545 }
546 #endif /* HAVE_XATTR_SUPPORT */
547
548 static int
549 unix_create_symlink(const struct wim_inode *inode, const char *path,
550                     size_t rpdatalen, struct unix_apply_ctx *ctx)
551 {
552         char target[REPARSE_POINT_MAX_SIZE];
553         struct blob_descriptor blob_override;
554         int ret;
555
556         blob_set_is_located_in_attached_buffer(&blob_override,
557                                                ctx->data_buffer, rpdatalen);
558
559         ret = wim_inode_readlink(inode, target, sizeof(target) - 1,
560                                  &blob_override,
561                                  ctx->target_abspath,
562                                  ctx->target_abspath_nchars);
563         if (unlikely(ret < 0)) {
564                 errno = -ret;
565                 return WIMLIB_ERR_READLINK;
566         }
567         target[ret] = '\0';
568
569 retry_symlink:
570         if (symlink(target, path)) {
571                 if (errno == EEXIST && !unlink(path))
572                         goto retry_symlink;
573                 return WIMLIB_ERR_LINK;
574         }
575         return 0;
576 }
577
578 static void
579 unix_cleanup_open_fds(struct unix_apply_ctx *ctx, unsigned offset)
580 {
581         for (unsigned i = offset; i < ctx->num_open_fds; i++)
582                 filedes_close(&ctx->open_fds[i]);
583         ctx->num_open_fds = 0;
584         ctx->any_sparse_files = false;
585 }
586
587 static int
588 unix_begin_extract_blob_instance(const struct blob_descriptor *blob,
589                                  const struct wim_inode *inode,
590                                  const struct wim_inode_stream *strm,
591                                  struct unix_apply_ctx *ctx)
592 {
593         const char *path = unix_build_inode_extraction_path(inode, ctx);
594         int fd;
595
596         if (strm->stream_type == STREAM_TYPE_REPARSE_POINT ||
597             strm->stream_type == STREAM_TYPE_LINUX_XATTR) {
598                 /* On UNIX, symbolic links must be created with symlink(), which
599                  * requires that the full link target be available.
600                  * Similar for extended attribute "streams".  */
601                 if (!prepare_data_buffer(ctx, blob->size))
602                         return WIMLIB_ERR_NOMEM;
603                 return 0;
604         }
605
606         wimlib_assert(stream_is_unnamed_data_stream(strm));
607
608         /* Unnamed data stream of "regular" file  */
609
610         /* This should be ensured by extract_blob_list()  */
611         wimlib_assert(ctx->num_open_fds < MAX_OPEN_FILES);
612
613         fd = open(path, O_WRONLY | O_NOFOLLOW);
614         if (fd < 0) {
615                 ERROR_WITH_ERRNO("Can't open regular file \"%s\"", path);
616                 return WIMLIB_ERR_OPEN;
617         }
618         if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
619                 ctx->is_sparse_file[ctx->num_open_fds] = true;
620                 ctx->any_sparse_files = true;
621         } else {
622                 ctx->is_sparse_file[ctx->num_open_fds] = false;
623 #ifdef HAVE_POSIX_FALLOCATE
624                 posix_fallocate(fd, 0, blob->size);
625 #endif
626         }
627         filedes_init(&ctx->open_fds[ctx->num_open_fds++], fd);
628         return 0;
629 }
630
631 /* Called when starting to read a blob for extraction  */
632 static int
633 unix_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
634 {
635         struct unix_apply_ctx *ctx = _ctx;
636         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
637
638         for (u32 i = 0; i < blob->out_refcnt; i++) {
639                 int ret = unix_begin_extract_blob_instance(blob,
640                                                            targets[i].inode,
641                                                            targets[i].stream,
642                                                            ctx);
643                 if (ret) {
644                         ctx->data_buffer_ptr = NULL;
645                         unix_cleanup_open_fds(ctx, 0);
646                         return ret;
647                 }
648         }
649         return 0;
650 }
651
652 /* Called when the next chunk of a blob has been read for extraction  */
653 static int
654 unix_extract_chunk(const struct blob_descriptor *blob, u64 offset,
655                    const void *chunk, size_t size, void *_ctx)
656 {
657         struct unix_apply_ctx *ctx = _ctx;
658         const void * const end = chunk + size;
659         const void *p;
660         bool zeroes;
661         size_t len;
662         unsigned i;
663         int ret;
664
665         /*
666          * For sparse files, only write nonzero regions.  This lets the
667          * filesystem use holes to represent zero regions.
668          */
669         for (p = chunk; p != end; p += len, offset += len) {
670                 zeroes = maybe_detect_sparse_region(p, end - p, &len,
671                                                     ctx->any_sparse_files);
672                 for (i = 0; i < ctx->num_open_fds; i++) {
673                         if (!zeroes || !ctx->is_sparse_file[i]) {
674                                 ret = full_pwrite(&ctx->open_fds[i],
675                                                   p, len, offset);
676                                 if (ret)
677                                         goto err;
678                         }
679                 }
680         }
681
682         /* Copy the data chunk into the buffer (if needed)  */
683         if (ctx->data_buffer_ptr)
684                 ctx->data_buffer_ptr = mempcpy(ctx->data_buffer_ptr,
685                                                chunk, size);
686         return 0;
687
688 err:
689         ERROR_WITH_ERRNO("Error writing data to filesystem");
690         return ret;
691 }
692
693 /* Called when a blob has been fully read for extraction  */
694 static int
695 unix_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
696 {
697         struct unix_apply_ctx *ctx = _ctx;
698         int ret;
699         unsigned j;
700         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
701
702         ctx->data_buffer_ptr = NULL;
703
704         if (status) {
705                 unix_cleanup_open_fds(ctx, 0);
706                 return status;
707         }
708
709         j = 0;
710         ret = 0;
711         for (u32 i = 0; i < blob->out_refcnt; i++) {
712                 struct wim_inode *inode = targets[i].inode;
713                 struct wim_inode_stream *strm = targets[i].stream;
714
715                 if (strm->stream_type == STREAM_TYPE_REPARSE_POINT) {
716                         /* We finally have the symlink data, so we can create
717                          * the symlink.  */
718                         const char *path;
719
720                         path = unix_build_inode_extraction_path(inode, ctx);
721                         ret = unix_create_symlink(inode, path, blob->size, ctx);
722                         if (ret) {
723                                 ERROR_WITH_ERRNO("Can't create symbolic link "
724                                                  "\"%s\"", path);
725                                 break;
726                         }
727                 }
728         #ifdef HAVE_XATTR_SUPPORT
729                 else if (strm->stream_type == STREAM_TYPE_LINUX_XATTR) {
730                         if (inode_is_symlink(inode)) {
731                                 /*
732                                  * We can't apply xattrs to a symlink until it
733                                  * has been created, but that requires the
734                                  * reparse stream and we might be given the
735                                  * reparse and xattr streams in either order.
736                                  * Solution: cache xattrs for symlinks in
737                                  * memory, then apply them at the end...
738                                  */
739                                 if (!ctx->delayed_xattrs) {
740                                         ctx->delayed_xattrs = new_blob_table(32);
741                                         if (!ctx->delayed_xattrs) {
742                                                 ret = WIMLIB_ERR_NOMEM;
743                                                 break;
744                                         }
745                                 }
746                                 if (!new_blob_from_data_buffer(ctx->data_buffer,
747                                                                blob->size,
748                                                                ctx->delayed_xattrs))
749                                 {
750                                         ret = WIMLIB_ERR_NOMEM;
751                                         break;
752                                 }
753                         } else {
754                                 ret = apply_xattrs(inode, ctx->data_buffer,
755                                                    blob->size, ctx);
756                                 if (ret)
757                                         break;
758                         }
759                 }
760         #endif /* HAVE_XATTR_SUPPORT */
761                 else {
762                         struct filedes *fd = &ctx->open_fds[j];
763
764                         /* If the file is sparse, extend it to its final size. */
765                         if (ctx->is_sparse_file[j] && ftruncate(fd->fd, blob->size)) {
766                                 ERROR_WITH_ERRNO("Error extending \"%s\" to final size",
767                                                  unix_build_inode_extraction_path(inode, ctx));
768                                 ret = WIMLIB_ERR_WRITE;
769                                 break;
770                         }
771
772                         if (filedes_close(fd)) {
773                                 ERROR_WITH_ERRNO("Error closing \"%s\"",
774                                                  unix_build_inode_extraction_path(inode, ctx));
775                                 ret = WIMLIB_ERR_WRITE;
776                                 break;
777                         }
778                         j++;
779                 }
780         }
781         unix_cleanup_open_fds(ctx, j);
782         return ret;
783 }
784
785 /* Apply metadata to all extracted files (and directories). */
786 static int
787 unix_apply_metadata(struct list_head *dentry_list, struct unix_apply_ctx *ctx)
788 {
789         const struct wim_dentry *dentry;
790         const struct wim_inode *inode;
791         int ret;
792
793         list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node)
794         {
795                 inode = dentry->d_inode;
796                 if (dentry != inode_first_extraction_dentry(inode))
797                         continue;
798                 ret = unix_set_metadata(inode, ctx);
799                 if (!ret)
800                         ret = report_file_metadata_applied(&ctx->common);
801                 if (ret)
802                         return ret;
803         }
804         return 0;
805 }
806
807 static int
808 unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
809 {
810         int ret;
811         struct unix_apply_ctx *ctx = (struct unix_apply_ctx *)_ctx;
812         size_t path_max;
813         u64 full_count;
814         u64 symlink_count;
815
816         /* Compute the maximum path length that will be needed, then allocate
817          * some path buffers.  */
818         path_max = unix_compute_path_max(dentry_list, ctx);
819
820         for (unsigned i = 0; i < NUM_PATHBUFS; i++) {
821                 ctx->pathbufs[i] = MALLOC(path_max);
822                 if (!ctx->pathbufs[i]) {
823                         ret = WIMLIB_ERR_NOMEM;
824                         goto out;
825                 }
826                 /* Pre-fill the target in each path buffer.  We'll just append
827                  * the rest of the paths after this.  */
828                 memcpy(ctx->pathbufs[i],
829                        ctx->common.target, ctx->common.target_nchars);
830         }
831
832         /*
833          * We do the extraction in three phases:
834          *
835          *      1. Create all directories and files except for symlinks
836          *      2. Extract streams
837          *      3. Apply metadata
838          *
839          * In phase (2), the streams which may be extracted include unnamed data
840          * streams (regular file contents), reparse streams (translated to
841          * symlink targets), and extended attribute (xattr) streams.  These may
842          * come up for extraction in any order.  Therefore, at least when xattr
843          * streams are present, all files must be created earlier, in phase (1).
844          *
845          * Symlinks are an exception: they cannot be created until the reparse
846          * stream comes up for extraction.  Currently we hack around this by
847          * caching the xattrs of symlinks in memory until they can be applied
848          * between phases (2) and (3).
849          *
850          * Note that phase (3) must happen after all data all xattr extraction
851          * because it might set the file mode's to readonly (which precludes
852          * setxattr), and it also will set timestamps including the last
853          * modification time (which precludes write).
854          */
855
856         unix_count_inodes(dentry_list, &full_count, &symlink_count);
857
858         ret = start_file_structure_phase(&ctx->common,
859                                          full_count - symlink_count);
860         if (ret)
861                 goto out;
862
863         ret = unix_create_file_structure(dentry_list, ctx);
864         if (ret)
865                 goto out;
866
867         ret = end_file_structure_phase(&ctx->common);
868         if (ret)
869                 goto out;
870
871         /* Get full path to target if needed for absolute symlink fixups.  */
872         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX) &&
873             ctx->common.required_features.symlink_reparse_points)
874         {
875                 ctx->target_abspath = realpath(ctx->common.target, NULL);
876                 if (!ctx->target_abspath) {
877                         ret = WIMLIB_ERR_NOMEM;
878                         goto out;
879                 }
880                 ctx->target_abspath_nchars = strlen(ctx->target_abspath);
881         }
882
883         struct read_blob_callbacks cbs = {
884                 .begin_blob     = unix_begin_extract_blob,
885                 .continue_blob  = unix_extract_chunk,
886                 .end_blob       = unix_end_extract_blob,
887                 .ctx            = ctx,
888         };
889         ret = extract_blob_list(&ctx->common, &cbs);
890         if (ret)
891                 goto out;
892
893 #ifdef HAVE_XATTR_SUPPORT
894         if (unlikely(ctx->delayed_xattrs)) {
895                 ret = apply_delayed_xattrs(dentry_list, ctx);
896                 if (ret)
897                         goto out;
898         }
899 #endif
900
901         ret = start_file_metadata_phase(&ctx->common, full_count);
902         if (ret)
903                 goto out;
904
905         ret = unix_apply_metadata(dentry_list, ctx);
906         if (ret)
907                 goto out;
908
909         ret = end_file_metadata_phase(&ctx->common);
910         if (ret)
911                 goto out;
912
913         if (ctx->num_special_files_ignored) {
914                 WARNING("%lu special files were not extracted due to EPERM!",
915                         ctx->num_special_files_ignored);
916         }
917 out:
918 #ifdef HAVE_XATTR_SUPPORT
919         free_blob_table(ctx->delayed_xattrs);
920 #endif
921         FREE(ctx->data_buffer);
922         for (unsigned i = 0; i < NUM_PATHBUFS; i++)
923                 FREE(ctx->pathbufs[i]);
924         FREE(ctx->target_abspath);
925         return ret;
926 }
927
928 const struct apply_operations unix_apply_ops = {
929         .name                   = "UNIX",
930         .get_supported_features = unix_get_supported_features,
931         .extract                = unix_extract,
932         .context_size           = sizeof(struct unix_apply_ctx),
933 };