]> wimlib.net Git - wimlib/blob - src/mount_image.c
Improve tstr <=> UTF-16LE conversions
[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 #include "wimlib/error.h"
35
36 #ifdef WITH_FUSE
37
38 #ifdef __WIN32__
39 #  error "FUSE mount not supported on Win32!  Please configure --without-fuse"
40 #endif
41
42 #include "wimlib/encoding.h"
43 #include "wimlib/file_io.h"
44 #include "wimlib/dentry.h"
45 #include "wimlib/inode.h"
46 #include "wimlib/lookup_table.h"
47 #include "wimlib/metadata.h"
48 #include "wimlib/paths.h"
49 #include "wimlib/reparse.h"
50 #include "wimlib/resource.h"
51 #include "wimlib/timestamp.h"
52 #include "wimlib/version.h"
53 #include "wimlib/write.h"
54 #include "wimlib/xml.h"
55
56 #include <errno.h>
57 #include <ftw.h>
58 #include <limits.h>
59 #include <mqueue.h>
60 #include <signal.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <sys/stat.h>
64 #include <sys/time.h>
65 #include <sys/types.h>
66 #include <sys/wait.h>
67 #include <unistd.h>
68 #include <utime.h>
69
70 #define FUSE_USE_VERSION 26
71 #include <fuse.h>
72
73 #ifdef ENABLE_XATTR
74 #include <attr/xattr.h>
75 #endif
76
77 #define MSG_VERSION_TOO_HIGH    -1
78 #define MSG_BREAK_LOOP          -2
79
80 /* File descriptor to a file open on the WIM filesystem. */
81 struct wimfs_fd {
82         struct wim_inode *f_inode;
83         struct wim_lookup_table_entry *f_lte;
84         struct filedes staging_fd;
85         u16 idx;
86         u32 stream_id;
87 };
88
89 struct wimfs_context {
90         /* The WIMStruct for the mounted WIM. */
91         WIMStruct *wim;
92
93         /* Name of the staging directory for a read-write mount.  Whenever a new file is
94          * created, it is done so in the staging directory.  Furthermore, whenever a
95          * file in the WIM is modified, it is extracted to the staging directory.  If
96          * changes are commited when the WIM is unmounted, the file resources are merged
97          * in from the staging directory when writing the new WIM. */
98         char *staging_dir_name;
99         size_t staging_dir_name_len;
100
101         /* Flags passed to wimlib_mount(). */
102         int mount_flags;
103
104         /* Default flags to use when looking up a WIM dentry (depends on whether
105          * the Windows interface to alternate data streams is being used or
106          * not). */
107         int default_lookup_flags;
108
109         /* Next inode number to be assigned.  Note: I didn't bother with a
110          * bitmap of free inode numbers since this isn't even a "real"
111          * filesystem anyway. */
112         u64 next_ino;
113
114         /* List of inodes in the mounted image */
115         struct list_head *image_inode_list;
116
117         /* Original list of streams in the mounted image, linked by
118          * mount_orig_stream_list.  */
119         struct list_head orig_stream_list;
120
121         /* Name and message queue descriptors for message queues between the
122          * filesystem daemon process and the unmount process.  These are used
123          * when the filesystem is unmounted and the process running
124          * wimlib_unmount_image() needs to communicate with the filesystem
125          * daemon running fuse_main() (i.e. the process created by a call to
126          * wimlib_mount_image().  */
127         char *unmount_to_daemon_mq_name;
128         char *daemon_to_unmount_mq_name;
129         mqd_t unmount_to_daemon_mq;
130         mqd_t daemon_to_unmount_mq;
131
132         uid_t default_uid;
133         gid_t default_gid;
134
135         int status;
136         bool have_status;
137 };
138
139 static void
140 init_wimfs_context(struct wimfs_context *ctx)
141 {
142         memset(ctx, 0, sizeof(*ctx));
143         ctx->unmount_to_daemon_mq = (mqd_t)-1;
144         ctx->daemon_to_unmount_mq = (mqd_t)-1;
145 }
146
147 #define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data)
148
149 static inline struct wimfs_context *
150 wimfs_get_context(void)
151 {
152         return WIMFS_CTX(fuse_get_context());
153 }
154
155 static inline WIMStruct *
156 wimfs_get_WIMStruct(void)
157 {
158         return wimfs_get_context()->wim;
159 }
160
161 static inline int
162 get_lookup_flags(const struct wimfs_context *ctx)
163 {
164         return ctx->default_lookup_flags;
165 }
166
167 /* Returns nonzero if write permission is requested on the file open flags */
168 static inline int
169 flags_writable(int open_flags)
170 {
171         int accmode = (open_flags & O_ACCMODE);
172         return (accmode == O_RDWR || accmode == O_WRONLY);
173 }
174
175 /*
176  * Allocate a file descriptor for a stream.
177  *
178  * @inode:      inode containing the stream we're opening
179  * @stream_id:  ID of the stream we're opening
180  * @lte:        Lookup table entry for the stream (may be NULL)
181  * @fd_ret:     Return the allocated file descriptor if successful.
182  *
183  * Return 0 iff successful or negative error code if unsuccessful.
184  */
185 static int
186 alloc_wimfs_fd(struct wim_inode *inode,
187                u32 stream_id,
188                struct wim_lookup_table_entry *lte,
189                struct wimfs_fd **fd_ret)
190 {
191         static const u16 fds_per_alloc = 8;
192         static const u16 max_fds = 0xffff;
193
194         DEBUG("Allocating fd for stream ID %u from inode %#"PRIx64" "
195               "(open = %u, allocated = %u)",
196               stream_id, inode->i_ino, inode->i_num_opened_fds,
197               inode->i_num_allocated_fds);
198
199         if (inode->i_num_opened_fds == inode->i_num_allocated_fds) {
200                 struct wimfs_fd **fds;
201                 u16 num_new_fds;
202
203                 if (inode->i_num_allocated_fds == max_fds)
204                         return -EMFILE;
205
206                 num_new_fds = min(fds_per_alloc,
207                                   max_fds - inode->i_num_allocated_fds);
208
209                 fds = REALLOC(inode->i_fds,
210                               (inode->i_num_allocated_fds + num_new_fds) *
211                                 sizeof(inode->i_fds[0]));
212                 if (!fds)
213                         return -ENOMEM;
214
215                 memset(&fds[inode->i_num_allocated_fds], 0,
216                        num_new_fds * sizeof(fds[0]));
217                 inode->i_fds = fds;
218                 inode->i_num_allocated_fds += num_new_fds;
219         }
220         for (u16 i = 0; ; i++) {
221                 if (!inode->i_fds[i]) {
222                         struct wimfs_fd *fd = CALLOC(1, sizeof(*fd));
223                         if (!fd)
224                                 return -ENOMEM;
225
226                         fd->f_inode     = inode;
227                         fd->f_lte       = lte;
228                         filedes_invalidate(&fd->staging_fd);
229                         fd->idx         = i;
230                         fd->stream_id   = stream_id;
231                         *fd_ret         = fd;
232                         inode->i_fds[i] = fd;
233                         inode->i_num_opened_fds++;
234                         if (lte)
235                                 lte->num_opened_fds++;
236                         DEBUG("Allocated fd (idx = %u)", fd->idx);
237                         return 0;
238                 }
239         }
240 }
241
242 static void
243 inode_put_fd(struct wim_inode *inode, struct wimfs_fd *fd)
244 {
245         wimlib_assert(inode != NULL);
246         wimlib_assert(fd->f_inode == inode);
247         wimlib_assert(inode->i_num_opened_fds != 0);
248         wimlib_assert(fd->idx < inode->i_num_allocated_fds);
249         wimlib_assert(inode->i_fds[fd->idx] == fd);
250
251         inode->i_fds[fd->idx] = NULL;
252         FREE(fd);
253         if (--inode->i_num_opened_fds == 0) {
254                 FREE(inode->i_fds);
255                 inode->i_fds = NULL;
256                 inode->i_num_allocated_fds = 0;
257                 if (inode->i_nlink == 0)
258                         free_inode(inode);
259         }
260 }
261
262 static int
263 lte_put_fd(struct wim_lookup_table_entry *lte, struct wimfs_fd *fd)
264 {
265         wimlib_assert(fd->f_lte == lte);
266
267         if (!lte) /* Empty stream with no lookup table entry */
268                 return 0;
269
270         /* Close staging file descriptor if needed. */
271
272         if (lte->resource_location == RESOURCE_IN_STAGING_FILE
273              && filedes_valid(&fd->staging_fd))
274         {
275                 if (filedes_close(&fd->staging_fd)) {
276                         ERROR_WITH_ERRNO("Failed to close staging file");
277                         return -errno;
278                 }
279         }
280         lte_decrement_num_opened_fds(lte);
281         return 0;
282 }
283
284 /* Close a file descriptor. */
285 static int
286 close_wimfs_fd(struct wimfs_fd *fd)
287 {
288         int ret;
289         DEBUG("Closing fd (ino = %#"PRIx64", opened = %u, allocated = %u)",
290               fd->f_inode->i_ino, fd->f_inode->i_num_opened_fds,
291               fd->f_inode->i_num_allocated_fds);
292         ret = lte_put_fd(fd->f_lte, fd);
293         if (ret)
294                 return ret;
295
296         inode_put_fd(fd->f_inode, fd);
297         return 0;
298 }
299
300 static mode_t
301 fuse_mask_mode(mode_t mode, struct fuse_context *fuse_ctx)
302 {
303 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
304         mode &= ~fuse_ctx->umask;
305 #endif
306         return mode;
307 }
308
309 /*
310  * Add a new dentry with a new inode to a WIM image.
311  *
312  * Returns 0 on success, or negative error number on failure.
313  */
314 static int
315 create_dentry(struct fuse_context *fuse_ctx, const char *path,
316               mode_t mode, int attributes, struct wim_dentry **dentry_ret)
317 {
318         struct wim_dentry *parent;
319         struct wim_dentry *new;
320         const char *basename;
321         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
322         int ret;
323
324         parent = get_parent_dentry(wimfs_ctx->wim, path, WIMLIB_CASE_SENSITIVE);
325         if (!parent)
326                 return -errno;
327
328         if (!dentry_is_directory(parent))
329                 return -ENOTDIR;
330
331         basename = path_basename(path);
332         if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE))
333                 return -EEXIST;
334
335         ret = new_dentry_with_inode(basename, &new);
336         if (ret)
337                 return -ENOMEM;
338
339         new->d_inode->i_resolved = 1;
340         new->d_inode->i_ino = wimfs_ctx->next_ino++;
341         new->d_inode->i_attributes = attributes;
342
343         if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
344                 if (inode_set_unix_data(new->d_inode,
345                                         fuse_ctx->uid,
346                                         fuse_ctx->gid,
347                                         fuse_mask_mode(mode, fuse_ctx),
348                                         wimfs_ctx->wim->lookup_table,
349                                         UNIX_DATA_ALL | UNIX_DATA_CREATE))
350                 {
351                         free_dentry(new);
352                         return -ENOMEM;
353                 }
354         }
355         dentry_add_child(parent, new);
356         list_add_tail(&new->d_inode->i_list, wimfs_ctx->image_inode_list);
357         if (dentry_ret)
358                 *dentry_ret = new;
359         return 0;
360 }
361
362 static struct wim_inode *
363 wim_pathname_to_inode(WIMStruct *wim, const tchar *path)
364 {
365         struct wim_dentry *dentry;
366         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
367         if (dentry)
368                 return dentry->d_inode;
369         else
370                 return NULL;
371 }
372
373 /*
374  * Remove a dentry from a mounted WIM image; i.e. remove an alias for an inode.
375  */
376 static void
377 remove_dentry(struct wim_dentry *dentry,
378               struct wim_lookup_table *lookup_table)
379 {
380         /* Put a reference to each stream the inode contains.  */
381         inode_unref_streams(dentry->d_inode, lookup_table);
382
383         /* Unlink the dentry from the image's dentry tree.  */
384         unlink_dentry(dentry);
385
386         /* Delete the dentry.  This will also decrement the link count of the
387          * corresponding inode.  */
388         free_dentry(dentry);
389 }
390
391 static mode_t
392 inode_default_unix_mode(const struct wim_inode *inode)
393 {
394         if (inode_is_symlink(inode))
395                 return S_IFLNK | 0777;
396         else if (inode_is_directory(inode))
397                 return S_IFDIR | 0777;
398         else
399                 return S_IFREG | 0777;
400 }
401
402 /* Transfers file attributes from a struct wim_inode to a `stat' buffer.
403  *
404  * The lookup table entry tells us which stream in the inode we are statting.
405  * For a named data stream, everything returned is the same as the unnamed data
406  * stream except possibly the size and block count. */
407 static int
408 inode_to_stbuf(const struct wim_inode *inode,
409                const struct wim_lookup_table_entry *lte,
410                struct stat *stbuf)
411 {
412         const struct wimfs_context *ctx = wimfs_get_context();
413
414         memset(stbuf, 0, sizeof(struct stat));
415         stbuf->st_mode = inode_default_unix_mode(inode);
416         stbuf->st_uid = ctx->default_uid;
417         stbuf->st_gid = ctx->default_gid;
418         if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
419                 struct wimlib_unix_data unix_data;
420                 if (inode_get_unix_data(inode, &unix_data, NULL) == 0) {
421                         stbuf->st_uid = unix_data.uid;
422                         stbuf->st_gid = unix_data.gid;
423                         stbuf->st_mode = unix_data.mode;
424                 }
425         }
426         stbuf->st_ino = (ino_t)inode->i_ino;
427         stbuf->st_nlink = inode->i_nlink;
428         if (lte)
429                 stbuf->st_size = lte->size;
430         else
431                 stbuf->st_size = 0;
432 #ifdef HAVE_STAT_NANOSECOND_PRECISION
433         stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time);
434         stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time);
435         stbuf->st_ctim = stbuf->st_mtim;
436 #else
437         stbuf->st_atime = wim_timestamp_to_unix(inode->i_last_access_time);
438         stbuf->st_mtime = wim_timestamp_to_unix(inode->i_last_write_time);
439         stbuf->st_ctime = stbuf->st_mtime;
440 #endif
441         stbuf->st_blocks = (stbuf->st_size + 511) / 512;
442         return 0;
443 }
444
445 static void
446 touch_inode(struct wim_inode *inode)
447 {
448         u64 now = get_wim_timestamp();
449         inode->i_last_access_time = now;
450         inode->i_last_write_time = now;
451 }
452
453 /* Creates a new staging file and returns its file descriptor opened for
454  * writing.
455  *
456  * @name_ret: A location into which the a pointer to the newly allocated name of
457  *            the staging file is stored.
458  *
459  * @ctx:      Context for the WIM filesystem; this provides the name of the
460  *            staging directory.
461  *
462  * On success, returns the file descriptor for the staging file, opened for
463  * writing.  On failure, returns -1 and sets errno.
464  */
465 static int
466 create_staging_file(char **name_ret, struct wimfs_context *ctx)
467 {
468         size_t name_len;
469         char *name;
470         struct stat stbuf;
471         int fd;
472         int errno_save;
473
474         static const size_t STAGING_FILE_NAME_LEN = 20;
475
476         name_len = ctx->staging_dir_name_len + 1 + STAGING_FILE_NAME_LEN;
477         name = MALLOC(name_len + 1);
478         if (!name) {
479                 errno = ENOMEM;
480                 return -1;
481         }
482
483         do {
484
485                 memcpy(name, ctx->staging_dir_name, ctx->staging_dir_name_len);
486                 name[ctx->staging_dir_name_len] = '/';
487                 randomize_char_array_with_alnum(name + ctx->staging_dir_name_len + 1,
488                                                 STAGING_FILE_NAME_LEN);
489                 name[name_len] = '\0';
490
491
492         /* Just in case, verify that the randomly generated name doesn't name an
493          * existing file, and try again if so  */
494         } while (stat(name, &stbuf) == 0);
495
496         if (errno != ENOENT) /* other error?! */
497                 return -1;
498
499         /* doesn't exist--- ok */
500
501         DEBUG("Creating staging file `%s'", name);
502
503         fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600);
504         if (fd == -1) {
505                 errno_save = errno;
506                 FREE(name);
507                 errno = errno_save;
508         } else {
509                 *name_ret = name;
510         }
511         return fd;
512 }
513
514 /*
515  * Extract a WIM resource to the staging directory.
516  *
517  * @inode:  Inode that contains the stream we are extracting
518  *
519  * @stream_id: Identifier for the stream (it stays constant even if the indices
520  * of the stream entries are changed)
521  *
522  * @lte: Pointer to pointer to the lookup table entry for the stream we need to
523  * extract, or NULL if there was no lookup table entry present for the stream
524  *
525  * @size:  Number of bytes of the stream we want to extract (this supports the
526  * wimfs_truncate() function).  It may be more than the actual stream length, in
527  * which case the extra space is filled with zeroes.
528  *
529  * @ctx:  Context for the WIM filesystem.
530  *
531  * Returns 0 on success or a negative error code on failure.
532  */
533 static int
534 extract_resource_to_staging_dir(struct wim_inode *inode,
535                                 u32 stream_id,
536                                 struct wim_lookup_table_entry **lte,
537                                 off_t size,
538                                 struct wimfs_context *ctx)
539 {
540         char *staging_file_name;
541         int ret;
542         int fd;
543         struct wim_lookup_table_entry *old_lte, *new_lte;
544         off_t extract_size;
545
546         DEBUG("Extracting resource to staging dir: inode %"PRIu64", "
547               "stream id %"PRIu32, inode->i_ino, stream_id);
548
549         old_lte = *lte;
550
551         wimlib_assert(old_lte == NULL ||
552                       old_lte->resource_location != RESOURCE_IN_STAGING_FILE);
553
554         /* Create the staging file */
555         fd = create_staging_file(&staging_file_name, ctx);
556         if (fd == -1)
557                 return -errno;
558
559         /* Extract the stream to the staging file (possibly truncated) */
560         if (old_lte) {
561                 struct filedes wimlib_fd;
562                 filedes_init(&wimlib_fd, fd);
563                 extract_size = min(old_lte->size, size);
564                 ret = extract_stream_to_fd(old_lte, &wimlib_fd, extract_size);
565         } else {
566                 ret = 0;
567                 extract_size = 0;
568         }
569
570         /* In the case of truncate() to more than the file length, extend the
571          * file with zeroes by calling ftruncate() on the underlying staging
572          * file */
573         if (ret == 0 && size > extract_size)
574                 ret = ftruncate(fd, size);
575
576         /* Close the staging file descriptor and check for errors.  If there's
577          * an error, unlink the staging file. */
578         if (ret != 0 || close(fd) != 0) {
579                 if (errno != 0)
580                         ret = -errno;
581                 else
582                         ret = -EIO;
583                 close(fd);
584                 goto out_delete_staging_file;
585         }
586
587         /* Now deal with the lookup table entries.  We may be able to re-use the
588          * existing entry, but we may have to create a new one instead. */
589
590         if (old_lte && inode->i_nlink == old_lte->refcnt) {
591                 /* The reference count of the existing lookup table entry is the
592                  * same as the link count of the inode that contains the stream
593                  * we're opening.  Therefore, ALL the references to the lookup
594                  * table entry correspond to the stream we're trying to extract,
595                  * so the lookup table entry can be re-used.  */
596                 DEBUG("Re-using lookup table entry");
597                 lookup_table_unlink(ctx->wim->lookup_table, old_lte);
598                 new_lte = old_lte;
599         } else {
600                 if (old_lte) {
601                         /* There's an existing lookup table entry, but its
602                          * reference count is greater than the link count for
603                          * the inode containing a stream we're opening.
604                          * Therefore, we need to split the lookup table entry.
605                          */
606                         wimlib_assert(old_lte->refcnt > inode->i_nlink);
607                         DEBUG("Splitting lookup table entry "
608                               "(inode->i_nlink = %u, old_lte->refcnt = %u)",
609                               inode->i_nlink, old_lte->refcnt);
610                 }
611
612                 new_lte = new_lookup_table_entry();
613                 if (!new_lte) {
614                         ret = -ENOMEM;
615                         goto out_delete_staging_file;
616                 }
617
618                 /* There may already be open file descriptors to this stream if
619                  * it's previously been opened read-only, but just now we're
620                  * opening it read-write.  Identify those file descriptors and
621                  * change their lookup table entry pointers to point to the new
622                  * lookup table entry, and open staging file descriptors for
623                  * them.
624                  *
625                  * At the same time, we need to count the number of these opened
626                  * file descriptors to the new lookup table entry.  If there's
627                  * an old lookup table entry, this number needs to be subtracted
628                  * from the fd's opened to the old entry. */
629                 for (u16 i = 0, j = 0; j < inode->i_num_opened_fds; i++) {
630                         struct wimfs_fd *fd = inode->i_fds[i];
631                         if (fd) {
632                                 if (fd->stream_id == stream_id) {
633                                         int raw_fd;
634
635                                         wimlib_assert(fd->f_lte == old_lte);
636                                         wimlib_assert(!filedes_valid(&fd->staging_fd));
637                                         fd->f_lte = new_lte;
638                                         new_lte->num_opened_fds++;
639                                         raw_fd = open(staging_file_name, O_RDONLY);
640                                         if (raw_fd < 0) {
641                                                 ret = -errno;
642                                                 goto out_revert_fd_changes;
643                                         }
644                                         filedes_init(&fd->staging_fd, raw_fd);
645                                 }
646                                 j++;
647                         }
648                 }
649                 DEBUG("%hu fd's were already opened to the file we extracted",
650                       new_lte->num_opened_fds);
651                 if (old_lte) {
652                         old_lte->num_opened_fds -= new_lte->num_opened_fds;
653                         old_lte->refcnt -= inode->i_nlink;
654                 }
655         }
656
657         lte_put_resource(new_lte);
658         new_lte->refcnt              = inode->i_nlink;
659         new_lte->resource_location   = RESOURCE_IN_STAGING_FILE;
660         new_lte->staging_file_name   = staging_file_name;
661         new_lte->size                = size;
662
663         add_unhashed_stream(new_lte, inode, stream_id,
664                             &wim_get_current_image_metadata(ctx->wim)->unhashed_streams);
665         *retrieve_lte_pointer(new_lte) = new_lte;
666         *lte = new_lte;
667         return 0;
668 out_revert_fd_changes:
669         for (u16 i = 0, j = 0; j < new_lte->num_opened_fds; i++) {
670                 struct wimfs_fd *fd = inode->i_fds[i];
671                 if (fd && fd->stream_id == stream_id && fd->f_lte == new_lte) {
672                         fd->f_lte = old_lte;
673                         if (filedes_valid(&fd->staging_fd)) {
674                                 filedes_close(&fd->staging_fd);
675                                 filedes_invalidate(&fd->staging_fd);
676                         }
677                         j++;
678                 }
679         }
680         free_lookup_table_entry(new_lte);
681 out_delete_staging_file:
682         unlink(staging_file_name);
683         FREE(staging_file_name);
684         return ret;
685 }
686
687 /*
688  * Creates a randomly named staging directory and saves its name in the
689  * filesystem context structure.
690  */
691 static int
692 make_staging_dir(struct wimfs_context *ctx, const char *user_prefix)
693 {
694         static const size_t random_suffix_len = 10;
695         static const char *common_suffix = ".staging";
696         static const size_t common_suffix_len = 8;
697
698         char *staging_dir_name = NULL;
699         size_t staging_dir_name_len;
700         size_t prefix_len;
701         const char *wim_basename;
702         char *real_user_prefix = NULL;
703         int ret;
704
705         if (user_prefix) {
706                 real_user_prefix = realpath(user_prefix, NULL);
707                 if (!real_user_prefix) {
708                         ERROR_WITH_ERRNO("Could not resolve `%s'",
709                                          real_user_prefix);
710                         ret = WIMLIB_ERR_NOTDIR;
711                         goto out;
712                 }
713                 wim_basename = path_basename(ctx->wim->filename);
714                 prefix_len = strlen(real_user_prefix) + 1 + strlen(wim_basename);
715         } else {
716                 prefix_len = strlen(ctx->wim->filename);
717         }
718
719         staging_dir_name_len = prefix_len + common_suffix_len + random_suffix_len;
720
721         staging_dir_name = MALLOC(staging_dir_name_len + 1);
722         if (!staging_dir_name) {
723                 ret = WIMLIB_ERR_NOMEM;
724                 goto out;
725         }
726
727         if (real_user_prefix)
728                 sprintf(staging_dir_name, "%s/%s", real_user_prefix, wim_basename);
729         else
730                 strcpy(staging_dir_name, ctx->wim->filename);
731
732         strcat(staging_dir_name, common_suffix);
733
734         randomize_char_array_with_alnum(staging_dir_name + prefix_len + common_suffix_len,
735                                         random_suffix_len);
736
737         staging_dir_name[staging_dir_name_len] = '\0';
738
739         if (mkdir(staging_dir_name, 0700) != 0) {
740                 ERROR_WITH_ERRNO("Failed to create temporary directory `%s'",
741                                  staging_dir_name);
742                 ret = WIMLIB_ERR_MKDIR;
743         } else {
744                 ret = 0;
745         }
746 out:
747         FREE(real_user_prefix);
748         if (ret == 0) {
749                 ctx->staging_dir_name = staging_dir_name;
750                 ctx->staging_dir_name_len = staging_dir_name_len;
751         } else {
752                 FREE(staging_dir_name);
753         }
754         return ret;
755 }
756
757 static int
758 remove_file_or_directory(const char *fpath, const struct stat *sb,
759                          int typeflag, struct FTW *ftwbuf)
760 {
761         if (remove(fpath) == 0)
762                 return 0;
763         else {
764                 ERROR_WITH_ERRNO("Cannot remove `%s'", fpath);
765                 return WIMLIB_ERR_DELETE_STAGING_DIR;
766         }
767 }
768
769 /*
770  * Deletes the staging directory and all the files contained in it.
771  */
772 static int
773 delete_staging_dir(struct wimfs_context *ctx)
774 {
775         int ret;
776         ret = nftw(ctx->staging_dir_name, remove_file_or_directory,
777                    10, FTW_DEPTH);
778         FREE(ctx->staging_dir_name);
779         ctx->staging_dir_name = NULL;
780         return ret;
781 }
782
783 static int
784 inode_close_fds(struct wim_inode *inode)
785 {
786         u16 num_opened_fds = inode->i_num_opened_fds;
787         for (u16 i = 0, j = 0; j < num_opened_fds; i++) {
788                 struct wimfs_fd *fd = inode->i_fds[i];
789                 if (fd) {
790                         wimlib_assert(fd->f_inode == inode);
791                         int ret = close_wimfs_fd(fd);
792                         if (ret != 0)
793                                 return ret;
794                         j++;
795                 }
796         }
797         return 0;
798 }
799
800 /* Overwrites the WIM file, with changes saved. */
801 static int
802 rebuild_wim(struct wimfs_context *ctx, int write_flags,
803             wimlib_progress_func_t progress_func)
804 {
805         int ret;
806         struct wim_lookup_table_entry *lte, *tmp;
807         WIMStruct *wim = ctx->wim;
808         struct wim_image_metadata *imd = wim_get_current_image_metadata(ctx->wim);
809
810         DEBUG("Closing all staging file descriptors.");
811         image_for_each_unhashed_stream_safe(lte, tmp, imd) {
812                 ret = inode_close_fds(lte->back_inode);
813                 if (ret)
814                         return ret;
815         }
816
817         DEBUG("Freeing entries for zero-length streams");
818         image_for_each_unhashed_stream_safe(lte, tmp, imd) {
819                 wimlib_assert(lte->unhashed);
820                 if (lte->size == 0) {
821                         struct wim_lookup_table_entry **back_ptr;
822                         back_ptr = retrieve_lte_pointer(lte);
823                         *back_ptr = NULL;
824                         list_del(&lte->unhashed_list);
825                         free_lookup_table_entry(lte);
826                 }
827         }
828
829         xml_update_image_info(wim, wim->current_image);
830         ret = wimlib_overwrite(wim, write_flags, 0, progress_func);
831         if (ret)
832                 ERROR("Failed to commit changes to mounted WIM image");
833         return ret;
834 }
835
836 /* Simple function that returns the concatenation of 2 strings. */
837 static char *
838 strcat_dup(const char *s1, const char *s2, size_t max_len)
839 {
840         size_t len = strlen(s1) + strlen(s2);
841         if (len > max_len)
842                 len = max_len;
843         char *p = MALLOC(len + 1);
844         if (!p)
845                 return NULL;
846         snprintf(p, len + 1, "%s%s", s1, s2);
847         return p;
848 }
849
850 static int
851 set_message_queue_names(struct wimfs_context *ctx, const char *mount_dir)
852 {
853         static const char *u2d_prefix = "/wimlib-unmount-to-daemon-mq";
854         static const char *d2u_prefix = "/wimlib-daemon-to-unmount-mq";
855         char *dir_path;
856         char *p;
857         int ret;
858
859         dir_path = realpath(mount_dir, NULL);
860         if (!dir_path) {
861                 ERROR_WITH_ERRNO("Failed to resolve path \"%s\"", mount_dir);
862                 if (errno == ENOMEM)
863                         return WIMLIB_ERR_NOMEM;
864                 else
865                         return WIMLIB_ERR_NOTDIR;
866         }
867
868         for (p = dir_path; *p; p++)
869                 if (*p == '/')
870                         *p = 0xff;
871
872         ctx->unmount_to_daemon_mq_name = strcat_dup(u2d_prefix, dir_path,
873                                                     NAME_MAX);
874         if (!ctx->unmount_to_daemon_mq_name) {
875                 ret = WIMLIB_ERR_NOMEM;
876                 goto out_free_dir_path;
877         }
878         ctx->daemon_to_unmount_mq_name = strcat_dup(d2u_prefix, dir_path,
879                                                     NAME_MAX);
880         if (!ctx->daemon_to_unmount_mq_name) {
881                 ret = WIMLIB_ERR_NOMEM;
882                 goto out_free_unmount_to_daemon_mq_name;
883         }
884
885         ret = 0;
886         goto out_free_dir_path;
887 out_free_unmount_to_daemon_mq_name:
888         FREE(ctx->unmount_to_daemon_mq_name);
889         ctx->unmount_to_daemon_mq_name = NULL;
890 out_free_dir_path:
891         FREE(dir_path);
892         return ret;
893 }
894
895 static void
896 free_message_queue_names(struct wimfs_context *ctx)
897 {
898         FREE(ctx->unmount_to_daemon_mq_name);
899         FREE(ctx->daemon_to_unmount_mq_name);
900         ctx->unmount_to_daemon_mq_name = NULL;
901         ctx->daemon_to_unmount_mq_name = NULL;
902 }
903
904 /*
905  * Opens two POSIX message queue: one for sending messages from the unmount
906  * process to the daemon process, and one to go the other way.  The names of the
907  * message queues, which must be system-wide unique, are be based on the mount
908  * point.
909  *
910  * @daemon specifies whether the calling process is the filesystem daemon or the
911  * unmount process.
912  */
913 static int
914 open_message_queues(struct wimfs_context *ctx, bool daemon)
915 {
916         int unmount_to_daemon_mq_flags = O_WRONLY | O_CREAT;
917         int daemon_to_unmount_mq_flags = O_RDONLY | O_CREAT;
918         mode_t mode;
919         mode_t orig_umask;
920         int ret;
921
922         if (daemon) {
923                 swap(unmount_to_daemon_mq_flags, daemon_to_unmount_mq_flags);
924                 mode = 0600;
925         } else {
926                 mode = 0666;
927         }
928
929         orig_umask = umask(0000);
930         DEBUG("Opening message queue \"%s\"", ctx->unmount_to_daemon_mq_name);
931         ctx->unmount_to_daemon_mq = mq_open(ctx->unmount_to_daemon_mq_name,
932                                             unmount_to_daemon_mq_flags, mode, NULL);
933
934         if (ctx->unmount_to_daemon_mq == (mqd_t)-1) {
935                 ERROR_WITH_ERRNO("mq_open()");
936                 ret = WIMLIB_ERR_MQUEUE;
937                 goto out;
938         }
939
940         DEBUG("Opening message queue \"%s\"", ctx->daemon_to_unmount_mq_name);
941         ctx->daemon_to_unmount_mq = mq_open(ctx->daemon_to_unmount_mq_name,
942                                             daemon_to_unmount_mq_flags, mode, NULL);
943
944         if (ctx->daemon_to_unmount_mq == (mqd_t)-1) {
945                 ERROR_WITH_ERRNO("mq_open()");
946                 mq_close(ctx->unmount_to_daemon_mq);
947                 mq_unlink(ctx->unmount_to_daemon_mq_name);
948                 ctx->unmount_to_daemon_mq = (mqd_t)-1;
949                 ret = WIMLIB_ERR_MQUEUE;
950                 goto out;
951         }
952         ret = 0;
953 out:
954         umask(orig_umask);
955         return ret;
956 }
957
958 /* Try to determine the maximum message size of a message queue.  The return
959  * value is the maximum message size, or a guess of 8192 bytes if it cannot be
960  * determined. */
961 static long
962 mq_get_msgsize(mqd_t mq)
963 {
964         static const char *msgsize_max_file = "/proc/sys/fs/mqueue/msgsize_max";
965         FILE *fp;
966         struct mq_attr attr;
967         long msgsize;
968
969         if (mq_getattr(mq, &attr) == 0) {
970                 msgsize = attr.mq_msgsize;
971         } else {
972                 ERROR_WITH_ERRNO("mq_getattr()");
973                 ERROR("Attempting to read %s", msgsize_max_file);
974                 fp = fopen(msgsize_max_file, "rb");
975                 if (fp) {
976                         if (fscanf(fp, "%ld", &msgsize) != 1) {
977                                 ERROR("Assuming message size of 8192");
978                                 msgsize = 8192;
979                         }
980                         fclose(fp);
981                 } else {
982                         ERROR_WITH_ERRNO("Failed to open the file `%s'",
983                                          msgsize_max_file);
984                         ERROR("Assuming message size of 8192");
985                         msgsize = 8192;
986                 }
987         }
988         return msgsize;
989 }
990
991 static int
992 get_mailbox(mqd_t mq, long needed_msgsize, long *msgsize_ret,
993             void **mailbox_ret)
994 {
995         long msgsize;
996         void *mailbox;
997
998         msgsize = mq_get_msgsize(mq);
999
1000         if (msgsize < needed_msgsize) {
1001                 ERROR("Message queue max size must be at least %ld!",
1002                       needed_msgsize);
1003                 return WIMLIB_ERR_MQUEUE;
1004         }
1005
1006         mailbox = MALLOC(msgsize);
1007         if (!mailbox) {
1008                 ERROR("Failed to allocate %ld bytes for mailbox", msgsize);
1009                 return WIMLIB_ERR_NOMEM;
1010         }
1011         *msgsize_ret = msgsize;
1012         *mailbox_ret = mailbox;
1013         return 0;
1014 }
1015
1016 static void
1017 unlink_message_queues(struct wimfs_context *ctx)
1018 {
1019         mq_unlink(ctx->unmount_to_daemon_mq_name);
1020         mq_unlink(ctx->daemon_to_unmount_mq_name);
1021 }
1022
1023 /* Closes the message queues, which are allocated in static variables */
1024 static void
1025 close_message_queues(struct wimfs_context *ctx)
1026 {
1027         DEBUG("Closing message queues");
1028         mq_close(ctx->unmount_to_daemon_mq);
1029         ctx->unmount_to_daemon_mq = (mqd_t)(-1);
1030         mq_close(ctx->daemon_to_unmount_mq);
1031         ctx->daemon_to_unmount_mq = (mqd_t)(-1);
1032         unlink_message_queues(ctx);
1033 }
1034
1035
1036 struct unmount_msg_hdr {
1037         u32 min_version;
1038         u32 cur_version;
1039         u32 msg_type;
1040         u32 msg_size;
1041 } _packed_attribute;
1042
1043 struct msg_unmount_request {
1044         struct unmount_msg_hdr hdr;
1045         u32 unmount_flags;
1046         u8 want_progress_messages;
1047 } _packed_attribute;
1048
1049 struct msg_daemon_info {
1050         struct unmount_msg_hdr hdr;
1051         pid_t daemon_pid;
1052         u32 mount_flags;
1053 } _packed_attribute;
1054
1055 struct msg_unmount_finished {
1056         struct unmount_msg_hdr hdr;
1057         s32 status;
1058 } _packed_attribute;
1059
1060 struct msg_write_streams_progress {
1061         struct unmount_msg_hdr hdr;
1062         union wimlib_progress_info info;
1063 } _packed_attribute;
1064
1065 enum {
1066         MSG_TYPE_UNMOUNT_REQUEST,
1067         MSG_TYPE_DAEMON_INFO,
1068         MSG_TYPE_WRITE_STREAMS_PROGRESS,
1069         MSG_TYPE_UNMOUNT_FINISHED,
1070         MSG_TYPE_MAX,
1071 };
1072
1073 struct msg_handler_context_hdr {
1074         int timeout_seconds;
1075 };
1076
1077 struct unmount_msg_handler_context {
1078         struct msg_handler_context_hdr hdr;
1079         pid_t daemon_pid;
1080         int mount_flags;
1081         int status;
1082         wimlib_progress_func_t progress_func;
1083 };
1084
1085 struct daemon_msg_handler_context {
1086         struct msg_handler_context_hdr hdr;
1087         struct wimfs_context *wimfs_ctx;
1088 };
1089
1090 static int
1091 send_unmount_request_msg(mqd_t mq, int unmount_flags, u8 want_progress_messages)
1092 {
1093         DEBUG("Sending unmount request msg");
1094         struct msg_unmount_request msg = {
1095                 .hdr = {
1096                         .min_version = ((unmount_flags & WIMLIB_UNMOUNT_FLAG_NEW_IMAGE) ?
1097                                                 WIMLIB_MAKEVERSION(1, 6, 2) :
1098                                                 WIMLIB_MAKEVERSION(1, 2, 1)),
1099                         .cur_version = WIMLIB_VERSION_CODE,
1100                         .msg_type    = MSG_TYPE_UNMOUNT_REQUEST,
1101                         .msg_size    = sizeof(msg),
1102                 },
1103                 .unmount_flags = unmount_flags,
1104                 .want_progress_messages = want_progress_messages,
1105         };
1106
1107         if (mq_send(mq, (void*)&msg, sizeof(msg), 1)) {
1108                 ERROR_WITH_ERRNO("Failed to communicate with filesystem daemon");
1109                 return WIMLIB_ERR_MQUEUE;
1110         }
1111         return 0;
1112 }
1113
1114 static int
1115 send_daemon_info_msg(mqd_t mq, pid_t pid, int mount_flags)
1116 {
1117         DEBUG("Sending daemon info msg (pid = %d, mount_flags=%x)",
1118               pid, mount_flags);
1119
1120         struct msg_daemon_info msg = {
1121                 .hdr = {
1122                         .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
1123                         .cur_version = WIMLIB_VERSION_CODE,
1124                         .msg_type = MSG_TYPE_DAEMON_INFO,
1125                         .msg_size = sizeof(msg),
1126                 },
1127                 .daemon_pid = pid,
1128                 .mount_flags = mount_flags,
1129         };
1130         if (mq_send(mq, (void*)&msg, sizeof(msg), 1)) {
1131                 ERROR_WITH_ERRNO("Failed to send daemon info to unmount process");
1132                 return WIMLIB_ERR_MQUEUE;
1133         }
1134         return 0;
1135 }
1136
1137 static void
1138 send_unmount_finished_msg(mqd_t mq, int status)
1139 {
1140         DEBUG("Sending unmount finished msg");
1141         struct msg_unmount_finished msg = {
1142                 .hdr = {
1143                         .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
1144                         .cur_version = WIMLIB_VERSION_CODE,
1145                         .msg_type = MSG_TYPE_UNMOUNT_FINISHED,
1146                         .msg_size = sizeof(msg),
1147                 },
1148                 .status = status,
1149         };
1150         if (mq_send(mq, (void*)&msg, sizeof(msg), 1))
1151                 ERROR_WITH_ERRNO("Failed to send status to unmount process");
1152 }
1153
1154 static int
1155 unmount_progress_func(enum wimlib_progress_msg msg,
1156                       const union wimlib_progress_info *info)
1157 {
1158         if (msg == WIMLIB_PROGRESS_MSG_WRITE_STREAMS) {
1159                 struct msg_write_streams_progress msg = {
1160                         .hdr = {
1161                                 .min_version = WIMLIB_MAKEVERSION(1, 2, 1),
1162                                 .cur_version = WIMLIB_VERSION_CODE,
1163                                 .msg_type = MSG_TYPE_WRITE_STREAMS_PROGRESS,
1164                                 .msg_size = sizeof(msg),
1165                         },
1166                         .info = *info,
1167                 };
1168                 if (mq_send(wimfs_get_context()->daemon_to_unmount_mq,
1169                             (void*)&msg, sizeof(msg), 1))
1170                 {
1171                         ERROR_WITH_ERRNO("Failed to send progress information "
1172                                          "to unmount process");
1173                 }
1174         }
1175         return 0;
1176 }
1177
1178 static void
1179 release_extra_refcnts(struct wimfs_context *ctx)
1180 {
1181         struct list_head *list = &ctx->orig_stream_list;
1182         struct wim_lookup_table *lookup_table = ctx->wim->lookup_table;
1183         struct wim_lookup_table_entry *lte, *tmp;
1184
1185         list_for_each_entry_safe(lte, tmp, list, orig_stream_list) {
1186                 u32 n = lte->out_refcnt;
1187                 while (n--)
1188                         lte_decrement_refcnt(lte, lookup_table);
1189         }
1190 }
1191
1192 /* Moves the currently selected image, which may have been modified, to a new
1193  * index, and sets the original index to refer to a reset (unmodified) copy of
1194  * the image.  */
1195 static int
1196 renew_current_image(struct wimfs_context *ctx)
1197 {
1198         WIMStruct *wim = ctx->wim;
1199         int ret;
1200         int idx = wim->current_image - 1;
1201         struct wim_image_metadata *imd = wim->image_metadata[idx];
1202         struct wim_image_metadata *replace_imd;
1203         struct wim_lookup_table_entry *new_lte;
1204
1205         if (imd->metadata_lte->resource_location != RESOURCE_IN_WIM) {
1206                 ERROR("Can't reset modified image that doesn't yet "
1207                       "exist in the on-disk WIM file!");
1208                 return WIMLIB_ERR_METADATA_NOT_FOUND;
1209         }
1210
1211         /* Create 'replace_imd' structure to use for the reset original,
1212          * unmodified image.  */
1213         replace_imd = new_image_metadata();
1214         if (!replace_imd)
1215                 return WIMLIB_ERR_NOMEM;
1216
1217         /* Create new stream reference for the modified image's metadata
1218          * resource, which doesn't exist yet.  */
1219         ret = WIMLIB_ERR_NOMEM;
1220         new_lte = new_lookup_table_entry();
1221         if (!new_lte)
1222                 goto err_put_replace_imd;
1223         new_lte->flags = WIM_RESHDR_FLAG_METADATA;
1224         new_lte->unhashed = 1;
1225
1226         /* Make the image being moved available at a new index.  Increments the
1227          * WIM's image count, but does not increment the reference count of the
1228          * 'struct image_metadata'.  */
1229         ret = append_image_metadata(wim, imd);
1230         if (ret)
1231                 goto err_free_new_lte;
1232
1233         ret = xml_add_image(wim, T(""));
1234         if (ret)
1235                 goto err_undo_append;
1236
1237         replace_imd->metadata_lte = imd->metadata_lte;
1238         imd->metadata_lte = new_lte;
1239         wim->image_metadata[idx] = replace_imd;
1240         wim->current_image = wim->hdr.image_count;
1241         return 0;
1242
1243 err_undo_append:
1244         wim->hdr.image_count--;
1245 err_free_new_lte:
1246         free_lookup_table_entry(new_lte);
1247 err_put_replace_imd:
1248         put_image_metadata(replace_imd, NULL);
1249         return ret;
1250 }
1251
1252 static int
1253 msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
1254 {
1255         const struct msg_unmount_request *msg = _msg;
1256         struct daemon_msg_handler_context *handler_ctx = _handler_ctx;
1257         struct wimfs_context *wimfs_ctx;
1258         int status = 0;
1259         int ret;
1260         int unmount_flags;
1261         wimlib_progress_func_t progress_func;
1262
1263         DEBUG("Handling unmount request msg");
1264
1265         wimfs_ctx = handler_ctx->wimfs_ctx;
1266         if (msg->hdr.msg_size < sizeof(*msg)) {
1267                 status = WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1268                 goto out;
1269         }
1270
1271         unmount_flags = msg->unmount_flags;
1272         if (msg->want_progress_messages)
1273                 progress_func = unmount_progress_func;
1274         else
1275                 progress_func = NULL;
1276
1277         ret = send_daemon_info_msg(wimfs_ctx->daemon_to_unmount_mq, getpid(),
1278                                    wimfs_ctx->mount_flags);
1279         if (ret != 0) {
1280                 status = ret;
1281                 goto out;
1282         }
1283
1284         if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
1285                 if (unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) {
1286
1287                         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_NEW_IMAGE) {
1288                                 ret = renew_current_image(wimfs_ctx);
1289                                 if (ret) {
1290                                         status = ret;
1291                                         goto out;
1292                                 }
1293                         } else {
1294                                 release_extra_refcnts(wimfs_ctx);
1295                         }
1296                         INIT_LIST_HEAD(&wimfs_ctx->orig_stream_list);
1297
1298                         int write_flags = 0;
1299                         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY)
1300                                 write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
1301                         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_REBUILD)
1302                                 write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
1303                         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_RECOMPRESS)
1304                                 write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
1305                         status = rebuild_wim(wimfs_ctx, write_flags,
1306                                              progress_func);
1307                 }
1308         } else {
1309                 DEBUG("Read-only mount");
1310                 status = 0;
1311         }
1312
1313 out:
1314         if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
1315                 ret = delete_staging_dir(wimfs_ctx);
1316                 if (ret != 0) {
1317                         ERROR("Failed to delete the staging directory");
1318                         if (status == 0)
1319                                 status = ret;
1320                 }
1321         }
1322         wimfs_ctx->status = status;
1323         wimfs_ctx->have_status = true;
1324         return MSG_BREAK_LOOP;
1325 }
1326
1327 static int
1328 msg_daemon_info_handler(const void *_msg, void *_handler_ctx)
1329 {
1330         const struct msg_daemon_info *msg = _msg;
1331         struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
1332
1333         DEBUG("Handling daemon info msg");
1334         if (msg->hdr.msg_size < sizeof(*msg))
1335                 return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1336         handler_ctx->daemon_pid = msg->daemon_pid;
1337         handler_ctx->mount_flags = msg->mount_flags;
1338         handler_ctx->hdr.timeout_seconds = 1;
1339         DEBUG("pid of daemon is %d; mount flags were %#x",
1340               handler_ctx->daemon_pid,
1341               handler_ctx->mount_flags);
1342         return 0;
1343 }
1344
1345 static int
1346 msg_write_streams_progress_handler(const void *_msg, void *_handler_ctx)
1347 {
1348         const struct msg_write_streams_progress *msg = _msg;
1349         struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
1350
1351         if (msg->hdr.msg_size < sizeof(*msg))
1352                 return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1353         if (handler_ctx->progress_func) {
1354                 handler_ctx->progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
1355                                            &msg->info);
1356         }
1357         return 0;
1358 }
1359
1360 static int
1361 msg_unmount_finished_handler(const void *_msg, void *_handler_ctx)
1362 {
1363         const struct msg_unmount_finished *msg = _msg;
1364         struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
1365
1366         DEBUG("Handling unmount finished message");
1367         if (msg->hdr.msg_size < sizeof(*msg))
1368                 return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1369         handler_ctx->status = msg->status;
1370         DEBUG("status is %d", handler_ctx->status);
1371         return MSG_BREAK_LOOP;
1372 }
1373
1374 static int
1375 unmount_timed_out_cb(void *_handler_ctx)
1376 {
1377         const struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
1378
1379         if (handler_ctx->daemon_pid == 0 ||
1380             (kill(handler_ctx->daemon_pid, 0) != 0 && errno == ESRCH))
1381         {
1382                 ERROR("The filesystem daemon has crashed!  Changes to the "
1383                       "WIM may not have been commited.");
1384                 return WIMLIB_ERR_FILESYSTEM_DAEMON_CRASHED;
1385         }
1386
1387         DEBUG("Filesystem daemon is still alive... "
1388               "Waiting another %d seconds", handler_ctx->hdr.timeout_seconds);
1389         return 0;
1390 }
1391
1392 static int
1393 daemon_timed_out_cb(void *_handler_ctx)
1394 {
1395         ERROR("Timed out waiting for unmount request! "
1396               "Changes to the mounted WIM will not be committed.");
1397         return WIMLIB_ERR_TIMEOUT;
1398 }
1399
1400 typedef int (*msg_handler_t)(const void *_msg, void *_handler_ctx);
1401
1402 struct msg_handler_callbacks {
1403         int (*timed_out)(void * _handler_ctx);
1404         msg_handler_t msg_handlers[MSG_TYPE_MAX];
1405 };
1406
1407 static const struct msg_handler_callbacks unmount_msg_handler_callbacks = {
1408         .timed_out = unmount_timed_out_cb,
1409         .msg_handlers = {
1410                 [MSG_TYPE_DAEMON_INFO] = msg_daemon_info_handler,
1411                 [MSG_TYPE_WRITE_STREAMS_PROGRESS] = msg_write_streams_progress_handler,
1412                 [MSG_TYPE_UNMOUNT_FINISHED] = msg_unmount_finished_handler,
1413         },
1414 };
1415
1416 static const struct msg_handler_callbacks daemon_msg_handler_callbacks = {
1417         .timed_out = daemon_timed_out_cb,
1418         .msg_handlers = {
1419                 [MSG_TYPE_UNMOUNT_REQUEST] = msg_unmount_request_handler,
1420         },
1421 };
1422
1423 static int
1424 receive_message(mqd_t mq,
1425                 struct msg_handler_context_hdr *handler_ctx,
1426                 const msg_handler_t msg_handlers[],
1427                 long mailbox_size, void *mailbox)
1428 {
1429         struct timeval now;
1430         struct timespec timeout;
1431         ssize_t bytes_received;
1432         struct unmount_msg_hdr *hdr;
1433         int ret;
1434
1435         gettimeofday(&now, NULL);
1436         timeout.tv_sec = now.tv_sec + handler_ctx->timeout_seconds;
1437         timeout.tv_nsec = now.tv_usec * 1000;
1438
1439         bytes_received = mq_timedreceive(mq, mailbox,
1440                                          mailbox_size, NULL, &timeout);
1441         hdr = mailbox;
1442         if (bytes_received == -1) {
1443                 if (errno == ETIMEDOUT) {
1444                         ret = WIMLIB_ERR_TIMEOUT;
1445                 } else {
1446                         ERROR_WITH_ERRNO("mq_timedreceive()");
1447                         ret = WIMLIB_ERR_MQUEUE;
1448                 }
1449         } else if (bytes_received < sizeof(*hdr) ||
1450                    bytes_received != hdr->msg_size) {
1451                 ret = WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1452         } else if (WIMLIB_VERSION_CODE < hdr->min_version) {
1453                 /*ERROR("Cannot understand the received message. "*/
1454                       /*"Please upgrade wimlib to at least v%d.%d.%d",*/
1455                       /*WIMLIB_GET_MAJOR_VERSION(hdr->min_version),*/
1456                       /*WIMLIB_GET_MINOR_VERSION(hdr->min_version),*/
1457                       /*WIMLIB_GET_PATCH_VERSION(hdr->min_version));*/
1458                 ret = MSG_VERSION_TOO_HIGH;
1459         } else if (hdr->msg_type >= MSG_TYPE_MAX) {
1460                 ret = WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1461         } else if (msg_handlers[hdr->msg_type] == NULL) {
1462                 ret = WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
1463         } else {
1464                 ret = msg_handlers[hdr->msg_type](mailbox, handler_ctx);
1465         }
1466         return ret;
1467 }
1468
1469 static int
1470 message_loop(mqd_t mq,
1471              const struct msg_handler_callbacks *callbacks,
1472              struct msg_handler_context_hdr *handler_ctx)
1473 {
1474         static const size_t MAX_MSG_SIZE = 512;
1475         long msgsize;
1476         void *mailbox;
1477         int ret;
1478
1479         DEBUG("Entering message loop");
1480
1481         ret = get_mailbox(mq, MAX_MSG_SIZE, &msgsize, &mailbox);
1482         if (ret != 0)
1483                 return ret;
1484         while (1) {
1485                 ret = receive_message(mq, handler_ctx,
1486                                       callbacks->msg_handlers,
1487                                       msgsize, mailbox);
1488                 if (ret == 0 || ret == MSG_VERSION_TOO_HIGH) {
1489                         continue;
1490                 } else if (ret == MSG_BREAK_LOOP) {
1491                         ret = 0;
1492                         break;
1493                 } else if (ret == WIMLIB_ERR_TIMEOUT) {
1494                         if (callbacks->timed_out)
1495                                 ret = callbacks->timed_out(handler_ctx);
1496                         if (ret == 0)
1497                                 continue;
1498                         else
1499                                 break;
1500                 } else {
1501                         ERROR_WITH_ERRNO("Error communicating with "
1502                                          "filesystem daemon");
1503                         break;
1504                 }
1505         }
1506         FREE(mailbox);
1507         DEBUG("Exiting message loop");
1508         return ret;
1509 }
1510
1511 /* Execute `fusermount -u', which is installed setuid root, to unmount the WIM.
1512  *
1513  * FUSE does not yet implement synchronous unmounts.  This means that fusermount
1514  * -u will return before the filesystem daemon returns from wimfs_destroy().
1515  *  This is partly what we want, because we need to send a message from this
1516  *  process to the filesystem daemon telling whether --commit was specified or
1517  *  not.  However, after that, the unmount process must wait for the filesystem
1518  *  daemon to finish writing the WIM file.
1519  */
1520 static int
1521 execute_fusermount(const char *dir, bool lazy)
1522 {
1523         pid_t pid;
1524         int ret;
1525         int status;
1526
1527         pid = fork();
1528         if (pid == -1) {
1529                 ERROR_WITH_ERRNO("Failed to fork()");
1530                 return WIMLIB_ERR_FORK;
1531         }
1532         if (pid == 0) {
1533                 /* Child */
1534                 char *argv[10];
1535                 char **argp = argv;
1536                 *argp++ = "fusermount";
1537                 if (lazy)
1538                         *argp++ = "-z";
1539                 *argp++ = "-u";
1540                 *argp++ = (char*)dir;
1541                 *argp = NULL;
1542                 execvp("fusermount", argv);
1543                 ERROR_WITH_ERRNO("Failed to execute `fusermount'");
1544                 exit(WIMLIB_ERR_FUSERMOUNT);
1545         }
1546
1547         /* Parent */
1548         ret = waitpid(pid, &status, 0);
1549         if (ret == -1) {
1550                 ERROR_WITH_ERRNO("Failed to wait for fusermount process to "
1551                                  "terminate");
1552                 return WIMLIB_ERR_FUSERMOUNT;
1553         }
1554
1555         if (!WIFEXITED(status)) {
1556                 ERROR("'fusermount' did not terminate normally!");
1557                 return WIMLIB_ERR_FUSERMOUNT;
1558         }
1559
1560         status = WEXITSTATUS(status);
1561
1562         if (status == 0)
1563                 return 0;
1564
1565         if (status != WIMLIB_ERR_FUSERMOUNT)
1566                 return WIMLIB_ERR_FUSERMOUNT;
1567
1568         /* Try again, but with the `umount' program.  This is required on other
1569          * FUSE implementations such as FreeBSD's that do not have a
1570          * `fusermount' program. */
1571         ERROR("Falling back to 'umount'.  Note: you may need to be "
1572               "root for this to work");
1573         pid = fork();
1574         if (pid == -1) {
1575                 ERROR_WITH_ERRNO("Failed to fork()");
1576                 return WIMLIB_ERR_FORK;
1577         }
1578         if (pid == 0) {
1579                 /* Child */
1580                 char *argv[10];
1581                 char **argp = argv;
1582                 *argp++ = "umount";
1583                 if (lazy)
1584                         *argp++ = "-l";
1585                 *argp++ = (char*)dir;
1586                 *argp = NULL;
1587                 execvp("umount", argv);
1588                 ERROR_WITH_ERRNO("Failed to execute `umount'");
1589                 exit(WIMLIB_ERR_FUSERMOUNT);
1590         }
1591
1592         /* Parent */
1593         ret = waitpid(pid, &status, 0);
1594         if (ret == -1) {
1595                 ERROR_WITH_ERRNO("Failed to wait for `umount' process to "
1596                                  "terminate");
1597                 return WIMLIB_ERR_FUSERMOUNT;
1598         }
1599
1600         if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
1601                 ERROR("`umount' did not successfully complete");
1602                 return WIMLIB_ERR_FUSERMOUNT;
1603         }
1604
1605         return 0;
1606 }
1607
1608 static int
1609 wimfs_chmod(const char *path, mode_t mask)
1610 {
1611         struct wim_dentry *dentry;
1612         struct wimfs_context *ctx = wimfs_get_context();
1613         int ret;
1614
1615         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1616                 return -EPERM;
1617
1618         ret = wim_pathname_to_stream(ctx->wim, path, LOOKUP_FLAG_DIRECTORY_OK,
1619                                      &dentry, NULL, NULL);
1620         if (ret)
1621                 return ret;
1622
1623         ret = inode_set_unix_data(dentry->d_inode, ctx->default_uid,
1624                                   ctx->default_gid, mask,
1625                                   ctx->wim->lookup_table, UNIX_DATA_MODE);
1626         return ret ? -ENOMEM : 0;
1627 }
1628
1629 static int
1630 wimfs_chown(const char *path, uid_t uid, gid_t gid)
1631 {
1632         struct wim_dentry *dentry;
1633         struct wimfs_context *ctx = wimfs_get_context();
1634         int ret;
1635
1636         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1637                 return -EPERM;
1638
1639         ret = wim_pathname_to_stream(ctx->wim, path, LOOKUP_FLAG_DIRECTORY_OK,
1640                                      &dentry, NULL, NULL);
1641         if (ret)
1642                 return ret;
1643
1644         ret = inode_set_unix_data(dentry->d_inode, uid, gid,
1645                                   inode_default_unix_mode(dentry->d_inode),
1646                                   ctx->wim->lookup_table,
1647                                   UNIX_DATA_UID | UNIX_DATA_GID);
1648         return ret ? -ENOMEM : 0;
1649 }
1650
1651 /* Called when the filesystem is unmounted. */
1652 static void
1653 wimfs_destroy(void *p)
1654 {
1655         struct wimfs_context *wimfs_ctx = wimfs_get_context();
1656         if (open_message_queues(wimfs_ctx, true) == 0) {
1657                 struct daemon_msg_handler_context handler_ctx = {
1658                         .hdr = {
1659                                 .timeout_seconds = 5,
1660                         },
1661                         .wimfs_ctx = wimfs_ctx,
1662                 };
1663                 message_loop(wimfs_ctx->unmount_to_daemon_mq,
1664                              &daemon_msg_handler_callbacks,
1665                              &handler_ctx.hdr);
1666         }
1667 }
1668
1669 static int
1670 wimfs_fgetattr(const char *path, struct stat *stbuf,
1671                struct fuse_file_info *fi)
1672 {
1673         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
1674         return inode_to_stbuf(fd->f_inode, fd->f_lte, stbuf);
1675 }
1676
1677 static int
1678 wimfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
1679 {
1680         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
1681         int ret = ftruncate(fd->staging_fd.fd, size);
1682         if (ret)
1683                 return -errno;
1684         touch_inode(fd->f_inode);
1685         fd->f_lte->size = size;
1686         return 0;
1687 }
1688
1689 /*
1690  * Fills in a `struct stat' that corresponds to a file or directory in the WIM.
1691  */
1692 static int
1693 wimfs_getattr(const char *path, struct stat *stbuf)
1694 {
1695         struct wim_dentry *dentry;
1696         struct wim_lookup_table_entry *lte;
1697         int ret;
1698         struct wimfs_context *ctx = wimfs_get_context();
1699
1700         ret = wim_pathname_to_stream(ctx->wim, path,
1701                                      get_lookup_flags(ctx) |
1702                                         LOOKUP_FLAG_DIRECTORY_OK,
1703                                      &dentry, &lte, NULL);
1704         if (ret != 0)
1705                 return ret;
1706         return inode_to_stbuf(dentry->d_inode, lte, stbuf);
1707 }
1708
1709 #ifdef ENABLE_XATTR
1710 /* Read an alternate data stream through the XATTR interface, or get its size */
1711 static int
1712 wimfs_getxattr(const char *path, const char *name, char *value,
1713                size_t size)
1714 {
1715         int ret;
1716         struct wim_inode *inode;
1717         struct wim_ads_entry *ads_entry;
1718         u64 stream_size;
1719         struct wim_lookup_table_entry *lte;
1720         struct wimfs_context *ctx = wimfs_get_context();
1721
1722         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1723                 return -ENOTSUP;
1724
1725         if (strlen(name) <= 5 || memcmp(name, "user.", 5) != 0)
1726                 return -ENOATTR;
1727         name += 5;
1728
1729         inode = wim_pathname_to_inode(ctx->wim, path);
1730         if (!inode)
1731                 return -errno;
1732
1733         ads_entry = inode_get_ads_entry(inode, name, NULL);
1734         if (!ads_entry)
1735                 return -ENOATTR;
1736
1737         lte = ads_entry->lte;
1738         stream_size = lte->size;
1739
1740         if (size == 0)
1741                 return stream_size;
1742
1743         if (stream_size > size)
1744                 return -ERANGE;
1745
1746         ret = read_full_stream_into_buf(lte, value);
1747         if (ret) {
1748                 if (errno)
1749                         return -errno;
1750                 else
1751                         return -EIO;
1752         }
1753         return stream_size;
1754 }
1755 #endif
1756
1757 /* Create a hard link */
1758 static int
1759 wimfs_link(const char *to, const char *from)
1760 {
1761         struct wim_dentry *from_dentry, *from_dentry_parent;
1762         const char *link_name;
1763         struct wim_inode *inode;
1764         WIMStruct *wim = wimfs_get_WIMStruct();
1765         int ret;
1766
1767         inode = wim_pathname_to_inode(wim, to);
1768         if (!inode)
1769                 return -errno;
1770
1771         if (inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
1772                                    FILE_ATTRIBUTE_REPARSE_POINT))
1773                 return -EPERM;
1774
1775         from_dentry_parent = get_parent_dentry(wim, from, WIMLIB_CASE_SENSITIVE);
1776         if (!from_dentry_parent)
1777                 return -errno;
1778         if (!dentry_is_directory(from_dentry_parent))
1779                 return -ENOTDIR;
1780
1781         link_name = path_basename(from);
1782         if (get_dentry_child_with_name(from_dentry_parent, link_name,
1783                                        WIMLIB_CASE_SENSITIVE))
1784                 return -EEXIST;
1785
1786         ret = new_dentry(link_name, &from_dentry);
1787         if (ret)
1788                 return -ENOMEM;
1789
1790         inode->i_nlink++;
1791         inode_ref_streams(inode);
1792         from_dentry->d_inode = inode;
1793         inode_add_dentry(from_dentry, inode);
1794         dentry_add_child(from_dentry_parent, from_dentry);
1795         return 0;
1796 }
1797
1798 #ifdef ENABLE_XATTR
1799 static int
1800 wimfs_listxattr(const char *path, char *list, size_t size)
1801 {
1802         size_t needed_size;
1803         struct wim_inode *inode;
1804         struct wimfs_context *ctx = wimfs_get_context();
1805         u16 i;
1806         char *p;
1807         bool size_only = (size == 0);
1808
1809         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1810                 return -ENOTSUP;
1811
1812         /* List alternate data streams, or get the list size */
1813
1814         inode = wim_pathname_to_inode(ctx->wim, path);
1815         if (!inode)
1816                 return -errno;
1817
1818         p = list;
1819         for (i = 0; i < inode->i_num_ads; i++) {
1820
1821                 if (!ads_entry_is_named_stream(&inode->i_ads_entries[i]))
1822                         continue;
1823
1824                 char *stream_name_mbs;
1825                 size_t stream_name_mbs_nbytes;
1826                 int ret;
1827
1828                 ret = utf16le_to_tstr(inode->i_ads_entries[i].stream_name,
1829                                       inode->i_ads_entries[i].stream_name_nbytes,
1830                                       &stream_name_mbs,
1831                                       &stream_name_mbs_nbytes);
1832                 if (ret)
1833                         return -errno;
1834
1835                 needed_size = stream_name_mbs_nbytes + 6;
1836                 if (!size_only) {
1837                         if (needed_size > size) {
1838                                 FREE(stream_name_mbs);
1839                                 return -ERANGE;
1840                         }
1841                         sprintf(p, "user.%s", stream_name_mbs);
1842                         size -= needed_size;
1843                 }
1844                 p += needed_size;
1845                 FREE(stream_name_mbs);
1846         }
1847         return p - list;
1848 }
1849 #endif
1850
1851
1852 /* Create a directory in the WIM image. */
1853 static int
1854 wimfs_mkdir(const char *path, mode_t mode)
1855 {
1856         return create_dentry(fuse_get_context(), path, mode | S_IFDIR,
1857                              FILE_ATTRIBUTE_DIRECTORY, NULL);
1858 }
1859
1860 /* Create a regular file or alternate data stream in the WIM image. */
1861 static int
1862 wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
1863 {
1864         const char *stream_name;
1865         struct fuse_context *fuse_ctx = fuse_get_context();
1866         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1867
1868         if (!S_ISREG(mode))
1869                 return -EPERM;
1870
1871         if ((wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
1872              && (stream_name = path_stream_name(path))) {
1873                 /* Make an alternate data stream */
1874                 struct wim_ads_entry *new_entry;
1875                 struct wim_inode *inode;
1876
1877                 char *p = (char*)stream_name - 1;
1878                 wimlib_assert(*p == ':');
1879                 *p = '\0';
1880
1881                 inode = wim_pathname_to_inode(wimfs_ctx->wim, path);
1882                 if (!inode)
1883                         return -errno;
1884                 if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)
1885                         return -ENOENT;
1886                 if (inode_get_ads_entry(inode, stream_name, NULL))
1887                         return -EEXIST;
1888                 new_entry = inode_add_ads(inode, stream_name);
1889                 if (!new_entry)
1890                         return -ENOMEM;
1891                 return 0;
1892         } else {
1893                 /* Make a normal file (not an alternate data stream) */
1894                 return create_dentry(fuse_ctx, path, mode | S_IFREG,
1895                                      FILE_ATTRIBUTE_NORMAL, NULL);
1896         }
1897 }
1898
1899 /* Open a file.  */
1900 static int
1901 wimfs_open(const char *path, struct fuse_file_info *fi)
1902 {
1903         struct wim_dentry *dentry;
1904         struct wim_lookup_table_entry *lte;
1905         int ret;
1906         struct wimfs_fd *fd;
1907         struct wim_inode *inode;
1908         u16 stream_idx;
1909         u32 stream_id;
1910         struct wimfs_context *ctx = wimfs_get_context();
1911         struct wim_lookup_table_entry **back_ptr;
1912
1913         ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
1914                                      &dentry, &lte, &stream_idx);
1915         if (ret)
1916                 return ret;
1917
1918         inode = dentry->d_inode;
1919
1920         if (stream_idx == 0) {
1921                 stream_id = 0;
1922                 back_ptr = &inode->i_lte;
1923         } else {
1924                 stream_id = inode->i_ads_entries[stream_idx - 1].stream_id;
1925                 back_ptr = &inode->i_ads_entries[stream_idx - 1].lte;
1926         }
1927
1928         /* The file resource may be in the staging directory (read-write mounts
1929          * only) or in the WIM.  If it's in the staging directory, we need to
1930          * open a native file descriptor for the corresponding file.  Otherwise,
1931          * we can read the file resource directly from the WIM file if we are
1932          * opening it read-only, but we need to extract the resource to the
1933          * staging directory if we are opening it writable. */
1934
1935         if (flags_writable(fi->flags) &&
1936             (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) {
1937                 u64 size = (lte) ? lte->size : 0;
1938                 ret = extract_resource_to_staging_dir(inode, stream_id,
1939                                                       &lte, size, ctx);
1940                 if (ret)
1941                         return ret;
1942                 *back_ptr = lte;
1943         }
1944
1945         ret = alloc_wimfs_fd(inode, stream_id, lte, &fd);
1946         if (ret)
1947                 return ret;
1948
1949         if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
1950                 int raw_fd;
1951
1952                 raw_fd = open(lte->staging_file_name, fi->flags);
1953                 if (raw_fd < 0) {
1954                         int errno_save = errno;
1955                         close_wimfs_fd(fd);
1956                         return -errno_save;
1957                 }
1958                 filedes_init(&fd->staging_fd, raw_fd);
1959         }
1960         fi->fh = (uintptr_t)fd;
1961         return 0;
1962 }
1963
1964 /* Opens a directory. */
1965 static int
1966 wimfs_opendir(const char *path, struct fuse_file_info *fi)
1967 {
1968         struct wim_inode *inode;
1969         int ret;
1970         struct wimfs_fd *fd = NULL;
1971         struct wimfs_context *ctx = wimfs_get_context();
1972         WIMStruct *wim = ctx->wim;
1973
1974         inode = wim_pathname_to_inode(wim, path);
1975         if (!inode)
1976                 return -errno;
1977         if (!inode_is_directory(inode))
1978                 return -ENOTDIR;
1979         ret = alloc_wimfs_fd(inode, 0, NULL, &fd);
1980         fi->fh = (uintptr_t)fd;
1981         return ret;
1982 }
1983
1984
1985 /*
1986  * Read data from a file in the WIM or in the staging directory.
1987  */
1988 static int
1989 wimfs_read(const char *path, char *buf, size_t size,
1990            off_t offset, struct fuse_file_info *fi)
1991 {
1992         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
1993         ssize_t ret;
1994         u64 stream_size;
1995
1996         if (!fd)
1997                 return -EBADF;
1998
1999         if (size == 0)
2000                 return 0;
2001
2002         if (fd->f_lte)
2003                 stream_size = fd->f_lte->size;
2004         else
2005                 stream_size = 0;
2006
2007         if (offset > stream_size)
2008                 return -EOVERFLOW;
2009
2010         size = min(size, stream_size - offset);
2011         if (size == 0)
2012                 return 0;
2013
2014         switch (fd->f_lte->resource_location) {
2015         case RESOURCE_IN_STAGING_FILE:
2016                 ret = raw_pread(&fd->staging_fd, buf, size, offset);
2017                 if (ret == -1)
2018                         ret = -errno;
2019                 break;
2020         case RESOURCE_IN_WIM:
2021                 if (read_partial_wim_stream_into_buf(fd->f_lte, size,
2022                                                      offset, buf))
2023                         ret = errno ? -errno : -EIO;
2024                 else
2025                         ret = size;
2026                 break;
2027         case RESOURCE_IN_ATTACHED_BUFFER:
2028                 memcpy(buf, fd->f_lte->attached_buffer + offset, size);
2029                 ret = size;
2030                 break;
2031         default:
2032                 ERROR("Invalid resource location");
2033                 ret = -EIO;
2034                 break;
2035         }
2036         return ret;
2037 }
2038
2039 /* Fills in the entries of the directory specified by @path using the
2040  * FUSE-provided function @filler.  */
2041 static int
2042 wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
2043               off_t offset, struct fuse_file_info *fi)
2044 {
2045         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
2046         struct wim_inode *inode;
2047         struct wim_dentry *child;
2048         int ret;
2049
2050         if (!fd)
2051                 return -EBADF;
2052
2053         inode = fd->f_inode;
2054
2055         ret = filler(buf, ".", NULL, 0);
2056         if (ret)
2057                 return ret;
2058         ret = filler(buf, "..", NULL, 0);
2059         if (ret)
2060                 return ret;
2061
2062         for_inode_child(child, inode) {
2063                 char *file_name_mbs;
2064                 size_t file_name_mbs_nbytes;
2065
2066                 ret = utf16le_to_tstr(child->file_name,
2067                                       child->file_name_nbytes,
2068                                       &file_name_mbs,
2069                                       &file_name_mbs_nbytes);
2070                 if (ret)
2071                         return -errno;
2072
2073                 ret = filler(buf, file_name_mbs, NULL, 0);
2074                 FREE(file_name_mbs);
2075                 if (ret)
2076                         return ret;
2077         }
2078         return 0;
2079 }
2080
2081
2082 static int
2083 wimfs_readlink(const char *path, char *buf, size_t buf_len)
2084 {
2085         struct wimfs_context *ctx = wimfs_get_context();
2086         struct wim_inode *inode = wim_pathname_to_inode(ctx->wim, path);
2087         int ret;
2088         if (!inode)
2089                 return -errno;
2090         if (!inode_is_symlink(inode))
2091                 return -EINVAL;
2092         if (buf_len == 0)
2093                 return -EINVAL;
2094         ret = wim_inode_readlink(inode, buf, buf_len - 1, NULL);
2095         if (ret >= 0) {
2096                 wimlib_assert(ret <= buf_len - 1);
2097                 buf[ret] = '\0';
2098                 ret = 0;
2099         } else if (ret == -ENAMETOOLONG) {
2100                 buf[buf_len - 1] = '\0';
2101         }
2102         return ret;
2103 }
2104
2105 /* Close a file. */
2106 static int
2107 wimfs_release(const char *path, struct fuse_file_info *fi)
2108 {
2109         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
2110         return close_wimfs_fd(fd);
2111 }
2112
2113 /* Close a directory */
2114 static int
2115 wimfs_releasedir(const char *path, struct fuse_file_info *fi)
2116 {
2117         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
2118         return close_wimfs_fd(fd);
2119 }
2120
2121 #ifdef ENABLE_XATTR
2122 /* Remove an alternate data stream through the XATTR interface */
2123 static int
2124 wimfs_removexattr(const char *path, const char *name)
2125 {
2126         struct wim_inode *inode;
2127         struct wim_ads_entry *ads_entry;
2128         u16 ads_idx;
2129         struct wimfs_context *ctx = wimfs_get_context();
2130
2131         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
2132                 return -ENOTSUP;
2133
2134         if (strlen(name) < 5 || memcmp(name, "user.", 5) != 0)
2135                 return -ENOATTR;
2136         name += 5;
2137
2138         inode = wim_pathname_to_inode(ctx->wim, path);
2139         if (!inode)
2140                 return -errno;
2141
2142         ads_entry = inode_get_ads_entry(inode, name, &ads_idx);
2143         if (!ads_entry)
2144                 return -ENOATTR;
2145         inode_remove_ads(inode, ads_idx, ctx->wim->lookup_table);
2146         return 0;
2147 }
2148 #endif
2149
2150 /* Renames a file or directory.  See rename (3) */
2151 static int
2152 wimfs_rename(const char *from, const char *to)
2153 {
2154         return rename_wim_path(wimfs_get_WIMStruct(), from, to,
2155                                WIMLIB_CASE_SENSITIVE, NULL);
2156 }
2157
2158 /* Remove a directory */
2159 static int
2160 wimfs_rmdir(const char *path)
2161 {
2162         struct wim_dentry *dentry;
2163         WIMStruct *wim = wimfs_get_WIMStruct();
2164
2165         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
2166         if (!dentry)
2167                 return -errno;
2168
2169         if (!dentry_is_directory(dentry))
2170                 return -ENOTDIR;
2171
2172         if (dentry_has_children(dentry))
2173                 return -ENOTEMPTY;
2174
2175         remove_dentry(dentry, wim->lookup_table);
2176         return 0;
2177 }
2178
2179 #ifdef ENABLE_XATTR
2180 /* Write an alternate data stream through the XATTR interface */
2181 static int
2182 wimfs_setxattr(const char *path, const char *name,
2183                const char *value, size_t size, int flags)
2184 {
2185         struct wim_ads_entry *existing_ads_entry;
2186         struct wim_inode *inode;
2187         u16 ads_idx;
2188         struct wimfs_context *ctx = wimfs_get_context();
2189         int ret;
2190
2191         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
2192                 return -ENOTSUP;
2193
2194         if (strlen(name) <= 5 || memcmp(name, "user.", 5) != 0)
2195                 return -ENOATTR;
2196         name += 5;
2197
2198         inode = wim_pathname_to_inode(ctx->wim, path);
2199         if (!inode)
2200                 return -errno;
2201
2202         existing_ads_entry = inode_get_ads_entry(inode, name, &ads_idx);
2203         if (existing_ads_entry) {
2204                 if (flags & XATTR_CREATE)
2205                         return -EEXIST;
2206         } else {
2207                 if (flags & XATTR_REPLACE)
2208                         return -ENOATTR;
2209         }
2210
2211         ret = inode_add_ads_with_data(inode, name, value,
2212                                       size, ctx->wim->lookup_table);
2213         if (ret == 0) {
2214                 if (existing_ads_entry)
2215                         inode_remove_ads(inode, ads_idx, ctx->wim->lookup_table);
2216         } else {
2217                 ret = -ENOMEM;
2218         }
2219         return ret;
2220 }
2221 #endif
2222
2223 static int
2224 wimfs_symlink(const char *to, const char *from)
2225 {
2226         struct fuse_context *fuse_ctx = fuse_get_context();
2227         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
2228         struct wim_dentry *dentry;
2229         int ret;
2230
2231         ret = create_dentry(fuse_ctx, from, S_IFLNK | 0777,
2232                             FILE_ATTRIBUTE_REPARSE_POINT, &dentry);
2233         if (ret == 0) {
2234                 dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
2235                 ret = wim_inode_set_symlink(dentry->d_inode, to,
2236                                             wimfs_ctx->wim->lookup_table);
2237                 if (ret) {
2238                         remove_dentry(dentry, wimfs_ctx->wim->lookup_table);
2239                         if (ret == WIMLIB_ERR_NOMEM)
2240                                 ret = -ENOMEM;
2241                         else
2242                                 ret = -EIO;
2243                 }
2244         }
2245         return ret;
2246 }
2247
2248
2249 /* Reduce the size of a file */
2250 static int
2251 wimfs_truncate(const char *path, off_t size)
2252 {
2253         struct wim_dentry *dentry;
2254         struct wim_lookup_table_entry *lte;
2255         int ret;
2256         u16 stream_idx;
2257         u32 stream_id;
2258         struct wim_inode *inode;
2259         struct wimfs_context *ctx = wimfs_get_context();
2260
2261         ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
2262                                      &dentry, &lte, &stream_idx);
2263
2264         if (ret != 0)
2265                 return ret;
2266
2267         if (lte == NULL && size == 0)
2268                 return 0;
2269
2270         if (lte != NULL && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
2271                 ret = truncate(lte->staging_file_name, size);
2272                 if (ret)
2273                         ret = -errno;
2274                 else
2275                         lte->size = size;
2276         } else {
2277                 /* File in WIM.  Extract it to the staging directory, but only
2278                  * the first @size bytes of it. */
2279                 struct wim_lookup_table_entry **back_ptr;
2280
2281                 inode = dentry->d_inode;
2282                 if (stream_idx == 0) {
2283                         stream_id = 0;
2284                         back_ptr = &inode->i_lte;
2285                 } else {
2286                         stream_id = inode->i_ads_entries[stream_idx - 1].stream_id;
2287                         back_ptr = &inode->i_ads_entries[stream_idx - 1].lte;
2288                 }
2289                 ret = extract_resource_to_staging_dir(inode, stream_id,
2290                                                       &lte, size, ctx);
2291                 *back_ptr = lte;
2292         }
2293         return ret;
2294 }
2295
2296 /* Unlink a non-directory or alternate data stream */
2297 static int
2298 wimfs_unlink(const char *path)
2299 {
2300         struct wim_dentry *dentry;
2301         struct wim_lookup_table_entry *lte;
2302         int ret;
2303         u16 stream_idx;
2304         struct wimfs_context *ctx = wimfs_get_context();
2305
2306         ret = wim_pathname_to_stream(ctx->wim, path, get_lookup_flags(ctx),
2307                                      &dentry, &lte, &stream_idx);
2308
2309         if (ret != 0)
2310                 return ret;
2311
2312         if (inode_stream_name_nbytes(dentry->d_inode, stream_idx) == 0)
2313                 remove_dentry(dentry, ctx->wim->lookup_table);
2314         else
2315                 inode_remove_ads(dentry->d_inode, stream_idx - 1,
2316                                  ctx->wim->lookup_table);
2317         return 0;
2318 }
2319
2320 #ifdef HAVE_UTIMENSAT
2321 /*
2322  * Change the timestamp on a file dentry.
2323  *
2324  * Note that alternate data streams do not have their own timestamps.
2325  */
2326 static int
2327 wimfs_utimens(const char *path, const struct timespec tv[2])
2328 {
2329         struct wim_inode *inode;
2330         WIMStruct *wim = wimfs_get_WIMStruct();
2331
2332         inode = wim_pathname_to_inode(wim, path);
2333         if (!inode)
2334                 return -errno;
2335
2336         if (tv[0].tv_nsec != UTIME_OMIT) {
2337                 if (tv[0].tv_nsec == UTIME_NOW)
2338                         inode->i_last_access_time = get_wim_timestamp();
2339                 else
2340                         inode->i_last_access_time = timespec_to_wim_timestamp(tv[0]);
2341         }
2342         if (tv[1].tv_nsec != UTIME_OMIT) {
2343                 if (tv[1].tv_nsec == UTIME_NOW)
2344                         inode->i_last_write_time = get_wim_timestamp();
2345                 else
2346                         inode->i_last_write_time = timespec_to_wim_timestamp(tv[1]);
2347         }
2348         return 0;
2349 }
2350 #else /* HAVE_UTIMENSAT */
2351 static int
2352 wimfs_utime(const char *path, struct utimbuf *times)
2353 {
2354         struct wim_inode *inode;
2355         WIMStruct *wim = wimfs_get_WIMStruct();
2356
2357         inode = wim_pathname_to_inode(wim, path);
2358         if (!inode)
2359                 return -errno;
2360
2361         inode->i_last_write_time = unix_timestamp_to_wim(times->modtime);
2362         inode->i_last_access_time = unix_timestamp_to_wim(times->actime);
2363         return 0;
2364 }
2365 #endif /* !HAVE_UTIMENSAT */
2366
2367 /* Writes to a file in the WIM filesystem.
2368  * It may be an alternate data stream, but here we don't even notice because we
2369  * just get a lookup table entry. */
2370 static int
2371 wimfs_write(const char *path, const char *buf, size_t size,
2372             off_t offset, struct fuse_file_info *fi)
2373 {
2374         struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
2375         int ret;
2376
2377         if (!fd)
2378                 return -EBADF;
2379
2380         wimlib_assert(fd->f_lte != NULL);
2381         wimlib_assert(fd->f_lte->staging_file_name != NULL);
2382         wimlib_assert(filedes_valid(&fd->staging_fd));
2383         wimlib_assert(fd->f_inode != NULL);
2384
2385         /* Write the data. */
2386         ret = raw_pwrite(&fd->staging_fd, buf, size, offset);
2387         if (ret == -1)
2388                 return -errno;
2389
2390         /* Update file size */
2391         if (offset + size > fd->f_lte->size) {
2392                 DEBUG("Update file size %"PRIu64 " => %"PRIu64"",
2393                       fd->f_lte->size, offset + size);
2394                 fd->f_lte->size = offset + size;
2395         }
2396
2397         /* Update timestamps */
2398         touch_inode(fd->f_inode);
2399         return ret;
2400 }
2401
2402 static struct fuse_operations wimfs_operations = {
2403         .chmod       = wimfs_chmod,
2404         .chown       = wimfs_chown,
2405         .destroy     = wimfs_destroy,
2406         .fgetattr    = wimfs_fgetattr,
2407         .ftruncate   = wimfs_ftruncate,
2408         .getattr     = wimfs_getattr,
2409 #ifdef ENABLE_XATTR
2410         .getxattr    = wimfs_getxattr,
2411 #endif
2412         .link        = wimfs_link,
2413 #ifdef ENABLE_XATTR
2414         .listxattr   = wimfs_listxattr,
2415 #endif
2416         .mkdir       = wimfs_mkdir,
2417         .mknod       = wimfs_mknod,
2418         .open        = wimfs_open,
2419         .opendir     = wimfs_opendir,
2420         .read        = wimfs_read,
2421         .readdir     = wimfs_readdir,
2422         .readlink    = wimfs_readlink,
2423         .release     = wimfs_release,
2424         .releasedir  = wimfs_releasedir,
2425 #ifdef ENABLE_XATTR
2426         .removexattr = wimfs_removexattr,
2427 #endif
2428         .rename      = wimfs_rename,
2429         .rmdir       = wimfs_rmdir,
2430 #ifdef ENABLE_XATTR
2431         .setxattr    = wimfs_setxattr,
2432 #endif
2433         .symlink     = wimfs_symlink,
2434         .truncate    = wimfs_truncate,
2435         .unlink      = wimfs_unlink,
2436 #ifdef HAVE_UTIMENSAT
2437         .utimens     = wimfs_utimens,
2438 #else
2439         .utime       = wimfs_utime,
2440 #endif
2441         .write       = wimfs_write,
2442
2443         /* wimfs keeps file descriptor structures (struct wimfs_fd), so there is
2444          * no need to have the file path provided on operations such as read()
2445          * where only the file descriptor is needed. */
2446 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
2447         .flag_nullpath_ok = 1,
2448 #endif
2449 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 9)
2450         .flag_nopath = 1,
2451         .flag_utime_omit_ok = 1,
2452 #endif
2453 };
2454
2455
2456 /* API function documented in wimlib.h  */
2457 WIMLIBAPI int
2458 wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
2459                    int mount_flags, const char *staging_dir)
2460 {
2461         int argc;
2462         char *argv[16];
2463         int ret;
2464         char *dir_copy;
2465         struct wim_image_metadata *imd;
2466         struct wimfs_context ctx;
2467         struct wim_inode *inode;
2468
2469         DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
2470               wim, image, dir, mount_flags);
2471
2472         if (!wim || !dir)
2473                 return WIMLIB_ERR_INVALID_PARAM;
2474
2475         if (mount_flags & ~(WIMLIB_MOUNT_FLAG_READWRITE |
2476                             WIMLIB_MOUNT_FLAG_DEBUG |
2477                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
2478                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
2479                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS |
2480                             WIMLIB_MOUNT_FLAG_UNIX_DATA |
2481                             WIMLIB_MOUNT_FLAG_ALLOW_OTHER))
2482                 return WIMLIB_ERR_INVALID_PARAM;
2483
2484         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2485                 ret = can_delete_from_wim(wim);
2486                 if (ret)
2487                         return ret;
2488         }
2489
2490         ret = select_wim_image(wim, image);
2491         if (ret)
2492                 return ret;
2493
2494         DEBUG("Selected image %d", image);
2495
2496         imd = wim_get_current_image_metadata(wim);
2497
2498         if (imd->modified) {
2499                 /* wimfs_read() only supports a limited number of stream
2500                  * locations, not including RESOURCE_IN_FILE_ON_DISK,
2501                  * RESOURCE_IN_NTFS_VOLUME, etc. that might appear if files were
2502                  * added to the WIM image.  */
2503                 ERROR("Cannot mount an image with newly added files!");
2504                 return WIMLIB_ERR_INVALID_PARAM;
2505         }
2506
2507         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2508                 ret = lock_wim(wim, wim->in_fd.fd);
2509                 if (ret)
2510                         return ret;
2511         }
2512
2513         /* Use default stream interface if one was not specified */
2514         if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
2515                        WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
2516                        WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
2517                 mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
2518
2519         DEBUG("Initializing struct wimfs_context");
2520         init_wimfs_context(&ctx);
2521         ctx.wim = wim;
2522         ctx.mount_flags = mount_flags;
2523         ctx.image_inode_list = &imd->inode_list;
2524         ctx.default_uid = getuid();
2525         ctx.default_gid = getgid();
2526         wimlib_assert(list_empty(&imd->unhashed_streams));
2527         if (mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
2528                 ctx.default_lookup_flags = LOOKUP_FLAG_ADS_OK;
2529
2530         DEBUG("Unlinking message queues in case they already exist");
2531         ret = set_message_queue_names(&ctx, dir);
2532         if (ret)
2533                 goto out_unlock;
2534         unlink_message_queues(&ctx);
2535
2536         DEBUG("Preparing arguments to fuse_main()");
2537
2538         dir_copy = STRDUP(dir);
2539         if (!dir_copy) {
2540                 ret = WIMLIB_ERR_NOMEM;
2541                 goto out_free_message_queue_names;
2542         }
2543
2544         argc = 0;
2545         argv[argc++] = "wimlib";
2546         argv[argc++] = dir_copy;
2547
2548         /* disable multi-threaded operation */
2549         argv[argc++] = "-s";
2550
2551         if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
2552                 argv[argc++] = "-d";
2553
2554         /*
2555          * We provide the use_ino option to the FUSE mount because we are going
2556          * to assign inode numbers ourselves. */
2557         char optstring[256] =
2558                 "use_ino"
2559                 ",subtype=wimfs"
2560                 ",attr_timeout=0"
2561 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
2562                 ",hard_remove"
2563 #endif
2564                 ",default_permissions"
2565                 ;
2566         argv[argc++] = "-o";
2567         argv[argc++] = optstring;
2568         if ((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
2569                 /* Read-write mount.  Make the staging directory */
2570                 ret = make_staging_dir(&ctx, staging_dir);
2571                 if (ret)
2572                         goto out_free_dir_copy;
2573         } else {
2574                 /* Read-only mount */
2575                 strcat(optstring, ",ro");
2576         }
2577         if (mount_flags & WIMLIB_MOUNT_FLAG_ALLOW_OTHER)
2578                 strcat(optstring, ",allow_other");
2579         argv[argc] = NULL;
2580
2581 #ifdef ENABLE_DEBUG
2582         {
2583                 int i;
2584                 DEBUG("FUSE command line (argc = %d): ", argc);
2585                 for (i = 0; i < argc; i++) {
2586                         fputs(argv[i], stdout);
2587                         putchar(' ');
2588                 }
2589                 putchar('\n');
2590                 fflush(stdout);
2591         }
2592 #endif
2593
2594         /* Assign inode numbers.  Also, if a read-write mount was requested,
2595          * mark the dentry tree as modified, and add each stream referenced by
2596          * files in the image to a list and preemptively double the number of
2597          * references to each.  The latter is done to allow implementing the
2598          * WIMLIB_UNMOUNT_FLAG_NEW_IMAGE semantics.  */
2599         ctx.next_ino = 1;
2600         INIT_LIST_HEAD(&ctx.orig_stream_list);
2601         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2602                 imd->modified = 1;
2603                 image_for_each_inode(inode, imd) {
2604                         inode->i_ino = ctx.next_ino++;
2605                         for (unsigned i = 0; i <= inode->i_num_ads; i++) {
2606                                 struct wim_lookup_table_entry *lte;
2607
2608                                 lte = inode_stream_lte(inode, i, wim->lookup_table);
2609                                 if (lte)
2610                                         lte->out_refcnt = 0;
2611                         }
2612                 }
2613                 image_for_each_inode(inode, imd) {
2614                         for (unsigned i = 0; i <= inode->i_num_ads; i++) {
2615                                 struct wim_lookup_table_entry *lte;
2616
2617                                 lte = inode_stream_lte(inode, i,
2618                                                        wim->lookup_table);
2619                                 if (lte) {
2620                                         if (lte->out_refcnt == 0)
2621                                                 list_add(&lte->orig_stream_list,
2622                                                          &ctx.orig_stream_list);
2623                                         lte->out_refcnt += inode->i_nlink;
2624                                         lte->refcnt += inode->i_nlink;
2625                                 }
2626                         }
2627                 }
2628         } else {
2629                 image_for_each_inode(inode, imd)
2630                         inode->i_ino = ctx.next_ino++;
2631         }
2632
2633         DEBUG("(next_ino = %"PRIu64")", ctx.next_ino);
2634
2635         DEBUG("Calling fuse_main()");
2636
2637         ret = fuse_main(argc, argv, &wimfs_operations, &ctx);
2638
2639         DEBUG("Returned from fuse_main() (ret = %d)", ret);
2640
2641         if (ret) {
2642                 ret = WIMLIB_ERR_FUSE;
2643         } else {
2644                 if (ctx.have_status)
2645                         ret = ctx.status;
2646                 else
2647                         ret = WIMLIB_ERR_TIMEOUT;
2648         }
2649         if (ctx.daemon_to_unmount_mq != (mqd_t)(-1)) {
2650                 send_unmount_finished_msg(ctx.daemon_to_unmount_mq, ret);
2651                 close_message_queues(&ctx);
2652         }
2653
2654         release_extra_refcnts(&ctx);
2655
2656         /* Try to delete the staging directory if a deletion wasn't yet
2657          * attempted due to an earlier error */
2658         if (ctx.staging_dir_name)
2659                 delete_staging_dir(&ctx);
2660 out_free_dir_copy:
2661         FREE(dir_copy);
2662 out_unlock:
2663         wim->wim_locked = 0;
2664 out_free_message_queue_names:
2665         free_message_queue_names(&ctx);
2666         return ret;
2667 }
2668
2669 /* API function documented in wimlib.h  */
2670 WIMLIBAPI int
2671 wimlib_unmount_image(const char *dir, int unmount_flags,
2672                      wimlib_progress_func_t progress_func)
2673 {
2674         int ret;
2675         struct wimfs_context wimfs_ctx;
2676
2677         if (unmount_flags & ~(WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY |
2678                               WIMLIB_UNMOUNT_FLAG_COMMIT |
2679                               WIMLIB_UNMOUNT_FLAG_REBUILD |
2680                               WIMLIB_UNMOUNT_FLAG_RECOMPRESS |
2681                               WIMLIB_UNMOUNT_FLAG_LAZY |
2682                               WIMLIB_UNMOUNT_FLAG_NEW_IMAGE))
2683                 return WIMLIB_ERR_INVALID_PARAM;
2684
2685         init_wimfs_context(&wimfs_ctx);
2686
2687         ret = set_message_queue_names(&wimfs_ctx, dir);
2688         if (ret != 0)
2689                 goto out;
2690
2691         ret = open_message_queues(&wimfs_ctx, false);
2692         if (ret != 0)
2693                 goto out_free_message_queue_names;
2694
2695         ret = send_unmount_request_msg(wimfs_ctx.unmount_to_daemon_mq,
2696                                        unmount_flags,
2697                                        progress_func != NULL);
2698         if (ret != 0)
2699                 goto out_close_message_queues;
2700
2701         ret = execute_fusermount(dir, (unmount_flags & WIMLIB_UNMOUNT_FLAG_LAZY) != 0);
2702         if (ret != 0)
2703                 goto out_close_message_queues;
2704
2705         struct unmount_msg_handler_context handler_ctx = {
2706                 .hdr = {
2707                         .timeout_seconds = 5,
2708                 },
2709                 .daemon_pid = 0,
2710                 .progress_func = progress_func,
2711         };
2712
2713         ret = message_loop(wimfs_ctx.daemon_to_unmount_mq,
2714                            &unmount_msg_handler_callbacks,
2715                            &handler_ctx.hdr);
2716         if (ret == 0)
2717                 ret = handler_ctx.status;
2718 out_close_message_queues:
2719         close_message_queues(&wimfs_ctx);
2720 out_free_message_queue_names:
2721         free_message_queue_names(&wimfs_ctx);
2722 out:
2723         return ret;
2724 }
2725
2726 #else /* WITH_FUSE */
2727
2728
2729 static int
2730 mount_unsupported_error(void)
2731 {
2732 #if defined(__WIN32__)
2733         ERROR("Sorry-- Mounting WIM images is not supported on Windows!");
2734 #else
2735         ERROR("wimlib was compiled with --without-fuse, which disables support "
2736               "for mounting WIMs.");
2737 #endif
2738         return WIMLIB_ERR_UNSUPPORTED;
2739 }
2740
2741 WIMLIBAPI int
2742 wimlib_unmount_image(const tchar *dir, int unmount_flags,
2743                      wimlib_progress_func_t progress_func)
2744 {
2745         return mount_unsupported_error();
2746 }
2747
2748 WIMLIBAPI int
2749 wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
2750                    int mount_flags, const tchar *staging_dir)
2751 {
2752         return mount_unsupported_error();
2753 }
2754
2755 #endif /* !WITH_FUSE */