]> wimlib.net Git - wimlib/blob - src/mount_image.c
mount_image.c: Update directory timestamps
[wimlib] / src / mount_image.c
1 /*
2  * mount_image.c
3  *
4  * This file implements mounting of WIM files using FUSE, which stands for
5  * Filesystem in Userspace.  FUSE allows a filesystem to be implemented in a
6  * userspace process by implementing the filesystem primitives--- read(),
7  * write(), readdir(), etc.
8  */
9
10 /*
11  * Copyright (C) 2012, 2013, 2014 Eric Biggers
12  *
13  * This file is part of wimlib, a library for working with WIM files.
14  *
15  * wimlib is free software; you can redistribute it and/or modify it under the
16  * terms of the GNU General Public License as published by the Free
17  * Software Foundation; either version 3 of the License, or (at your option)
18  * any later version.
19  *
20  * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
21  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
22  * A PARTICULAR PURPOSE. See the GNU General Public License for more
23  * details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with wimlib; if not, see http://www.gnu.org/licenses/.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #  include "config.h"
31 #endif
32
33 #include "wimlib.h"
34
35 #ifdef WITH_FUSE
36
37 #ifdef __WIN32__
38 #  error "FUSE mount not supported on Windows!  Please configure --without-fuse"
39 #endif
40
41 #include "wimlib/dentry.h"
42 #include "wimlib/encoding.h"
43 #include "wimlib/metadata.h"
44 #include "wimlib/paths.h"
45 #include "wimlib/progress.h"
46 #include "wimlib/reparse.h"
47 #include "wimlib/timestamp.h"
48 #include "wimlib/unix_data.h"
49 #include "wimlib/write.h"
50 #include "wimlib/xml.h"
51
52 #include <dirent.h>
53 #include <errno.h>
54 #include <limits.h>
55 #include <mqueue.h>
56 #include <pthread.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <sys/stat.h>
60 #include <sys/time.h>
61 #include <sys/types.h>
62 #include <unistd.h>
63 #include <utime.h>
64
65 #define FUSE_USE_VERSION 26
66 #include <fuse.h>
67 #include <attr/xattr.h>
68
69 #ifndef O_NOFOLLOW
70 #  define O_NOFOLLOW 0  /* Security only...  */
71 #endif
72
73 #define WIMFS_MQUEUE_NAME_LEN 32
74
75 #define WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS 0x80000000
76
77 struct wimfs_unmount_info {
78         unsigned unmount_flags;
79         char mq_name[WIMFS_MQUEUE_NAME_LEN + 1];
80 };
81
82 struct commit_progress_report {
83         enum wimlib_progress_msg msg;
84         union wimlib_progress_info info;
85 };
86
87 /* Description of an open file on a mounted WIM image.  Actually, this
88  * represents the open state of a particular data stream of an inode, rather
89  * than the inode itself.  (An inode might have multiple named data streams in
90  * addition to the default, unnamed data stream.)  At a given time, an inode in
91  * the WIM image might have multiple file descriptors open to it, each to any
92  * one of its data streams.  */
93 struct wimfs_fd {
94
95         /* Pointer to the inode of this open file.
96          * 'i_num_opened_fds' of the inode tracks the number of file descriptors
97          * that reference it.  */
98         struct wim_inode *f_inode;
99
100         /* Pointer to the lookup table entry for the data stream that has been
101          * opened.  'num_opened_fds' of the lookup table entry tracks the number
102          * of file descriptors that reference it.  Or, this value may be NULL,
103          * which indicates that the opened stream is empty and consequently does
104          * not have a lookup table entry.  */
105         struct wim_lookup_table_entry *f_lte;
106
107         /* If valid (filedes_valid(&f_staging_fd)), this contains the
108          * corresponding native file descriptor for the staging file that has
109          * been created for reading from and/or writing to this open stream.  A
110          * single staging file might have multiple file descriptors open to it
111          * simultaneously, each used by a different 'struct wimfs_fd'.
112          *
113          * Or, if invalid (!filedes_valid(&f_staging_fd)), this 'struct
114          * wimfs_fd' is not associated with a staging file.  This is permissible
115          * only if this 'struct wimfs_fd' was opened read-only and the stream
116          * has not yet been extracted to a staging file.  */
117         struct filedes f_staging_fd;
118
119         /* 0-based index of this file descriptor in the file descriptor table of
120          * its inode.  */
121         u16 f_idx;
122
123         /* Unique ID of the opened stream in the inode.  This will stay the same
124          * even if the indices of the inode's alternate data streams are changed
125          * by a deletion.  */
126         u32 f_stream_id;
127 };
128
129 #define WIMFS_FD(fi) ((struct wimfs_fd *)(uintptr_t)((fi)->fh))
130
131 /* Context structure for a mounted WIM image.  */
132 struct wimfs_context {
133         /* The WIMStruct containing the mounted image.  The mounted image is the
134          * currently selected image (wim->current_image).  */
135         WIMStruct *wim;
136
137         /* Flags passed to wimlib_mount_image() (WIMLIB_MOUNT_FLAG_*).  */
138         int mount_flags;
139
140         /* Default flags for path lookup in the WIM image.  */
141         int default_lookup_flags;
142
143         /* Information about the user who has mounted the WIM image  */
144         uid_t owner_uid;
145         gid_t owner_gid;
146
147         /* Information about the staging directory for a read-write mount.  */
148         int parent_dir_fd;
149         int staging_dir_fd;
150         char *staging_dir_name;
151
152         /* For read-write mounts, the inode number to be assigned to the next
153          * created file.  Note: since this isn't a persistent filesystem and we
154          * can re-assign the inode numbers just before mounting the image, it's
155          * good enough to just generate inode numbers sequentially.  */
156         u64 next_ino;
157
158         /* Number of file descriptors open to the mounted WIM image.  */
159         unsigned long num_open_fds;
160
161         /* Original list of single-instance streams in the mounted image, linked
162          * by 'struct wim_lookup_table_entry'.orig_stream_list.  */
163         struct list_head orig_stream_list;
164 };
165
166 #define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data)
167
168 /* Retrieve the context structure for the currently mounted WIM image.
169  *
170  * Note: this is a per-thread variable.  It is possible for different threads to
171  * mount different images at the same time in the same process, although they
172  * must use different WIMStructs!  */
173 static inline struct wimfs_context *
174 wimfs_get_context(void)
175 {
176         return WIMFS_CTX(fuse_get_context());
177 }
178
179 static void
180 wimfs_inc_num_open_fds(void)
181 {
182         wimfs_get_context()->num_open_fds++;
183 }
184
185 static void
186 wimfs_dec_num_open_fds(void)
187 {
188         wimfs_get_context()->num_open_fds--;
189 }
190
191 /* Retrieve the WIMStruct for the currently mounted WIM image.  */
192 static inline WIMStruct *
193 wimfs_get_WIMStruct(void)
194 {
195         return wimfs_get_context()->wim;
196 }
197
198 static inline int
199 get_lookup_flags(const struct wimfs_context *ctx)
200 {
201         return ctx->default_lookup_flags;
202 }
203
204 /* Is write permission requested on the file?  */
205 static inline bool
206 flags_writable(int open_flags)
207 {
208         int accmode = (open_flags & O_ACCMODE);
209         return (accmode == O_RDWR || accmode == O_WRONLY);
210 }
211
212 static mode_t
213 fuse_mask_mode(mode_t mode, const struct fuse_context *fuse_ctx)
214 {
215 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
216         mode &= ~fuse_ctx->umask;
217 #endif
218         return mode;
219 }
220
221 /*
222  * Allocate a file descriptor to a data stream in the mounted WIM image.
223  *
224  * @inode
225  *      A pointer to the inode containing the stream being opened.
226  * @stream_id
227  *      The ID of the data stream being opened within the inode.
228  * @lte
229  *      A pointer to the lookup table entry for the stream data.  Or, for a
230  *      0-byte stream, this may be NULL.
231  * @fd_ret
232  *      On success, a pointer to the new file descriptor will be stored here.
233  *
234  * Returns 0 or a -errno code.
235  */
236 static int
237 alloc_wimfs_fd(struct wim_inode *inode,
238                u32 stream_id,
239                struct wim_lookup_table_entry *lte,
240                struct wimfs_fd **fd_ret)
241 {
242         static const u16 min_fds_per_alloc = 8;
243         static const u16 max_fds = 0xffff;
244         u16 i;
245         struct wimfs_fd *fd;
246
247         if (inode->i_num_opened_fds == inode->i_num_allocated_fds) {
248                 u16 num_new_fds;
249                 struct wimfs_fd **fds;
250
251                 /* Expand this inode's file descriptor table.  */
252
253                 num_new_fds = max(min_fds_per_alloc,
254                                   inode->i_num_allocated_fds / 4);
255
256                 num_new_fds = min(num_new_fds,
257                                   max_fds - inode->i_num_allocated_fds);
258
259                 if (num_new_fds == 0)
260                         return -EMFILE;
261
262                 fds = REALLOC(inode->i_fds,
263                               (inode->i_num_allocated_fds + num_new_fds) *
264                                 sizeof(fds[0]));
265                 if (!fds)
266                         return -ENOMEM;
267
268                 memset(&fds[inode->i_num_allocated_fds], 0,
269                        num_new_fds * sizeof(fds[0]));
270                 inode->i_fds = fds;
271                 inode->i_num_allocated_fds += num_new_fds;
272                 inode->i_next_fd = inode->i_num_opened_fds;
273         }
274
275         /* Allocate the file descriptor in the first available space in the
276          * inode's file descriptor table.
277          *
278          * i_next_fd is the lower bound on the next open slot.  */
279         for (i = inode->i_next_fd; inode->i_fds[i]; i++)
280                 ;
281
282         fd = MALLOC(sizeof(*fd));
283         if (!fd)
284                 return -ENOMEM;
285
286         fd->f_inode     = inode;
287         fd->f_lte       = lte;
288         filedes_invalidate(&fd->f_staging_fd);
289         fd->f_idx       = i;
290         fd->f_stream_id = stream_id;
291         *fd_ret         = fd;
292         inode->i_fds[i] = fd;
293         inode->i_num_opened_fds++;
294         if (lte)
295                 lte->num_opened_fds++;
296         wimfs_inc_num_open_fds();
297         inode->i_next_fd = i + 1;
298         return 0;
299 }
300
301 /*
302  * Close a file descriptor to a data stream in the mounted WIM image.
303  *
304  * Returns 0 or a -errno code.  The file descriptor is always closed.
305  */
306 static int
307 close_wimfs_fd(struct wimfs_fd *fd)
308 {
309         int ret = 0;
310         struct wim_inode *inode;
311
312         /* Close the staging file if open.  */
313         if (filedes_valid(&fd->f_staging_fd))
314                  if (filedes_close(&fd->f_staging_fd))
315                          ret = -errno;
316
317         /* Release this file descriptor from its lookup table entry.  */
318         if (fd->f_lte)
319                 lte_decrement_num_opened_fds(fd->f_lte);
320
321         wimfs_dec_num_open_fds();
322
323         /* Release this file descriptor from its inode.  */
324         inode = fd->f_inode;
325         inode->i_fds[fd->f_idx] = NULL;
326         if (fd->f_idx < inode->i_next_fd)
327                 inode->i_next_fd = fd->f_idx;
328         FREE(fd);
329         if (--inode->i_num_opened_fds == 0) {
330                 /* The last file descriptor to this inode was closed.  */
331                 FREE(inode->i_fds);
332                 inode->i_fds = NULL;
333                 inode->i_num_allocated_fds = 0;
334                 if (inode->i_nlink == 0)
335                         /* No links to this inode remain.  Get rid of it.  */
336                         free_inode(inode);
337         }
338         return ret;
339 }
340
341 /*
342  * Translate a path into the corresponding inode in the mounted WIM image.
343  *
344  * See get_dentry() for more information.
345  *
346  * Returns a pointer to the resulting inode, or NULL with errno set.
347  */
348 static struct wim_inode *
349 wim_pathname_to_inode(WIMStruct *wim, const char *path)
350 {
351         struct wim_dentry *dentry;
352
353         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
354         if (!dentry)
355                 return NULL;
356         return dentry->d_inode;
357 }
358
359 /*
360  * Create a new file in the mounted WIM image.
361  *
362  * @fuse_ctx
363  *      The FUSE context for the mounted image.
364  * @path
365  *      The path at which to create the first link to the new file.  If a file
366  *      already exists at this path, -EEXIST is returned.
367  * @mode
368  *      The UNIX mode for the new file.  This is only honored if
369  *      WIMLIB_MOUNT_FLAG_UNIX_DATA was passed to wimlib_mount_image().
370  * @rdev
371  *      The device ID for the new file, encoding the major and minor device
372  *      numbers.  This is only honored if WIMLIB_MOUNT_FLAG_UNIX_DATA was passed
373  *      to wimlib_mount_image().
374  * @attributes
375  *      Windows file attributes to use for the new file.
376  * @dentry_ret
377  *      On success, a pointer to the new dentry is returned here.  Its d_inode
378  *      member will point to the new inode that was created for it and added to
379  *      the mounted WIM image.
380  *
381  * Returns 0 or a -errno code.
382  */
383 static int
384 create_dentry(struct fuse_context *fuse_ctx, const char *path,
385               mode_t mode, dev_t rdev, u32 attributes,
386               struct wim_dentry **dentry_ret)
387 {
388         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
389         struct wim_dentry *parent;
390         const char *basename;
391         struct wim_dentry *new_dentry;
392         struct wim_inode *new_inode;
393
394         parent = get_parent_dentry(wimfs_ctx->wim, path, WIMLIB_CASE_SENSITIVE);
395         if (!parent)
396                 return -errno;
397
398         if (!dentry_is_directory(parent))
399                 return -ENOTDIR;
400
401         basename = path_basename(path);
402
403         if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE))
404                 return -EEXIST;
405
406         if (new_dentry_with_inode(basename, &new_dentry))
407                 return -ENOMEM;
408
409         new_inode = new_dentry->d_inode;
410
411         new_inode->i_resolved = 1;
412         new_inode->i_ino = wimfs_ctx->next_ino++;
413         new_inode->i_attributes = attributes;
414
415         if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
416                 struct wimlib_unix_data unix_data;
417
418                 unix_data.uid = fuse_ctx->uid;
419                 unix_data.gid = fuse_ctx->gid;
420                 unix_data.mode = fuse_mask_mode(mode, fuse_ctx);
421                 unix_data.rdev = rdev;
422                 if (!inode_set_unix_data(new_inode, &unix_data, UNIX_DATA_ALL))
423                 {
424                         free_dentry(new_dentry);
425                         return -ENOMEM;
426                 }
427         }
428
429         list_add_tail(&new_inode->i_list,
430                       &wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
431
432         dentry_add_child(parent, new_dentry);
433
434         if (dentry_ret)
435                 *dentry_ret = new_dentry;
436         return 0;
437 }
438
439 /*
440  * Remove a dentry from the mounted WIM image; i.e. remove an alias for an
441  * inode.
442  */
443 static void
444 remove_dentry(struct wim_dentry *dentry,
445               struct wim_lookup_table *lookup_table)
446 {
447         /* Drop the reference to each stream the inode contains.  */
448         inode_unref_streams(dentry->d_inode, lookup_table);
449
450         /* Unlink the dentry from the image's dentry tree.  */
451         unlink_dentry(dentry);
452
453         /* Delete the dentry.  This will also decrement the link count of the
454          * corresponding inode, and possibly cause it to be deleted as well.  */
455         free_dentry(dentry);
456 }
457
458 /* Generate UNIX filetype mode bits for the specified WIM inode, based on its
459  * Windows file attributes.  */
460 static mode_t
461 inode_unix_file_type(const struct wim_inode *inode)
462 {
463         if (inode_is_symlink(inode))
464                 return S_IFLNK;
465         else if (inode_is_directory(inode))
466                 return S_IFDIR;
467         else
468                 return S_IFREG;
469 }
470
471 /* Generate a default UNIX mode for the specified WIM inode.  */
472 static mode_t
473 inode_default_unix_mode(const struct wim_inode *inode)
474 {
475         return inode_unix_file_type(inode) | 0777;
476 }
477
478 /*
479  * Retrieve standard UNIX metadata ('struct stat') for a WIM inode.
480  *
481  * @lte specifies the stream of the inode that is being queried.  We mostly
482  * return the same information for all streams, but st_size and st_blocks may be
483  * different for different streams.
484  *
485  * This always returns 0.
486  */
487 static int
488 inode_to_stbuf(const struct wim_inode *inode,
489                const struct wim_lookup_table_entry *lte,
490                struct stat *stbuf)
491 {
492         const struct wimfs_context *ctx = wimfs_get_context();
493         struct wimlib_unix_data unix_data;
494
495         memset(stbuf, 0, sizeof(struct stat));
496         if ((ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) &&
497             inode_get_unix_data(inode, &unix_data))
498         {
499                 /* Use the user ID, group ID, mode, and device ID from the
500                  * inode's extra UNIX metadata information.  */
501                 stbuf->st_uid = unix_data.uid;
502                 stbuf->st_gid = unix_data.gid;
503                 stbuf->st_mode = unix_data.mode;
504                 stbuf->st_rdev = unix_data.rdev;
505         } else {
506                 /* Generate default values for the user ID, group ID, and mode.
507                  *
508                  * Note: in the case of an allow_other mount, fuse_context.uid
509                  * may not be the same as wimfs_context.owner_uid!  */
510                 stbuf->st_uid = ctx->owner_uid;
511                 stbuf->st_gid = ctx->owner_gid;
512                 stbuf->st_mode = inode_default_unix_mode(inode);
513         }
514         stbuf->st_ino = inode->i_ino;
515         stbuf->st_nlink = inode->i_nlink;
516         if (lte)
517                 stbuf->st_size = lte->size;
518 #ifdef HAVE_STAT_NANOSECOND_PRECISION
519         stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time);
520         stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time);
521         stbuf->st_ctim = stbuf->st_mtim;
522 #else
523         stbuf->st_atime = wim_timestamp_to_unix(inode->i_last_access_time);
524         stbuf->st_mtime = wim_timestamp_to_unix(inode->i_last_write_time);
525         stbuf->st_ctime = stbuf->st_mtime;
526 #endif
527         stbuf->st_blocks = (stbuf->st_size + 511) / 512;
528         return 0;
529 }
530
531 /* Update the last access and last write timestamps of a WIM inode.  */
532 static void
533 touch_inode(struct wim_inode *inode)
534 {
535         u64 now = get_wim_timestamp();
536         inode->i_last_access_time = now;
537         inode->i_last_write_time = now;
538 }
539
540 static void
541 touch_parent(struct wim_dentry *dentry)
542 {
543         touch_inode(dentry->parent->d_inode);
544 }
545
546 /*
547  * Create a new file in the staging directory for a read-write mounted image.
548  *
549  * On success, returns the file descriptor for the new staging file, opened for
550  * writing.  In addition, stores the allocated name of the staging file in
551  * @name_ret.
552  *
553  * On failure, returns -1 and sets errno.
554  */
555 static int
556 create_staging_file(const struct wimfs_context *ctx, char **name_ret)
557 {
558
559         static const size_t STAGING_FILE_NAME_LEN = 20;
560         char *name;
561         int fd;
562
563         name = MALLOC(STAGING_FILE_NAME_LEN + 1);
564         if (!name)
565                 return -1;
566         name[STAGING_FILE_NAME_LEN] = '\0';
567
568 retry:
569         randomize_char_array_with_alnum(name, STAGING_FILE_NAME_LEN);
570         fd = openat(ctx->staging_dir_fd, name,
571                     O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
572         if (unlikely(fd < 0)) {
573                 if (unlikely(errno == EEXIST))
574                         /* Try again with another name.  */
575                         goto retry;
576                 FREE(name);
577         } else {
578                 *name_ret = name;
579         }
580         return fd;
581 }
582
583 /*
584  * Extract a WIM resource to the staging directory.
585  * This is necessary if a stream using the resource is being opened for writing.
586  *
587  * @inode
588  *      The inode containing the stream being opened for writing.
589  *
590  * @stream_idx
591  *      The index of the stream in @inode being opened for writing.
592  *
593  * @lte_ptr
594  *      *lte_ptr is the lookup table entry for the stream being extracted, or
595  *      NULL if the stream does not have a lookup table entry (which is possible
596  *      if the stream is empty).  On success, *lte_ptr will be set to point to a
597  *      lookup table entry that represents the resource in its new location in a
598  *      staging file.  This may be the same as the old entry in the case that it
599  *      was reused, or it may be a new entry.
600  *
601  * @size
602  *      Number of bytes of the stream to extract and include in the staging file
603  *      resource.  It may be less than the actual stream length, in which case
604  *      only a prefix of the resource will be extracted.  It may also be more
605  *      than the actual stream length, in which case the extra space will be
606  *      zero-filled.
607  *
608  * Returns 0 or a -errno code.
609  */
610 static int
611 extract_resource_to_staging_dir(struct wim_inode *inode,
612                                 u16 stream_idx,
613                                 struct wim_lookup_table_entry **lte_ptr,
614                                 off_t size,
615                                 const struct wimfs_context *ctx)
616 {
617         struct wim_lookup_table_entry *old_lte;
618         struct wim_lookup_table_entry *new_lte;
619         char *staging_file_name;
620         int staging_fd;
621         off_t extract_size;
622         int result;
623         u32 stream_id;
624         int ret;
625
626         old_lte = *lte_ptr;
627
628         /* Create the staging file.  */
629         staging_fd = create_staging_file(ctx, &staging_file_name);
630         if (unlikely(staging_fd < 0))
631                 return -errno;
632
633         /* Extract the stream to the staging file (possibly truncated).  */
634         if (old_lte) {
635                 struct filedes fd;
636
637                 filedes_init(&fd, staging_fd);
638                 errno = 0;
639                 extract_size = min(old_lte->size, size);
640                 result = extract_stream_to_fd(old_lte, &fd, extract_size);
641         } else {
642                 extract_size = 0;
643                 result = 0;
644         }
645
646         /* In the case of truncate() to more than the file length, extend the
647          * staging file with zeroes by calling ftruncate().  */
648         if (!result && size > extract_size)
649                 result = ftruncate(staging_fd, size);
650
651         /* Close the staging file.  */
652         if (close(staging_fd))
653                 result = -1;
654
655         /* If an error occurred, unlink the staging file.  */
656         if (unlikely(result)) {
657                 /* extract_stream_to_fd() should set errno, but if it didn't,
658                  * set a default value.  */
659                 ret = errno ? -errno : -EIO;
660                 goto out_delete_staging_file;
661         }
662
663         /* Now deal with the lookup table entries.  We may be able to re-use the
664          * existing entry, but we may have to create a new one instead.  */
665
666         stream_id = inode_stream_idx_to_id(inode, stream_idx);
667
668         if (old_lte && inode->i_nlink == old_lte->refcnt) {
669                 /* The reference count of the existing lookup table entry is the
670                  * same as the link count of the inode that contains the stream
671                  * we're opening.  Therefore, all the references to the lookup
672                  * table entry correspond to the stream we're trying to extract,
673                  * so the lookup table entry can be re-used.  */
674                 lookup_table_unlink(ctx->wim->lookup_table, old_lte);
675                 lte_put_resource(old_lte);
676                 new_lte = old_lte;
677         } else {
678                 /* We need to split the old lookup table entry because it also
679                  * has other references.  Or, there was no old lookup table
680                  * entry, so we need to create a new one anyway.  */
681
682                 new_lte = new_lookup_table_entry();
683                 if (unlikely(!new_lte)) {
684                         ret = -ENOMEM;
685                         goto out_delete_staging_file;
686                 }
687
688                 /* There may already be open file descriptors to this stream if
689                  * it's previously been opened read-only, but just now we're
690                  * opening it read-write.  Identify those file descriptors and
691                  * change their lookup table entry pointers to point to the new
692                  * lookup table entry, and open staging file descriptors for
693                  * them.
694                  *
695                  * At the same time, we need to count the number of these opened
696                  * file descriptors to the new lookup table entry.  If there's
697                  * an old lookup table entry, this number needs to be subtracted
698                  * from the fd's opened to the old entry.  */
699                 for (u16 i = 0, j = 0; j < inode->i_num_opened_fds; i++) {
700                         struct wimfs_fd *fd;
701                         int raw_fd;
702
703                         fd = inode->i_fds[i];
704                         if (!fd)
705                                 continue;
706
707                         j++;
708
709                         if (fd->f_stream_id != stream_id)
710                                 continue;
711
712                         /* This is a readonly fd for the same stream.  */
713                         fd->f_lte = new_lte;
714                         new_lte->num_opened_fds++;
715                         raw_fd = openat(ctx->staging_dir_fd, staging_file_name,
716                                         O_RDONLY | O_NOFOLLOW);
717                         if (unlikely(raw_fd < 0)) {
718                                 ret = -errno;
719                                 goto out_revert_fd_changes;
720                         }
721                         filedes_init(&fd->f_staging_fd, raw_fd);
722                 }
723                 if (old_lte) {
724                         old_lte->num_opened_fds -= new_lte->num_opened_fds;
725                         old_lte->refcnt -= inode->i_nlink;
726                 }
727         }
728
729         new_lte->refcnt            = inode->i_nlink;
730         new_lte->resource_location = RESOURCE_IN_STAGING_FILE;
731         new_lte->staging_file_name = staging_file_name;
732         new_lte->staging_dir_fd    = ctx->staging_dir_fd;
733         new_lte->size              = size;
734
735         add_unhashed_stream(new_lte, inode, stream_id,
736                             &wim_get_current_image_metadata(ctx->wim)->unhashed_streams);
737         if (stream_idx == 0)
738                 inode->i_lte = new_lte;
739         else
740                 inode->i_ads_entries[stream_idx - 1].lte = new_lte;
741         *lte_ptr = new_lte;
742         return 0;
743
744 out_revert_fd_changes:
745         for (u16 i = 0; new_lte->num_opened_fds; i++) {
746                 struct wimfs_fd *fd = inode->i_fds[i];
747                 if (fd && fd->f_stream_id == stream_id) {
748                         fd->f_lte = old_lte;
749                         if (filedes_valid(&fd->f_staging_fd)) {
750                                 filedes_close(&fd->f_staging_fd);
751                                 filedes_invalidate(&fd->f_staging_fd);
752                         }
753                         new_lte->num_opened_fds--;
754                 }
755         }
756         free_lookup_table_entry(new_lte);
757 out_delete_staging_file:
758         unlinkat(ctx->staging_dir_fd, staging_file_name, 0);
759         FREE(staging_file_name);
760         return ret;
761 }
762
763 /*
764  * Create the staging directory for the WIM file.
765  *
766  * The staging directory will be created in the directory specified by the open
767  * file descriptor @parent_dir_fd.  It will be given a randomly generated name
768  * based on @wim_basename, the name of the WIM file.
769  *
770  * On success, returns a file descriptor to the open staging directory with
771  * O_RDONLY access.  In addition, stores the allocated name of the staging
772  * directory (relative to @parent_dir_fd) in @staging_dir_name_ret.
773  * On failure, returns -1 and sets errno.
774  */
775 static int
776 make_staging_dir_at(int parent_dir_fd, const char *wim_basename,
777                     char **staging_dir_name_ret)
778 {
779         static const char common_suffix[8] = ".staging";
780         static const size_t random_suffix_len = 10;
781         size_t wim_basename_len;
782         size_t staging_dir_name_len;
783         char *staging_dir_name;
784         char *p;
785         int fd;
786
787         wim_basename_len = strlen(wim_basename);
788         staging_dir_name_len = wim_basename_len + sizeof(common_suffix) +
789                                random_suffix_len;
790         staging_dir_name = MALLOC(staging_dir_name_len + 1);
791         if (!staging_dir_name)
792                 return -1;
793
794         p = staging_dir_name;
795         p = mempcpy(p, wim_basename, wim_basename_len);
796         p = mempcpy(p, common_suffix, sizeof(common_suffix));
797         randomize_char_array_with_alnum(p, random_suffix_len);
798         p += random_suffix_len;
799         *p = '\0';
800
801         if (mkdirat(parent_dir_fd, staging_dir_name, 0700))
802                 goto err1;
803
804         fd = openat(parent_dir_fd, staging_dir_name,
805                     O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
806         if (fd < 0)
807                 goto err2;
808
809         *staging_dir_name_ret = staging_dir_name;
810         return fd;
811
812 err2:
813         unlinkat(parent_dir_fd, staging_dir_name, AT_REMOVEDIR);
814 err1:
815         FREE(staging_dir_name);
816         return -1;
817 }
818
819 /*
820  * Create the staging directory and set ctx->staging_dir_fd,
821  * ctx->staging_dir_name, and ctx->parent_dir_fd.
822  */
823 static int
824 make_staging_dir(struct wimfs_context *ctx, const char *parent_dir_path)
825 {
826         const char *wim_basename;
827         char *end = NULL;
828         int ret;
829
830         wim_basename = path_basename(ctx->wim->filename);
831
832         if (!parent_dir_path) {
833                 /* The user did not specify a directory.  Default to creating
834                  * the staging directory alongside the WIM file.  */
835                 if (wim_basename > ctx->wim->filename) {
836                         parent_dir_path = ctx->wim->filename;
837                         end = (char *)(wim_basename - 1);
838                         /* *end must be a slash.  Temporarily overwrite it so we
839                          * can open the parent directory.  */
840                         *end = '\0';
841                 } else {
842                         parent_dir_path = ".";
843                 }
844         }
845
846         /* Open the parent directory (in which we'll create our staging
847          * directory).  */
848         ctx->parent_dir_fd = open(parent_dir_path, O_RDONLY | O_DIRECTORY);
849         if (ctx->parent_dir_fd < 0) {
850                 ERROR_WITH_ERRNO("Can't open directory \"%s\"",
851                                  parent_dir_path);
852                 ret = WIMLIB_ERR_OPENDIR;
853                 goto out_restore_wim_filename;
854         }
855
856         ctx->staging_dir_fd = make_staging_dir_at(ctx->parent_dir_fd,
857                                                   wim_basename,
858                                                   &ctx->staging_dir_name);
859         if (ctx->staging_dir_fd < 0) {
860                 ERROR_WITH_ERRNO("Can't create staging directory in \"%s\"",
861                                  parent_dir_path);
862                 close(ctx->parent_dir_fd);
863                 ret = WIMLIB_ERR_MKDIR;
864                 goto out_restore_wim_filename;
865         }
866         ret = 0;
867 out_restore_wim_filename:
868         if (end)
869                 *end = '/';
870         return ret;
871 }
872
873 /* Deletes the staging directory, undoing the effects of a succesful call to
874  * make_staging_dir().  */
875 static void
876 delete_staging_dir(struct wimfs_context *ctx)
877 {
878         DIR *dir;
879         struct dirent *ent;
880
881         dir = fdopendir(ctx->staging_dir_fd);
882         if (dir) {
883                 while ((ent = readdir(dir)))
884                         unlinkat(ctx->staging_dir_fd, ent->d_name, 0);
885                 closedir(dir);
886         } else {
887                 close(ctx->staging_dir_fd);
888         }
889         if (unlinkat(ctx->parent_dir_fd, ctx->staging_dir_name, AT_REMOVEDIR))
890                 WARNING_WITH_ERRNO("Could not delete staging directory");
891         FREE(ctx->staging_dir_name);
892         close(ctx->parent_dir_fd);
893 }
894
895 static void
896 reassign_inode_numbers(struct wimfs_context *ctx)
897 {
898         struct wim_image_metadata *imd;
899         struct wim_inode *inode;
900
901         ctx->next_ino = 1;
902         imd = wim_get_current_image_metadata(ctx->wim);
903         image_for_each_inode(inode, imd)
904                 inode->i_ino = ctx->next_ino++;
905 }
906
907 static void
908 release_extra_refcnts(struct wimfs_context *ctx)
909 {
910         struct list_head *list = &ctx->orig_stream_list;
911         struct wim_lookup_table *lookup_table = ctx->wim->lookup_table;
912         struct wim_lookup_table_entry *lte, *tmp;
913
914         list_for_each_entry_safe(lte, tmp, list, orig_stream_list) {
915                 u32 n = lte->out_refcnt;
916                 while (n--)
917                         lte_decrement_refcnt(lte, lookup_table);
918         }
919 }
920
921 static void
922 delete_empty_streams(struct wimfs_context *ctx)
923 {
924         struct wim_lookup_table_entry *lte, *tmp;
925         struct wim_image_metadata *imd;
926
927         imd = wim_get_current_image_metadata(ctx->wim);
928
929         image_for_each_unhashed_stream_safe(lte, tmp, imd) {
930                 if (!lte->size) {
931                         *retrieve_lte_pointer(lte) = NULL;
932                         list_del(&lte->unhashed_list);
933                         free_lookup_table_entry(lte);
934                 }
935         }
936 }
937
938 static void
939 inode_close_fds(struct wim_inode *inode)
940 {
941         u16 num_open_fds = inode->i_num_opened_fds;
942         for (u16 i = 0; num_open_fds; i++) {
943                 if (inode->i_fds[i]) {
944                         close_wimfs_fd(inode->i_fds[i]);
945                         num_open_fds--;
946                 }
947         }
948 }
949
950 static void
951 close_all_fds(struct wimfs_context *ctx)
952 {
953         struct wim_inode *inode, *tmp;
954         struct wim_image_metadata *imd;
955
956         imd = wim_get_current_image_metadata(ctx->wim);
957
958         list_for_each_entry_safe(inode, tmp, &imd->inode_list, i_list)
959                 inode_close_fds(inode);
960 }
961
962 /* Moves the currently selected image, which may have been modified, to a new
963  * index, and sets the original index to refer to a reset (unmodified) copy of
964  * the image.  */
965 static int
966 renew_current_image(struct wimfs_context *ctx)
967 {
968         WIMStruct *wim = ctx->wim;
969         int idx = wim->current_image - 1;
970         struct wim_image_metadata *imd = wim->image_metadata[idx];
971         struct wim_image_metadata *replace_imd;
972         struct wim_lookup_table_entry *new_lte;
973         int ret;
974
975         /* Create 'replace_imd' structure to use for the reset original,
976          * unmodified image.  */
977         ret = WIMLIB_ERR_NOMEM;
978         replace_imd = new_image_metadata();
979         if (!replace_imd)
980                 goto err;
981
982         /* Create new stream reference for the modified image's metadata
983          * resource, which doesn't exist yet.  */
984         ret = WIMLIB_ERR_NOMEM;
985         new_lte = new_lookup_table_entry();
986         if (!new_lte)
987                 goto err_put_replace_imd;
988         new_lte->flags = WIM_RESHDR_FLAG_METADATA;
989         new_lte->unhashed = 1;
990
991         /* Make the image being moved available at a new index.  Increments the
992          * WIM's image count, but does not increment the reference count of the
993          * 'struct image_metadata'.  */
994         ret = append_image_metadata(wim, imd);
995         if (ret)
996                 goto err_free_new_lte;
997
998         ret = xml_add_image(wim, T(""));
999         if (ret)
1000                 goto err_undo_append;
1001
1002         replace_imd->metadata_lte = imd->metadata_lte;
1003         imd->metadata_lte = new_lte;
1004         wim->image_metadata[idx] = replace_imd;
1005         wim->current_image = wim->hdr.image_count;
1006         return 0;
1007
1008 err_undo_append:
1009         wim->hdr.image_count--;
1010 err_free_new_lte:
1011         free_lookup_table_entry(new_lte);
1012 err_put_replace_imd:
1013         put_image_metadata(replace_imd, NULL);
1014 err:
1015         return ret;
1016 }
1017
1018 static enum wimlib_progress_status
1019 commit_progress_func(enum wimlib_progress_msg msg,
1020                      union wimlib_progress_info *info, void *progctx)
1021 {
1022         mqd_t mq = *(mqd_t *)progctx;
1023         struct commit_progress_report report;
1024
1025         memset(&report, 0, sizeof(report));
1026         report.msg = msg;
1027         if (info)
1028                 report.info = *info;
1029         mq_send(mq, (const char *)&report, sizeof(report), 1);
1030         return WIMLIB_PROGRESS_STATUS_CONTINUE;
1031 }
1032
1033 /* Commit the mounted image to the underlying WIM file.  */
1034 static int
1035 commit_image(struct wimfs_context *ctx, int unmount_flags, mqd_t mq)
1036 {
1037         int write_flags;
1038
1039         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS)
1040                 wimlib_register_progress_function(ctx->wim,
1041                                                   commit_progress_func, &mq);
1042         else
1043                 wimlib_register_progress_function(ctx->wim, NULL, NULL);
1044
1045         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_NEW_IMAGE) {
1046                 int ret = renew_current_image(ctx);
1047                 if (ret)
1048                         return ret;
1049         } else {
1050                 release_extra_refcnts(ctx);
1051         }
1052         INIT_LIST_HEAD(&ctx->orig_stream_list);
1053         delete_empty_streams(ctx);
1054         xml_update_image_info(ctx->wim, ctx->wim->current_image);
1055
1056         write_flags = 0;
1057         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY)
1058                 write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
1059         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_REBUILD)
1060                 write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
1061         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_RECOMPRESS)
1062                 write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
1063         return wimlib_overwrite(ctx->wim, write_flags, 0);
1064 }
1065
1066 static int
1067 unmount_wimfs(const struct wimfs_unmount_info *info)
1068 {
1069         struct fuse_context *fuse_ctx = fuse_get_context();
1070         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1071         int unmount_flags = info->unmount_flags;
1072         mqd_t mq = (mqd_t)-1;
1073         int status;
1074
1075         if (fuse_ctx->uid != wimfs_ctx->owner_uid &&
1076             fuse_ctx->uid != 0)
1077                 return -EPERM;
1078
1079         if (info->mq_name[0]) {
1080                 mq = mq_open(info->mq_name, O_WRONLY | O_NONBLOCK);
1081                 if (mq == (mqd_t)-1)
1082                         return -errno;
1083         }
1084
1085         /* Ignore COMMIT if the image is mounted read-only.  */
1086         if (!(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
1087                 unmount_flags &= ~WIMLIB_UNMOUNT_FLAG_COMMIT;
1088
1089         if (wimfs_ctx->num_open_fds) {
1090                 if ((unmount_flags & (WIMLIB_UNMOUNT_FLAG_COMMIT |
1091                                       WIMLIB_UNMOUNT_FLAG_FORCE))
1092                                  == WIMLIB_UNMOUNT_FLAG_COMMIT)
1093                 {
1094                         status = WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY;
1095                         goto out_send_status;
1096                 }
1097                 close_all_fds(wimfs_ctx);
1098         }
1099
1100         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT)
1101                 status = commit_image(wimfs_ctx, unmount_flags, mq);
1102         else
1103                 status = 0;
1104         fuse_exit(fuse_ctx->fuse);
1105 out_send_status:
1106         if (mq != (mqd_t)-1) {
1107                 mq_send(mq, (const char *)&status, sizeof(int), 1);
1108                 mq_close(mq);
1109         }
1110         return 0;
1111 }
1112
1113 static int
1114 wimfs_chmod(const char *path, mode_t mask)
1115 {
1116         const struct wimfs_context *ctx = wimfs_get_context();
1117         struct wim_inode *inode;
1118         struct wimlib_unix_data unix_data;
1119
1120         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1121                 return -EOPNOTSUPP;
1122
1123         inode = wim_pathname_to_inode(ctx->wim, path);
1124         if (!inode)
1125                 return -errno;
1126
1127         unix_data.uid = ctx->owner_uid;
1128         unix_data.gid = ctx->owner_gid;
1129         unix_data.mode = mask;
1130         unix_data.rdev = 0;
1131
1132         if (!inode_set_unix_data(inode, &unix_data, UNIX_DATA_MODE))
1133                 return -ENOMEM;
1134
1135         return 0;
1136 }
1137
1138 static int
1139 wimfs_chown(const char *path, uid_t uid, gid_t gid)
1140 {
1141         const struct wimfs_context *ctx = wimfs_get_context();
1142         struct wim_inode *inode;
1143         struct wimlib_unix_data unix_data;
1144         int which;
1145
1146         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1147                 return -EOPNOTSUPP;
1148
1149         inode = wim_pathname_to_inode(ctx->wim, path);
1150         if (!inode)
1151                 return -errno;
1152
1153         which = 0;
1154
1155         if (uid != (uid_t)-1)
1156                 which |= UNIX_DATA_UID;
1157         else
1158                 uid = ctx->owner_uid;
1159
1160         if (gid != (gid_t)-1)
1161                 which |= UNIX_DATA_GID;
1162         else
1163                 gid = ctx->owner_gid;
1164
1165         unix_data.uid = uid;
1166         unix_data.gid = gid;
1167         unix_data.mode = inode_default_unix_mode(inode);
1168         unix_data.rdev = 0;
1169
1170         if (!inode_set_unix_data(inode, &unix_data, which))
1171                 return -ENOMEM;
1172
1173         return 0;
1174 }
1175
1176 static int
1177 wimfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
1178 {
1179         struct wimfs_fd *fd = WIMFS_FD(fi);
1180         return inode_to_stbuf(fd->f_inode, fd->f_lte, stbuf);
1181 }
1182
1183 static int
1184 wimfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
1185 {
1186         struct wimfs_fd *fd = WIMFS_FD(fi);
1187         if (ftruncate(fd->f_staging_fd.fd, size))
1188                 return -errno;
1189         touch_inode(fd->f_inode);
1190         fd->f_lte->size = size;
1191         return 0;
1192 }
1193
1194 static int
1195 wimfs_getattr(const char *path, struct stat *stbuf)
1196 {
1197         const struct wimfs_context *ctx = wimfs_get_context();
1198         struct wim_dentry *dentry;
1199         struct wim_lookup_table_entry *lte;
1200         int ret;
1201
1202         ret = wim_pathname_to_stream(ctx->wim, path,
1203                                      get_lookup_flags(ctx) |
1204                                         LOOKUP_FLAG_DIRECTORY_OK,
1205                                      &dentry, &lte, NULL);
1206         if (ret)
1207                 return ret;
1208         return inode_to_stbuf(dentry->d_inode, lte, stbuf);
1209 }
1210
1211 static int
1212 copy_xattr(char *dest, size_t destsize, const void *src, size_t srcsize)
1213 {
1214         if (!destsize)
1215                 return srcsize;
1216         if (destsize < srcsize)
1217                 return -ERANGE;
1218         memcpy(dest, src, srcsize);
1219         return srcsize;
1220 }
1221
1222 static int
1223 wimfs_getxattr(const char *path, const char *name, char *value,
1224                size_t size)
1225 {
1226         struct fuse_context *fuse_ctx = fuse_get_context();
1227         const struct wimfs_context *ctx = WIMFS_CTX(fuse_ctx);
1228         struct wim_inode *inode;
1229         struct wim_ads_entry *ads_entry;
1230         struct wim_lookup_table_entry *lte;
1231
1232         if (!strncmp(name, "wimfs.", 6)) {
1233                 /* Handle some magical extended attributes.  These really should
1234                  * be ioctls, but directory ioctls aren't supported until
1235                  * libfuse 2.9, and even then they are broken.  */
1236                 name += 6;
1237                 if (!strcmp(name, "wim_filename")) {
1238                         return copy_xattr(value, size, ctx->wim->filename,
1239                                           strlen(ctx->wim->filename));
1240                 }
1241                 if (!strcmp(name, "wim_info")) {
1242                         struct wimlib_wim_info info;
1243
1244                         wimlib_get_wim_info(ctx->wim, &info);
1245
1246                         return copy_xattr(value, size, &info, sizeof(info));
1247                 }
1248                 if (!strcmp(name, "mounted_image")) {
1249                         return copy_xattr(value, size,
1250                                           &ctx->wim->current_image, sizeof(int));
1251                 }
1252                 if (!strcmp(name, "mount_flags")) {
1253                         return copy_xattr(value, size,
1254                                           &ctx->mount_flags, sizeof(int));
1255                 }
1256                 if (!strcmp(name, "unmount")) {
1257                         struct wimfs_unmount_info info;
1258                         memset(&info, 0, sizeof(info));
1259                         return unmount_wimfs(&info);
1260                 }
1261                 return -ENOATTR;
1262         }
1263
1264         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1265                 return -ENOTSUP;
1266
1267         if (strncmp(name, "user.", 5))
1268                 return -ENOATTR;
1269         name += 5;
1270
1271         /* Querying a named data stream  */
1272
1273         inode = wim_pathname_to_inode(ctx->wim, path);
1274         if (!inode)
1275                 return -errno;
1276
1277         ads_entry = inode_get_ads_entry(inode, name);
1278         if (!ads_entry)
1279                 return (errno == ENOENT) ? -ENOATTR : -errno;
1280
1281         lte = ads_entry->lte;
1282         if (!lte)
1283                 return 0;
1284
1285         if (unlikely(lte->size > INT_MAX))
1286                 return -EFBIG;
1287
1288         if (size) {
1289                 if (lte->size > size)
1290                         return -ERANGE;
1291
1292                 if (read_full_stream_into_buf(lte, value))
1293                         return -errno;
1294         }
1295         return lte->size;
1296 }
1297
1298 static int
1299 wimfs_link(const char *existing_path, const char *new_path)
1300 {
1301         WIMStruct *wim = wimfs_get_WIMStruct();
1302         const char *new_name;
1303         struct wim_inode *inode;
1304         struct wim_dentry *dir;
1305         struct wim_dentry *new_alias;
1306
1307         inode = wim_pathname_to_inode(wim, existing_path);
1308         if (!inode)
1309                 return -errno;
1310
1311         if (inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
1312                                    FILE_ATTRIBUTE_REPARSE_POINT))
1313                 return -EPERM;
1314
1315         new_name = path_basename(new_path);
1316
1317         dir = get_parent_dentry(wim, new_path, WIMLIB_CASE_SENSITIVE);
1318         if (!dir)
1319                 return -errno;
1320
1321         if (!dentry_is_directory(dir))
1322                 return -ENOTDIR;
1323
1324         if (get_dentry_child_with_name(dir, new_name, WIMLIB_CASE_SENSITIVE))
1325                 return -EEXIST;
1326
1327         if (new_dentry(new_name, &new_alias))
1328                 return -ENOMEM;
1329
1330         new_alias->d_inode = inode;
1331         inode_add_dentry(new_alias, inode);
1332         dentry_add_child(dir, new_alias);
1333         touch_inode(dir->d_inode);
1334         inode->i_nlink++;
1335         inode_ref_streams(inode);
1336         return 0;
1337 }
1338
1339 static int
1340 wimfs_listxattr(const char *path, char *list, size_t size)
1341 {
1342         const struct wimfs_context *ctx = wimfs_get_context();
1343         const struct wim_inode *inode;
1344         char *p = list;
1345         char *end = list + size;
1346         int total_size = 0;
1347
1348         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1349                 return -ENOTSUP;
1350
1351         /* List named data streams, or get the list size.  We report each named
1352          * data stream "X" as an extended attribute "user.X".  */
1353
1354         inode = wim_pathname_to_inode(ctx->wim, path);
1355         if (!inode)
1356                 return -errno;
1357
1358         for (u16 i = 0; i < inode->i_num_ads; i++) {
1359                 const struct wim_ads_entry *entry;
1360                 char *stream_name_mbs;
1361                 size_t stream_name_mbs_nbytes;
1362
1363                 entry = &inode->i_ads_entries[i];
1364
1365                 if (!entry->stream_name_nbytes)
1366                         continue;
1367
1368                 if (utf16le_to_tstr(entry->stream_name,
1369                                     entry->stream_name_nbytes,
1370                                     &stream_name_mbs,
1371                                     &stream_name_mbs_nbytes))
1372                         return -errno;
1373
1374                 if (unlikely(INT_MAX - total_size < stream_name_mbs_nbytes + 6)) {
1375                         FREE(stream_name_mbs);
1376                         return -EFBIG;
1377                 }
1378
1379                 total_size += stream_name_mbs_nbytes + 6;
1380                 if (size) {
1381                         if (end - p < stream_name_mbs_nbytes + 6) {
1382                                 FREE(stream_name_mbs);
1383                                 return -ERANGE;
1384                         }
1385                         p = mempcpy(p, "user.", 5);
1386                         p = mempcpy(p, stream_name_mbs, stream_name_mbs_nbytes);
1387                         *p++ = '\0';
1388                 }
1389                 FREE(stream_name_mbs);
1390         }
1391         return total_size;
1392 }
1393
1394 static int
1395 wimfs_mkdir(const char *path, mode_t mode)
1396 {
1397         struct wim_dentry *dentry;
1398         int ret;
1399
1400         /* Note: according to fuse.h, mode may not include S_IFDIR  */
1401         ret = create_dentry(fuse_get_context(), path, mode | S_IFDIR, 0,
1402                             FILE_ATTRIBUTE_DIRECTORY, &dentry);
1403         if (ret)
1404                 return ret;
1405         touch_parent(dentry);
1406         return 0;
1407 }
1408
1409 static int
1410 wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
1411 {
1412         struct fuse_context *fuse_ctx = fuse_get_context();
1413         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1414         const char *stream_name;
1415
1416         if ((wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
1417              && (stream_name = path_stream_name(path)))
1418         {
1419                 struct wim_ads_entry *old_entry;
1420                 struct wim_ads_entry *new_entry;
1421                 struct wim_inode *inode;
1422                 char *p;
1423
1424                 /* Create a named data stream.  */
1425
1426                 if (!S_ISREG(mode))
1427                         return -EOPNOTSUPP;
1428
1429                 p = (char *)stream_name - 1;
1430
1431                 *p = '\0';
1432                 inode = wim_pathname_to_inode(wimfs_ctx->wim, path);
1433                 *p = ':';
1434                 if (!inode)
1435                         return -errno;
1436
1437                 old_entry = inode_get_ads_entry(inode, stream_name);
1438                 if (old_entry)
1439                         return -EEXIST;
1440                 if (errno != ENOENT)
1441                         return -errno;
1442
1443                 new_entry = inode_add_ads(inode, stream_name);
1444                 if (!new_entry)
1445                         return -errno;
1446                 return 0;
1447         } else {
1448                 /* Create a regular file, device node, named pipe, or socket.
1449                  */
1450                 struct wim_dentry *dentry;
1451                 int ret;
1452
1453                 if (!S_ISREG(mode) &&
1454                     !(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1455                         return -EPERM;
1456
1457                 /* Note: we still use FILE_ATTRIBUTE_NORMAL for device nodes,
1458                  * named pipes, and sockets.  The real mode is in the UNIX
1459                  * metadata.  */
1460                 ret = create_dentry(fuse_ctx, path, mode, rdev,
1461                                     FILE_ATTRIBUTE_NORMAL, &dentry);
1462                 if (ret)
1463                         return ret;
1464                 touch_parent(dentry);
1465                 return 0;
1466         }
1467 }
1468
1469 static int
1470 wimfs_open(const char *path, struct fuse_file_info *fi)
1471 {
1472         struct wimfs_context *ctx = wimfs_get_context();
1473         struct wim_dentry *dentry;
1474         struct wim_inode *inode;
1475         struct wim_lookup_table_entry *lte;
1476         u16 stream_idx;
1477         struct wimfs_fd *fd;
1478         int ret;
1479
1480         ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
1481                                      &dentry, &lte, &stream_idx);
1482         if (ret)
1483                 return ret;
1484
1485         inode = dentry->d_inode;
1486
1487         /* The file resource may be in the staging directory (read-write mounts
1488          * only) or in the WIM.  If it's in the staging directory, we need to
1489          * open a native file descriptor for the corresponding file.  Otherwise,
1490          * we can read the file resource directly from the WIM file if we are
1491          * opening it read-only, but we need to extract the resource to the
1492          * staging directory if we are opening it writable.  */
1493
1494         if (flags_writable(fi->flags) &&
1495             (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) {
1496                 ret = extract_resource_to_staging_dir(inode,
1497                                                       stream_idx,
1498                                                       &lte,
1499                                                       lte ? lte->size : 0,
1500                                                       ctx);
1501                 if (ret)
1502                         return ret;
1503         }
1504
1505         ret = alloc_wimfs_fd(inode, inode_stream_idx_to_id(inode, stream_idx),
1506                              lte, &fd);
1507         if (ret)
1508                 return ret;
1509
1510         if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
1511                 int raw_fd;
1512
1513                 raw_fd = openat(lte->staging_dir_fd, lte->staging_file_name,
1514                                 (fi->flags & O_ACCMODE) | O_NOFOLLOW);
1515                 if (raw_fd < 0) {
1516                         close_wimfs_fd(fd);
1517                         return -errno;
1518                 }
1519                 filedes_init(&fd->f_staging_fd, raw_fd);
1520         }
1521         fi->fh = (uintptr_t)fd;
1522         return 0;
1523 }
1524
1525 static int
1526 wimfs_opendir(const char *path, struct fuse_file_info *fi)
1527 {
1528         WIMStruct *wim = wimfs_get_WIMStruct();
1529         struct wim_inode *inode;
1530         struct wimfs_fd *fd;
1531         int ret;
1532
1533         inode = wim_pathname_to_inode(wim, path);
1534         if (!inode)
1535                 return -errno;
1536         if (!inode_is_directory(inode))
1537                 return -ENOTDIR;
1538         ret = alloc_wimfs_fd(inode, 0, NULL, &fd);
1539         if (ret)
1540                 return ret;
1541         fi->fh = (uintptr_t)fd;
1542         return 0;
1543 }
1544
1545 static int
1546 wimfs_read(const char *path, char *buf, size_t size,
1547            off_t offset, struct fuse_file_info *fi)
1548 {
1549         struct wimfs_fd *fd = WIMFS_FD(fi);
1550         const struct wim_lookup_table_entry *lte;
1551         ssize_t ret;
1552
1553         lte = fd->f_lte;
1554         if (!lte)
1555                 return 0;
1556
1557         if (offset >= lte->size)
1558                 return 0;
1559
1560         if (size > lte->size - offset)
1561                 size = lte->size - offset;
1562
1563         if (!size)
1564                 return 0;
1565
1566         switch (lte->resource_location) {
1567         case RESOURCE_IN_WIM:
1568                 if (read_partial_wim_stream_into_buf(lte, size, offset, buf))
1569                         ret = -errno;
1570                 else
1571                         ret = size;
1572                 break;
1573         case RESOURCE_IN_STAGING_FILE:
1574                 ret = raw_pread(&fd->f_staging_fd, buf, size, offset);
1575                 if (ret < 0)
1576                         ret = -errno;
1577                 break;
1578         case RESOURCE_IN_ATTACHED_BUFFER:
1579                 memcpy(buf, lte->attached_buffer + offset, size);
1580                 ret = size;
1581                 break;
1582         default:
1583                 ret = -EINVAL;
1584                 break;
1585         }
1586         return ret;
1587 }
1588
1589 static int
1590 wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
1591               off_t offset, struct fuse_file_info *fi)
1592 {
1593         struct wimfs_fd *fd = WIMFS_FD(fi);
1594         const struct wim_inode *inode;
1595         const struct wim_dentry *child;
1596         int ret;
1597
1598         inode = fd->f_inode;
1599
1600         ret = filler(buf, ".", NULL, 0);
1601         if (ret)
1602                 return ret;
1603         ret = filler(buf, "..", NULL, 0);
1604         if (ret)
1605                 return ret;
1606
1607         for_inode_child(child, inode) {
1608                 char *file_name_mbs;
1609                 size_t file_name_mbs_nbytes;
1610
1611                 ret = utf16le_to_tstr(child->file_name,
1612                                       child->file_name_nbytes,
1613                                       &file_name_mbs,
1614                                       &file_name_mbs_nbytes);
1615                 if (ret)
1616                         return -errno;
1617
1618                 ret = filler(buf, file_name_mbs, NULL, 0);
1619                 FREE(file_name_mbs);
1620                 if (ret)
1621                         return ret;
1622         }
1623         return 0;
1624 }
1625
1626 static int
1627 wimfs_readlink(const char *path, char *buf, size_t buf_len)
1628 {
1629         WIMStruct *wim = wimfs_get_WIMStruct();
1630         const struct wim_inode *inode;
1631         ssize_t ret;
1632
1633         inode = wim_pathname_to_inode(wim, path);
1634         if (!inode)
1635                 return -errno;
1636         if (!inode_is_symlink(inode))
1637                 return -EINVAL;
1638         if (buf_len == 0)
1639                 return -EINVAL;
1640         ret = wim_inode_readlink(inode, buf, buf_len - 1, NULL);
1641         if (ret >= 0) {
1642                 buf[ret] = '\0';
1643                 ret = 0;
1644         } else if (ret == -ENAMETOOLONG) {
1645                 buf[buf_len - 1] = '\0';
1646         }
1647         return ret;
1648 }
1649
1650 /* We use this for both release() and releasedir(), since in both cases we
1651  * simply need to close the file descriptor.  */
1652 static int
1653 wimfs_release(const char *path, struct fuse_file_info *fi)
1654 {
1655         return close_wimfs_fd(WIMFS_FD(fi));
1656 }
1657
1658 static int
1659 wimfs_removexattr(const char *path, const char *name)
1660 {
1661         struct wimfs_context *ctx = wimfs_get_context();
1662         struct wim_inode *inode;
1663         struct wim_ads_entry *ads_entry;
1664
1665         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1666                 return -ENOTSUP;
1667
1668         if (strncmp(name, "user.", 5))
1669                 return -ENOATTR;
1670         name += 5;
1671
1672         /* Removing a named data stream.  */
1673
1674         inode = wim_pathname_to_inode(ctx->wim, path);
1675         if (!inode)
1676                 return -errno;
1677
1678         ads_entry = inode_get_ads_entry(inode, name);
1679         if (!ads_entry)
1680                 return (errno == ENOENT) ? -ENOATTR : -errno;
1681
1682         inode_remove_ads(inode, ads_entry, ctx->wim->lookup_table);
1683         return 0;
1684 }
1685
1686 static int
1687 wimfs_rename(const char *from, const char *to)
1688 {
1689         return rename_wim_path(wimfs_get_WIMStruct(), from, to,
1690                                WIMLIB_CASE_SENSITIVE, NULL);
1691 }
1692
1693 static int
1694 wimfs_rmdir(const char *path)
1695 {
1696         WIMStruct *wim = wimfs_get_WIMStruct();
1697         struct wim_dentry *dentry;
1698
1699         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
1700         if (!dentry)
1701                 return -errno;
1702
1703         if (!dentry_is_directory(dentry))
1704                 return -ENOTDIR;
1705
1706         if (dentry_has_children(dentry))
1707                 return -ENOTEMPTY;
1708
1709         touch_parent(dentry);
1710         remove_dentry(dentry, wim->lookup_table);
1711         return 0;
1712 }
1713
1714 static int
1715 wimfs_setxattr(const char *path, const char *name,
1716                const char *value, size_t size, int flags)
1717 {
1718         struct wimfs_context *ctx = wimfs_get_context();
1719         struct wim_inode *inode;
1720         struct wim_ads_entry *existing_entry;
1721
1722         if (!strncmp(name, "wimfs.", 6)) {
1723                 /* Handle some magical extended attributes.  These really should
1724                  * be ioctls, but directory ioctls aren't supported until
1725                  * libfuse 2.9, and even then they are broken.  */
1726                 name += 6;
1727                 if (!strcmp(name, "unmount")) {
1728                         if (size < sizeof(struct wimfs_unmount_info))
1729                                 return -EINVAL;
1730                         return unmount_wimfs((const void *)value);
1731                 }
1732                 return -ENOATTR;
1733         }
1734
1735         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1736                 return -ENOTSUP;
1737
1738         if (strncmp(name, "user.", 5))
1739                 return -ENOATTR;
1740         name += 5;
1741
1742         /* Setting the contents of a named data stream.  */
1743
1744         inode = wim_pathname_to_inode(ctx->wim, path);
1745         if (!inode)
1746                 return -errno;
1747
1748         existing_entry = inode_get_ads_entry(inode, name);
1749         if (existing_entry) {
1750                 if (flags & XATTR_CREATE)
1751                         return -EEXIST;
1752         } else {
1753                 if (errno != ENOENT)
1754                         return -errno;
1755                 if (flags & XATTR_REPLACE)
1756                         return -ENOATTR;
1757         }
1758
1759         if (!inode_add_ads_with_data(inode, name, value,
1760                                      size, ctx->wim->lookup_table))
1761                 return -errno;
1762         if (existing_entry)
1763                 inode_remove_ads(inode, existing_entry, ctx->wim->lookup_table);
1764         return 0;
1765 }
1766
1767 static int
1768 wimfs_symlink(const char *to, const char *from)
1769 {
1770         struct fuse_context *fuse_ctx = fuse_get_context();
1771         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1772         struct wim_dentry *dentry;
1773         int ret;
1774
1775         ret = create_dentry(fuse_ctx, from, S_IFLNK | 0777, 0,
1776                             FILE_ATTRIBUTE_REPARSE_POINT, &dentry);
1777         if (ret)
1778                 return ret;
1779         dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
1780         ret = wim_inode_set_symlink(dentry->d_inode, to,
1781                                     wimfs_ctx->wim->lookup_table);
1782         if (ret) {
1783                 remove_dentry(dentry, wimfs_ctx->wim->lookup_table);
1784                 if (ret == WIMLIB_ERR_NOMEM)
1785                         ret = -ENOMEM;
1786                 else
1787                         ret = -EINVAL;
1788         } else {
1789                 touch_parent(dentry);
1790         }
1791         return ret;
1792 }
1793
1794 static int
1795 wimfs_truncate(const char *path, off_t size)
1796 {
1797         const struct wimfs_context *ctx = wimfs_get_context();
1798         struct wim_dentry *dentry;
1799         struct wim_lookup_table_entry *lte;
1800         u16 stream_idx;
1801         int ret;
1802         int fd;
1803
1804         ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
1805                                      &dentry, &lte, &stream_idx);
1806
1807         if (ret)
1808                 return ret;
1809
1810         if (!lte && !size)
1811                 return 0;
1812
1813         if (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE) {
1814                 return extract_resource_to_staging_dir(dentry->d_inode,
1815                                                        stream_idx, &lte,
1816                                                        size, ctx);
1817         }
1818
1819         /* Truncate the staging file.  */
1820         fd = openat(lte->staging_dir_fd, lte->staging_file_name,
1821                     O_WRONLY | O_NOFOLLOW);
1822         if (fd < 0)
1823                 return -errno;
1824         ret = ftruncate(fd, size);
1825         if (close(fd) || ret)
1826                 return -errno;
1827         lte->size = size;
1828         return 0;
1829 }
1830
1831 static int
1832 wimfs_unlink(const char *path)
1833 {
1834         const struct wimfs_context *ctx = wimfs_get_context();
1835         struct wim_dentry *dentry;
1836         u16 stream_idx;
1837         int ret;
1838
1839         ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
1840                                      &dentry, NULL, &stream_idx);
1841
1842         if (ret)
1843                 return ret;
1844
1845         if (inode_stream_name_nbytes(dentry->d_inode, stream_idx) == 0) {
1846                 touch_parent(dentry);
1847                 remove_dentry(dentry, ctx->wim->lookup_table);
1848         } else {
1849                 inode_remove_ads(dentry->d_inode,
1850                                  &dentry->d_inode->i_ads_entries[stream_idx - 1],
1851                                  ctx->wim->lookup_table);
1852         }
1853         return 0;
1854 }
1855
1856 #ifdef HAVE_UTIMENSAT
1857 /*
1858  * Change the timestamp on a file dentry.
1859  *
1860  * Note that alternate data streams do not have their own timestamps.
1861  */
1862 static int
1863 wimfs_utimens(const char *path, const struct timespec tv[2])
1864 {
1865         WIMStruct *wim = wimfs_get_WIMStruct();
1866         struct wim_inode *inode;
1867
1868         inode = wim_pathname_to_inode(wim, path);
1869         if (!inode)
1870                 return -errno;
1871
1872         if (tv[0].tv_nsec != UTIME_OMIT) {
1873                 if (tv[0].tv_nsec == UTIME_NOW)
1874                         inode->i_last_access_time = get_wim_timestamp();
1875                 else
1876                         inode->i_last_access_time = timespec_to_wim_timestamp(tv[0]);
1877         }
1878         if (tv[1].tv_nsec != UTIME_OMIT) {
1879                 if (tv[1].tv_nsec == UTIME_NOW)
1880                         inode->i_last_write_time = get_wim_timestamp();
1881                 else
1882                         inode->i_last_write_time = timespec_to_wim_timestamp(tv[1]);
1883         }
1884         return 0;
1885 }
1886 #else /* HAVE_UTIMENSAT */
1887 static int
1888 wimfs_utime(const char *path, struct utimbuf *times)
1889 {
1890         WIMStruct *wim = wimfs_get_WIMStruct();
1891         struct wim_inode *inode;
1892
1893         inode = wim_pathname_to_inode(wim, path);
1894         if (!inode)
1895                 return -errno;
1896
1897         inode->i_last_access_time = unix_timestamp_to_wim(times->actime);
1898         inode->i_last_write_time = unix_timestamp_to_wim(times->modtime);
1899         return 0;
1900 }
1901 #endif /* !HAVE_UTIMENSAT */
1902
1903 static int
1904 wimfs_write(const char *path, const char *buf, size_t size,
1905             off_t offset, struct fuse_file_info *fi)
1906 {
1907         struct wimfs_fd *fd = WIMFS_FD(fi);
1908         ssize_t ret;
1909
1910         ret = raw_pwrite(&fd->f_staging_fd, buf, size, offset);
1911         if (ret < 0)
1912                 return -errno;
1913
1914         if (offset + size > fd->f_lte->size)
1915                 fd->f_lte->size = offset + size;
1916
1917         touch_inode(fd->f_inode);
1918         return ret;
1919 }
1920
1921 static struct fuse_operations wimfs_operations = {
1922         .chmod       = wimfs_chmod,
1923         .chown       = wimfs_chown,
1924         .fgetattr    = wimfs_fgetattr,
1925         .ftruncate   = wimfs_ftruncate,
1926         .getattr     = wimfs_getattr,
1927         .getxattr    = wimfs_getxattr,
1928         .link        = wimfs_link,
1929         .listxattr   = wimfs_listxattr,
1930         .mkdir       = wimfs_mkdir,
1931         .mknod       = wimfs_mknod,
1932         .open        = wimfs_open,
1933         .opendir     = wimfs_opendir,
1934         .read        = wimfs_read,
1935         .readdir     = wimfs_readdir,
1936         .readlink    = wimfs_readlink,
1937         .release     = wimfs_release,
1938         .releasedir  = wimfs_release,
1939         .removexattr = wimfs_removexattr,
1940         .rename      = wimfs_rename,
1941         .rmdir       = wimfs_rmdir,
1942         .setxattr    = wimfs_setxattr,
1943         .symlink     = wimfs_symlink,
1944         .truncate    = wimfs_truncate,
1945         .unlink      = wimfs_unlink,
1946 #ifdef HAVE_UTIMENSAT
1947         .utimens     = wimfs_utimens,
1948 #else
1949         .utime       = wimfs_utime,
1950 #endif
1951         .write       = wimfs_write,
1952
1953         /* We keep track of file descriptor structures (struct wimfs_fd), so
1954          * there is no need to have the file path provided on operations such as
1955          * read().  */
1956 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
1957         .flag_nullpath_ok = 1,
1958 #endif
1959 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 9)
1960         .flag_nopath = 1,
1961         .flag_utime_omit_ok = 1,
1962 #endif
1963 };
1964
1965 /* API function documented in wimlib.h  */
1966 WIMLIBAPI int
1967 wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
1968                    int mount_flags, const char *staging_dir)
1969 {
1970         int ret;
1971         struct wim_image_metadata *imd;
1972         struct wimfs_context ctx;
1973         char *fuse_argv[16];
1974         int fuse_argc;
1975
1976         if (!wim || !dir || !*dir)
1977                 return WIMLIB_ERR_INVALID_PARAM;
1978
1979         if (mount_flags & ~(WIMLIB_MOUNT_FLAG_READWRITE |
1980                             WIMLIB_MOUNT_FLAG_DEBUG |
1981                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
1982                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
1983                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS |
1984                             WIMLIB_MOUNT_FLAG_UNIX_DATA |
1985                             WIMLIB_MOUNT_FLAG_ALLOW_OTHER))
1986                 return WIMLIB_ERR_INVALID_PARAM;
1987
1988         /* For read-write mount, check for write access to the WIM.  */
1989         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
1990                 ret = can_delete_from_wim(wim);
1991                 if (ret)
1992                         return ret;
1993         }
1994
1995         /* Select the image to mount.  */
1996         ret = select_wim_image(wim, image);
1997         if (ret)
1998                 return ret;
1999
2000         /* Get the metadata for the image to mount.  */
2001         imd = wim_get_current_image_metadata(wim);
2002
2003         if (imd->modified) {
2004                 /* To avoid complicating things, we don't support mounting
2005                  * images to which in-memory modifications have already been
2006                  * made.  */
2007                 ERROR("Cannot mount a modified WIM image!");
2008                 return WIMLIB_ERR_INVALID_PARAM;
2009         }
2010
2011         ret = lock_wim_for_append(wim, wim->in_fd.fd);
2012         if (ret)
2013                 return ret;
2014
2015         /* If the user did not specify an interface for accessing named
2016          * data streams, use the default (extended attributes).  */
2017         if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
2018                              WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
2019                              WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
2020                 mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
2021
2022         /* Start initializing the wimfs_context.  */
2023         memset(&ctx, 0, sizeof(struct wimfs_context));
2024         ctx.wim = wim;
2025         ctx.mount_flags = mount_flags;
2026         if (mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
2027                 ctx.default_lookup_flags = LOOKUP_FLAG_ADS_OK;
2028         /* For read-write mount, create the staging directory.  */
2029         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2030                 ret = make_staging_dir(&ctx, staging_dir);
2031                 if (ret)
2032                         goto out_unlock;
2033         }
2034         ctx.owner_uid = getuid();
2035         ctx.owner_gid = getgid();
2036
2037         /* Add each stream referenced by files in the image to a list and
2038          * preemptively double the number of references to each.  The latter is
2039          * done to allow implementing the WIMLIB_UNMOUNT_FLAG_NEW_IMAGE
2040          * semantics.  */
2041         INIT_LIST_HEAD(&ctx.orig_stream_list);
2042         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2043                 unsigned i;
2044                 struct wim_inode *inode;
2045                 struct wim_lookup_table_entry *lte;
2046
2047                 image_for_each_inode(inode, imd) {
2048                         for (i = 0; i <= inode->i_num_ads; i++) {
2049                                 lte = inode_stream_lte(inode, i,
2050                                                        wim->lookup_table);
2051                                 if (lte)
2052                                         lte->out_refcnt = 0;
2053                         }
2054                 }
2055
2056                 image_for_each_inode(inode, imd) {
2057                         for (i = 0; i <= inode->i_num_ads; i++) {
2058                                 lte = inode_stream_lte(inode, i,
2059                                                        wim->lookup_table);
2060                                 if (lte) {
2061                                         if (lte->out_refcnt == 0)
2062                                                 list_add(&lte->orig_stream_list,
2063                                                          &ctx.orig_stream_list);
2064                                         lte->out_refcnt += inode->i_nlink;
2065                                         lte->refcnt += inode->i_nlink;
2066                                 }
2067                         }
2068                 }
2069         }
2070
2071         /* Assign new inode numbers.  */
2072         reassign_inode_numbers(&ctx);
2073
2074         /* If a read-write mount, mark the image as modified.  */
2075         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
2076                 imd->modified = 1;
2077
2078         /* Build the FUSE command line.  */
2079
2080         fuse_argc = 0;
2081         fuse_argv[fuse_argc++] = "wimlib";
2082         fuse_argv[fuse_argc++] = (char *)dir;
2083
2084         /* Disable multi-threaded operation.  */
2085         fuse_argv[fuse_argc++] = "-s";
2086
2087         /* Enable FUSE debug mode (don't fork) if requested by the user.  */
2088         if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
2089                 fuse_argv[fuse_argc++] = "-d";
2090
2091         /*
2092          * Build the FUSE mount options:
2093          *
2094          * use_ino
2095          *      FUSE will use the inode numbers we provide.  We want this,
2096          *      because we have inodes and will number them ourselves.
2097          *
2098          * subtype=wimfs
2099          *      Name for our filesystem (main type is "fuse").
2100          *
2101          * hard_remove
2102          *      If an open file is unlinked, unlink it for real rather than
2103          *      renaming it to a hidden file.  Our code supports this; an
2104          *      unlinked inode is retained until all its file descriptors have
2105          *      been closed.
2106          *
2107          * default_permissions
2108          *      FUSE will perform permission checking.  Useful when
2109          *      WIMLIB_MOUNT_FLAG_UNIX_DATA is provided and the WIM image
2110          *      contains the UNIX permissions for each file.
2111          *
2112          * kernel_cache
2113          *      Cache the contents of files.  This will speed up repeated access
2114          *      to files on a mounted WIM image, since they won't need to be
2115          *      decompressed repeatedly.  This option is valid because data in
2116          *      the WIM image should never be changed externally.  (Although, if
2117          *      someone really wanted to they could modify the WIM file or mess
2118          *      with the staging directory; but then they're asking for
2119          *      trouble.)
2120          *
2121          * entry_timeout=1000000000
2122          *      Cache positive name lookups indefinitely, since names can only
2123          *      be added, removed, or modified through the mounted filesystem
2124          *      itself.
2125          *
2126          * negative_timeout=1000000000
2127          *      Cache negative name lookups indefinitely, since names can only
2128          *      be added, removed, or modified through the mounted filesystem
2129          *      itself.
2130          *
2131          * attr_timeout=0
2132          *      Don't cache file/directory attributes.  This is needed as a
2133          *      workaround for the fact that when caching attributes, the high
2134          *      level interface to libfuse considers a file which has several
2135          *      hard-linked names as several different files.  (Otherwise, we
2136          *      could cache our file/directory attributes indefinitely, since
2137          *      they can only be changed through the mounted filesystem itself.)
2138          */
2139         char optstring[256] =
2140                 "use_ino"
2141                 ",subtype=wimfs"
2142                 ",attr_timeout=0"
2143                 ",hard_remove"
2144                 ",default_permissions"
2145                 ",kernel_cache"
2146                 ",entry_timeout=1000000000"
2147                 ",negative_timeout=1000000000"
2148                 ",attr_timeout=0"
2149                 ;
2150         fuse_argv[fuse_argc++] = "-o";
2151         fuse_argv[fuse_argc++] = optstring;
2152         if (!(mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
2153                 strcat(optstring, ",ro");
2154         if (mount_flags & WIMLIB_MOUNT_FLAG_ALLOW_OTHER)
2155                 strcat(optstring, ",allow_other");
2156         fuse_argv[fuse_argc] = NULL;
2157
2158         /* Mount our filesystem.  */
2159         ret = fuse_main(fuse_argc, fuse_argv, &wimfs_operations, &ctx);
2160
2161         /* Cleanup and return.  */
2162         if (ret)
2163                 ret = WIMLIB_ERR_FUSE;
2164         release_extra_refcnts(&ctx);
2165         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
2166                 delete_staging_dir(&ctx);
2167 out_unlock:
2168         unlock_wim_for_append(wim, wim->in_fd.fd);
2169         return ret;
2170 }
2171
2172 struct commit_progress_thread_args {
2173         mqd_t mq;
2174         wimlib_progress_func_t progfunc;
2175         void *progctx;
2176         int status;
2177 };
2178
2179 static void *
2180 commit_progress_thread_proc(void *_args)
2181 {
2182         struct commit_progress_thread_args *args = _args;
2183         struct commit_progress_report report;
2184         ssize_t ret;
2185
2186         args->status = WIMLIB_ERR_NOT_A_MOUNTPOINT;
2187         for (;;) {
2188                 ret = mq_receive(args->mq,
2189                                  (char *)&report, sizeof(report), NULL);
2190                 if (ret < 0) {
2191                         if (errno == EINTR)
2192                                 continue;
2193                         break;
2194                 }
2195                 if (ret == sizeof(int)) {
2196                         args->status = *(int *)&report;
2197                         break;
2198                 }
2199                 if (ret < sizeof(report))
2200                         continue;
2201                 call_progress(args->progfunc, report.msg,
2202                               &report.info, args->progctx);
2203         }
2204         return NULL;
2205 }
2206
2207 static void
2208 generate_message_queue_name(char name[WIMFS_MQUEUE_NAME_LEN + 1])
2209 {
2210         name[0] = '/';
2211         memcpy(name + 1, "wimfs-", 6);
2212         randomize_char_array_with_alnum(name + 7, WIMFS_MQUEUE_NAME_LEN - 7);
2213         name[WIMFS_MQUEUE_NAME_LEN] = '\0';
2214 }
2215
2216 static mqd_t
2217 create_message_queue(const char *name, bool have_progfunc)
2218 {
2219         bool am_root = (getuid() == 0);
2220         mode_t umask_save = 0;
2221         mode_t mode = 0600;
2222         struct mq_attr attr;
2223         mqd_t mq;
2224
2225         memset(&attr, 0, sizeof(attr));
2226         attr.mq_maxmsg = 8;
2227         if (have_progfunc)
2228                 attr.mq_msgsize = sizeof(struct commit_progress_report);
2229         else
2230                 attr.mq_msgsize = sizeof(int);
2231
2232         if (am_root) {
2233                 /* Filesystem mounted as normal user with --allow-other should
2234                  * be able to send messages to root user, if they're doing the
2235                  * unmount.  */
2236                 umask_save = umask(0);
2237                 mode = 0666;
2238         }
2239         mq = mq_open(name, O_RDWR | O_CREAT | O_EXCL, mode, &attr);
2240         if (am_root)
2241                 umask(umask_save);
2242         return mq;
2243 }
2244
2245 /* Unmount a read-write mounted WIM image, committing the changes.  */
2246 static int
2247 do_unmount_commit(const char *dir, int unmount_flags,
2248                   wimlib_progress_func_t progfunc, void *progctx)
2249 {
2250         struct wimfs_unmount_info unmount_info;
2251         mqd_t mq;
2252         struct commit_progress_thread_args args;
2253         pthread_t commit_progress_tid;
2254         int ret;
2255
2256         memset(&unmount_info, 0, sizeof(unmount_info));
2257         unmount_info.unmount_flags = unmount_flags;
2258         generate_message_queue_name(unmount_info.mq_name);
2259
2260         mq = create_message_queue(unmount_info.mq_name, progfunc != NULL);
2261         if (mq == (mqd_t)-1) {
2262                 ERROR_WITH_ERRNO("Can't create POSIX message queue");
2263                 return WIMLIB_ERR_MQUEUE;
2264         }
2265
2266         /* The current thread will be stuck in setxattr() until the image is
2267          * committed.  Create a thread to handle the progress messages.  */
2268         if (progfunc) {
2269                 args.mq = mq;
2270                 args.progfunc = progfunc;
2271                 args.progctx = progctx;
2272                 ret = pthread_create(&commit_progress_tid, NULL,
2273                                      commit_progress_thread_proc, &args);
2274                 if (ret) {
2275                         errno = ret;
2276                         ERROR_WITH_ERRNO("Can't create thread");
2277                         ret = WIMLIB_ERR_NOMEM;
2278                         goto out_delete_mq;
2279                 }
2280                 unmount_info.unmount_flags |= WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS;
2281         }
2282
2283         if (!setxattr(dir, "wimfs.unmount",
2284                      (const char *)&unmount_info, sizeof(unmount_info), 0))
2285                 ret = 0;
2286         else if (errno == EACCES || errno == EPERM)
2287                 ret = WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT;
2288         else
2289                 ret = WIMLIB_ERR_NOT_A_MOUNTPOINT;
2290
2291         if (progfunc) {
2292                 /* Terminate the progress thread and retrieve final unmount
2293                  * status.  */
2294
2295                 int tmp = -1;
2296                 mq_send(mq, (const char *)&tmp, sizeof(int), 1);
2297
2298                 pthread_join(commit_progress_tid, NULL);
2299                 if (!ret && args.status != -1)
2300                         ret = args.status;
2301         } else if (!ret) {
2302                 /* Retrieve the final unmount status.  */
2303
2304                 int tmp = -1;
2305                 int len;
2306
2307                 mq_send(mq, (const char *)&tmp, sizeof(int), 1);
2308                 len = mq_receive(mq, (char *)&tmp, sizeof(int), NULL);
2309
2310                 if (len == 4 && tmp != -1)
2311                         ret = tmp;
2312                 else
2313                         ret = WIMLIB_ERR_NOT_A_MOUNTPOINT;
2314         }
2315 out_delete_mq:
2316         mq_close(mq);
2317         mq_unlink(unmount_info.mq_name);
2318         return ret;
2319 }
2320
2321 /* Unmount a read-only or read-write mounted WIM image, discarding any changes.
2322  */
2323 static int
2324 do_unmount_discard(const char *dir)
2325 {
2326         if (!getxattr(dir, "wimfs.unmount", NULL, 0))
2327                 return 0;
2328         else if (errno == EACCES || errno == EPERM)
2329                 return WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT;
2330         else
2331                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2332 }
2333
2334 static int
2335 begin_unmount(const char *dir, int unmount_flags, int *mount_flags_ret,
2336               wimlib_progress_func_t progfunc, void *progctx)
2337 {
2338         int mount_flags;
2339         int mounted_image;
2340         int wim_filename_len;
2341         union wimlib_progress_info progress;
2342
2343         if (getxattr(dir, "wimfs.mount_flags",
2344                      &mount_flags, sizeof(int)) != sizeof(int))
2345                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2346
2347         *mount_flags_ret = mount_flags;
2348
2349         if (!progfunc)
2350                 return 0;
2351
2352         if (getxattr(dir, "wimfs.mounted_image",
2353                      &mounted_image, sizeof(int)) != sizeof(int))
2354                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2355
2356         wim_filename_len = getxattr(dir, "wimfs.wim_filename", NULL, 0);
2357         if (wim_filename_len < 0)
2358                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2359
2360         char wim_filename[wim_filename_len + 1];
2361         if (getxattr(dir, "wimfs.wim_filename",
2362                      wim_filename, wim_filename_len) != wim_filename_len)
2363                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2364         wim_filename[wim_filename_len] = '\0';
2365
2366         progress.unmount.mountpoint = dir;
2367         progress.unmount.mounted_wim = wim_filename;
2368         progress.unmount.mounted_image = mounted_image;
2369         progress.unmount.mount_flags = mount_flags;
2370         progress.unmount.unmount_flags = unmount_flags;
2371
2372         return call_progress(progfunc, WIMLIB_PROGRESS_MSG_UNMOUNT_BEGIN,
2373                              &progress, progctx);
2374 }
2375
2376 /* API function documented in wimlib.h  */
2377 WIMLIBAPI int
2378 wimlib_unmount_image_with_progress(const char *dir, int unmount_flags,
2379                                    wimlib_progress_func_t progfunc, void *progctx)
2380 {
2381         int mount_flags;
2382         int ret;
2383
2384         wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8);
2385
2386         if (unmount_flags & ~(WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY |
2387                               WIMLIB_UNMOUNT_FLAG_COMMIT |
2388                               WIMLIB_UNMOUNT_FLAG_REBUILD |
2389                               WIMLIB_UNMOUNT_FLAG_RECOMPRESS |
2390                               WIMLIB_UNMOUNT_FLAG_FORCE |
2391                               WIMLIB_UNMOUNT_FLAG_NEW_IMAGE))
2392                 return WIMLIB_ERR_INVALID_PARAM;
2393
2394         ret = begin_unmount(dir, unmount_flags, &mount_flags,
2395                             progfunc, progctx);
2396         if (ret)
2397                 return ret;
2398
2399         if ((unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) &&
2400             (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
2401                 return do_unmount_commit(dir, unmount_flags,
2402                                          progfunc, progctx);
2403         else
2404                 return do_unmount_discard(dir);
2405 }
2406
2407 #else /* WITH_FUSE */
2408
2409
2410 static int
2411 mount_unsupported_error(void)
2412 {
2413 #if defined(__WIN32__)
2414         ERROR("Sorry-- Mounting WIM images is not supported on Windows!");
2415 #else
2416         ERROR("wimlib was compiled with --without-fuse, which disables support "
2417               "for mounting WIMs.");
2418 #endif
2419         return WIMLIB_ERR_UNSUPPORTED;
2420 }
2421
2422 WIMLIBAPI int
2423 wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
2424                                    wimlib_progress_func_t progfunc, void *progctx)
2425 {
2426         return mount_unsupported_error();
2427 }
2428
2429 WIMLIBAPI int
2430 wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
2431                    int mount_flags, const tchar *staging_dir)
2432 {
2433         return mount_unsupported_error();
2434 }
2435
2436 #endif /* !WITH_FUSE */
2437
2438 WIMLIBAPI int
2439 wimlib_unmount_image(const tchar *dir, int unmount_flags)
2440 {
2441         return wimlib_unmount_image_with_progress(dir, unmount_flags, NULL, NULL);
2442 }