verify.c, buffer_io.h
[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 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 #include "wimlib_internal.h"
30
31 #ifdef WITH_FUSE
32
33 #include "sha1.h"
34 #include "lookup_table.h"
35 #include "xml.h"
36 #include "buffer_io.h"
37 #include "timestamp.h"
38 #include <limits.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <sys/wait.h>
42 #define FUSE_USE_VERSION 26
43 #include <errno.h>
44 #include <string.h>
45 #include <sys/time.h>
46 #include <fuse.h>
47 #include <ftw.h>
48 #include <mqueue.h>
49 #include <utime.h>
50
51 #ifdef ENABLE_XATTR
52 #include <attr/xattr.h>
53 #endif
54
55 /* File descriptor to a file open on the WIM filesystem. */
56 struct wimlib_fd {
57         struct inode *f_inode;
58         struct lookup_table_entry *f_lte;
59         int staging_fd;
60         u16 idx;
61         u32 stream_id;
62 };
63
64 struct wimfs_context {
65         /* The WIMStruct for the mounted WIM. */
66         WIMStruct *wim;
67
68         /* Name of the staging directory for a read-write mount.  Whenever a new file is
69          * created, it is done so in the staging directory.  Furthermore, whenever a
70          * file in the WIM is modified, it is extracted to the staging directory.  If
71          * changes are commited when the WIM is unmounted, the file resources are merged
72          * in from the staging directory when writing the new WIM. */
73         char *staging_dir_name;
74         size_t staging_dir_name_len;
75
76         /* Flags passed to wimlib_mount(). */
77         int mount_flags;
78
79         /* Next inode number to be assigned. */
80         u64 next_ino;
81
82         /* List of lookup table entries in the staging directory */
83         struct list_head staging_list;
84
85         /* Name and message queue descriptors for message queues between the filesystem
86          * daemon process and the unmount process.  These are used when the filesystem
87          * is unmounted and the process running wimlib_mount() (i.e. the `imagex
88          * unmount' command) needs to communicate with the filesystem daemon running
89          * fuse_main() (i.e. that spawned by the `imagex mount' or `imagex mountrw'
90          * commands */
91         char *unmount_to_daemon_mq_name;
92         char *daemon_to_unmount_mq_name;
93         mqd_t unmount_to_daemon_mq;
94         mqd_t daemon_to_unmount_mq;
95 };
96
97 static void init_wimfs_context(struct wimfs_context *ctx)
98 {
99         memset(ctx, 0, sizeof(*ctx));
100         ctx->unmount_to_daemon_mq = (mqd_t)-1;
101         ctx->daemon_to_unmount_mq = (mqd_t)-1;
102         INIT_LIST_HEAD(&ctx->staging_list);
103 }
104
105 static inline struct wimfs_context *wimfs_get_context()
106 {
107         return (struct wimfs_context*)fuse_get_context()->private_data;
108 }
109
110 static inline WIMStruct *wimfs_get_WIMStruct()
111 {
112         return wimfs_get_context()->wim;
113 }
114
115 static inline bool wimfs_ctx_readonly(const struct wimfs_context *ctx)
116 {
117         return (ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) == 0;
118 }
119
120 static inline int get_lookup_flags(const struct wimfs_context *ctx)
121 {
122         if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
123                 return LOOKUP_FLAG_ADS_OK;
124         else
125                 return 0;
126 }
127
128 /* Returns nonzero if write permission is requested on the file open flags */
129 static inline int flags_writable(int open_flags)
130 {
131         return open_flags & (O_RDWR | O_WRONLY);
132 }
133
134 /*
135  * Allocate a file descriptor for a stream.
136  *
137  * @inode:      inode containing the stream we're opening
138  * @stream_id:  ID of the stream we're opening
139  * @lte:        Lookup table entry for the stream (may be NULL)
140  * @fd_ret:     Return the allocated file descriptor if successful.
141  * @readonly:   True if this is a read-only mount.
142  *
143  * Return 0 iff successful or error code if unsuccessful.
144  */
145 static int alloc_wimlib_fd(struct inode *inode,
146                            u32 stream_id,
147                            struct lookup_table_entry *lte,
148                            struct wimlib_fd **fd_ret,
149                            bool readonly)
150 {
151         static const u16 fds_per_alloc = 8;
152         static const u16 max_fds = 0xffff;
153         int ret;
154
155         pthread_mutex_lock(&inode->i_mutex);
156
157         DEBUG("Allocating fd for stream ID %u from inode %lx (open = %u, allocated = %u)",
158               stream_id, inode->ino, inode->num_opened_fds,
159               inode->num_allocated_fds);
160
161         if (inode->num_opened_fds == inode->num_allocated_fds) {
162                 struct wimlib_fd **fds;
163                 u16 num_new_fds;
164
165                 if (inode->num_allocated_fds == max_fds) {
166                         ret = -EMFILE;
167                         goto out;
168                 }
169                 num_new_fds = min(fds_per_alloc,
170                                   max_fds - inode->num_allocated_fds);
171
172                 fds = REALLOC(inode->fds,
173                               (inode->num_allocated_fds + num_new_fds) *
174                                 sizeof(inode->fds[0]));
175                 if (!fds) {
176                         ret = -ENOMEM;
177                         goto out;
178                 }
179                 memset(&fds[inode->num_allocated_fds], 0,
180                        num_new_fds * sizeof(fds[0]));
181                 inode->fds = fds;
182                 inode->num_allocated_fds += num_new_fds;
183         }
184         for (u16 i = 0; ; i++) {
185                 if (!inode->fds[i]) {
186                         struct wimlib_fd *fd = CALLOC(1, sizeof(*fd));
187                         if (!fd) {
188                                 ret = -ENOMEM;
189                                 break;
190                         }
191                         fd->f_inode    = inode;
192                         fd->f_lte      = lte;
193                         fd->staging_fd = -1;
194                         fd->idx        = i;
195                         fd->stream_id  = stream_id;
196                         *fd_ret        = fd;
197                         inode->fds[i]  = fd;
198                         inode->num_opened_fds++;
199                         if (lte && !readonly)
200                                 lte->num_opened_fds++;
201                         DEBUG("Allocated fd (idx = %u)", fd->idx);
202                         ret = 0;
203                         break;
204                 }
205         }
206 out:
207         pthread_mutex_unlock(&inode->i_mutex);
208         return ret;
209 }
210
211 static void inode_put_fd(struct inode *inode, struct wimlib_fd *fd)
212 {
213         wimlib_assert(fd != NULL);
214         wimlib_assert(inode != NULL);
215
216         pthread_mutex_lock(&inode->i_mutex);
217
218         wimlib_assert(fd->f_inode == inode);
219         wimlib_assert(inode->num_opened_fds != 0);
220         wimlib_assert(fd->idx < inode->num_allocated_fds);
221         wimlib_assert(inode->fds[fd->idx] == fd);
222
223         inode->fds[fd->idx] = NULL;
224         FREE(fd);
225         if (--inode->num_opened_fds == 0 && inode->link_count == 0) {
226                 pthread_mutex_unlock(&inode->i_mutex);
227                 free_inode(inode);
228         } else {
229                 pthread_mutex_unlock(&inode->i_mutex);
230         }
231 }
232
233 static int lte_put_fd(struct lookup_table_entry *lte, struct wimlib_fd *fd)
234 {
235         wimlib_assert(fd != NULL);
236         wimlib_assert(fd->f_lte == lte);
237
238         if (!lte) /* Empty stream with no lookup table entry */
239                 return 0;
240
241         /* Close staging file descriptor if needed. */
242
243         if (lte->resource_location == RESOURCE_IN_STAGING_FILE
244              && fd->staging_fd != -1)
245         {
246                 if (close(fd->staging_fd) != 0) {
247                         ERROR_WITH_ERRNO("Failed to close staging file");
248                         return -errno;
249                 }
250         }
251         lte_decrement_num_opened_fds(lte);
252         return 0;
253 }
254
255 /* Close a file descriptor. */
256 static int close_wimlib_fd(struct wimlib_fd *fd)
257 {
258         int ret;
259         wimlib_assert(fd != NULL);
260         DEBUG("Closing fd (inode = %lu, opened = %u, allocated = %u)",
261               fd->f_inode->ino, fd->f_inode->num_opened_fds,
262               fd->f_inode->num_allocated_fds);
263         ret = lte_put_fd(fd->f_lte, fd);
264         if (ret != 0)
265                 return ret;
266
267         inode_put_fd(fd->f_inode, fd);
268         return 0;
269 }
270
271 /* Remove a dentry; i.e. remove a reference to the corresponding inode.
272  *
273  * If there are no remaining references to the inode either through dentries or
274  * open file descriptors, the inode is freed.  Otherwise, the inode is not
275  * removed, but the dentry is unlinked and freed.
276  *
277  * Either way, all lookup table entries referenced by the inode have their
278  * reference count decremented.  If a lookup table entry has no open file
279  * descriptors and no references remaining, it is freed, and the staging file is
280  * unlinked.
281  */
282 static void remove_dentry(struct dentry *dentry,
283                           struct lookup_table *lookup_table)
284 {
285         struct inode *inode = dentry->d_inode;
286         struct lookup_table_entry *lte;
287         unsigned i;
288
289         for (i = 0; i <= inode->num_ads; i++) {
290                 lte = inode_stream_lte_resolved(inode, i);
291                 if (lte)
292                         lte_decrement_refcnt(lte, lookup_table);
293         }
294         unlink_dentry(dentry);
295         put_dentry(dentry);
296 }
297
298 /* Creates a new staging file and returns its file descriptor opened for
299  * writing.
300  *
301  * @name_ret: A location into which the a pointer to the newly allocated name of
302  *                      the staging file is stored.
303  * @return:  The file descriptor for the new file.  Returns -1 and sets errno on
304  *              error, for any reason possible from the creat() function.
305  */
306 static int create_staging_file(char **name_ret, int open_flags,
307                                struct wimfs_context *ctx)
308 {
309         size_t name_len;
310         char *name;
311         struct stat stbuf;
312         int fd;
313         int errno_save;
314
315         name_len = ctx->staging_dir_name_len + 1 + SHA1_HASH_SIZE;
316         name = MALLOC(name_len + 1);
317         if (!name) {
318                 errno = ENOMEM;
319                 return -1;
320         }
321
322         do {
323
324                 memcpy(name, ctx->staging_dir_name, ctx->staging_dir_name_len);
325                 name[ctx->staging_dir_name_len] = '/';
326                 randomize_char_array_with_alnum(name + ctx->staging_dir_name_len + 1,
327                                                 SHA1_HASH_SIZE);
328                 name[name_len] = '\0';
329
330
331         /* Just in case, verify that the randomly generated name doesn't name an
332          * existing file, and try again if so  */
333         } while (stat(name, &stbuf) == 0);
334
335         if (errno != ENOENT)
336                 /* other error! */
337                 return -1;
338
339         /* doesn't exist--- ok */
340
341         DEBUG("Creating staging file `%s'", name);
342
343         fd = open(name, open_flags | O_CREAT | O_TRUNC, 0600);
344         if (fd == -1) {
345                 errno_save = errno;
346                 FREE(name);
347                 errno = errno_save;
348         } else {
349                 *name_ret = name;
350         }
351         return fd;
352 }
353
354 /*
355  * Extract a WIM resource to the staging directory.
356  *
357  * @inode:  Inode that contains the stream we are extracting
358  *
359  * @stream_id: Identifier for the stream (it stays constant even if the indices
360  * of the stream entries are changed)
361  *
362  * @lte: Pointer to pointer to the lookup table entry for the stream we need to
363  * extract, or NULL if there was no lookup table entry present for the stream
364  *
365  * @size:  Number of bytes of the stream we want to extract (this supports the
366  * wimfs_truncate() function).
367  */
368 static int extract_resource_to_staging_dir(struct inode *inode,
369                                            u32 stream_id,
370                                            struct lookup_table_entry **lte,
371                                            off_t size,
372                                            struct wimfs_context *ctx)
373 {
374         char *staging_file_name;
375         int ret;
376         int fd;
377         struct lookup_table_entry *old_lte, *new_lte;
378
379         DEBUG("Extracting resource to staging dir: inode %"PRIu64", "
380               "stream id %"PRIu32, inode->ino, stream_id);
381
382         old_lte = *lte;
383         fd = create_staging_file(&staging_file_name, O_WRONLY, ctx);
384         if (fd == -1)
385                 return -errno;
386
387         if (old_lte)
388                 ret = extract_wim_resource_to_fd(old_lte, fd, size);
389         else
390                 ret = 0;
391         if (ret != 0 || close(fd) != 0) {
392                 if (errno != 0)
393                         ret = -errno;
394                 else
395                         ret = -EIO;
396                 close(fd);
397                 goto out_delete_staging_file;
398         }
399
400         if (old_lte && inode->link_count == old_lte->refcnt) {
401                 /* The reference count of the existing lookup table
402                  * entry is the same as the link count of the inode that
403                  * contains the stream we're opening.  Therefore, ALL
404                  * the references to the lookup table entry correspond
405                  * to the stream we're trying to extract, so the lookup
406                  * table entry can be re-used.  */
407                 DEBUG("Re-using lookup table entry");
408                 lookup_table_unlink(ctx->wim->lookup_table, old_lte);
409                 new_lte = old_lte;
410         } else {
411                 if (old_lte) {
412                         /* There's an existing lookup table entry, but its
413                          * reference count is creater than the link count for
414                          * the inode containing a stream we're opening.
415                          * Therefore, we need to split the lookup table entry.
416                          * */
417                         wimlib_assert(old_lte->refcnt > inode->link_count);
418                         DEBUG("Splitting lookup table entry "
419                               "(inode->link_count = %u, old_lte->refcnt = %u)",
420                               inode->link_count, old_lte->refcnt);
421
422                 }
423
424                 new_lte = new_lookup_table_entry();
425                 if (!new_lte) {
426                         ret = -ENOMEM;
427                         goto out_delete_staging_file;
428                 }
429
430                 /* There may already be open file descriptors to this stream if
431                  * it's previously been opened read-only, but just now we're
432                  * opening it read-write.  Identify those file descriptors and
433                  * change their lookup table entry pointers to point to the new
434                  * lookup table entry, and open staging file descriptors for
435                  * them.
436                  *
437                  * At the same time, we need to count the number of these opened
438                  * file descriptors to the new lookup table entry.  If there's
439                  * an old lookup table entry, this number needs to be subtracted
440                  * from the fd's opened to the old entry. */
441                 for (u16 i = 0, j = 0; j < inode->num_opened_fds; i++) {
442                         struct wimlib_fd *fd = inode->fds[i];
443                         if (fd) {
444                                 if (fd->stream_id == stream_id) {
445                                         wimlib_assert(fd->f_lte == old_lte);
446                                         wimlib_assert(fd->staging_fd == -1);
447                                         fd->f_lte = new_lte;
448                                         new_lte->num_opened_fds++;
449                                         fd->staging_fd = open(staging_file_name, O_RDONLY);
450                                         if (fd->staging_fd == -1) {
451                                                 ret = -errno;
452                                                 goto out_revert_fd_changes;
453                                         }
454                                 }
455                                 j++;
456                         }
457                 }
458                 DEBUG("%hu fd's were already opened to the file we extracted",
459                       new_lte->num_opened_fds);
460                 if (old_lte) {
461                         old_lte->num_opened_fds -= new_lte->num_opened_fds;
462                         old_lte->refcnt -= inode->link_count;
463                 }
464         }
465
466         new_lte->resource_entry.original_size = size;
467         new_lte->refcnt                       = inode->link_count;
468         new_lte->resource_location            = RESOURCE_IN_STAGING_FILE;
469         new_lte->staging_file_name            = staging_file_name;
470         new_lte->lte_inode                    = inode;
471         random_hash(new_lte->hash);
472
473         if (stream_id == 0)
474                 inode->lte = new_lte;
475         else
476                 for (u16 i = 0; i < inode->num_ads; i++)
477                         if (inode->ads_entries[i].stream_id == stream_id)
478                                 inode->ads_entries[i].lte = new_lte;
479
480         lookup_table_insert(ctx->wim->lookup_table, new_lte);
481         list_add(&new_lte->staging_list, &ctx->staging_list);
482         *lte = new_lte;
483         return 0;
484 out_revert_fd_changes:
485         for (u16 i = 0, j = 0; j < new_lte->num_opened_fds; i++) {
486                 struct wimlib_fd *fd = inode->fds[i];
487                 if (fd && fd->stream_id == stream_id && fd->f_lte == new_lte) {
488                         fd->f_lte = old_lte;
489                         if (fd->staging_fd != -1) {
490                                 close(fd->staging_fd);
491                                 fd->staging_fd = -1;
492                         }
493                         j++;
494                 }
495         }
496         free_lookup_table_entry(new_lte);
497 out_delete_staging_file:
498         unlink(staging_file_name);
499         FREE(staging_file_name);
500         return ret;
501 }
502
503 /*
504  * Creates a randomly named staging directory and saves its name in the
505  * filesystem context structure.
506  */
507 static int make_staging_dir(struct wimfs_context *ctx,
508                             const char *user_prefix)
509 {
510         static const size_t random_suffix_len = 10;
511         static const char *common_suffix = ".staging";
512         static const size_t common_suffix_len = 8;
513
514         char *staging_dir_name = NULL;
515         size_t staging_dir_name_len;
516         size_t prefix_len;
517         const char *wim_basename;
518         char *real_user_prefix = NULL;
519         int ret;
520
521         if (user_prefix) {
522                 real_user_prefix = realpath(user_prefix, NULL);
523                 if (!real_user_prefix) {
524                         ERROR_WITH_ERRNO("Could not resolve `%s'",
525                                          real_user_prefix);
526                         ret = WIMLIB_ERR_NOTDIR;
527                         goto out;
528                 }
529                 wim_basename = path_basename(ctx->wim->filename);
530                 prefix_len = strlen(real_user_prefix) + 1 + strlen(wim_basename);
531         } else {
532                 prefix_len = strlen(ctx->wim->filename);
533         }
534
535         staging_dir_name_len = prefix_len + common_suffix_len + random_suffix_len;
536
537         staging_dir_name = MALLOC(staging_dir_name_len + 1);
538         if (!staging_dir_name) {
539                 ret = WIMLIB_ERR_NOMEM;
540                 goto out;
541         }
542
543         if (real_user_prefix)
544                 sprintf(staging_dir_name, "%s/%s", real_user_prefix, wim_basename);
545         else
546                 strcpy(staging_dir_name, ctx->wim->filename);
547
548         strcat(staging_dir_name, common_suffix);
549
550         randomize_char_array_with_alnum(staging_dir_name + prefix_len + common_suffix_len,
551                                         random_suffix_len);
552
553         staging_dir_name[staging_dir_name_len] = '\0';
554
555         if (mkdir(staging_dir_name, 0700) != 0) {
556                 ERROR_WITH_ERRNO("Failed to create temporary directory `%s'",
557                                  staging_dir_name);
558                 ret = WIMLIB_ERR_MKDIR;
559         } else {
560                 ret = 0;
561         }
562 out:
563         FREE(real_user_prefix);
564         if (ret == 0) {
565                 ctx->staging_dir_name = staging_dir_name;
566                 ctx->staging_dir_name_len = staging_dir_name_len;
567         } else {
568                 FREE(staging_dir_name);
569         }
570         return ret;
571 }
572
573 static int remove_file_or_directory(const char *fpath, const struct stat *sb,
574                                     int typeflag, struct FTW *ftwbuf)
575 {
576         if (remove(fpath) == 0)
577                 return 0;
578         else {
579                 ERROR_WITH_ERRNO("Cannot remove `%s'", fpath);
580                 return WIMLIB_ERR_DELETE_STAGING_DIR;
581         }
582 }
583
584
585 /*
586  * Deletes the staging directory and all the files contained in it.
587  */
588 static int delete_staging_dir(struct wimfs_context *ctx)
589 {
590         int ret;
591         wimlib_assert(ctx->staging_dir_name != NULL);
592         ret = nftw(ctx->staging_dir_name, remove_file_or_directory,
593                    10, FTW_DEPTH);
594         FREE(ctx->staging_dir_name);
595         ctx->staging_dir_name = NULL;
596         return ret;
597 }
598
599
600 /* Simple function that returns the concatenation of 2 strings. */
601 static char *strcat_dup(const char *s1, const char *s2, size_t max_len)
602 {
603         size_t len = strlen(s1) + strlen(s2);
604         if (len > max_len)
605                 len = max_len;
606         char *p = MALLOC(len + 1);
607         if (!p)
608                 return NULL;
609         snprintf(p, len + 1, "%s%s", s1, s2);
610         return p;
611 }
612
613 static int set_message_queue_names(struct wimfs_context *ctx,
614                                    const char *mount_dir)
615 {
616         static const char *u2d_prefix = "/wimlib-unmount-to-daemon-mq";
617         static const char *d2u_prefix = "/wimlib-daemon-to-unmount-mq";
618         char *dir_path;
619         char *p;
620         int ret;
621
622         dir_path = realpath(mount_dir, NULL);
623         if (!dir_path) {
624                 ERROR_WITH_ERRNO("Failed to resolve path \"%s\"", mount_dir);
625                 return WIMLIB_ERR_NOTDIR;
626         }
627
628         DEBUG("Using absolute dir_path = `%s'", dir_path);
629
630
631         p = dir_path;
632         while (*p) {
633                 if (*p == '/')
634                         *p = 0xff;
635                 p++;
636         }
637
638         ctx->unmount_to_daemon_mq_name = strcat_dup(u2d_prefix, dir_path,
639                                                     NAME_MAX);
640         if (!ctx->unmount_to_daemon_mq_name) {
641                 ret = WIMLIB_ERR_NOMEM;
642                 goto out_free_dir_path;
643         }
644         ctx->daemon_to_unmount_mq_name = strcat_dup(d2u_prefix, dir_path,
645                                                     NAME_MAX);
646         if (!ctx->daemon_to_unmount_mq_name) {
647                 ret = WIMLIB_ERR_NOMEM;
648                 goto out_free_unmount_to_daemon_mq_name;
649         }
650
651         ret = 0;
652         goto out_free_dir_path;
653 out_free_unmount_to_daemon_mq_name:
654         FREE(ctx->unmount_to_daemon_mq_name);
655         ctx->unmount_to_daemon_mq_name = NULL;
656 out_free_dir_path:
657         FREE(dir_path);
658         return ret;
659 }
660
661 static void free_message_queue_names(struct wimfs_context *ctx)
662 {
663         FREE(ctx->unmount_to_daemon_mq_name);
664         FREE(ctx->daemon_to_unmount_mq_name);
665         ctx->unmount_to_daemon_mq_name = NULL;
666         ctx->daemon_to_unmount_mq_name = NULL;
667 }
668
669 /*
670  * Opens two POSIX message queue: one for sending messages from the unmount
671  * process to the daemon process, and one to go the other way.  The names of the
672  * message queues, which must be system-wide unique, are be based on the mount
673  * point.  (There of course is still a possibility of a collision if one were to
674  * unmount two identically named directories simultaneously...)
675  *
676  * @daemon specifies whether the calling process is the filesystem daemon or the
677  * unmount process.
678  */
679 static int open_message_queues(struct wimfs_context *ctx, bool daemon)
680 {
681         int flags;
682         int ret;
683
684         wimlib_assert(ctx->unmount_to_daemon_mq_name != NULL &&
685                       ctx->daemon_to_unmount_mq_name != NULL);
686
687         if (daemon)
688                 flags = O_RDONLY | O_CREAT;
689         else
690                 flags = O_WRONLY | O_CREAT;
691
692         DEBUG("Opening message queue \"%s\"", ctx->unmount_to_daemon_mq_name);
693         ctx->unmount_to_daemon_mq = mq_open(ctx->unmount_to_daemon_mq_name,
694                                             flags, 0700, NULL);
695
696         if (ctx->unmount_to_daemon_mq == (mqd_t)-1) {
697                 ERROR_WITH_ERRNO("mq_open()");
698                 ret = WIMLIB_ERR_MQUEUE;
699                 goto out;
700         }
701
702         if (daemon)
703                 flags = O_WRONLY | O_CREAT;
704         else
705                 flags = O_RDONLY | O_CREAT;
706
707         DEBUG("Opening message queue \"%s\"", ctx->daemon_to_unmount_mq_name);
708         ctx->daemon_to_unmount_mq = mq_open(ctx->daemon_to_unmount_mq_name,
709                                             flags, 0700, NULL);
710
711         if (ctx->daemon_to_unmount_mq == (mqd_t)-1) {
712                 ERROR_WITH_ERRNO("mq_open()");
713                 ret = WIMLIB_ERR_MQUEUE;
714                 goto out_close_unmount_to_daemon_mq;
715         }
716         ret = 0;
717         goto out;
718 out_close_unmount_to_daemon_mq:
719         mq_close(ctx->unmount_to_daemon_mq);
720         mq_unlink(ctx->unmount_to_daemon_mq_name);
721         ctx->unmount_to_daemon_mq = (mqd_t)-1;
722 out:
723         return ret;
724 }
725
726 /* Try to determine the maximum message size of a message queue.  The return
727  * value is the maximum message size, or a guess of 8192 bytes if it cannot be
728  * determined. */
729 static long mq_get_msgsize(mqd_t mq)
730 {
731         static const char *msgsize_max_file = "/proc/sys/fs/mqueue/msgsize_max";
732         FILE *fp;
733         struct mq_attr attr;
734         long msgsize;
735
736         if (mq_getattr(mq, &attr) == 0) {
737                 msgsize = attr.mq_msgsize;
738         } else {
739                 ERROR_WITH_ERRNO("mq_getattr()");
740                 ERROR("Attempting to read %s", msgsize_max_file);
741                 fp = fopen(msgsize_max_file, "rb");
742                 if (fp) {
743                         if (fscanf(fp, "%ld", &msgsize) != 1) {
744                                 ERROR("Assuming message size of 8192");
745                                 msgsize = 8192;
746                         }
747                         fclose(fp);
748                 } else {
749                         ERROR_WITH_ERRNO("Failed to open the file `%s'",
750                                          msgsize_max_file);
751                         ERROR("Assuming message size of 8192");
752                         msgsize = 8192;
753                 }
754         }
755         return msgsize;
756 }
757
758 static int get_mailbox(mqd_t mq, long needed_msgsize, long *msgsize_ret,
759                        char **mailbox_ret)
760 {
761         long msgsize;
762         char *mailbox;
763
764         msgsize = mq_get_msgsize(mq);
765
766         if (msgsize < needed_msgsize) {
767                 ERROR("Message queue max size must be at least %ld!",
768                       needed_msgsize);
769                 return WIMLIB_ERR_MQUEUE;
770         }
771
772         mailbox = MALLOC(msgsize);
773         if (!mailbox) {
774                 ERROR("Failed to allocate %ld bytes for mailbox", msgsize);
775                 return WIMLIB_ERR_NOMEM;
776         }
777         *msgsize_ret = msgsize;
778         *mailbox_ret = mailbox;
779         return 0;
780 }
781
782 static void unlink_message_queues(struct wimfs_context *ctx)
783 {
784         mq_unlink(ctx->unmount_to_daemon_mq_name);
785         mq_unlink(ctx->daemon_to_unmount_mq_name);
786 }
787
788 /* Closes the message queues, which are allocated in static variables */
789 static void close_message_queues(struct wimfs_context *ctx)
790 {
791         mq_close(ctx->unmount_to_daemon_mq);
792         ctx->unmount_to_daemon_mq = (mqd_t)(-1);
793         mq_close(ctx->daemon_to_unmount_mq);
794         ctx->daemon_to_unmount_mq = (mqd_t)(-1);
795         unlink_message_queues(ctx);
796 }
797
798 static int wimfs_access(const char *path, int mask)
799 {
800         /* Permissions not implemented */
801         return 0;
802 }
803
804 static int wimfs_chmod(const char *path, mode_t mask)
805 {
806         struct dentry *dentry;
807         struct wimfs_context *ctx = wimfs_get_context();
808         struct inode *inode;
809         struct stat stbuf;
810         int ret;
811
812         ret = lookup_resource(ctx->wim, path,
813                               get_lookup_flags(ctx) | LOOKUP_FLAG_DIRECTORY_OK,
814                               &dentry, NULL, NULL);
815         if (ret != 0)
816                 return ret;
817         inode = dentry->d_inode;
818         inode_to_stbuf(inode, NULL, &stbuf);
819         if (mask == stbuf.st_mode)
820                 return 0;
821         else
822                 return -EPERM;
823
824 }
825
826 static void inode_update_lte_ptr(struct inode *inode,
827                                  struct lookup_table_entry *old_lte,
828                                  struct lookup_table_entry *new_lte)
829 {
830         if (inode->lte == old_lte) {
831                 inode->lte = new_lte;
832         } else {
833                 for (unsigned i = 0; i < inode->num_ads; i++) {
834                         if (inode->ads_entries[i].lte == old_lte) {
835                                 inode->ads_entries[i].lte = new_lte;
836                                 break;
837                         }
838                 }
839         }
840 }
841
842 static int update_lte_of_staging_file(struct lookup_table_entry *lte,
843                                       struct lookup_table *table)
844 {
845         struct lookup_table_entry *duplicate_lte;
846         int ret;
847         u8 hash[SHA1_HASH_SIZE];
848         struct stat stbuf;
849
850         wimlib_assert(lte->resource_location == RESOURCE_IN_STAGING_FILE);
851         wimlib_assert(lte->staging_file_name);
852
853         ret = sha1sum(lte->staging_file_name, hash);
854         if (ret != 0)
855                 return ret;
856
857         lookup_table_unlink(table, lte);
858
859         duplicate_lte = __lookup_resource(table, hash);
860
861         if (duplicate_lte) {
862                 /* Merge duplicate lookup table entries */
863                 duplicate_lte->refcnt += lte->refcnt;
864                 list_del(&lte->staging_list);
865                 inode_update_lte_ptr(lte->lte_inode, lte, duplicate_lte);
866                 free_lookup_table_entry(lte);
867         } else {
868                 if (stat(lte->staging_file_name, &stbuf) != 0) {
869                         ERROR_WITH_ERRNO("Failed to stat `%s'", lte->staging_file_name);
870                         return WIMLIB_ERR_STAT;
871                 }
872                 if (stbuf.st_size == 0) {
873                         /* Zero-length stream.  No lookup table entry needed. */
874                         inode_update_lte_ptr(lte->lte_inode, lte, NULL);
875                         free_lookup_table_entry(lte);
876                 } else {
877                         wimlib_assert(&lte->file_on_disk == &lte->staging_file_name);
878                         lte->resource_entry.original_size = stbuf.st_size;
879                         lte->resource_entry.size = stbuf.st_size;
880                         lte->resource_location = RESOURCE_IN_FILE_ON_DISK;
881                         lte->lte_inode = NULL;
882                         copy_hash(lte->hash, hash);
883                         lookup_table_insert(table, lte);
884                 }
885         }
886         return 0;
887 }
888
889 static int inode_close_fds(struct inode *inode)
890 {
891         u16 num_opened_fds = inode->num_opened_fds;
892         for (u16 i = 0, j = 0; j < num_opened_fds; i++) {
893                 struct wimlib_fd *fd = inode->fds[i];
894                 if (fd) {
895                         wimlib_assert(fd->f_inode == inode);
896                         int ret = close_wimlib_fd(fd);
897                         if (ret != 0)
898                                 return ret;
899                         j++;
900                 }
901         }
902         return 0;
903 }
904
905 /* Overwrites the WIM file, with changes saved. */
906 static int rebuild_wim(struct wimfs_context *ctx, int write_flags)
907 {
908         int ret;
909         struct lookup_table_entry *lte, *tmp;
910         WIMStruct *w = ctx->wim;
911
912
913         DEBUG("Closing all staging file descriptors.");
914         list_for_each_entry_safe(lte, tmp, &ctx->staging_list, staging_list) {
915                 ret = inode_close_fds(lte->lte_inode);
916                 if (ret != 0)
917                         return ret;
918         }
919
920         DEBUG("Calculating SHA1 checksums for all new staging files.");
921         list_for_each_entry_safe(lte, tmp, &ctx->staging_list, staging_list) {
922                 ret = update_lte_of_staging_file(lte, ctx->wim->lookup_table);
923                 if (ret != 0)
924                         return ret;
925         }
926
927         xml_update_image_info(w, w->current_image);
928
929         ret = wimlib_overwrite(w, write_flags, 0, NULL);
930         if (ret != 0) {
931                 ERROR("Failed to commit changes");
932                 return ret;
933         }
934         return ret;
935 }
936
937 /* Called when the filesystem is unmounted. */
938 static void wimfs_destroy(void *p)
939 {
940         /* For read-write mounts, the `imagex unmount' command, which is
941          * running in a separate process and is executing the
942          * wimlib_unmount() function, will send this process a byte
943          * through a message queue that indicates whether the --commit
944          * option was specified or not. */
945
946         long msgsize;
947         struct timespec timeout;
948         struct timeval now;
949         ssize_t bytes_received;
950         int ret;
951         char commit;
952         char check_integrity;
953         char status;
954         char *mailbox;
955         struct wimfs_context *ctx = wimfs_get_context();
956         int write_flags;
957
958         if (open_message_queues(ctx, true))
959                 return;
960
961         if (get_mailbox(ctx->unmount_to_daemon_mq, 2, &msgsize, &mailbox))
962                 goto out_close_message_queues;
963
964         /* Wait at most 3 seconds before giving up and discarding changes. */
965         gettimeofday(&now, NULL);
966         timeout.tv_sec = now.tv_sec + 3;
967         timeout.tv_nsec = now.tv_usec * 1000;
968         DEBUG("Waiting for message telling us whether to commit or not, and "
969               "whether to include integrity checks.");
970
971         bytes_received = mq_timedreceive(ctx->unmount_to_daemon_mq, mailbox,
972                                          msgsize, NULL, &timeout);
973         if (bytes_received == -1) {
974                 ERROR_WITH_ERRNO("mq_timedreceive()");
975                 ERROR("Not committing.");
976                 commit = 0;
977                 check_integrity = 0;
978         } else {
979                 DEBUG("Received message: [%d %d]", mailbox[0], mailbox[1]);
980                 commit = mailbox[0];
981                 check_integrity = mailbox[1];
982         }
983
984         status = 0;
985         if (ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
986                 if (commit) {
987                         if (check_integrity)
988                                 write_flags = WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
989                         else
990                                 write_flags = 0;
991                         status = rebuild_wim(ctx, write_flags);
992                 }
993                 ret = delete_staging_dir(ctx);
994                 if (ret != 0) {
995                         ERROR("Failed to delete the staging directory");
996                         if (status == 0)
997                                 status = ret;
998                 }
999         } else {
1000                 DEBUG("Read-only mount");
1001         }
1002         DEBUG("Sending status %hhd", status);
1003         ret = mq_send(ctx->daemon_to_unmount_mq, &status, 1, 1);
1004         if (ret == -1)
1005                 ERROR_WITH_ERRNO("Failed to send status to unmount process");
1006         FREE(mailbox);
1007 out_close_message_queues:
1008         close_message_queues(ctx);
1009 }
1010
1011 #if 0
1012 static int wimfs_fallocate(const char *path, int mode,
1013                            off_t offset, off_t len, struct fuse_file_info *fi)
1014 {
1015         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1016         wimlib_assert(fd->staging_fd != -1);
1017         return fallocate(fd->staging_fd, mode, offset, len);
1018 }
1019
1020 #endif
1021
1022 static int wimfs_fgetattr(const char *path, struct stat *stbuf,
1023                           struct fuse_file_info *fi)
1024 {
1025         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1026         return inode_to_stbuf(fd->f_inode, fd->f_lte, stbuf);
1027 }
1028
1029 static int wimfs_ftruncate(const char *path, off_t size,
1030                            struct fuse_file_info *fi)
1031 {
1032         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1033         int ret = ftruncate(fd->staging_fd, size);
1034         if (ret != 0)
1035                 return -errno;
1036         if (fd->f_lte && size < fd->f_lte->resource_entry.original_size)
1037                 fd->f_lte->resource_entry.original_size = size;
1038         return 0;
1039 }
1040
1041 /*
1042  * Fills in a `struct stat' that corresponds to a file or directory in the WIM.
1043  */
1044 static int wimfs_getattr(const char *path, struct stat *stbuf)
1045 {
1046         struct dentry *dentry;
1047         struct lookup_table_entry *lte;
1048         int ret;
1049         struct wimfs_context *ctx = wimfs_get_context();
1050
1051         ret = lookup_resource(ctx->wim, path,
1052                               get_lookup_flags(ctx) | LOOKUP_FLAG_DIRECTORY_OK,
1053                               &dentry, &lte, NULL);
1054         if (ret != 0)
1055                 return ret;
1056         return inode_to_stbuf(dentry->d_inode, lte, stbuf);
1057 }
1058
1059 #ifdef ENABLE_XATTR
1060 /* Read an alternate data stream through the XATTR interface, or get its size */
1061 static int wimfs_getxattr(const char *path, const char *name, char *value,
1062                           size_t size)
1063 {
1064         int ret;
1065         struct inode *inode;
1066         struct ads_entry *ads_entry;
1067         size_t res_size;
1068         struct lookup_table_entry *lte;
1069         struct wimfs_context *ctx = wimfs_get_context();
1070
1071         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1072                 return -ENOTSUP;
1073
1074         if (strlen(name) < 5 || memcmp(name, "user.", 5) != 0)
1075                 return -ENOATTR;
1076         name += 5;
1077
1078         inode = wim_pathname_to_inode(ctx->wim, path);
1079         if (!inode)
1080                 return -ENOENT;
1081
1082         ads_entry = inode_get_ads_entry(inode, name, NULL);
1083         if (!ads_entry)
1084                 return -ENOATTR;
1085
1086         lte = ads_entry->lte;
1087         res_size = wim_resource_size(lte);
1088
1089         if (size == 0)
1090                 return res_size;
1091
1092         if (res_size > size)
1093                 return -ERANGE;
1094
1095         ret = read_full_wim_resource(lte, (u8*)value,
1096                                      WIMLIB_RESOURCE_FLAG_MULTITHREADED);
1097         if (ret != 0)
1098                 return -EIO;
1099
1100         return res_size;
1101 }
1102 #endif
1103
1104 /* Create a hard link */
1105 static int wimfs_link(const char *to, const char *from)
1106 {
1107         struct dentry *from_dentry, *from_dentry_parent;
1108         const char *link_name;
1109         struct inode *inode;
1110         struct lookup_table_entry *lte;
1111         WIMStruct *w = wimfs_get_WIMStruct();
1112
1113         inode = wim_pathname_to_inode(w, to);
1114         if (!inode)
1115                 return -ENOENT;
1116
1117         if (!inode_is_regular_file(inode))
1118                 return -EPERM;
1119
1120         from_dentry_parent = get_parent_dentry(w, from);
1121         if (!from_dentry_parent)
1122                 return -ENOENT;
1123         if (!dentry_is_directory(from_dentry_parent))
1124                 return -ENOTDIR;
1125
1126         link_name = path_basename(from);
1127         if (get_dentry_child_with_name(from_dentry_parent, link_name))
1128                 return -EEXIST;
1129         from_dentry = new_dentry(link_name);
1130         if (!from_dentry)
1131                 return -ENOMEM;
1132
1133
1134         inode_add_dentry(from_dentry, inode);
1135         from_dentry->d_inode = inode;
1136         inode->link_count++;
1137
1138         for (unsigned i = 0; i <= inode->num_ads; i++) {
1139                 lte = inode_stream_lte_resolved(inode, i);
1140                 if (lte)
1141                         lte->refcnt++;
1142         }
1143
1144         dentry_add_child(from_dentry_parent, from_dentry);
1145         return 0;
1146 }
1147
1148 #ifdef ENABLE_XATTR
1149 static int wimfs_listxattr(const char *path, char *list, size_t size)
1150 {
1151         size_t needed_size;
1152         struct inode *inode;
1153         struct wimfs_context *ctx = wimfs_get_context();
1154
1155         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1156                 return -ENOTSUP;
1157
1158         /* List alternate data streams, or get the list size */
1159
1160         inode = wim_pathname_to_inode(ctx->wim, path);
1161         if (!inode)
1162                 return -ENOENT;
1163
1164         if (size == 0) {
1165                 needed_size = 0;
1166                 for (u16 i = 0; i < inode->num_ads; i++)
1167                         needed_size += inode->ads_entries[i].stream_name_utf8_len + 6;
1168                 return needed_size;
1169         } else {
1170                 char *p = list;
1171                 for (u16 i = 0; i < inode->num_ads; i++) {
1172                         needed_size = inode->ads_entries[i].stream_name_utf8_len + 6;
1173                         if (needed_size > size)
1174                                 return -ERANGE;
1175                         p += sprintf(p, "user.%s",
1176                                      inode->ads_entries[i].stream_name_utf8) + 1;
1177                         size -= needed_size;
1178                 }
1179                 return p - list;
1180         }
1181 }
1182 #endif
1183
1184 /*
1185  * Create a directory in the WIM.
1186  * @mode is currently ignored.
1187  */
1188 static int wimfs_mkdir(const char *path, mode_t mode)
1189 {
1190         struct dentry *parent;
1191         struct dentry *newdir;
1192         const char *basename;
1193         struct wimfs_context *ctx = wimfs_get_context();
1194
1195         parent = get_parent_dentry(ctx->wim, path);
1196         if (!parent)
1197                 return -ENOENT;
1198
1199         if (!dentry_is_directory(parent))
1200                 return -ENOTDIR;
1201
1202         basename = path_basename(path);
1203         if (get_dentry_child_with_name(parent, basename))
1204                 return -EEXIST;
1205
1206         newdir = new_dentry_with_inode(basename);
1207         newdir->d_inode->attributes |= FILE_ATTRIBUTE_DIRECTORY;
1208         newdir->d_inode->resolved = true;
1209         newdir->d_inode->ino = ctx->next_ino++;
1210         dentry_add_child(parent, newdir);
1211         return 0;
1212 }
1213
1214 /* Creates a regular file. */
1215 static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
1216 {
1217         const char *stream_name;
1218         struct wimfs_context *ctx = wimfs_get_context();
1219         if ((ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
1220              && (stream_name = path_stream_name(path))) {
1221                 /* Make an alternate data stream */
1222                 struct ads_entry *new_entry;
1223                 struct inode *inode;
1224
1225                 char *p = (char*)stream_name - 1;
1226                 wimlib_assert(*p == ':');
1227                 *p = '\0';
1228
1229                 inode = wim_pathname_to_inode(ctx->wim, path);
1230                 if (!inode)
1231                         return -ENOENT;
1232                 if (!inode_is_regular_file(inode))
1233                         return -ENOENT;
1234                 if (inode_get_ads_entry(inode, stream_name, NULL))
1235                         return -EEXIST;
1236                 new_entry = inode_add_ads(inode, stream_name);
1237                 if (!new_entry)
1238                         return -ENOMEM;
1239         } else {
1240                 struct dentry *dentry, *parent;
1241                 const char *basename;
1242
1243                 /* Make a normal file (not an alternate data stream) */
1244
1245                 /* Make sure that the parent of @path exists and is a directory, and
1246                  * that the dentry named by @path does not already exist.  */
1247                 parent = get_parent_dentry(ctx->wim, path);
1248                 if (!parent)
1249                         return -ENOENT;
1250                 if (!dentry_is_directory(parent))
1251                         return -ENOTDIR;
1252
1253                 basename = path_basename(path);
1254                 if (get_dentry_child_with_name(parent, path))
1255                         return -EEXIST;
1256
1257                 dentry = new_dentry_with_inode(basename);
1258                 if (!dentry)
1259                         return -ENOMEM;
1260                 dentry->d_inode->resolved = true;
1261                 dentry->d_inode->ino = ctx->next_ino++;
1262                 dentry_add_child(parent, dentry);
1263         }
1264         return 0;
1265 }
1266
1267
1268 /* Open a file.  */
1269 static int wimfs_open(const char *path, struct fuse_file_info *fi)
1270 {
1271         struct dentry *dentry;
1272         struct lookup_table_entry *lte;
1273         int ret;
1274         struct wimlib_fd *fd;
1275         struct inode *inode;
1276         u16 stream_idx;
1277         u32 stream_id;
1278         struct wimfs_context *ctx = wimfs_get_context();
1279
1280         ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
1281                               &dentry, &lte, &stream_idx);
1282         if (ret != 0)
1283                 return ret;
1284
1285         inode = dentry->d_inode;
1286
1287         if (stream_idx == 0)
1288                 stream_id = 0;
1289         else
1290                 stream_id = inode->ads_entries[stream_idx - 1].stream_id;
1291
1292         /* The file resource may be in the staging directory (read-write mounts
1293          * only) or in the WIM.  If it's in the staging directory, we need to
1294          * open a native file descriptor for the corresponding file.  Otherwise,
1295          * we can read the file resource directly from the WIM file if we are
1296          * opening it read-only, but we need to extract the resource to the
1297          * staging directory if we are opening it writable. */
1298
1299         if (flags_writable(fi->flags) &&
1300             (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) {
1301                 u64 size = (lte) ? wim_resource_size(lte) : 0;
1302                 ret = extract_resource_to_staging_dir(inode, stream_id,
1303                                                       &lte, size, ctx);
1304                 if (ret != 0)
1305                         return ret;
1306         }
1307
1308         ret = alloc_wimlib_fd(inode, stream_id, lte, &fd,
1309                               wimfs_ctx_readonly(ctx));
1310         if (ret != 0)
1311                 return ret;
1312
1313         if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
1314                 fd->staging_fd = open(lte->staging_file_name, fi->flags);
1315                 if (fd->staging_fd == -1) {
1316                         close_wimlib_fd(fd);
1317                         return -errno;
1318                 }
1319         }
1320         fi->fh = (uintptr_t)fd;
1321         return 0;
1322 }
1323
1324 /* Opens a directory. */
1325 static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
1326 {
1327         struct inode *inode;
1328         int ret;
1329         struct wimlib_fd *fd = NULL;
1330         struct wimfs_context *ctx = wimfs_get_context();
1331         WIMStruct *w = ctx->wim;
1332
1333         inode = wim_pathname_to_inode(w, path);
1334         if (!inode)
1335                 return -ENOENT;
1336         if (!inode_is_directory(inode))
1337                 return -ENOTDIR;
1338         ret = alloc_wimlib_fd(inode, 0, NULL, &fd, wimfs_ctx_readonly(ctx));
1339         fi->fh = (uintptr_t)fd;
1340         return ret;
1341 }
1342
1343
1344 /*
1345  * Read data from a file in the WIM or in the staging directory.
1346  */
1347 static int wimfs_read(const char *path, char *buf, size_t size,
1348                       off_t offset, struct fuse_file_info *fi)
1349 {
1350         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1351
1352         if (!fd)
1353                 return -EBADF;
1354
1355         if (!fd->f_lte) /* Empty stream with no lookup table entry */
1356                 return 0;
1357
1358         if (fd->f_lte->resource_location == RESOURCE_IN_STAGING_FILE) {
1359                 /* Read from staging file */
1360
1361                 wimlib_assert(fd->f_lte->staging_file_name);
1362                 wimlib_assert(fd->staging_fd != -1);
1363
1364                 ssize_t ret;
1365                 DEBUG("Seek to offset %zu", offset);
1366
1367                 if (lseek(fd->staging_fd, offset, SEEK_SET) == -1)
1368                         return -errno;
1369                 ret = read(fd->staging_fd, buf, size);
1370                 if (ret == -1)
1371                         return -errno;
1372                 return ret;
1373         } else {
1374                 /* Read from WIM */
1375
1376                 wimlib_assert(fd->f_lte->resource_location == RESOURCE_IN_WIM);
1377
1378                 u64 res_size = wim_resource_size(fd->f_lte);
1379
1380                 if (offset > res_size)
1381                         return -EOVERFLOW;
1382
1383                 size = min(size, res_size - offset);
1384
1385                 if (read_wim_resource(fd->f_lte, (u8*)buf,
1386                                       size, offset,
1387                                       WIMLIB_RESOURCE_FLAG_MULTITHREADED) != 0)
1388                         return -EIO;
1389                 return size;
1390         }
1391 }
1392
1393 struct fill_params {
1394         void *buf;
1395         fuse_fill_dir_t filler;
1396 };
1397
1398 static int dentry_fuse_fill(struct dentry *dentry, void *arg)
1399 {
1400         struct fill_params *fill_params = arg;
1401         return fill_params->filler(fill_params->buf, dentry->file_name_utf8,
1402                                    NULL, 0);
1403 }
1404
1405 /* Fills in the entries of the directory specified by @path using the
1406  * FUSE-provided function @filler.  */
1407 static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
1408                          off_t offset, struct fuse_file_info *fi)
1409 {
1410         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1411         struct inode *inode;
1412
1413         if (!fd)
1414                 return -EBADF;
1415
1416         inode = fd->f_inode;
1417
1418         struct fill_params fill_params = {
1419                 .buf = buf,
1420                 .filler = filler,
1421         };
1422
1423         filler(buf, ".", NULL, 0);
1424         filler(buf, "..", NULL, 0);
1425
1426         return for_dentry_in_rbtree(inode->children.rb_node,
1427                                     dentry_fuse_fill, &fill_params);
1428 }
1429
1430
1431 static int wimfs_readlink(const char *path, char *buf, size_t buf_len)
1432 {
1433         struct wimfs_context *ctx = wimfs_get_context();
1434         struct inode *inode = wim_pathname_to_inode(ctx->wim, path);
1435         int ret;
1436         if (!inode)
1437                 return -ENOENT;
1438         if (!inode_is_symlink(inode))
1439                 return -EINVAL;
1440
1441         ret = inode_readlink(inode, buf, buf_len, ctx->wim,
1442                              WIMLIB_RESOURCE_FLAG_MULTITHREADED);
1443         if (ret > 0)
1444                 ret = 0;
1445         return ret;
1446 }
1447
1448 /* Close a file. */
1449 static int wimfs_release(const char *path, struct fuse_file_info *fi)
1450 {
1451         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1452         return close_wimlib_fd(fd);
1453 }
1454
1455 /* Close a directory */
1456 static int wimfs_releasedir(const char *path, struct fuse_file_info *fi)
1457 {
1458         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1459         return close_wimlib_fd(fd);
1460 }
1461
1462 #ifdef ENABLE_XATTR
1463 /* Remove an alternate data stream through the XATTR interface */
1464 static int wimfs_removexattr(const char *path, const char *name)
1465 {
1466         struct inode *inode;
1467         struct ads_entry *ads_entry;
1468         u16 ads_idx;
1469         struct wimfs_context *ctx = wimfs_get_context();
1470
1471         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1472                 return -ENOTSUP;
1473
1474         if (strlen(name) < 5 || memcmp(name, "user.", 5) != 0)
1475                 return -ENOATTR;
1476         name += 5;
1477
1478         inode = wim_pathname_to_inode(ctx->wim, path);
1479         if (!inode)
1480                 return -ENOENT;
1481
1482         ads_entry = inode_get_ads_entry(inode, name, &ads_idx);
1483         if (!ads_entry)
1484                 return -ENOATTR;
1485         inode_remove_ads(inode, ads_idx, ctx->wim->lookup_table);
1486         return 0;
1487 }
1488 #endif
1489
1490 /* Renames a file or directory.  See rename (3) */
1491 static int wimfs_rename(const char *from, const char *to)
1492 {
1493         struct dentry *src;
1494         struct dentry *dst;
1495         struct dentry *parent_of_dst;
1496         char *file_name_utf16 = NULL, *file_name_utf8 = NULL;
1497         u16 file_name_utf16_len, file_name_utf8_len;
1498         WIMStruct *w = wimfs_get_WIMStruct();
1499         int ret;
1500
1501         /* This rename() implementation currently only supports actual files
1502          * (not alternate data streams) */
1503
1504         src = get_dentry(w, from);
1505         if (!src)
1506                 return -ENOENT;
1507
1508         dst = get_dentry(w, to);
1509
1510
1511         ret = get_names(&file_name_utf16, &file_name_utf8,
1512                         &file_name_utf16_len, &file_name_utf8_len,
1513                         path_basename(to));
1514         if (ret != 0)
1515                 return -ENOMEM;
1516
1517         if (dst) {
1518                 /* Destination file exists */
1519
1520                 if (src == dst) /* Same file */
1521                         return 0;
1522
1523                 if (!dentry_is_directory(src)) {
1524                         /* Cannot rename non-directory to directory. */
1525                         if (dentry_is_directory(dst))
1526                                 return -EISDIR;
1527                 } else {
1528                         /* Cannot rename directory to a non-directory or a non-empty
1529                          * directory */
1530                         if (!dentry_is_directory(dst))
1531                                 return -ENOTDIR;
1532                         if (inode_has_children(dst->d_inode))
1533                                 return -ENOTEMPTY;
1534                 }
1535                 parent_of_dst = dst->parent;
1536                 remove_dentry(dst, w->lookup_table);
1537         } else {
1538                 /* Destination does not exist */
1539                 parent_of_dst = get_parent_dentry(w, to);
1540                 if (!parent_of_dst)
1541                         return -ENOENT;
1542
1543                 if (!dentry_is_directory(parent_of_dst))
1544                         return -ENOTDIR;
1545         }
1546
1547         FREE(src->file_name);
1548         FREE(src->file_name_utf8);
1549         src->file_name          = file_name_utf16;
1550         src->file_name_utf8     = file_name_utf8;
1551         src->file_name_len      = file_name_utf16_len;
1552         src->file_name_utf8_len = file_name_utf8_len;
1553
1554         unlink_dentry(src);
1555         dentry_add_child(parent_of_dst, src);
1556         return 0;
1557 }
1558
1559 /* Remove a directory */
1560 static int wimfs_rmdir(const char *path)
1561 {
1562         struct dentry *dentry;
1563         WIMStruct *w = wimfs_get_WIMStruct();
1564
1565         dentry = get_dentry(w, path);
1566         if (!dentry)
1567                 return -ENOENT;
1568
1569         if (!dentry_is_empty_directory(dentry))
1570                 return -ENOTEMPTY;
1571
1572         remove_dentry(dentry, w->lookup_table);
1573         return 0;
1574 }
1575
1576 #ifdef ENABLE_XATTR
1577 /* Write an alternate data stream through the XATTR interface */
1578 static int wimfs_setxattr(const char *path, const char *name,
1579                           const char *value, size_t size, int flags)
1580 {
1581         struct ads_entry *existing_ads_entry;
1582         struct ads_entry *new_ads_entry;
1583         struct lookup_table_entry *existing_lte;
1584         struct lookup_table_entry *lte;
1585         struct inode *inode;
1586         u8 value_hash[SHA1_HASH_SIZE];
1587         u16 ads_idx;
1588         struct wimfs_context *ctx = wimfs_get_context();
1589
1590         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1591                 return -ENOTSUP;
1592
1593         if (strlen(name) < 5 || memcmp(name, "user.", 5) != 0)
1594                 return -ENOATTR;
1595         name += 5;
1596
1597         inode = wim_pathname_to_inode(ctx->wim, path);
1598         if (!inode)
1599                 return -ENOENT;
1600
1601         existing_ads_entry = inode_get_ads_entry(inode, name, &ads_idx);
1602         if (existing_ads_entry) {
1603                 if (flags & XATTR_CREATE)
1604                         return -EEXIST;
1605                 inode_remove_ads(inode, ads_idx, ctx->wim->lookup_table);
1606         } else {
1607                 if (flags & XATTR_REPLACE)
1608                         return -ENOATTR;
1609         }
1610         new_ads_entry = inode_add_ads(inode, name);
1611         if (!new_ads_entry)
1612                 return -ENOMEM;
1613
1614         sha1_buffer((const u8*)value, size, value_hash);
1615
1616         existing_lte = __lookup_resource(ctx->wim->lookup_table, value_hash);
1617
1618         if (existing_lte) {
1619                 lte = existing_lte;
1620                 lte->refcnt++;
1621         } else {
1622                 u8 *value_copy;
1623                 lte = new_lookup_table_entry();
1624                 if (!lte)
1625                         return -ENOMEM;
1626                 value_copy = MALLOC(size);
1627                 if (!value_copy) {
1628                         FREE(lte);
1629                         return -ENOMEM;
1630                 }
1631                 memcpy(value_copy, value, size);
1632                 lte->resource_location            = RESOURCE_IN_ATTACHED_BUFFER;
1633                 lte->attached_buffer              = value_copy;
1634                 lte->resource_entry.original_size = size;
1635                 lte->resource_entry.size          = size;
1636                 lte->resource_entry.flags         = 0;
1637                 copy_hash(lte->hash, value_hash);
1638                 lookup_table_insert(ctx->wim->lookup_table, lte);
1639         }
1640         new_ads_entry->lte = lte;
1641         return 0;
1642 }
1643 #endif
1644
1645 static int wimfs_symlink(const char *to, const char *from)
1646 {
1647         struct dentry *dentry_parent, *dentry;
1648         const char *link_name;
1649         struct inode *inode;
1650         struct wimfs_context *ctx = wimfs_get_context();
1651
1652         dentry_parent = get_parent_dentry(ctx->wim, from);
1653         if (!dentry_parent)
1654                 return -ENOENT;
1655         if (!dentry_is_directory(dentry_parent))
1656                 return -ENOTDIR;
1657
1658         link_name = path_basename(from);
1659
1660         if (get_dentry_child_with_name(dentry_parent, link_name))
1661                 return -EEXIST;
1662         dentry = new_dentry_with_inode(link_name);
1663         if (!dentry)
1664                 return -ENOMEM;
1665         inode = dentry->d_inode;
1666
1667         inode->attributes  = FILE_ATTRIBUTE_REPARSE_POINT;
1668         inode->reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
1669         inode->ino         = ctx->next_ino++;
1670         inode->resolved    = true;
1671
1672         if (inode_set_symlink(inode, to, ctx->wim->lookup_table, NULL) != 0)
1673                 goto out_free_dentry;
1674
1675         dentry_add_child(dentry_parent, dentry);
1676         return 0;
1677 out_free_dentry:
1678         free_dentry(dentry);
1679         return -ENOMEM;
1680 }
1681
1682
1683 /* Reduce the size of a file */
1684 static int wimfs_truncate(const char *path, off_t size)
1685 {
1686         struct dentry *dentry;
1687         struct lookup_table_entry *lte;
1688         int ret;
1689         u16 stream_idx;
1690         u32 stream_id;
1691         struct inode *inode;
1692         struct wimfs_context *ctx = wimfs_get_context();
1693
1694         ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
1695                               &dentry, &lte, &stream_idx);
1696
1697         if (ret != 0)
1698                 return ret;
1699
1700         if (!lte) /* Already a zero-length file */
1701                 return 0;
1702
1703         inode = dentry->d_inode;
1704
1705         if (stream_idx == 0)
1706                 stream_id = 0;
1707         else
1708                 stream_id = inode->ads_entries[stream_idx - 1].stream_id;
1709
1710         if (lte->resource_location == RESOURCE_IN_STAGING_FILE) {
1711                 wimlib_assert(lte->staging_file_name);
1712                 ret = truncate(lte->staging_file_name, size);
1713                 if (ret != 0)
1714                         return -errno;
1715                 lte->resource_entry.original_size = size;
1716         } else {
1717                 wimlib_assert(lte->resource_location == RESOURCE_IN_WIM);
1718                 /* File in WIM.  Extract it to the staging directory, but only
1719                  * the first @size bytes of it. */
1720                 ret = extract_resource_to_staging_dir(inode, stream_id,
1721                                                       &lte, size, ctx);
1722         }
1723         return ret;
1724 }
1725
1726 /* Remove a regular file */
1727 static int wimfs_unlink(const char *path)
1728 {
1729         struct dentry *dentry;
1730         struct lookup_table_entry *lte;
1731         int ret;
1732         u16 stream_idx;
1733         struct wimfs_context *ctx = wimfs_get_context();
1734
1735         ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
1736                               &dentry, &lte, &stream_idx);
1737
1738         if (ret != 0)
1739                 return ret;
1740
1741         if (stream_idx == 0)
1742                 remove_dentry(dentry, ctx->wim->lookup_table);
1743         else
1744                 inode_remove_ads(dentry->d_inode, stream_idx - 1,
1745                                  ctx->wim->lookup_table);
1746         return 0;
1747 }
1748
1749 #ifdef HAVE_UTIMENSAT
1750 /*
1751  * Change the timestamp on a file dentry.
1752  *
1753  * Note that alternate data streams do not have their own timestamps.
1754  */
1755 static int wimfs_utimens(const char *path, const struct timespec tv[2])
1756 {
1757         struct dentry *dentry;
1758         struct inode *inode;
1759         WIMStruct *w = wimfs_get_WIMStruct();
1760
1761         dentry = get_dentry(w, path);
1762         if (!dentry)
1763                 return -ENOENT;
1764         inode = dentry->d_inode;
1765
1766         if (tv[0].tv_nsec != UTIME_OMIT) {
1767                 if (tv[0].tv_nsec == UTIME_NOW)
1768                         inode->last_access_time = get_wim_timestamp();
1769                 else
1770                         inode->last_access_time = timespec_to_wim_timestamp(&tv[0]);
1771         }
1772         if (tv[1].tv_nsec != UTIME_OMIT) {
1773                 if (tv[1].tv_nsec == UTIME_NOW)
1774                         inode->last_write_time = get_wim_timestamp();
1775                 else
1776                         inode->last_write_time = timespec_to_wim_timestamp(&tv[1]);
1777         }
1778         return 0;
1779 }
1780 #else
1781 static int wimfs_utime(const char *path, struct utimbuf *times)
1782 {
1783         struct dentry *dentry;
1784         struct inode *inode;
1785         WIMStruct *w = wimfs_get_WIMStruct();
1786
1787         dentry = get_dentry(w, path);
1788         if (!dentry)
1789                 return -ENOENT;
1790         inode = dentry->d_inode;
1791
1792         inode->last_write_time = unix_timestamp_to_wim(times->modtime);
1793         inode->last_access_time = unix_timestamp_to_wim(times->actime);
1794         return 0;
1795 }
1796 #endif
1797
1798 /* Writes to a file in the WIM filesystem.
1799  * It may be an alternate data stream, but here we don't even notice because we
1800  * just get a lookup table entry. */
1801 static int wimfs_write(const char *path, const char *buf, size_t size,
1802                        off_t offset, struct fuse_file_info *fi)
1803 {
1804         struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
1805         int ret;
1806         u64 now;
1807
1808         if (!fd)
1809                 return -EBADF;
1810
1811         wimlib_assert(fd->f_lte);
1812         wimlib_assert(fd->f_lte->staging_file_name);
1813         wimlib_assert(fd->staging_fd != -1);
1814         wimlib_assert(fd->f_inode);
1815
1816         /* Seek to the requested position */
1817         if (lseek(fd->staging_fd, offset, SEEK_SET) == -1)
1818                 return -errno;
1819
1820         /* Write the data. */
1821         ret = write(fd->staging_fd, buf, size);
1822         if (ret == -1)
1823                 return -errno;
1824
1825         now = get_wim_timestamp();
1826         fd->f_inode->last_write_time = now;
1827         fd->f_inode->last_access_time = now;
1828         return ret;
1829 }
1830
1831 static struct fuse_operations wimfs_operations = {
1832         .access      = wimfs_access,
1833         .chmod       = wimfs_chmod,
1834         .destroy     = wimfs_destroy,
1835 #if 0
1836         .fallocate   = wimfs_fallocate,
1837 #endif
1838         .fgetattr    = wimfs_fgetattr,
1839         .ftruncate   = wimfs_ftruncate,
1840         .getattr     = wimfs_getattr,
1841 #ifdef ENABLE_XATTR
1842         .getxattr    = wimfs_getxattr,
1843 #endif
1844         .link        = wimfs_link,
1845 #ifdef ENABLE_XATTR
1846         .listxattr   = wimfs_listxattr,
1847 #endif
1848         .mkdir       = wimfs_mkdir,
1849         .mknod       = wimfs_mknod,
1850         .open        = wimfs_open,
1851         .opendir     = wimfs_opendir,
1852         .read        = wimfs_read,
1853         .readdir     = wimfs_readdir,
1854         .readlink    = wimfs_readlink,
1855         .release     = wimfs_release,
1856         .releasedir  = wimfs_releasedir,
1857 #ifdef ENABLE_XATTR
1858         .removexattr = wimfs_removexattr,
1859 #endif
1860         .rename      = wimfs_rename,
1861         .rmdir       = wimfs_rmdir,
1862 #ifdef ENABLE_XATTR
1863         .setxattr    = wimfs_setxattr,
1864 #endif
1865         .symlink     = wimfs_symlink,
1866         .truncate    = wimfs_truncate,
1867         .unlink      = wimfs_unlink,
1868 #ifdef HAVE_UTIMENSAT
1869         .utimens     = wimfs_utimens,
1870 #else
1871         .utime       = wimfs_utime,
1872 #endif
1873         .write       = wimfs_write,
1874
1875 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
1876         .flag_nullpath_ok = 1,
1877 #endif
1878 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 9)
1879         .flag_nopath = 1,
1880         .flag_utime_omit_ok = 1,
1881 #endif
1882 };
1883
1884
1885 /* Mounts an image from a WIM file. */
1886 WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
1887                                  int mount_flags, WIMStruct **additional_swms,
1888                                  unsigned num_additional_swms,
1889                                  const char *staging_dir)
1890 {
1891         int argc = 0;
1892         char *argv[16];
1893         int ret;
1894         char *dir_copy;
1895         struct lookup_table *joined_tab, *wim_tab_save;
1896         struct image_metadata *imd;
1897         struct wimfs_context ctx;
1898
1899         DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
1900               wim, image, dir, mount_flags);
1901
1902         if (!wim || !dir)
1903                 return WIMLIB_ERR_INVALID_PARAM;
1904
1905         ret = verify_swm_set(wim, additional_swms, num_additional_swms);
1906         if (ret != 0)
1907                 return ret;
1908
1909         if ((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) && (wim->hdr.total_parts != 1)) {
1910                 ERROR("Cannot mount a split WIM read-write");
1911                 return WIMLIB_ERR_SPLIT_UNSUPPORTED;
1912         }
1913
1914         if (num_additional_swms) {
1915                 ret = new_joined_lookup_table(wim, additional_swms,
1916                                               num_additional_swms,
1917                                               &joined_tab);
1918                 if (ret != 0)
1919                         return ret;
1920                 wim_tab_save = wim->lookup_table;
1921                 wim->lookup_table = joined_tab;
1922         }
1923
1924         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
1925                 ret = wim_run_full_verifications(wim);
1926                 if (ret != 0)
1927                         goto out;
1928         }
1929
1930         ret = select_wim_image(wim, image);
1931
1932         if (ret != 0)
1933                 goto out;
1934
1935         imd = &wim->image_metadata[image - 1];
1936
1937         DEBUG("Selected image %d", image);
1938
1939         if (imd->root_dentry->refcnt != 1) {
1940                 ERROR("Cannot mount image that was just exported with "
1941                       "wimlib_export_image()");
1942                 ret = WIMLIB_ERR_INVALID_PARAM;
1943                 goto out;
1944         }
1945
1946         if (imd->modified) {
1947                 ERROR("Cannot mount image that was added "
1948                       "with wimlib_add_image()");
1949                 ret = WIMLIB_ERR_INVALID_PARAM;
1950                 goto out;
1951         }
1952
1953         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
1954                 ret = lock_wim(wim->fp, wim->filename);
1955                 if (ret != 0)
1956                         goto out;
1957         }
1958
1959         if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
1960                        WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
1961                        WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
1962                 mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
1963
1964
1965         DEBUG("Initializing struct wimfs_context");
1966         init_wimfs_context(&ctx);
1967         ctx.wim = wim;
1968         ctx.mount_flags = mount_flags;
1969
1970         DEBUG("Unlinking message queues in case they already exist");
1971         ret = set_message_queue_names(&ctx, dir);
1972         if (ret != 0)
1973                 goto out;
1974         unlink_message_queues(&ctx);
1975
1976         DEBUG("Preparing arguments to fuse_main()");
1977
1978         dir_copy = STRDUP(dir);
1979         if (!dir_copy)
1980                 goto out_free_message_queue_names;
1981
1982         argv[argc++] = "imagex";
1983         argv[argc++] = dir_copy;
1984
1985         /* disable multi-threaded operation for read-write mounts */
1986         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
1987                 argv[argc++] = "-s";
1988
1989         if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
1990                 argv[argc++] = "-d";
1991
1992         /*
1993          * We provide the use_ino option because we are going to assign inode
1994          * numbers oursides.  The inodes will be given unique numbers in the
1995          * assign_inode_numbers() function, and the static variable @next_ino is
1996          * set to the next available inode number.
1997          */
1998         char optstring[256] = "use_ino,subtype=wimfs,attr_timeout=0";
1999         argv[argc++] = "-o";
2000         argv[argc++] = optstring;
2001         if ((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
2002                 /* Read-write mount.  Make the staging directory */
2003                 ret = make_staging_dir(&ctx, staging_dir);
2004                 if (ret != 0)
2005                         goto out_free_dir_copy;
2006         } else {
2007                 /* Read-only mount */
2008                 strcat(optstring, ",ro");
2009         }
2010         argv[argc] = NULL;
2011
2012 #ifdef ENABLE_DEBUG
2013         {
2014                 int i;
2015                 DEBUG("FUSE command line (argc = %d): ", argc);
2016                 for (i = 0; i < argc; i++) {
2017                         fputs(argv[i], stdout);
2018                         putchar(' ');
2019                 }
2020                 putchar('\n');
2021                 fflush(stdout);
2022         }
2023 #endif
2024
2025         /* Mark dentry tree as modified if read-write mount. */
2026         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2027                 imd->modified = 1;
2028                 imd->has_been_mounted_rw = 1;
2029         }
2030
2031         /* Resolve all the lookup table entries of the dentry tree */
2032         DEBUG("Resolving lookup table entries");
2033         for_dentry_in_tree(imd->root_dentry, dentry_resolve_ltes,
2034                            wim->lookup_table);
2035
2036         ctx.next_ino = assign_inode_numbers(&imd->inode_list);
2037         DEBUG("(next_ino = %"PRIu64")", ctx.next_ino);
2038
2039
2040         DEBUG("Calling fuse_main()");
2041
2042         ret = fuse_main(argc, argv, &wimfs_operations, &ctx);
2043
2044         DEBUG("Returned from fuse_main() (ret = %d)", ret);
2045         if (ret)
2046                 ret = WIMLIB_ERR_FUSE;
2047 out_free_dir_copy:
2048         FREE(dir_copy);
2049 out_free_message_queue_names:
2050         free_message_queue_names(&ctx);
2051 out:
2052         if (num_additional_swms) {
2053                 free_lookup_table(wim->lookup_table);
2054                 wim->lookup_table = wim_tab_save;
2055         }
2056         return ret;
2057 }
2058
2059
2060 /*
2061  * Unmounts the WIM file that was previously mounted on @dir by using
2062  * wimlib_mount_image().
2063  */
2064 WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
2065                                    wimlib_progress_func_t progress_func)
2066 {
2067         pid_t pid;
2068         int status;
2069         int ret;
2070         char msg[2];
2071         struct timeval now;
2072         struct timespec timeout;
2073         long msgsize;
2074         struct wimfs_context ctx;
2075         char *mailbox;
2076
2077         init_wimfs_context(&ctx);
2078
2079         /* Open message queues between the unmount process and the
2080          * filesystem daemon. */
2081         ret = set_message_queue_names(&ctx, dir);
2082         if (ret != 0)
2083                 goto out;
2084
2085         ret = open_message_queues(&ctx, false);
2086         if (ret != 0)
2087                 goto out_free_message_queue_names;
2088
2089         /* Send a message to the filesystem daemon saying whether to commit or
2090          * not. */
2091         msg[0] = (unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) ? 1 : 0;
2092         msg[1] = (unmount_flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY) ? 1 : 0;
2093
2094         DEBUG("Sending message: %scommit, %scheck",
2095                         (msg[0] ? "" : "don't "),
2096                         (msg[1] ? "" : "don't "));
2097         ret = mq_send(ctx.unmount_to_daemon_mq, msg, 2, 1);
2098         if (ret == -1) {
2099                 ERROR_WITH_ERRNO("Failed to notify filesystem daemon whether "
2100                                  "we want to commit changes or not");
2101                 ret = WIMLIB_ERR_MQUEUE;
2102                 goto out_close_message_queues;
2103         }
2104
2105         /* Execute `fusermount -u', which is installed setuid root, to unmount
2106          * the WIM.
2107          *
2108          * FUSE does not yet implement synchronous unmounts.  This means that
2109          * fusermount -u will return before the filesystem daemon returns from
2110          * wimfs_destroy().  This is partly what we want, because we need to
2111          * send a message from this process to the filesystem daemon telling
2112          * whether --commit was specified or not.  However, after that, the
2113          * unmount process must wait for the filesystem daemon to finish writing
2114          * the WIM file.
2115          */
2116
2117         pid = fork();
2118         if (pid == -1) {
2119                 ERROR_WITH_ERRNO("Failed to fork()");
2120                 ret = WIMLIB_ERR_FORK;
2121                 goto out_close_message_queues;
2122         }
2123         if (pid == 0) {
2124                 /* Child */
2125                 execlp("fusermount", "fusermount", "-u", dir, NULL);
2126                 ERROR_WITH_ERRNO("Failed to execute `fusermount'");
2127                 exit(WIMLIB_ERR_FUSERMOUNT);
2128         }
2129
2130         /* Parent */
2131         ret = wait(&status);
2132         if (ret == -1) {
2133                 ERROR_WITH_ERRNO("Failed to wait for fusermount process to "
2134                                  "terminate");
2135                 ret = WIMLIB_ERR_FUSERMOUNT;
2136                 goto out_close_message_queues;
2137         }
2138
2139         if (status != 0) {
2140                 ERROR("fusermount exited with status %d", status);
2141
2142                 /* Try again, but with the `umount' program.  This is required
2143                  * on other FUSE implementations such as FreeBSD's that do not
2144                  * have a `fusermount' program. */
2145
2146                 pid = fork();
2147                 if (pid == -1) {
2148                         ERROR_WITH_ERRNO("Failed to fork()");
2149                         ret = WIMLIB_ERR_FORK;
2150                         goto out_close_message_queues;
2151                 }
2152                 if (pid == 0) {
2153                         /* Child */
2154                         execlp("umount", "umount", dir, NULL);
2155                         ERROR_WITH_ERRNO("Failed to execute `umount'");
2156                         exit(WIMLIB_ERR_FUSERMOUNT);
2157                 }
2158
2159                 /* Parent */
2160                 ret = wait(&status);
2161                 if (ret == -1) {
2162                         ERROR_WITH_ERRNO("Failed to wait for `umount' process to "
2163                                          "terminate");
2164                         ret = WIMLIB_ERR_FUSERMOUNT;
2165                         goto out_close_message_queues;
2166                 }
2167                 if (status != 0) {
2168                         ERROR("`umount' exited with failure status");
2169                         ret = WIMLIB_ERR_FUSERMOUNT;
2170                         goto out_close_message_queues;
2171                 }
2172         }
2173
2174         wimlib_assert(status == 0);
2175
2176         /* Wait for a message from the filesytem daemon indicating whether  the
2177          * filesystem was unmounted successfully (0) or an error occurred (1).
2178          * This may take a long time if a big WIM file needs to be rewritten. */
2179
2180         /* Wait at most 600??? seconds before giving up and returning false.
2181          * Either it's a really big WIM file, or (more likely) the
2182          * filesystem daemon has crashed or failed for some reason.
2183          *
2184          * XXX come up with some method to determine if the filesystem
2185          * daemon has really crashed or not.
2186          *
2187          * XXX Idea: have mount daemon write its PID into the WIM file header?
2188          * No, this wouldn't work because we know the directory but not the WIM
2189          * file...
2190          * */
2191
2192         gettimeofday(&now, NULL);
2193         timeout.tv_sec = now.tv_sec + 600;
2194         timeout.tv_nsec = now.tv_usec * 1000;
2195
2196         ret = get_mailbox(ctx.daemon_to_unmount_mq, 2, &msgsize, &mailbox);
2197         if (ret != 0)
2198                 goto out_close_message_queues;
2199
2200         mailbox[0] = 0;
2201         DEBUG("Waiting for message telling us whether the unmount was "
2202                         "successful or not.");
2203         ret = mq_timedreceive(ctx.daemon_to_unmount_mq, mailbox,
2204                               msgsize, NULL, &timeout);
2205         if (ret == -1) {
2206                 if (errno == ETIMEDOUT) {
2207                         ERROR("Timed out- probably the filesystem daemon "
2208                               "crashed and the WIM was not written "
2209                               "successfully.");
2210                         ret = WIMLIB_ERR_TIMEOUT;
2211                 } else {
2212                         ERROR_WITH_ERRNO("mq_receive()");
2213                         ret = WIMLIB_ERR_MQUEUE;
2214                 }
2215                 goto out_free_mailbox;
2216
2217         }
2218         DEBUG("Received message: Unmount %s", (mailbox[0] ? "Failed" : "Ok"));
2219         ret = mailbox[0];
2220         if (ret)
2221                 ERROR("Unmount failed");
2222 out_free_mailbox:
2223         FREE(mailbox);
2224 out_close_message_queues:
2225         close_message_queues(&ctx);
2226 out_free_message_queue_names:
2227         free_message_queue_names(&ctx);
2228 out:
2229         return ret;
2230 }
2231
2232 #else /* WITH_FUSE */
2233
2234
2235 static inline int mount_unsupported_error()
2236 {
2237         ERROR("wimlib was compiled with --without-fuse, which disables support "
2238               "for mounting WIMs.");
2239         return WIMLIB_ERR_UNSUPPORTED;
2240 }
2241
2242 WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
2243                                    wimlib_progress_func_t progress_func)
2244 {
2245         return mount_unsupported_error();
2246 }
2247
2248 WIMLIBAPI int wimlib_mount_image(WIMStruct *wim_p, int image, const char *dir,
2249                                  int mount_flags, WIMStruct **additional_swms,
2250                                  unsigned num_additional_swms,
2251                                  const char *staging_dir)
2252 {
2253         return mount_unsupported_error();
2254 }
2255
2256 #endif /* WITH_FUSE */