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