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