]> wimlib.net Git - wimlib/blob - src/unix_apply.c
timestamp.c: correctly convert negative UNIX timestamps
[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         /* Buffer for reading reparse point data into memory  */
100         u8 reparse_data[REPARSE_DATA_MAX_SIZE];
101
102         /* Pointer to the next byte in @reparse_data to fill  */
103         u8 *reparse_ptr;
104
105         /* Absolute path to the target directory (allocated buffer).  Only set
106          * if needed for absolute symbolic link fixups.  */
107         char *target_abspath;
108
109         /* Number of characters in target_abspath.  */
110         size_t target_abspath_nchars;
111
112         /* Number of special files we couldn't create due to EPERM  */
113         unsigned long num_special_files_ignored;
114 };
115
116 /* Returns the number of characters needed to represent the path to the
117  * specified @dentry when extracted, not including the null terminator or the
118  * path to the target directory itself.  */
119 static size_t
120 unix_dentry_path_length(const struct wim_dentry *dentry)
121 {
122         size_t len = 0;
123         const struct wim_dentry *d;
124
125         d = dentry;
126         do {
127                 len += d->d_extraction_name_nchars + 1;
128                 d = d->d_parent;
129         } while (!dentry_is_root(d) && will_extract_dentry(d));
130
131         return len;
132 }
133
134 /* Returns the maximum number of characters needed to represent the path to any
135  * dentry in @dentry_list when extracted, including the null terminator and the
136  * path to the target directory itself.  */
137 static size_t
138 unix_compute_path_max(const struct list_head *dentry_list,
139                       const struct unix_apply_ctx *ctx)
140 {
141         size_t max = 0;
142         size_t len;
143         const struct wim_dentry *dentry;
144
145         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
146                 len = unix_dentry_path_length(dentry);
147                 if (len > max)
148                         max = len;
149         }
150
151         /* Account for target and null terminator.  */
152         return ctx->common.target_nchars + max + 1;
153 }
154
155 /* Builds and returns the filesystem path to which to extract @dentry.
156  * This cycles through NUM_PATHBUFS different buffers.  */
157 static const char *
158 unix_build_extraction_path(const struct wim_dentry *dentry,
159                            struct unix_apply_ctx *ctx)
160 {
161         char *pathbuf;
162         char *p;
163         const struct wim_dentry *d;
164
165         pathbuf = ctx->pathbufs[ctx->which_pathbuf];
166         ctx->which_pathbuf = (ctx->which_pathbuf + 1) % NUM_PATHBUFS;
167
168         p = &pathbuf[ctx->common.target_nchars +
169                      unix_dentry_path_length(dentry)];
170         *p = '\0';
171         d = dentry;
172         do {
173                 p -= d->d_extraction_name_nchars;
174                 if (d->d_extraction_name_nchars)
175                         memcpy(p, d->d_extraction_name,
176                                d->d_extraction_name_nchars);
177                 *--p = '/';
178                 d = d->d_parent;
179         } while (!dentry_is_root(d) && will_extract_dentry(d));
180
181         return pathbuf;
182 }
183
184 /* This causes the next call to unix_build_extraction_path() to use the same
185  * path buffer as the previous call.  */
186 static void
187 unix_reuse_pathbuf(struct unix_apply_ctx *ctx)
188 {
189         ctx->which_pathbuf = (ctx->which_pathbuf - 1) % NUM_PATHBUFS;
190 }
191
192 /* Builds and returns the filesystem path to which to extract an unspecified
193  * alias of the @inode.  This cycles through NUM_PATHBUFS different buffers.  */
194 static const char *
195 unix_build_inode_extraction_path(const struct wim_inode *inode,
196                                  struct unix_apply_ctx *ctx)
197 {
198         return unix_build_extraction_path(inode_first_extraction_dentry(inode), ctx);
199 }
200
201 /* Should the specified file be extracted as a directory on UNIX?  We extract
202  * the file as a directory if FILE_ATTRIBUTE_DIRECTORY is set and the file does
203  * not have a symlink or junction reparse point.  It *may* have a different type
204  * of reparse point.  */
205 static inline bool
206 should_extract_as_directory(const struct wim_inode *inode)
207 {
208         return (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) &&
209                 !inode_is_symlink(inode);
210 }
211
212 /* Sets the timestamps on a file being extracted.
213  *
214  * Either @fd or @path must be specified (not -1 and not NULL, respectively).
215  */
216 static int
217 unix_set_timestamps(int fd, const char *path, u64 atime, u64 mtime)
218 {
219         {
220                 struct timespec times[2];
221
222                 times[0] = wim_timestamp_to_timespec(atime);
223                 times[1] = wim_timestamp_to_timespec(mtime);
224
225                 errno = ENOSYS;
226 #ifdef HAVE_FUTIMENS
227                 if (fd >= 0 && !futimens(fd, times))
228                         return 0;
229 #endif
230 #ifdef HAVE_UTIMENSAT
231                 if (fd < 0 && !utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW))
232                         return 0;
233 #endif
234                 if (errno != ENOSYS)
235                         return WIMLIB_ERR_SET_TIMESTAMPS;
236         }
237         {
238                 struct timeval times[2];
239
240                 times[0] = wim_timestamp_to_timeval(atime);
241                 times[1] = wim_timestamp_to_timeval(mtime);
242
243                 if (fd >= 0 && !futimes(fd, times))
244                         return 0;
245                 if (fd < 0 && !lutimes(path, times))
246                         return 0;
247                 return WIMLIB_ERR_SET_TIMESTAMPS;
248         }
249 }
250
251 static int
252 unix_set_owner_and_group(int fd, const char *path, uid_t uid, gid_t gid)
253 {
254         if (fd >= 0 && !fchown(fd, uid, gid))
255                 return 0;
256         if (fd < 0 && !lchown(path, uid, gid))
257                 return 0;
258         return WIMLIB_ERR_SET_SECURITY;
259 }
260
261 static int
262 unix_set_mode(int fd, const char *path, mode_t mode)
263 {
264         if (fd >= 0 && !fchmod(fd, mode))
265                 return 0;
266         if (fd < 0 && !chmod(path, mode))
267                 return 0;
268         return WIMLIB_ERR_SET_SECURITY;
269 }
270
271 #ifdef HAVE_XATTR_SUPPORT
272 /* Apply extended attributes to a file */
273 static int
274 apply_linux_xattrs(int fd, const struct wim_inode *inode,
275                    const char *path, struct unix_apply_ctx *ctx,
276                    const void *entries, size_t entries_size)
277 {
278         const void * const entries_end = entries + entries_size;
279         char name[XATTR_NAME_MAX + 1];
280
281         for (const struct wimlib_xattr_entry *entry = entries;
282              (void *)entry < entries_end; entry = xattr_entry_next(entry))
283         {
284                 u16 name_len;
285                 const void *value;
286                 u32 value_len;
287                 int res;
288
289                 if (!valid_xattr_entry(entry, entries_end - (void *)entry)) {
290                         if (!path) {
291                                 path = unix_build_inode_extraction_path(inode,
292                                                                         ctx);
293                         }
294                         ERROR("\"%s\": extended attribute is corrupt", path);
295                         return WIMLIB_ERR_INVALID_XATTR;
296                 }
297                 name_len = le16_to_cpu(entry->name_len);
298                 memcpy(name, entry->name, name_len);
299                 name[name_len] = '\0';
300
301                 value = entry->name + name_len;
302                 value_len = le32_to_cpu(entry->value_len);
303
304                 if (fd >= 0)
305                         res = fsetxattr(fd, name, value, value_len, 0);
306                 else
307                         res = lsetxattr(path, name, value, value_len, 0);
308
309                 if (unlikely(res != 0)) {
310                         if (!path) {
311                                 path = unix_build_inode_extraction_path(inode,
312                                                                         ctx);
313                         }
314                         if (is_security_xattr(name) &&
315                             (ctx->common.extract_flags &
316                              WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
317                         {
318                                 ERROR_WITH_ERRNO("\"%s\": unable to set extended attribute \"%s\"",
319                                                  path, name);
320                                 return WIMLIB_ERR_SET_XATTR;
321                         }
322                         WARNING_WITH_ERRNO("\"%s\": unable to set extended attribute \"%s\"",
323                                            path, name);
324                 }
325         }
326         return 0;
327 }
328 #endif /* HAVE_XATTR_SUPPORT */
329
330 /*
331  * Apply UNIX-specific metadata to a file if available.  This includes standard
332  * UNIX permissions (uid, gid, and mode) and possibly extended attributes too.
333  *
334  * Note that some xattrs which grant privileges, e.g. security.capability, are
335  * cleared by Linux on chown(), even when running as root.  Also, when running
336  * as non-root, if we need to chmod() the file to readonly, we can't do that
337  * before setting xattrs because setxattr() requires write permission.  These
338  * restrictions result in the following ordering which we follow: chown(),
339  * setxattr(), then chmod().
340  *
341  * N.B. the file may be specified by either 'fd' (for regular files) or 'path',
342  * and it may be a symlink.  For symlinks we need lchown() and lsetxattr() but
343  * need to skip the chmod(), since mode bits are not meaningful for symlinks.
344  */
345 static int
346 apply_unix_metadata(int fd, const struct wim_inode *inode,
347                     const char *path, struct unix_apply_ctx *ctx)
348 {
349         bool have_dat;
350         struct wimlib_unix_data dat;
351 #ifdef HAVE_XATTR_SUPPORT
352         const void *entries;
353         u32 entries_size;
354 #endif
355         int ret;
356
357         have_dat = inode_get_unix_data(inode, &dat);
358
359         if (have_dat) {
360                 ret = unix_set_owner_and_group(fd, path, dat.uid, dat.gid);
361                 if (ret) {
362                         if (!path)
363                                 path = unix_build_inode_extraction_path(inode, ctx);
364                         if (ctx->common.extract_flags &
365                             WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
366                         {
367                                 ERROR_WITH_ERRNO("\"%s\": unable to set uid=%"PRIu32" and gid=%"PRIu32,
368                                                  path, dat.uid, dat.gid);
369                                 return ret;
370                         }
371                         WARNING_WITH_ERRNO("\"%s\": unable to set uid=%"PRIu32" and gid=%"PRIu32,
372                                            path, dat.uid, dat.gid);
373                 }
374         }
375
376 #ifdef HAVE_XATTR_SUPPORT
377         entries = inode_get_linux_xattrs(inode, &entries_size);
378         if (entries) {
379                 ret = apply_linux_xattrs(fd, inode, path, ctx,
380                                          entries, entries_size);
381                 if (ret)
382                         return ret;
383         }
384 #endif
385
386         if (have_dat && !inode_is_symlink(inode)) {
387                 ret = unix_set_mode(fd, path, dat.mode);
388                 if (ret) {
389                         if (!path)
390                                 path = unix_build_inode_extraction_path(inode, ctx);
391                         if (ctx->common.extract_flags &
392                             WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
393                         {
394                                 ERROR_WITH_ERRNO("\"%s\": unable to set mode=0%"PRIo32,
395                                                  path, dat.mode);
396                                 return ret;
397                         }
398                         WARNING_WITH_ERRNO("\"%s\": unable to set mode=0%"PRIo32,
399                                            path, dat.mode);
400                 }
401         }
402
403         return 0;
404 }
405
406 /*
407  * Set metadata on an extracted file.
408  *
409  * @fd is an open file descriptor to the extracted file, or -1.  @path is the
410  * path to the extracted file, or NULL.  If valid, this function uses @fd.
411  * Otherwise, if valid, it uses @path.  Otherwise, it calculates the path to one
412  * alias of the extracted file and uses it.
413  */
414 static int
415 unix_set_metadata(int fd, const struct wim_inode *inode,
416                   const char *path, struct unix_apply_ctx *ctx)
417 {
418         int ret;
419
420         if (fd < 0 && !path)
421                 path = unix_build_inode_extraction_path(inode, ctx);
422
423         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
424                 ret = apply_unix_metadata(fd, inode, path, ctx);
425                 if (ret)
426                         return ret;
427         }
428
429         ret = unix_set_timestamps(fd, path, inode->i_last_access_time,
430                                   inode->i_last_write_time);
431         if (ret) {
432                 if (!path)
433                         path = unix_build_inode_extraction_path(inode, ctx);
434                 if (ctx->common.extract_flags &
435                     WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS)
436                 {
437                         ERROR_WITH_ERRNO("\"%s\": unable to set timestamps", path);
438                         return ret;
439                 }
440                 WARNING_WITH_ERRNO("\"%s\": unable to set timestamps", path);
441         }
442
443         return 0;
444 }
445
446 /* Extract all needed aliases of the @inode, where one alias, corresponding to
447  * @first_dentry, has already been extracted to @first_path.  */
448 static int
449 unix_create_hardlinks(const struct wim_inode *inode,
450                       const struct wim_dentry *first_dentry,
451                       const char *first_path, struct unix_apply_ctx *ctx)
452 {
453         const struct wim_dentry *dentry;
454         const char *newpath;
455
456         inode_for_each_extraction_alias(dentry, inode) {
457                 if (dentry == first_dentry)
458                         continue;
459
460                 newpath = unix_build_extraction_path(dentry, ctx);
461         retry_link:
462                 if (link(first_path, newpath)) {
463                         if (errno == EEXIST && !unlink(newpath))
464                                 goto retry_link;
465                         ERROR_WITH_ERRNO("Can't create hard link "
466                                          "\"%s\" => \"%s\"", newpath, first_path);
467                         return WIMLIB_ERR_LINK;
468                 }
469                 unix_reuse_pathbuf(ctx);
470         }
471         return 0;
472 }
473
474 /* If @dentry represents a directory, create it.  */
475 static int
476 unix_create_if_directory(const struct wim_dentry *dentry,
477                          struct unix_apply_ctx *ctx)
478 {
479         const char *path;
480         struct stat stbuf;
481
482         if (!should_extract_as_directory(dentry->d_inode))
483                 return 0;
484
485         path = unix_build_extraction_path(dentry, ctx);
486         if (mkdir(path, 0755) &&
487             /* It's okay if the path already exists, as long as it's a
488              * directory.  */
489             !(errno == EEXIST && !lstat(path, &stbuf) && S_ISDIR(stbuf.st_mode)))
490         {
491                 ERROR_WITH_ERRNO("Can't create directory \"%s\"", path);
492                 return WIMLIB_ERR_MKDIR;
493         }
494
495         return report_file_created(&ctx->common);
496 }
497
498 /* If @dentry represents an empty regular file or a special file, create it, set
499  * its metadata, and create any needed hard links.  */
500 static int
501 unix_extract_if_empty_file(const struct wim_dentry *dentry,
502                            struct unix_apply_ctx *ctx)
503 {
504         const struct wim_inode *inode;
505         struct wimlib_unix_data unix_data;
506         const char *path;
507         int ret;
508
509         inode = dentry->d_inode;
510
511         /* Extract all aliases only when the "first" comes up.  */
512         if (dentry != inode_first_extraction_dentry(inode))
513                 return 0;
514
515         /* Is this a directory, a symbolic link, or any type of nonempty file?
516          */
517         if (should_extract_as_directory(inode) || inode_is_symlink(inode) ||
518             inode_get_blob_for_unnamed_data_stream_resolved(inode))
519                 return 0;
520
521         /* Recognize special files in UNIX_DATA mode  */
522         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) &&
523             inode_get_unix_data(inode, &unix_data) &&
524             !S_ISREG(unix_data.mode))
525         {
526                 path = unix_build_extraction_path(dentry, ctx);
527         retry_mknod:
528                 if (mknod(path, unix_data.mode, unix_data.rdev)) {
529                         if (errno == EPERM) {
530                                 WARNING_WITH_ERRNO("Can't create special "
531                                                    "file \"%s\"", path);
532                                 ctx->num_special_files_ignored++;
533                                 return 0;
534                         }
535                         if (errno == EEXIST && !unlink(path))
536                                 goto retry_mknod;
537                         ERROR_WITH_ERRNO("Can't create special file \"%s\"",
538                                          path);
539                         return WIMLIB_ERR_MKNOD;
540                 }
541                 /* On special files, we can set timestamps immediately because
542                  * we don't need to write any data to them.  */
543                 ret = unix_set_metadata(-1, inode, path, ctx);
544         } else {
545                 int fd;
546
547                 path = unix_build_extraction_path(dentry, ctx);
548         retry_create:
549                 fd = open(path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
550                 if (fd < 0) {
551                         if (errno == EEXIST && !unlink(path))
552                                 goto retry_create;
553                         ERROR_WITH_ERRNO("Can't create regular file \"%s\"", path);
554                         return WIMLIB_ERR_OPEN;
555                 }
556                 /* On empty files, we can set timestamps immediately because we
557                  * don't need to write any data to them.  */
558                 ret = unix_set_metadata(fd, inode, path, ctx);
559                 if (close(fd) && !ret) {
560                         ERROR_WITH_ERRNO("Error closing \"%s\"", path);
561                         ret = WIMLIB_ERR_WRITE;
562                 }
563         }
564         if (ret)
565                 return ret;
566
567         ret = unix_create_hardlinks(inode, dentry, path, ctx);
568         if (ret)
569                 return ret;
570
571         return report_file_created(&ctx->common);
572 }
573
574 static int
575 unix_create_dirs_and_empty_files(const struct list_head *dentry_list,
576                                  struct unix_apply_ctx *ctx)
577 {
578         const struct wim_dentry *dentry;
579         int ret;
580
581         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
582                 ret = unix_create_if_directory(dentry, ctx);
583                 if (ret)
584                         return ret;
585         }
586         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
587                 ret = unix_extract_if_empty_file(dentry, ctx);
588                 if (ret)
589                         return ret;
590         }
591         return 0;
592 }
593
594 static void
595 unix_count_dentries(const struct list_head *dentry_list,
596                     u64 *dir_count_ret, u64 *empty_file_count_ret)
597 {
598         const struct wim_dentry *dentry;
599         u64 dir_count = 0;
600         u64 empty_file_count = 0;
601
602         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
603
604                 const struct wim_inode *inode = dentry->d_inode;
605
606                 if (should_extract_as_directory(inode))
607                         dir_count++;
608                 else if ((dentry == inode_first_extraction_dentry(inode)) &&
609                          !inode_is_symlink(inode) &&
610                          !inode_get_blob_for_unnamed_data_stream_resolved(inode))
611                         empty_file_count++;
612         }
613
614         *dir_count_ret = dir_count;
615         *empty_file_count_ret = empty_file_count;
616 }
617
618 static int
619 unix_create_symlink(const struct wim_inode *inode, const char *path,
620                     size_t rpdatalen, struct unix_apply_ctx *ctx)
621 {
622         char target[REPARSE_POINT_MAX_SIZE];
623         struct blob_descriptor blob_override;
624         int ret;
625
626         blob_set_is_located_in_attached_buffer(&blob_override,
627                                                ctx->reparse_data, rpdatalen);
628
629         ret = wim_inode_readlink(inode, target, sizeof(target) - 1,
630                                  &blob_override,
631                                  ctx->target_abspath,
632                                  ctx->target_abspath_nchars);
633         if (unlikely(ret < 0)) {
634                 errno = -ret;
635                 return WIMLIB_ERR_READLINK;
636         }
637         target[ret] = '\0';
638
639 retry_symlink:
640         if (symlink(target, path)) {
641                 if (errno == EEXIST && !unlink(path))
642                         goto retry_symlink;
643                 return WIMLIB_ERR_LINK;
644         }
645         return 0;
646 }
647
648 static void
649 unix_cleanup_open_fds(struct unix_apply_ctx *ctx, unsigned offset)
650 {
651         for (unsigned i = offset; i < ctx->num_open_fds; i++)
652                 filedes_close(&ctx->open_fds[i]);
653         ctx->num_open_fds = 0;
654         ctx->any_sparse_files = false;
655 }
656
657 static int
658 unix_begin_extract_blob_instance(const struct blob_descriptor *blob,
659                                  const struct wim_inode *inode,
660                                  const struct wim_inode_stream *strm,
661                                  struct unix_apply_ctx *ctx)
662 {
663         const struct wim_dentry *first_dentry;
664         const char *first_path;
665         int fd;
666
667         if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
668                 /* On UNIX, symbolic links must be created with symlink(), which
669                  * requires that the full link target be available.  */
670                 if (blob->size > REPARSE_DATA_MAX_SIZE) {
671                         ERROR_WITH_ERRNO("Reparse data of \"%s\" has size "
672                                          "%"PRIu64" bytes (exceeds %u bytes)",
673                                          inode_any_full_path(inode),
674                                          blob->size, REPARSE_DATA_MAX_SIZE);
675                         return WIMLIB_ERR_INVALID_REPARSE_DATA;
676                 }
677                 ctx->reparse_ptr = ctx->reparse_data;
678                 return 0;
679         }
680
681         wimlib_assert(stream_is_unnamed_data_stream(strm));
682
683         /* Unnamed data stream of "regular" file  */
684
685         /* This should be ensured by extract_blob_list()  */
686         wimlib_assert(ctx->num_open_fds < MAX_OPEN_FILES);
687
688         first_dentry = inode_first_extraction_dentry(inode);
689         first_path = unix_build_extraction_path(first_dentry, ctx);
690 retry_create:
691         fd = open(first_path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
692         if (fd < 0) {
693                 if (errno == EEXIST && !unlink(first_path))
694                         goto retry_create;
695                 ERROR_WITH_ERRNO("Can't create regular file \"%s\"", first_path);
696                 return WIMLIB_ERR_OPEN;
697         }
698         if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
699                 ctx->is_sparse_file[ctx->num_open_fds] = true;
700                 ctx->any_sparse_files = true;
701         } else {
702                 ctx->is_sparse_file[ctx->num_open_fds] = false;
703 #ifdef HAVE_POSIX_FALLOCATE
704                 posix_fallocate(fd, 0, blob->size);
705 #endif
706         }
707         filedes_init(&ctx->open_fds[ctx->num_open_fds++], fd);
708         return unix_create_hardlinks(inode, first_dentry, first_path, ctx);
709 }
710
711 /* Called when starting to read a blob for extraction  */
712 static int
713 unix_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
714 {
715         struct unix_apply_ctx *ctx = _ctx;
716         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
717
718         for (u32 i = 0; i < blob->out_refcnt; i++) {
719                 int ret = unix_begin_extract_blob_instance(blob,
720                                                            targets[i].inode,
721                                                            targets[i].stream,
722                                                            ctx);
723                 if (ret) {
724                         ctx->reparse_ptr = NULL;
725                         unix_cleanup_open_fds(ctx, 0);
726                         return ret;
727                 }
728         }
729         return 0;
730 }
731
732 /* Called when the next chunk of a blob has been read for extraction  */
733 static int
734 unix_extract_chunk(const struct blob_descriptor *blob, u64 offset,
735                    const void *chunk, size_t size, void *_ctx)
736 {
737         struct unix_apply_ctx *ctx = _ctx;
738         const void * const end = chunk + size;
739         const void *p;
740         bool zeroes;
741         size_t len;
742         unsigned i;
743         int ret;
744
745         /*
746          * For sparse files, only write nonzero regions.  This lets the
747          * filesystem use holes to represent zero regions.
748          */
749         for (p = chunk; p != end; p += len, offset += len) {
750                 zeroes = maybe_detect_sparse_region(p, end - p, &len,
751                                                     ctx->any_sparse_files);
752                 for (i = 0; i < ctx->num_open_fds; i++) {
753                         if (!zeroes || !ctx->is_sparse_file[i]) {
754                                 ret = full_pwrite(&ctx->open_fds[i],
755                                                   p, len, offset);
756                                 if (ret)
757                                         goto err;
758                         }
759                 }
760         }
761
762         if (ctx->reparse_ptr)
763                 ctx->reparse_ptr = mempcpy(ctx->reparse_ptr, chunk, size);
764         return 0;
765
766 err:
767         ERROR_WITH_ERRNO("Error writing data to filesystem");
768         return ret;
769 }
770
771 /* Called when a blob has been fully read for extraction  */
772 static int
773 unix_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
774 {
775         struct unix_apply_ctx *ctx = _ctx;
776         int ret;
777         unsigned j;
778         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
779
780         ctx->reparse_ptr = NULL;
781
782         if (status) {
783                 unix_cleanup_open_fds(ctx, 0);
784                 return status;
785         }
786
787         j = 0;
788         ret = 0;
789         for (u32 i = 0; i < blob->out_refcnt; i++) {
790                 struct wim_inode *inode = targets[i].inode;
791
792                 if (inode_is_symlink(inode)) {
793                         /* We finally have the symlink data, so we can create
794                          * the symlink.  */
795                         const char *path;
796
797                         path = unix_build_inode_extraction_path(inode, ctx);
798                         ret = unix_create_symlink(inode, path, blob->size, ctx);
799                         if (ret) {
800                                 ERROR_WITH_ERRNO("Can't create symbolic link "
801                                                  "\"%s\"", path);
802                                 break;
803                         }
804                         ret = unix_set_metadata(-1, inode, path, ctx);
805                         if (ret)
806                                 break;
807                 } else {
808                         struct filedes *fd = &ctx->open_fds[j];
809
810                         /* If the file is sparse, extend it to its final size. */
811                         if (ctx->is_sparse_file[j] && ftruncate(fd->fd, blob->size)) {
812                                 ERROR_WITH_ERRNO("Error extending \"%s\" to final size",
813                                                  unix_build_inode_extraction_path(inode, ctx));
814                                 ret = WIMLIB_ERR_WRITE;
815                                 break;
816                         }
817
818                         /* Set metadata on regular file just before closing.  */
819                         ret = unix_set_metadata(fd->fd, inode, NULL, ctx);
820                         if (ret)
821                                 break;
822
823                         if (filedes_close(fd)) {
824                                 ERROR_WITH_ERRNO("Error closing \"%s\"",
825                                                  unix_build_inode_extraction_path(inode, ctx));
826                                 ret = WIMLIB_ERR_WRITE;
827                                 break;
828                         }
829                         j++;
830                 }
831         }
832         unix_cleanup_open_fds(ctx, j);
833         return ret;
834 }
835
836 static int
837 unix_set_dir_metadata(struct list_head *dentry_list, struct unix_apply_ctx *ctx)
838 {
839         const struct wim_dentry *dentry;
840         int ret;
841
842         list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node) {
843                 if (should_extract_as_directory(dentry->d_inode)) {
844                         ret = unix_set_metadata(-1, dentry->d_inode, NULL, ctx);
845                         if (ret)
846                                 return ret;
847                         ret = report_file_metadata_applied(&ctx->common);
848                         if (ret)
849                                 return ret;
850                 }
851         }
852         return 0;
853 }
854
855 static int
856 unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
857 {
858         int ret;
859         struct unix_apply_ctx *ctx = (struct unix_apply_ctx *)_ctx;
860         size_t path_max;
861         u64 dir_count;
862         u64 empty_file_count;
863
864         /* Compute the maximum path length that will be needed, then allocate
865          * some path buffers.  */
866         path_max = unix_compute_path_max(dentry_list, ctx);
867
868         for (unsigned i = 0; i < NUM_PATHBUFS; i++) {
869                 ctx->pathbufs[i] = MALLOC(path_max);
870                 if (!ctx->pathbufs[i]) {
871                         ret = WIMLIB_ERR_NOMEM;
872                         goto out;
873                 }
874                 /* Pre-fill the target in each path buffer.  We'll just append
875                  * the rest of the paths after this.  */
876                 memcpy(ctx->pathbufs[i],
877                        ctx->common.target, ctx->common.target_nchars);
878         }
879
880         /* Extract directories and empty regular files.  Directories are needed
881          * because we can't extract any other files until their directories
882          * exist.  Empty files are needed because they don't have
883          * representatives in the blob list.  */
884
885         unix_count_dentries(dentry_list, &dir_count, &empty_file_count);
886
887         ret = start_file_structure_phase(&ctx->common, dir_count + empty_file_count);
888         if (ret)
889                 goto out;
890
891         ret = unix_create_dirs_and_empty_files(dentry_list, ctx);
892         if (ret)
893                 goto out;
894
895         ret = end_file_structure_phase(&ctx->common);
896         if (ret)
897                 goto out;
898
899         /* Get full path to target if needed for absolute symlink fixups.  */
900         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX) &&
901             ctx->common.required_features.symlink_reparse_points)
902         {
903                 ctx->target_abspath = realpath(ctx->common.target, NULL);
904                 if (!ctx->target_abspath) {
905                         ret = WIMLIB_ERR_NOMEM;
906                         goto out;
907                 }
908                 ctx->target_abspath_nchars = strlen(ctx->target_abspath);
909         }
910
911         /* Extract nonempty regular files and symbolic links.  */
912
913         struct read_blob_callbacks cbs = {
914                 .begin_blob     = unix_begin_extract_blob,
915                 .continue_blob  = unix_extract_chunk,
916                 .end_blob       = unix_end_extract_blob,
917                 .ctx            = ctx,
918         };
919         ret = extract_blob_list(&ctx->common, &cbs);
920         if (ret)
921                 goto out;
922
923
924         /* Set directory metadata.  We do this last so that we get the right
925          * directory timestamps.  */
926         ret = start_file_metadata_phase(&ctx->common, dir_count);
927         if (ret)
928                 goto out;
929
930         ret = unix_set_dir_metadata(dentry_list, ctx);
931         if (ret)
932                 goto out;
933
934         ret = end_file_metadata_phase(&ctx->common);
935         if (ret)
936                 goto out;
937
938         if (ctx->num_special_files_ignored) {
939                 WARNING("%lu special files were not extracted due to EPERM!",
940                         ctx->num_special_files_ignored);
941         }
942 out:
943         for (unsigned i = 0; i < NUM_PATHBUFS; i++)
944                 FREE(ctx->pathbufs[i]);
945         FREE(ctx->target_abspath);
946         return ret;
947 }
948
949 const struct apply_operations unix_apply_ops = {
950         .name                   = "UNIX",
951         .get_supported_features = unix_get_supported_features,
952         .extract                = unix_extract,
953         .context_size           = sizeof(struct unix_apply_ctx),
954 };