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