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