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