]> wimlib.net Git - wimlib/blob - src/ntfs-3g_apply.c
Add a clang-format file
[wimlib] / src / ntfs-3g_apply.c
1 /*
2  * ntfs-3g_apply.c
3  *
4  * Apply a WIM image directly to an NTFS volume using libntfs-3g.  Restore as
5  * much information as possible, including security data, file attributes, DOS
6  * names, alternate data streams, and object IDs.
7  *
8  * Note: because NTFS-3G offers inode-based interfaces, we actually don't need
9  * to deal with paths at all!  (Other than for error messages.)
10  */
11
12 /*
13  * Copyright (C) 2012-2017 Eric Biggers
14  *
15  * This file is free software; you can redistribute it and/or modify it under
16  * the terms of the GNU Lesser General Public License as published by the Free
17  * Software Foundation; either version 3 of the License, or (at your option) any
18  * later version.
19  *
20  * This file is distributed in the hope that it will be useful, but WITHOUT
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
23  * details.
24  *
25  * You should have received a copy of the GNU Lesser General Public License
26  * along with this file; if not, see https://www.gnu.org/licenses/.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #  include "config.h"
31 #endif
32
33 #include <errno.h>
34 #include <locale.h>
35 #include <string.h>
36
37 #include <ntfs-3g/attrib.h>
38 #include <ntfs-3g/object_id.h>
39 #include <ntfs-3g/reparse.h>
40 #include <ntfs-3g/security.h>
41
42 #include "wimlib/assert.h"
43 #include "wimlib/apply.h"
44 #include "wimlib/blob_table.h"
45 #include "wimlib/dentry.h"
46 #include "wimlib/encoding.h"
47 #include "wimlib/error.h"
48 #include "wimlib/metadata.h"
49 #include "wimlib/ntfs_3g.h"
50 #include "wimlib/object_id.h"
51 #include "wimlib/reparse.h"
52 #include "wimlib/security.h"
53
54 static int
55 ntfs_3g_get_supported_features(const char *target,
56                                struct wim_features *supported_features)
57 {
58         supported_features->readonly_files            = 1;
59         supported_features->hidden_files              = 1;
60         supported_features->system_files              = 1;
61         supported_features->archive_files             = 1;
62         supported_features->compressed_files          = 1;
63         supported_features->not_context_indexed_files = 1;
64         supported_features->sparse_files              = 1;
65         supported_features->named_data_streams        = 1;
66         supported_features->hard_links                = 1;
67         supported_features->reparse_points            = 1;
68         supported_features->security_descriptors      = 1;
69         supported_features->short_names               = 1;
70         supported_features->object_ids                = 1;
71         supported_features->timestamps                = 1;
72         supported_features->case_sensitive_filenames  = 1;
73         return 0;
74 }
75
76 struct ntfs_3g_apply_ctx {
77         /* Extract flags, the pointer to the WIMStruct, etc.  */
78         struct apply_ctx common;
79
80         /* Pointer to the open NTFS volume  */
81         ntfs_volume *vol;
82
83         ntfs_attr *open_attrs[MAX_OPEN_FILES];
84         unsigned num_open_attrs;
85         ntfs_inode *open_inodes[MAX_OPEN_FILES];
86         unsigned num_open_inodes;
87
88         /* For each currently open attribute, whether we're writing to it in
89          * "sparse" mode or not.  */
90         bool is_sparse_attr[MAX_OPEN_FILES];
91
92         /* Whether is_sparse_attr[] is true for any currently open attribute  */
93         bool any_sparse_attrs;
94
95         struct reparse_buffer_disk rpbuf;
96         u8 *reparse_ptr;
97
98         unsigned num_reparse_inodes;
99         ntfs_inode *ntfs_reparse_inodes[MAX_OPEN_FILES];
100         struct wim_inode *wim_reparse_inodes[MAX_OPEN_FILES];
101 };
102
103 static int
104 ntfs_3g_set_timestamps(ntfs_inode *ni, const struct wim_inode *inode)
105 {
106         u64 times[3] = {
107                 inode->i_creation_time,
108                 inode->i_last_write_time,
109                 inode->i_last_access_time,
110         };
111
112         if (ntfs_inode_set_times(ni, (const char *)times, sizeof(times), 0))
113                 return WIMLIB_ERR_SET_TIMESTAMPS;
114         return 0;
115 }
116
117 /* Restore the timestamps on the NTFS inode corresponding to @inode.  */
118 static int
119 ntfs_3g_restore_timestamps(ntfs_volume *vol, const struct wim_inode *inode)
120 {
121         ntfs_inode *ni;
122         int res;
123
124         ni = ntfs_inode_open(vol, inode->i_mft_no);
125         if (!ni)
126                 goto fail;
127
128         res = ntfs_3g_set_timestamps(ni, inode);
129
130         if (ntfs_inode_close(ni) || res)
131                 goto fail;
132
133         return 0;
134
135 fail:
136         ERROR_WITH_ERRNO("Failed to update timestamps of \"%s\" in NTFS volume",
137                          dentry_full_path(inode_first_extraction_dentry(inode)));
138         return WIMLIB_ERR_SET_TIMESTAMPS;
139 }
140
141 /* Restore the DOS name of the @dentry.
142  * This closes both @ni and @dir_ni.
143  * If either is NULL, then they are opened temporarily.  */
144 static int
145 ntfs_3g_restore_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
146                          struct wim_dentry *dentry, ntfs_volume *vol)
147 {
148         int ret;
149         const char *dos_name;
150         size_t dos_name_nbytes;
151
152         /* Note: ntfs_set_ntfs_dos_name() closes both inodes (even if it fails).
153          * And it takes in a multibyte string, even though it translates it to
154          * UTF-16LE internally... which is annoying because we currently have
155          * the UTF-16LE string but not the multibyte string.  */
156
157         ret = utf16le_get_tstr(dentry->d_short_name, dentry->d_short_name_nbytes,
158                                &dos_name, &dos_name_nbytes);
159         if (ret)
160                 goto out_close;
161
162         if (!dir_ni)
163                 dir_ni = ntfs_inode_open(vol, dentry->d_parent->d_inode->i_mft_no);
164         if (!ni)
165                 ni = ntfs_inode_open(vol, dentry->d_inode->i_mft_no);
166         if (dir_ni && ni) {
167                 ret = ntfs_set_ntfs_dos_name(ni, dir_ni,
168                                              dos_name, dos_name_nbytes, 0);
169                 dir_ni = NULL;
170                 ni = NULL;
171         } else {
172                 ret = -1;
173         }
174         utf16le_put_tstr(dos_name);
175         if (unlikely(ret)) {
176                 int err = errno;
177                 ERROR_WITH_ERRNO("Failed to set DOS name of \"%s\" in NTFS "
178                                  "volume", dentry_full_path(dentry));
179                 if (err == EILSEQ) {
180                         ERROR("This error may have been caused by a known "
181                               "bug in libntfs-3g where it is unable to set "
182                               "DOS names on files whose long names contain "
183                               "unpaired surrogate characters.  This bug "
184                               "was fixed in NTFS-3G version 2017.3.23.");
185                 }
186                 if (err == EINVAL) {
187                         utf16lechar c =
188                                 dentry->d_name[dentry->d_name_nbytes / 2 - 1];
189                         if (c == cpu_to_le16('.') || c == cpu_to_le16(' ')) {
190                                 ERROR("This error was probably caused by a "
191                                       "known bug in libntfs-3g where it is "
192                                       "unable to set DOS names on files whose "
193                                       "long names end with a dot or space "
194                                       "character.  This bug was fixed in "
195                                       "NTFS-3G version 2017.3.23.");
196                         }
197                 }
198                 ret = WIMLIB_ERR_SET_SHORT_NAME;
199                 goto out_close;
200         }
201
202         /* Unlike most other NTFS-3G functions, ntfs_set_ntfs_dos_name()
203          * changes the directory's last modification timestamp...
204          * Change it back.  */
205         return ntfs_3g_restore_timestamps(vol, dentry->d_parent->d_inode);
206
207 out_close:
208         /* ntfs_inode_close() can take a NULL argument, but it's probably best
209          * not to rely on this behavior.  */
210         if (ni)
211                 ntfs_inode_close(ni);
212         if (dir_ni)
213                 ntfs_inode_close(dir_ni);
214         return ret;
215 }
216
217 static int
218 ntfs_3g_restore_reparse_point(ntfs_inode *ni, const struct wim_inode *inode,
219                               unsigned blob_size, struct ntfs_3g_apply_ctx *ctx)
220 {
221         complete_reparse_point(&ctx->rpbuf, inode, blob_size);
222
223         if (ntfs_set_ntfs_reparse_data(ni, (const char *)&ctx->rpbuf,
224                                        REPARSE_DATA_OFFSET + blob_size, 0))
225         {
226                 int err = errno;
227                 ERROR_WITH_ERRNO("Failed to set reparse data on \"%s\"",
228                                  dentry_full_path(
229                                         inode_first_extraction_dentry(inode)));
230                 if (err == EINVAL && !(inode->i_reparse_tag & 0x80000000)) {
231                         WARNING("This reparse point had a non-Microsoft reparse "
232                                 "tag.  The preceding error may have been caused "
233                                 "by a known bug in libntfs-3g where it does not "
234                                 "correctly validate non-Microsoft reparse "
235                                 "points.  This bug was fixed in NTFS-3G version "
236                                 "2016.2.22.");
237                 }
238                 return WIMLIB_ERR_SET_REPARSE_DATA;
239         }
240
241         return 0;
242 }
243
244 static bool
245 ntfs_3g_has_empty_attributes(const struct wim_inode *inode)
246 {
247         for (unsigned i = 0; i < inode->i_num_streams; i++) {
248                 const struct wim_inode_stream *strm = &inode->i_streams[i];
249
250                 if (stream_blob_resolved(strm) == NULL &&
251                     (strm->stream_type == STREAM_TYPE_REPARSE_POINT ||
252                      stream_is_named_data_stream(strm)))
253                         return true;
254         }
255         return false;
256 }
257
258 /*
259  * Create empty attributes (named data streams and potentially a reparse point)
260  * for the specified file, if there are any.
261  *
262  * Since these won't have blob descriptors, they won't show up in the call to
263  * extract_blob_list().  Hence the need for the special case.
264  *
265  * Keep this in sync with ntfs_3g_has_empty_attributes()!
266  */
267 static int
268 ntfs_3g_create_empty_attributes(ntfs_inode *ni,
269                                 const struct wim_inode *inode,
270                                 struct ntfs_3g_apply_ctx *ctx)
271 {
272         for (unsigned i = 0; i < inode->i_num_streams; i++) {
273
274                 const struct wim_inode_stream *strm = &inode->i_streams[i];
275                 int ret;
276
277                 if (stream_blob_resolved(strm) != NULL)
278                         continue;
279
280                 if (strm->stream_type == STREAM_TYPE_REPARSE_POINT) {
281                         ret = ntfs_3g_restore_reparse_point(ni, inode, 0, ctx);
282                         if (ret)
283                                 return ret;
284                 } else if (stream_is_named_data_stream(strm)) {
285                         if (ntfs_attr_add(ni, AT_DATA, strm->stream_name,
286                                           utf16le_len_chars(strm->stream_name),
287                                           NULL, 0))
288                         {
289                                 ERROR_WITH_ERRNO("Failed to create named data "
290                                                  "stream of \"%s\"",
291                                                  dentry_full_path(
292                                         inode_first_extraction_dentry(inode)));
293                                 return WIMLIB_ERR_NTFS_3G;
294                         }
295                 }
296         }
297         return 0;
298 }
299
300 /* Set attributes, security descriptor, and timestamps on the NTFS inode @ni.
301  */
302 static int
303 ntfs_3g_set_metadata(ntfs_inode *ni, const struct wim_inode *inode,
304                      const struct ntfs_3g_apply_ctx *ctx)
305 {
306         int extract_flags;
307         const struct wim_security_data *sd;
308         struct wim_dentry *one_dentry;
309         int ret;
310
311         extract_flags = ctx->common.extract_flags;
312         sd = wim_get_current_security_data(ctx->common.wim);
313         one_dentry = inode_first_extraction_dentry(inode);
314
315         /* Object ID */
316         {
317                 u32 len;
318                 const void *object_id = inode_get_object_id(inode, &len);
319                 if (unlikely(object_id != NULL) &&
320                     ntfs_set_ntfs_object_id(ni, object_id, len, 0))
321                 {
322                         if (errno == EEXIST) {
323                                 WARNING("Duplicate object ID on file \"%s\"",
324                                         dentry_full_path(one_dentry));
325                         } else {
326                                 ERROR_WITH_ERRNO("Failed to set object ID on "
327                                                  "\"%s\" in NTFS volume",
328                                                  dentry_full_path(one_dentry));
329                                 return WIMLIB_ERR_NTFS_3G;
330                         }
331                 }
332         }
333
334         /* Attributes  */
335         if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) {
336                 u32 attrib = inode->i_attributes;
337
338                 if (ntfs_set_ntfs_attrib(ni, (const char *)&attrib,
339                                          sizeof(attrib), 0))
340                 {
341                         ERROR_WITH_ERRNO("Failed to set attributes on \"%s\" "
342                                          "in NTFS volume",
343                                          dentry_full_path(one_dentry));
344                         return WIMLIB_ERR_SET_ATTRIBUTES;
345                 }
346         }
347
348         /* Security descriptor  */
349         if (inode_has_security_descriptor(inode)
350             && !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
351         {
352                 struct SECURITY_CONTEXT sec_ctx = { ctx->vol };
353                 const void *desc;
354                 size_t desc_size;
355
356                 desc = sd->descriptors[inode->i_security_id];
357                 desc_size = sd->sizes[inode->i_security_id];
358
359                 ret = ntfs_set_ntfs_acl(&sec_ctx, ni, desc, desc_size, 0);
360
361                 if (unlikely(ret)) {
362                         int err = errno;
363                         ERROR_WITH_ERRNO("Failed to set security descriptor on "
364                                          "\"%s\" in NTFS volume",
365                                          dentry_full_path(one_dentry));
366                         if (err == EINVAL && wimlib_print_errors) {
367                                 fprintf(wimlib_error_file,
368                                         "The security descriptor is: ");
369                                 print_byte_field(desc, desc_size, wimlib_error_file);
370                                 fprintf(wimlib_error_file,
371                                         "\n\nThis error occurred because libntfs-3g thinks "
372                                         "the security descriptor is invalid.  There "
373                                         "are several known bugs with libntfs-3g's "
374                                         "security descriptor validation logic in older "
375                                         "versions.  Please upgrade to NTFS-3G version "
376                                         "2016.2.22 or later if you haven't already.\n");
377                         }
378                         return WIMLIB_ERR_SET_SECURITY;
379                 }
380         }
381
382         /* Timestamps  */
383         ret = ntfs_3g_set_timestamps(ni, inode);
384         if (ret) {
385                 ERROR_WITH_ERRNO("Failed to set timestamps on \"%s\" "
386                                  "in NTFS volume",
387                                  dentry_full_path(one_dentry));
388                 return ret;
389         }
390         return 0;
391 }
392
393 /* Recursively creates all the subdirectories of @dir, which has been created as
394  * the NTFS inode @dir_ni.  */
395 static int
396 ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir,
397                               struct ntfs_3g_apply_ctx *ctx)
398 {
399         struct wim_dentry *child;
400
401         for_dentry_child(child, dir) {
402                 ntfs_inode *ni;
403                 int ret;
404
405                 if (!(child->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
406                         continue;
407                 if (!will_extract_dentry(child))
408                         continue;
409
410                 ni = ntfs_create(dir_ni, 0, child->d_extraction_name,
411                                  child->d_extraction_name_nchars, S_IFDIR);
412                 if (!ni) {
413                         ERROR_WITH_ERRNO("Error creating \"%s\" in NTFS volume",
414                                          dentry_full_path(child));
415                         return WIMLIB_ERR_NTFS_3G;
416                 }
417
418                 child->d_inode->i_mft_no = ni->mft_no;
419
420                 ret = report_file_created(&ctx->common);
421                 if (!ret)
422                         ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx);
423                 if (!ret)
424                         ret = ntfs_3g_create_dirs_recursive(ni, child, ctx);
425
426                 if (ntfs_inode_close_in_dir(ni, dir_ni) && !ret) {
427                         ERROR_WITH_ERRNO("Error closing \"%s\" in NTFS volume",
428                                          dentry_full_path(child));
429                         ret = WIMLIB_ERR_NTFS_3G;
430                 }
431                 if (ret)
432                         return ret;
433         }
434         return 0;
435 }
436
437 /* For each WIM dentry in the @root tree that represents a directory, create the
438  * corresponding directory in the NTFS volume @ctx->vol.  */
439 static int
440 ntfs_3g_create_directories(struct wim_dentry *root,
441                            struct list_head *dentry_list,
442                            struct ntfs_3g_apply_ctx *ctx)
443 {
444         ntfs_inode *root_ni;
445         int ret;
446         struct wim_dentry *dentry;
447
448         /* Create the directories using POSIX names.  */
449
450         root_ni = ntfs_inode_open(ctx->vol, FILE_root);
451         if (!root_ni) {
452                 ERROR_WITH_ERRNO("Can't open root of NTFS volume");
453                 return WIMLIB_ERR_NTFS_3G;
454         }
455
456         root->d_inode->i_mft_no = FILE_root;
457
458         ret = ntfs_3g_set_metadata(root_ni, root->d_inode, ctx);
459         if (!ret)
460                 ret = ntfs_3g_create_dirs_recursive(root_ni, root, ctx);
461
462         if (ntfs_inode_close(root_ni) && !ret) {
463                 ERROR_WITH_ERRNO("Error closing root of NTFS volume");
464                 ret = WIMLIB_ERR_NTFS_3G;
465         }
466         if (ret)
467                 return ret;
468
469         /* Set the DOS name of any directory that has one.  In addition, create
470          * empty attributes for directories that have them.  Note that creating
471          * an empty reparse point attribute must happen *after* setting the DOS
472          * name in order to work around a case where ntfs_set_ntfs_dos_name()
473          * fails with EOPNOTSUPP.  This bug was fixed in NTFS-3G version
474          * 2016.2.22.  */
475         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
476                 const struct wim_inode *inode = dentry->d_inode;
477
478                 if (!(inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
479                         continue;
480                 if (dentry_has_short_name(dentry)) {
481                         ret = ntfs_3g_restore_dos_name(NULL, NULL, dentry,
482                                                        ctx->vol);
483                         if (ret)
484                                 return ret;
485                         ret = report_file_created(&ctx->common);
486                         if (ret)
487                                 return ret;
488                 }
489                 if (ntfs_3g_has_empty_attributes(inode)) {
490                         ntfs_inode *ni;
491
492                         ret = WIMLIB_ERR_NTFS_3G;
493                         ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
494                         if (ni) {
495                                 ret = ntfs_3g_create_empty_attributes(ni, inode,
496                                                                       ctx);
497                                 if (ntfs_inode_close(ni) && !ret)
498                                         ret = WIMLIB_ERR_NTFS_3G;
499                         }
500                         if (ret) {
501                                 ERROR_WITH_ERRNO("Failed to create empty "
502                                                  "attributes of directory "
503                                                  "\"%s\" in NTFS volume",
504                                                  dentry_full_path(dentry));
505                                 return ret;
506                         }
507                 }
508         }
509         return 0;
510 }
511
512 /* When creating an inode that will have a short (DOS) name, we create it using
513  * the long name associated with the short name.  This ensures that the short
514  * name gets associated with the correct long name.  */
515 static struct wim_dentry *
516 ntfs_3g_first_extraction_alias(struct wim_inode *inode)
517 {
518         struct wim_dentry *dentry;
519
520         inode_for_each_extraction_alias(dentry, inode)
521                 if (dentry_has_short_name(dentry))
522                         return dentry;
523         return inode_first_extraction_dentry(inode);
524 }
525
526 /*
527  * Add a hard link for the NTFS inode @ni at the location corresponding to the
528  * WIM dentry @dentry.
529  *
530  * The parent directory must have already been created on the NTFS volume.
531  *
532  * Returns 0 on success; returns WIMLIB_ERR_NTFS_3G and sets errno on failure.
533  */
534 static int
535 ntfs_3g_add_link(ntfs_inode *ni, struct wim_dentry *dentry)
536 {
537         ntfs_inode *dir_ni;
538         int res;
539
540         /* Open the inode of the parent directory.  */
541         dir_ni = ntfs_inode_open(ni->vol, dentry->d_parent->d_inode->i_mft_no);
542         if (!dir_ni)
543                 goto fail;
544
545         /* Create the link.  */
546         res = ntfs_link(ni, dir_ni, dentry->d_extraction_name,
547                         dentry->d_extraction_name_nchars);
548
549         /* Close the parent directory.  */
550         if (ntfs_inode_close(dir_ni) || res)
551                 goto fail;
552
553         return 0;
554
555 fail:
556         ERROR_WITH_ERRNO("Can't create link \"%s\" in NTFS volume",
557                          dentry_full_path(dentry));
558         return WIMLIB_ERR_NTFS_3G;
559 }
560
561 static int
562 ntfs_3g_create_nondirectory(struct wim_inode *inode,
563                             struct ntfs_3g_apply_ctx *ctx)
564 {
565         struct wim_dentry *first_dentry;
566         ntfs_inode *dir_ni;
567         ntfs_inode *ni;
568         struct wim_dentry *dentry;
569         int ret;
570
571         first_dentry = ntfs_3g_first_extraction_alias(inode);
572
573         /* Create first link.  */
574
575         dir_ni = ntfs_inode_open(ctx->vol, first_dentry->d_parent->d_inode->i_mft_no);
576         if (!dir_ni) {
577                 ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
578                                  dentry_full_path(first_dentry->d_parent));
579                 return WIMLIB_ERR_NTFS_3G;
580         }
581
582         ni = ntfs_create(dir_ni, 0, first_dentry->d_extraction_name,
583                          first_dentry->d_extraction_name_nchars, S_IFREG);
584
585         if (!ni) {
586                 ERROR_WITH_ERRNO("Can't create \"%s\" in NTFS volume",
587                                  dentry_full_path(first_dentry));
588                 ntfs_inode_close(dir_ni);
589                 return WIMLIB_ERR_NTFS_3G;
590         }
591
592         inode->i_mft_no = ni->mft_no;
593
594         /* Set short name if present.  */
595         if (dentry_has_short_name(first_dentry)) {
596
597                 ret = ntfs_3g_restore_dos_name(ni, dir_ni, first_dentry, ctx->vol);
598
599                 /* ntfs_3g_restore_dos_name() closed both 'ni' and 'dir_ni'.  */
600
601                 if (ret)
602                         return ret;
603
604                 /* Reopen the inode.  */
605                 ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
606                 if (!ni) {
607                         ERROR_WITH_ERRNO("Failed to reopen \"%s\" "
608                                          "in NTFS volume",
609                                          dentry_full_path(first_dentry));
610                         return WIMLIB_ERR_NTFS_3G;
611                 }
612         } else {
613                 /* Close the directory in which the first link was created.  */
614                 if (ntfs_inode_close(dir_ni)) {
615                         ERROR_WITH_ERRNO("Failed to close \"%s\" in NTFS volume",
616                                          dentry_full_path(first_dentry->d_parent));
617                         ret = WIMLIB_ERR_NTFS_3G;
618                         goto out_close_ni;
619                 }
620         }
621
622         /* Create additional links if present.  */
623         inode_for_each_extraction_alias(dentry, inode) {
624                 if (dentry != first_dentry) {
625                         ret = ntfs_3g_add_link(ni, dentry);
626                         if (ret)
627                                 goto out_close_ni;
628                 }
629         }
630
631         /* Set metadata.  */
632         ret = ntfs_3g_set_metadata(ni, inode, ctx);
633         if (ret)
634                 goto out_close_ni;
635
636         ret = ntfs_3g_create_empty_attributes(ni, inode, ctx);
637
638 out_close_ni:
639         /* Close the inode.  */
640         if (ntfs_inode_close(ni) && !ret) {
641                 ERROR_WITH_ERRNO("Error closing \"%s\" in NTFS volume",
642                                  dentry_full_path(first_dentry));
643                 ret = WIMLIB_ERR_NTFS_3G;
644         }
645         return ret;
646 }
647
648 /* For each WIM dentry in the @dentry_list that represents a nondirectory file,
649  * create the corresponding nondirectory file in the NTFS volume.
650  *
651  * Directories must have already been created.  */
652 static int
653 ntfs_3g_create_nondirectories(struct list_head *dentry_list,
654                               struct ntfs_3g_apply_ctx *ctx)
655 {
656         struct wim_dentry *dentry;
657         struct wim_inode *inode;
658         int ret;
659
660         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
661                 inode = dentry->d_inode;
662                 if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
663                         continue;
664                 if (dentry == inode_first_extraction_dentry(inode)) {
665                         ret = ntfs_3g_create_nondirectory(inode, ctx);
666                         if (ret)
667                                 return ret;
668                 }
669                 ret = report_file_created(&ctx->common);
670                 if (ret)
671                         return ret;
672         }
673         return 0;
674 }
675
676 static int
677 ntfs_3g_begin_extract_blob_instance(struct blob_descriptor *blob,
678                                     ntfs_inode *ni,
679                                     struct wim_inode *inode,
680                                     const struct wim_inode_stream *strm,
681                                     struct ntfs_3g_apply_ctx *ctx)
682 {
683         struct wim_dentry *one_dentry = inode_first_extraction_dentry(inode);
684         ntfschar *stream_name;
685         size_t stream_name_nchars;
686         ntfs_attr *na;
687
688         if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
689
690                 if (blob->size > REPARSE_DATA_MAX_SIZE) {
691                         ERROR("Reparse data of \"%s\" has size "
692                               "%"PRIu64" bytes (exceeds %u bytes)",
693                               dentry_full_path(one_dentry),
694                               blob->size, REPARSE_DATA_MAX_SIZE);
695                         return WIMLIB_ERR_INVALID_REPARSE_DATA;
696                 }
697                 ctx->reparse_ptr = ctx->rpbuf.rpdata;
698                 ctx->ntfs_reparse_inodes[ctx->num_reparse_inodes] = ni;
699                 ctx->wim_reparse_inodes[ctx->num_reparse_inodes] = inode;
700                 ctx->num_reparse_inodes++;
701                 return 0;
702         }
703
704         /* It's a data stream (may be unnamed or named).  */
705         wimlib_assert(strm->stream_type == STREAM_TYPE_DATA);
706
707         if (unlikely(stream_is_named(strm))) {
708                 stream_name = strm->stream_name;
709                 stream_name_nchars = utf16le_len_chars(stream_name);
710
711                 if (ntfs_attr_add(ni, AT_DATA, stream_name,
712                                   stream_name_nchars, NULL, 0))
713                 {
714                         ERROR_WITH_ERRNO("Failed to create named data stream of \"%s\"",
715                                          dentry_full_path(one_dentry));
716                         return WIMLIB_ERR_NTFS_3G;
717                 }
718         } else {
719                 /* Don't pass an empty string other than AT_UNNAMED to
720                  * ntfs_attr_open() --- it violates assumptions made by
721                  * libntfs-3g.  */
722                 stream_name = AT_UNNAMED;
723                 stream_name_nchars = 0;
724         }
725
726         /* This should be ensured by extract_blob_list()  */
727         wimlib_assert(ctx->num_open_attrs < MAX_OPEN_FILES);
728
729         na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_nchars);
730         if (!na) {
731                 ERROR_WITH_ERRNO("Failed to open data stream of \"%s\"",
732                                  dentry_full_path(one_dentry));
733                 return WIMLIB_ERR_NTFS_3G;
734         }
735
736         /*
737          * Note: there are problems with trying to combine compression with
738          * sparseness when extracting.  For example, doing ntfs_attr_truncate()
739          * at the end to extend the attribute to its final size actually extends
740          * to a compression block size boundary rather than to the requested
741          * size.  Until these problems are solved, we always write the full data
742          * to compressed attributes.  We also don't attempt to preallocate space
743          * for compressed attributes, since we don't know how much space they
744          * are going to actually need.
745          */
746         ctx->is_sparse_attr[ctx->num_open_attrs] = false;
747         if (!(na->data_flags & ATTR_COMPRESSION_MASK)) {
748                 if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
749                         ctx->is_sparse_attr[ctx->num_open_attrs] = true;
750                         ctx->any_sparse_attrs = true;
751                 } else {
752                         ntfs_attr_truncate_solid(na, blob->size);
753                 }
754         }
755         ctx->open_attrs[ctx->num_open_attrs++] = na;
756         return 0;
757 }
758
759 static int
760 ntfs_3g_cleanup_blob_extract(struct ntfs_3g_apply_ctx *ctx)
761 {
762         int ret = 0;
763
764         for (unsigned i = 0; i < ctx->num_open_attrs; i++) {
765                 if (ntfs_attr_pclose(ctx->open_attrs[i]))
766                         ret = -1;
767                 ntfs_attr_close(ctx->open_attrs[i]);
768         }
769
770         ctx->num_open_attrs = 0;
771
772         for (unsigned i = 0; i < ctx->num_open_inodes; i++) {
773                 if (ntfs_inode_close(ctx->open_inodes[i]))
774                         ret = -1;
775         }
776         ctx->num_open_inodes = 0;
777
778         ctx->any_sparse_attrs = false;
779         ctx->reparse_ptr = NULL;
780         ctx->num_reparse_inodes = 0;
781         return ret;
782 }
783
784 static ntfs_inode *
785 ntfs_3g_open_inode(struct wim_inode *inode, struct ntfs_3g_apply_ctx *ctx)
786 {
787         ntfs_inode *ni;
788
789         /* If the same blob is being extracted to multiple streams of the same
790          * inode, then we must only open the inode once.  */
791         if (unlikely(inode->i_num_streams > 1)) {
792                 for (unsigned i = 0; i < ctx->num_open_inodes; i++) {
793                         if (ctx->open_inodes[i]->mft_no == inode->i_mft_no) {
794                                 return ctx->open_inodes[i];
795                         }
796                 }
797         }
798
799         ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
800         if (unlikely(!ni)) {
801                 ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
802                                  dentry_full_path(
803                                         inode_first_extraction_dentry(inode)));
804                 return NULL;
805         }
806
807         ctx->open_inodes[ctx->num_open_inodes++] = ni;
808         return ni;
809 }
810
811 static int
812 ntfs_3g_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
813 {
814         struct ntfs_3g_apply_ctx *ctx = _ctx;
815         const struct blob_extraction_target *targets = blob_extraction_targets(blob);
816         int ret;
817         ntfs_inode *ni;
818
819         for (u32 i = 0; i < blob->out_refcnt; i++) {
820                 ret = WIMLIB_ERR_NTFS_3G;
821                 ni = ntfs_3g_open_inode(targets[i].inode, ctx);
822                 if (!ni)
823                         goto out_cleanup;
824
825                 ret = ntfs_3g_begin_extract_blob_instance(blob, ni,
826                                                           targets[i].inode,
827                                                           targets[i].stream, ctx);
828                 if (ret)
829                         goto out_cleanup;
830         }
831         ret = 0;
832         goto out;
833
834 out_cleanup:
835         ntfs_3g_cleanup_blob_extract(ctx);
836 out:
837         return ret;
838 }
839
840 /*
841  * Note: prior to NTFS-3G version 2016.2.22, ntfs_attr_pwrite() could return a
842  * short count in non-error cases, contrary to its documentation.  Specifically,
843  * a short count could be returned when writing to a compressed attribute and
844  * the requested count exceeded the size of an NTFS "compression block".
845  * Therefore, we must continue calling ntfs_attr_pwrite() until all bytes have
846  * been written or a real error has occurred.
847  */
848 static bool
849 ntfs_3g_full_pwrite(ntfs_attr *na, u64 offset, size_t size, const u8 *data)
850 {
851         while (size) {
852                 s64 res = ntfs_attr_pwrite(na, offset, size, data);
853                 if (unlikely(res <= 0))
854                         return false;
855                 wimlib_assert(res <= size);
856                 offset += res;
857                 size -= res;
858                 data += res;
859         }
860         return true;
861 }
862
863 static int
864 ntfs_3g_extract_chunk(const struct blob_descriptor *blob, u64 offset,
865                       const void *chunk, size_t size, void *_ctx)
866 {
867         struct ntfs_3g_apply_ctx *ctx = _ctx;
868         const void * const end = chunk + size;
869         const void *p;
870         bool zeroes;
871         size_t len;
872         unsigned i;
873
874         /*
875          * For sparse attributes, only write nonzero regions.  This lets the
876          * filesystem use holes to represent zero regions.
877          */
878         for (p = chunk; p != end; p += len, offset += len) {
879                 zeroes = maybe_detect_sparse_region(p, end - p, &len,
880                                                     ctx->any_sparse_attrs);
881                 for (i = 0; i < ctx->num_open_attrs; i++) {
882                         if (!zeroes || !ctx->is_sparse_attr[i]) {
883                                 if (!ntfs_3g_full_pwrite(ctx->open_attrs[i],
884                                                          offset, len, p))
885                                         goto err;
886                         }
887                 }
888         }
889
890         if (ctx->reparse_ptr)
891                 ctx->reparse_ptr = mempcpy(ctx->reparse_ptr, chunk, size);
892         return 0;
893
894 err:
895         ERROR_WITH_ERRNO("Error writing data to NTFS volume");
896         return WIMLIB_ERR_NTFS_3G;
897 }
898
899 static int
900 ntfs_3g_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
901 {
902         struct ntfs_3g_apply_ctx *ctx = _ctx;
903         int ret;
904
905         if (status) {
906                 ret = status;
907                 goto out;
908         }
909
910         /* Extend sparse attributes to their final size. */
911         if (ctx->any_sparse_attrs) {
912                 for (unsigned i = 0; i < ctx->num_open_attrs; i++) {
913                         if (!ctx->is_sparse_attr[i])
914                                 continue;
915                         if (ntfs_attr_truncate(ctx->open_attrs[i], blob->size))
916                         {
917                                 ERROR_WITH_ERRNO("Error extending attribute to "
918                                                  "final size");
919                                 ret = WIMLIB_ERR_WRITE;
920                                 goto out;
921                         }
922                 }
923         }
924
925         for (u32 i = 0; i < ctx->num_reparse_inodes; i++) {
926                 ret = ntfs_3g_restore_reparse_point(ctx->ntfs_reparse_inodes[i],
927                                                     ctx->wim_reparse_inodes[i],
928                                                     blob->size, ctx);
929                 if (ret)
930                         goto out;
931         }
932         ret = 0;
933 out:
934         if (ntfs_3g_cleanup_blob_extract(ctx) && !ret) {
935                 ERROR_WITH_ERRNO("Error writing data to NTFS volume");
936                 ret = WIMLIB_ERR_NTFS_3G;
937         }
938         return ret;
939 }
940
941 static u64
942 ntfs_3g_count_dentries(const struct list_head *dentry_list)
943 {
944         const struct wim_dentry *dentry;
945         u64 count = 0;
946
947         list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
948                 count++;
949                 if ((dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) &&
950                     dentry_has_short_name(dentry))
951                 {
952                         count++;
953                 }
954         }
955
956         return count;
957 }
958
959 static int
960 ntfs_3g_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
961 {
962         struct ntfs_3g_apply_ctx *ctx = (struct ntfs_3g_apply_ctx *)_ctx;
963         ntfs_volume *vol;
964         struct wim_dentry *root;
965         int ret;
966
967         /* For NTFS-3G extraction mode we require that the dentries to extract
968          * form a single tree.  */
969         root = list_first_entry(dentry_list, struct wim_dentry,
970                                 d_extraction_list_node);
971
972         /* Mount the NTFS volume.  */
973         vol = ntfs_mount(ctx->common.target, 0);
974         if (!vol) {
975                 ERROR_WITH_ERRNO("Failed to mount \"%s\" with NTFS-3G",
976                                  ctx->common.target);
977                 return WIMLIB_ERR_NTFS_3G;
978         }
979         ctx->vol = vol;
980
981         /* Opening $Secure is required to set security descriptors in NTFS v3.0
982          * format, where security descriptors are stored in a per-volume index
983          * rather than being fully specified for each file.  */
984         if (ntfs_open_secure(vol) && vol->major_ver >= 3) {
985                 ERROR_WITH_ERRNO("Unable to open security descriptor index of "
986                                  "NTFS volume \"%s\"", ctx->common.target);
987                 ret = WIMLIB_ERR_NTFS_3G;
988                 goto out_unmount;
989         }
990
991         /* Create all inodes and aliases, including short names, and set
992          * metadata (attributes, security descriptors, and timestamps).  */
993
994         ret = start_file_structure_phase(&ctx->common,
995                                          ntfs_3g_count_dentries(dentry_list));
996         if (ret)
997                 goto out_unmount;
998
999         ret = ntfs_3g_create_directories(root, dentry_list, ctx);
1000         if (ret)
1001                 goto out_unmount;
1002
1003         ret = ntfs_3g_create_nondirectories(dentry_list, ctx);
1004         if (ret)
1005                 goto out_unmount;
1006
1007         ret = end_file_structure_phase(&ctx->common);
1008         if (ret)
1009                 goto out_unmount;
1010
1011         /* Extract blobs.  */
1012         struct read_blob_callbacks cbs = {
1013                 .begin_blob     = ntfs_3g_begin_extract_blob,
1014                 .continue_blob  = ntfs_3g_extract_chunk,
1015                 .end_blob       = ntfs_3g_end_extract_blob,
1016                 .ctx            = ctx,
1017         };
1018         ret = extract_blob_list(&ctx->common, &cbs);
1019
1020         /* We do not need a final pass to set timestamps because libntfs-3g does
1021          * not update timestamps automatically (exception:
1022          * ntfs_set_ntfs_dos_name() does, but we handle this elsewhere).  */
1023
1024 out_unmount:
1025         if (vol->secure_ni) {
1026                 ntfs_index_ctx_put(vol->secure_xsii);
1027                 ntfs_index_ctx_put(vol->secure_xsdh);
1028                 if (ntfs_inode_close(vol->secure_ni) && !ret) {
1029                         ERROR_WITH_ERRNO("Failed to close security descriptor "
1030                                          "index of NTFS volume \"%s\"",
1031                                          ctx->common.target);
1032                         ret = WIMLIB_ERR_NTFS_3G;
1033                 }
1034                 vol->secure_ni = NULL;
1035         }
1036         if (ntfs_umount(ctx->vol, FALSE) && !ret) {
1037                 ERROR_WITH_ERRNO("Failed to unmount \"%s\" with NTFS-3G",
1038                                  ctx->common.target);
1039                 ret = WIMLIB_ERR_NTFS_3G;
1040         }
1041         return ret;
1042 }
1043
1044 const struct apply_operations ntfs_3g_apply_ops = {
1045         .name                   = "NTFS-3G",
1046         .get_supported_features = ntfs_3g_get_supported_features,
1047         .extract                = ntfs_3g_extract,
1048         .context_size           = sizeof(struct ntfs_3g_apply_ctx),
1049         .single_tree_only       = true,
1050 };