]> wimlib.net Git - wimlib/blob - src/unix_apply.c
3b31e194287fedf85326c7d42a95c857241a7f33
[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 /* Apply standard UNIX permissions (uid, gid, and mode) to a file */
331 static int
332 apply_unix_permissions(int fd, const struct wim_inode *inode,
333                        const char *path, struct unix_apply_ctx *ctx,
334                        const struct wimlib_unix_data *dat)
335 {
336         int ret;
337
338         ret = unix_set_owner_and_group(fd, path, dat->uid, dat->gid);
339         if (ret) {
340                 if (!path)
341                         path = unix_build_inode_extraction_path(inode, ctx);
342                 if (ctx->common.extract_flags &
343                     WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
344                 {
345                         ERROR_WITH_ERRNO("\"%s\": unable to set uid=%"PRIu32" and gid=%"PRIu32,
346                                          path, dat->uid, dat->gid);
347                         return ret;
348                 }
349                 WARNING_WITH_ERRNO("\"%s\": unable to set uid=%"PRIu32" and gid=%"PRIu32,
350                                    path, dat->uid, dat->gid);
351         }
352
353         if (!inode_is_symlink(inode)) {
354                 ret = unix_set_mode(fd, path, dat->mode);
355                 if (ret) {
356                         if (!path)
357                                 path = unix_build_inode_extraction_path(inode,
358                                                                         ctx);
359                         if (ctx->common.extract_flags &
360                             WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
361                         {
362                                 ERROR_WITH_ERRNO("\"%s\": unable to set mode=0%"PRIo32,
363                                                  path, dat->mode);
364                                 return ret;
365                         }
366                         WARNING_WITH_ERRNO("\"%s\": unable to set mode=0%"PRIo32,
367                                            path, dat->mode);
368                 }
369         }
370
371         return 0;
372 }
373
374 /*
375  * Set metadata on an extracted file.
376  *
377  * @fd is an open file descriptor to the extracted file, or -1.  @path is the
378  * path to the extracted file, or NULL.  If valid, this function uses @fd.
379  * Otherwise, if valid, it uses @path.  Otherwise, it calculates the path to one
380  * alias of the extracted file and uses it.
381  */
382 static int
383 unix_set_metadata(int fd, const struct wim_inode *inode,
384                   const char *path, struct unix_apply_ctx *ctx)
385 {
386         int ret;
387
388         if (fd < 0 && !path)
389                 path = unix_build_inode_extraction_path(inode, ctx);
390
391         if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
392                 struct wimlib_unix_data dat;
393         #ifdef HAVE_XATTR_SUPPORT
394                 const void *entries;
395                 u32 entries_size;
396
397                 entries = inode_get_linux_xattrs(inode, &entries_size);
398                 if (entries) {
399                         ret = apply_linux_xattrs(fd, inode, path, ctx,
400                                                  entries, entries_size);
401                         if (ret)
402                                 return ret;
403                 }
404         #endif
405                 if (inode_get_unix_data(inode, &dat)) {
406                         ret = apply_unix_permissions(fd, inode, path, ctx,
407                                                      &dat);
408                         if (ret)
409                                 return ret;
410                 }
411         }
412
413         ret = unix_set_timestamps(fd, path, inode->i_last_access_time,
414                                   inode->i_last_write_time);
415         if (ret) {
416                 if (!path)
417                         path = unix_build_inode_extraction_path(inode, ctx);
418                 if (ctx->common.extract_flags &
419                     WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS)
420                 {
421                         ERROR_WITH_ERRNO("\"%s\": unable to set timestamps", path);
422                         return ret;
423                 }
424                 WARNING_WITH_ERRNO("\"%s\": unable to set timestamps", path);
425         }
426
427         return 0;
428 }
429
430 /* Extract all needed aliases of the @inode, where one alias, corresponding to
431  * @first_dentry, has already been extracted to @first_path.  */
432 static int
433 unix_create_hardlinks(const struct wim_inode *inode,
434                       const struct wim_dentry *first_dentry,
435                       const char *first_path, struct unix_apply_ctx *ctx)
436 {
437         const struct wim_dentry *dentry;
438         const char *newpath;
439
440         inode_for_each_extraction_alias(dentry, inode) {
441                 if (dentry == first_dentry)
442                         continue;
443
444                 newpath = unix_build_extraction_path(dentry, ctx);
445         retry_link:
446                 if (link(first_path, newpath)) {
447                         if (errno == EEXIST && !unlink(newpath))
448                                 goto retry_link;
449                         ERROR_WITH_ERRNO("Can't create hard link "
450                                          "\"%s\" => \"%s\"", newpath, first_path);
451                         return WIMLIB_ERR_LINK;
452                 }
453                 unix_reuse_pathbuf(ctx);
454         }
455         return 0;
456 }
457
458 /* If @dentry represents a directory, create it.  */
459 static int
460 unix_create_if_directory(const struct wim_dentry *dentry,
461                          struct unix_apply_ctx *ctx)
462 {
463         const char *path;
464         struct stat stbuf;
465
466         if (!should_extract_as_directory(dentry->d_inode))
467                 return 0;
468
469         path = unix_build_extraction_path(dentry, ctx);
470         if (mkdir(path, 0755) &&
471             /* It's okay if the path already exists, as long as it's a
472              * directory.  */
473             !(errno == EEXIST && !lstat(path, &stbuf) && S_ISDIR(stbuf.st_mode)))
474         {
475                 ERROR_WITH_ERRNO("Can't create directory \"%s\"", path);
476                 return WIMLIB_ERR_MKDIR;
477         }
478
479         return report_file_created(&ctx->common);
480 }
481
482 /* If @dentry represents an empty regular file or a special file, create it, set
483  * its metadata, and create any needed hard links.  */
484 static int
485 unix_extract_if_empty_file(const struct wim_dentry *dentry,
486                            struct unix_apply_ctx *ctx)
487 {
488         const struct wim_inode *inode;
489         struct wimlib_unix_data unix_data;
490         const char *path;
491         int ret;
492
493         inode = dentry->d_inode;
494
495         /* Extract all aliases only when the "first" comes up.  */
496         if (dentry != inode_first_extraction_dentry(inode))
497                 return 0;
498
499         /* Is this a directory, a symbolic link, or any type of nonempty file?
500          */
501         if (should_extract_as_directory(inode) || inode_is_symlink(inode) ||
502             inode_get_blob_for_unnamed_data_stream_resolved(inode))
503                 return 0;
504
505         /* Recognize special files in UNIX_DATA mode  */
506         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) &&
507             inode_get_unix_data(inode, &unix_data) &&
508             !S_ISREG(unix_data.mode))
509         {
510                 path = unix_build_extraction_path(dentry, ctx);
511         retry_mknod:
512                 if (mknod(path, unix_data.mode, unix_data.rdev)) {
513                         if (errno == EPERM) {
514                                 WARNING_WITH_ERRNO("Can't create special "
515                                                    "file \"%s\"", path);
516                                 ctx->num_special_files_ignored++;
517                                 return 0;
518                         }
519                         if (errno == EEXIST && !unlink(path))
520                                 goto retry_mknod;
521                         ERROR_WITH_ERRNO("Can't create special file \"%s\"",
522                                          path);
523                         return WIMLIB_ERR_MKNOD;
524                 }
525                 /* On special files, we can set timestamps immediately because
526                  * we don't need to write any data to them.  */
527                 ret = unix_set_metadata(-1, inode, path, ctx);
528         } else {
529                 int fd;
530
531                 path = unix_build_extraction_path(dentry, ctx);
532         retry_create:
533                 fd = open(path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
534                 if (fd < 0) {
535                         if (errno == EEXIST && !unlink(path))
536                                 goto retry_create;
537                         ERROR_WITH_ERRNO("Can't create regular file \"%s\"", path);
538                         return WIMLIB_ERR_OPEN;
539                 }
540                 /* On empty files, we can set timestamps immediately because we
541                  * don't need to write any data to them.  */
542                 ret = unix_set_metadata(fd, inode, path, ctx);
543                 if (close(fd) && !ret) {
544                         ERROR_WITH_ERRNO("Error closing \"%s\"", path);
545                         ret = WIMLIB_ERR_WRITE;
546                 }
547         }
548         if (ret)
549                 return ret;
550
551         ret = unix_create_hardlinks(inode, dentry, path, ctx);
552         if (ret)
553                 return ret;
554
555         return report_file_created(&ctx->common);
556 }
557
558 static int
559 unix_create_dirs_and_empty_files(const struct list_head *dentry_list,
560                                  struct unix_apply_ctx *ctx)
561 {
562         const struct wim_dentry *dentry;
563         int ret;
564
565         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
566                 ret = unix_create_if_directory(dentry, ctx);
567                 if (ret)
568                         return ret;
569         }
570         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
571                 ret = unix_extract_if_empty_file(dentry, ctx);
572                 if (ret)
573                         return ret;
574         }
575         return 0;
576 }
577
578 static void
579 unix_count_dentries(const struct list_head *dentry_list,
580                     u64 *dir_count_ret, u64 *empty_file_count_ret)
581 {
582         const struct wim_dentry *dentry;
583         u64 dir_count = 0;
584         u64 empty_file_count = 0;
585
586         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
587
588                 const struct wim_inode *inode = dentry->d_inode;
589
590                 if (should_extract_as_directory(inode))
591                         dir_count++;
592                 else if ((dentry == inode_first_extraction_dentry(inode)) &&
593                          !inode_is_symlink(inode) &&
594                          !inode_get_blob_for_unnamed_data_stream_resolved(inode))
595                         empty_file_count++;
596         }
597
598         *dir_count_ret = dir_count;
599         *empty_file_count_ret = empty_file_count;
600 }
601
602 static int
603 unix_create_symlink(const struct wim_inode *inode, const char *path,
604                     size_t rpdatalen, struct unix_apply_ctx *ctx)
605 {
606         char target[REPARSE_POINT_MAX_SIZE];
607         struct blob_descriptor blob_override;
608         int ret;
609
610         blob_set_is_located_in_attached_buffer(&blob_override,
611                                                ctx->reparse_data, rpdatalen);
612
613         ret = wim_inode_readlink(inode, target, sizeof(target) - 1,
614                                  &blob_override,
615                                  ctx->target_abspath,
616                                  ctx->target_abspath_nchars);
617         if (unlikely(ret < 0)) {
618                 errno = -ret;
619                 return WIMLIB_ERR_READLINK;
620         }
621         target[ret] = '\0';
622
623 retry_symlink:
624         if (symlink(target, path)) {
625                 if (errno == EEXIST && !unlink(path))
626                         goto retry_symlink;
627                 return WIMLIB_ERR_LINK;
628         }
629         return 0;
630 }
631
632 static void
633 unix_cleanup_open_fds(struct unix_apply_ctx *ctx, unsigned offset)
634 {
635         for (unsigned i = offset; i < ctx->num_open_fds; i++)
636                 filedes_close(&ctx->open_fds[i]);
637         ctx->num_open_fds = 0;
638         ctx->any_sparse_files = false;
639 }
640
641 static int
642 unix_begin_extract_blob_instance(const struct blob_descriptor *blob,
643                                  const struct wim_inode *inode,
644                                  const struct wim_inode_stream *strm,
645                                  struct unix_apply_ctx *ctx)
646 {
647         const struct wim_dentry *first_dentry;
648         const char *first_path;
649         int fd;
650
651         if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
652                 /* On UNIX, symbolic links must be created with symlink(), which
653                  * requires that the full link target be available.  */
654                 if (blob->size > REPARSE_DATA_MAX_SIZE) {
655                         ERROR_WITH_ERRNO("Reparse data of \"%s\" has size "
656                                          "%"PRIu64" bytes (exceeds %u bytes)",
657                                          inode_any_full_path(inode),
658                                          blob->size, REPARSE_DATA_MAX_SIZE);
659                         return WIMLIB_ERR_INVALID_REPARSE_DATA;
660                 }
661                 ctx->reparse_ptr = ctx->reparse_data;
662                 return 0;
663         }
664
665         wimlib_assert(stream_is_unnamed_data_stream(strm));
666
667         /* Unnamed data stream of "regular" file  */
668
669         /* This should be ensured by extract_blob_list()  */
670         wimlib_assert(ctx->num_open_fds < MAX_OPEN_FILES);
671
672         first_dentry = inode_first_extraction_dentry(inode);
673         first_path = unix_build_extraction_path(first_dentry, ctx);
674 retry_create:
675         fd = open(first_path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
676         if (fd < 0) {
677                 if (errno == EEXIST && !unlink(first_path))
678                         goto retry_create;
679                 ERROR_WITH_ERRNO("Can't create regular file \"%s\"", first_path);
680                 return WIMLIB_ERR_OPEN;
681         }
682         if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
683                 ctx->is_sparse_file[ctx->num_open_fds] = true;
684                 ctx->any_sparse_files = true;
685         } else {
686                 ctx->is_sparse_file[ctx->num_open_fds] = false;
687 #ifdef HAVE_POSIX_FALLOCATE
688                 posix_fallocate(fd, 0, blob->size);
689 #endif
690         }
691         filedes_init(&ctx->open_fds[ctx->num_open_fds++], fd);
692         return unix_create_hardlinks(inode, first_dentry, first_path, ctx);
693 }
694
695 /* Called when starting to read a blob for extraction  */
696 static int
697 unix_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
698 {
699         struct unix_apply_ctx *ctx = _ctx;
700         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
701
702         for (u32 i = 0; i < blob->out_refcnt; i++) {
703                 int ret = unix_begin_extract_blob_instance(blob,
704                                                            targets[i].inode,
705                                                            targets[i].stream,
706                                                            ctx);
707                 if (ret) {
708                         ctx->reparse_ptr = NULL;
709                         unix_cleanup_open_fds(ctx, 0);
710                         return ret;
711                 }
712         }
713         return 0;
714 }
715
716 /* Called when the next chunk of a blob has been read for extraction  */
717 static int
718 unix_extract_chunk(const struct blob_descriptor *blob, u64 offset,
719                    const void *chunk, size_t size, void *_ctx)
720 {
721         struct unix_apply_ctx *ctx = _ctx;
722         const void * const end = chunk + size;
723         const void *p;
724         bool zeroes;
725         size_t len;
726         unsigned i;
727         int ret;
728
729         /*
730          * For sparse files, only write nonzero regions.  This lets the
731          * filesystem use holes to represent zero regions.
732          */
733         for (p = chunk; p != end; p += len, offset += len) {
734                 zeroes = maybe_detect_sparse_region(p, end - p, &len,
735                                                     ctx->any_sparse_files);
736                 for (i = 0; i < ctx->num_open_fds; i++) {
737                         if (!zeroes || !ctx->is_sparse_file[i]) {
738                                 ret = full_pwrite(&ctx->open_fds[i],
739                                                   p, len, offset);
740                                 if (ret)
741                                         goto err;
742                         }
743                 }
744         }
745
746         if (ctx->reparse_ptr)
747                 ctx->reparse_ptr = mempcpy(ctx->reparse_ptr, chunk, size);
748         return 0;
749
750 err:
751         ERROR_WITH_ERRNO("Error writing data to filesystem");
752         return ret;
753 }
754
755 /* Called when a blob has been fully read for extraction  */
756 static int
757 unix_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
758 {
759         struct unix_apply_ctx *ctx = _ctx;
760         int ret;
761         unsigned j;
762         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
763
764         ctx->reparse_ptr = NULL;
765
766         if (status) {
767                 unix_cleanup_open_fds(ctx, 0);
768                 return status;
769         }
770
771         j = 0;
772         ret = 0;
773         for (u32 i = 0; i < blob->out_refcnt; i++) {
774                 struct wim_inode *inode = targets[i].inode;
775
776                 if (inode_is_symlink(inode)) {
777                         /* We finally have the symlink data, so we can create
778                          * the symlink.  */
779                         const char *path;
780
781                         path = unix_build_inode_extraction_path(inode, ctx);
782                         ret = unix_create_symlink(inode, path, blob->size, ctx);
783                         if (ret) {
784                                 ERROR_WITH_ERRNO("Can't create symbolic link "
785                                                  "\"%s\"", path);
786                                 break;
787                         }
788                         ret = unix_set_metadata(-1, inode, path, ctx);
789                         if (ret)
790                                 break;
791                 } else {
792                         struct filedes *fd = &ctx->open_fds[j];
793
794                         /* If the file is sparse, extend it to its final size. */
795                         if (ctx->is_sparse_file[j] && ftruncate(fd->fd, blob->size)) {
796                                 ERROR_WITH_ERRNO("Error extending \"%s\" to final size",
797                                                  unix_build_inode_extraction_path(inode, ctx));
798                                 ret = WIMLIB_ERR_WRITE;
799                                 break;
800                         }
801
802                         /* Set metadata on regular file just before closing.  */
803                         ret = unix_set_metadata(fd->fd, inode, NULL, ctx);
804                         if (ret)
805                                 break;
806
807                         if (filedes_close(fd)) {
808                                 ERROR_WITH_ERRNO("Error closing \"%s\"",
809                                                  unix_build_inode_extraction_path(inode, ctx));
810                                 ret = WIMLIB_ERR_WRITE;
811                                 break;
812                         }
813                         j++;
814                 }
815         }
816         unix_cleanup_open_fds(ctx, j);
817         return ret;
818 }
819
820 static int
821 unix_set_dir_metadata(struct list_head *dentry_list, struct unix_apply_ctx *ctx)
822 {
823         const struct wim_dentry *dentry;
824         int ret;
825
826         list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node) {
827                 if (should_extract_as_directory(dentry->d_inode)) {
828                         ret = unix_set_metadata(-1, dentry->d_inode, NULL, ctx);
829                         if (ret)
830                                 return ret;
831                         ret = report_file_metadata_applied(&ctx->common);
832                         if (ret)
833                                 return ret;
834                 }
835         }
836         return 0;
837 }
838
839 static int
840 unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
841 {
842         int ret;
843         struct unix_apply_ctx *ctx = (struct unix_apply_ctx *)_ctx;
844         size_t path_max;
845         u64 dir_count;
846         u64 empty_file_count;
847
848         /* Compute the maximum path length that will be needed, then allocate
849          * some path buffers.  */
850         path_max = unix_compute_path_max(dentry_list, ctx);
851
852         for (unsigned i = 0; i < NUM_PATHBUFS; i++) {
853                 ctx->pathbufs[i] = MALLOC(path_max);
854                 if (!ctx->pathbufs[i]) {
855                         ret = WIMLIB_ERR_NOMEM;
856                         goto out;
857                 }
858                 /* Pre-fill the target in each path buffer.  We'll just append
859                  * the rest of the paths after this.  */
860                 memcpy(ctx->pathbufs[i],
861                        ctx->common.target, ctx->common.target_nchars);
862         }
863
864         /* Extract directories and empty regular files.  Directories are needed
865          * because we can't extract any other files until their directories
866          * exist.  Empty files are needed because they don't have
867          * representatives in the blob list.  */
868
869         unix_count_dentries(dentry_list, &dir_count, &empty_file_count);
870
871         ret = start_file_structure_phase(&ctx->common, dir_count + empty_file_count);
872         if (ret)
873                 goto out;
874
875         ret = unix_create_dirs_and_empty_files(dentry_list, ctx);
876         if (ret)
877                 goto out;
878
879         ret = end_file_structure_phase(&ctx->common);
880         if (ret)
881                 goto out;
882
883         /* Get full path to target if needed for absolute symlink fixups.  */
884         if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX) &&
885             ctx->common.required_features.symlink_reparse_points)
886         {
887                 ctx->target_abspath = realpath(ctx->common.target, NULL);
888                 if (!ctx->target_abspath) {
889                         ret = WIMLIB_ERR_NOMEM;
890                         goto out;
891                 }
892                 ctx->target_abspath_nchars = strlen(ctx->target_abspath);
893         }
894
895         /* Extract nonempty regular files and symbolic links.  */
896
897         struct read_blob_callbacks cbs = {
898                 .begin_blob     = unix_begin_extract_blob,
899                 .continue_blob  = unix_extract_chunk,
900                 .end_blob       = unix_end_extract_blob,
901                 .ctx            = ctx,
902         };
903         ret = extract_blob_list(&ctx->common, &cbs);
904         if (ret)
905                 goto out;
906
907
908         /* Set directory metadata.  We do this last so that we get the right
909          * directory timestamps.  */
910         ret = start_file_metadata_phase(&ctx->common, dir_count);
911         if (ret)
912                 goto out;
913
914         ret = unix_set_dir_metadata(dentry_list, ctx);
915         if (ret)
916                 goto out;
917
918         ret = end_file_metadata_phase(&ctx->common);
919         if (ret)
920                 goto out;
921
922         if (ctx->num_special_files_ignored) {
923                 WARNING("%lu special files were not extracted due to EPERM!",
924                         ctx->num_special_files_ignored);
925         }
926 out:
927         for (unsigned i = 0; i < NUM_PATHBUFS; i++)
928                 FREE(ctx->pathbufs[i]);
929         FREE(ctx->target_abspath);
930         return ret;
931 }
932
933 const struct apply_operations unix_apply_ops = {
934         .name                   = "UNIX",
935         .get_supported_features = unix_get_supported_features,
936         .extract                = unix_extract,
937         .context_size           = sizeof(struct unix_apply_ctx),
938 };