]> wimlib.net Git - wimlib/blob - src/mount_image.c
Fix file locking
[wimlib] / src / mount_image.c
1 /*
2  * mount_image.c
3  *
4  * This file implements mounting of WIM files using FUSE, which stands for
5  * Filesystem in Userspace.  FUSE allows a filesystem to be implemented in a
6  * userspace process by implementing the filesystem primitives--- read(),
7  * write(), readdir(), etc.
8  */
9
10 /*
11  * Copyright (C) 2012, 2013, 2014 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 #ifdef HAVE_CONFIG_H
30 #  include "config.h"
31 #endif
32
33 #include "wimlib.h"
34
35 #ifdef WITH_FUSE
36
37 #ifdef __WIN32__
38 #  error "FUSE mount not supported on Windows!  Please configure --without-fuse"
39 #endif
40
41 #include "wimlib/dentry.h"
42 #include "wimlib/encoding.h"
43 #include "wimlib/metadata.h"
44 #include "wimlib/paths.h"
45 #include "wimlib/progress.h"
46 #include "wimlib/reparse.h"
47 #include "wimlib/timestamp.h"
48 #include "wimlib/unix_data.h"
49 #include "wimlib/write.h"
50 #include "wimlib/xml.h"
51
52 #include <dirent.h>
53 #include <errno.h>
54 #include <limits.h>
55 #include <mqueue.h>
56 #include <pthread.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <sys/stat.h>
60 #include <sys/time.h>
61 #include <sys/types.h>
62 #include <unistd.h>
63 #include <utime.h>
64
65 #define FUSE_USE_VERSION 26
66 #include <fuse.h>
67 #include <attr/xattr.h>
68
69 #ifndef O_NOFOLLOW
70 #  define O_NOFOLLOW 0  /* Security only...  */
71 #endif
72
73 #define WIMFS_MQUEUE_NAME_LEN 32
74
75 #define WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS 0x80000000
76
77 struct wimfs_unmount_info {
78         unsigned unmount_flags;
79         char mq_name[WIMFS_MQUEUE_NAME_LEN + 1];
80 };
81
82 struct commit_progress_report {
83         enum wimlib_progress_msg msg;
84         union wimlib_progress_info info;
85 };
86
87 /* Description of an open file on a mounted WIM image.  Actually, this
88  * represents the open state of a particular data stream of an inode, rather
89  * than the inode itself.  (An inode might have multiple named data streams in
90  * addition to the default, unnamed data stream.)  At a given time, an inode in
91  * the WIM image might have multiple file descriptors open to it, each to any
92  * one of its data streams.  */
93 struct wimfs_fd {
94
95         /* Pointer to the inode of this open file.
96          * 'i_num_opened_fds' of the inode tracks the number of file descriptors
97          * that reference it.  */
98         struct wim_inode *f_inode;
99
100         /* Pointer to the lookup table entry for the data stream that has been
101          * opened.  'num_opened_fds' of the lookup table entry tracks the number
102          * of file descriptors that reference it.  Or, this value may be NULL,
103          * which indicates that the opened stream is empty and consequently does
104          * not have a lookup table entry.  */
105         struct wim_lookup_table_entry *f_lte;
106
107         /* If valid (filedes_valid(&f_staging_fd)), this contains the
108          * corresponding native file descriptor for the staging file that has
109          * been created for reading from and/or writing to this open stream.  A
110          * single staging file might have multiple file descriptors open to it
111          * simultaneously, each used by a different 'struct wimfs_fd'.
112          *
113          * Or, if invalid (!filedes_valid(&f_staging_fd)), this 'struct
114          * wimfs_fd' is not associated with a staging file.  This is permissible
115          * only if this 'struct wimfs_fd' was opened read-only and the stream
116          * has not yet been extracted to a staging file.  */
117         struct filedes f_staging_fd;
118
119         /* 0-based index of this file descriptor in the file descriptor table of
120          * its inode.  */
121         u16 f_idx;
122
123         /* Unique ID of the opened stream in the inode.  This will stay the same
124          * even if the indices of the inode's alternate data streams are changed
125          * by a deletion.  */
126         u32 f_stream_id;
127 };
128
129 #define WIMFS_FD(fi) ((struct wimfs_fd *)(uintptr_t)((fi)->fh))
130
131 /* Context structure for a mounted WIM image.  */
132 struct wimfs_context {
133         /* The WIMStruct containing the mounted image.  The mounted image is the
134          * currently selected image (wim->current_image).  */
135         WIMStruct *wim;
136
137         /* Flags passed to wimlib_mount_image() (WIMLIB_MOUNT_FLAG_*).  */
138         int mount_flags;
139
140         /* Default flags for path lookup in the WIM image.  */
141         int default_lookup_flags;
142
143         /* Information about the user who has mounted the WIM image  */
144         uid_t owner_uid;
145         gid_t owner_gid;
146
147         /* Information about the staging directory for a read-write mount.  */
148         int parent_dir_fd;
149         int staging_dir_fd;
150         char *staging_dir_name;
151
152         /* For read-write mounts, the inode number to be assigned to the next
153          * created file.  Note: since this isn't a persistent filesystem and we
154          * can re-assign the inode numbers just before mounting the image, it's
155          * good enough to just generate inode numbers sequentially.  */
156         u64 next_ino;
157
158         /* Number of file descriptors open to the mounted WIM image.  */
159         unsigned long num_open_fds;
160
161         /* Original list of single-instance streams in the mounted image, linked
162          * by 'struct wim_lookup_table_entry'.orig_stream_list.  */
163         struct list_head orig_stream_list;
164
165         /* Parameters for unmounting the image (can be set via extended
166          * attribute "wimfs.unmount_info").  */
167         struct wimfs_unmount_info unmount_info;
168 };
169
170 #define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data)
171
172 /* Retrieve the context structure for the currently mounted WIM image.
173  *
174  * Note: this is a per-thread variable.  It is possible for different threads to
175  * mount different images at the same time in the same process, although they
176  * must use different WIMStructs!  */
177 static inline struct wimfs_context *
178 wimfs_get_context(void)
179 {
180         return WIMFS_CTX(fuse_get_context());
181 }
182
183 static void
184 wimfs_inc_num_open_fds(void)
185 {
186         wimfs_get_context()->num_open_fds++;
187 }
188
189 static void
190 wimfs_dec_num_open_fds(void)
191 {
192         wimfs_get_context()->num_open_fds--;
193 }
194
195 /* Retrieve the WIMStruct for the currently mounted WIM image.  */
196 static inline WIMStruct *
197 wimfs_get_WIMStruct(void)
198 {
199         return wimfs_get_context()->wim;
200 }
201
202 /* Is write permission requested on the file?  */
203 static inline bool
204 flags_writable(int open_flags)
205 {
206         int accmode = (open_flags & O_ACCMODE);
207         return (accmode == O_RDWR || accmode == O_WRONLY);
208 }
209
210 static mode_t
211 fuse_mask_mode(mode_t mode, const struct fuse_context *fuse_ctx)
212 {
213 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
214         mode &= ~fuse_ctx->umask;
215 #endif
216         return mode;
217 }
218
219 /*
220  * Allocate a file descriptor to a data stream in the mounted WIM image.
221  *
222  * @inode
223  *      A pointer to the inode containing the stream being opened.
224  * @stream_id
225  *      The ID of the data stream being opened within the inode.
226  * @lte
227  *      A pointer to the lookup table entry for the stream data.  Or, for a
228  *      0-byte stream, this may be NULL.
229  * @fd_ret
230  *      On success, a pointer to the new file descriptor will be stored here.
231  *
232  * Returns 0 or a -errno code.
233  */
234 static int
235 alloc_wimfs_fd(struct wim_inode *inode,
236                u32 stream_id,
237                struct wim_lookup_table_entry *lte,
238                struct wimfs_fd **fd_ret)
239 {
240         static const u16 min_fds_per_alloc = 8;
241         static const u16 max_fds = 0xffff;
242         u16 i;
243         struct wimfs_fd *fd;
244
245         if (inode->i_num_opened_fds == inode->i_num_allocated_fds) {
246                 u16 num_new_fds;
247                 struct wimfs_fd **fds;
248
249                 /* Expand this inode's file descriptor table.  */
250
251                 num_new_fds = max(min_fds_per_alloc,
252                                   inode->i_num_allocated_fds / 4);
253
254                 num_new_fds = min(num_new_fds,
255                                   max_fds - inode->i_num_allocated_fds);
256
257                 if (num_new_fds == 0)
258                         return -EMFILE;
259
260                 fds = REALLOC(inode->i_fds,
261                               (inode->i_num_allocated_fds + num_new_fds) *
262                                 sizeof(fds[0]));
263                 if (!fds)
264                         return -ENOMEM;
265
266                 memset(&fds[inode->i_num_allocated_fds], 0,
267                        num_new_fds * sizeof(fds[0]));
268                 inode->i_fds = fds;
269                 inode->i_num_allocated_fds += num_new_fds;
270                 inode->i_next_fd = inode->i_num_opened_fds;
271         }
272
273         /* Allocate the file descriptor in the first available space in the
274          * inode's file descriptor table.
275          *
276          * i_next_fd is the lower bound on the next open slot.  */
277         for (i = inode->i_next_fd; inode->i_fds[i]; i++)
278                 ;
279
280         fd = MALLOC(sizeof(*fd));
281         if (!fd)
282                 return -ENOMEM;
283
284         fd->f_inode     = inode;
285         fd->f_lte       = lte;
286         filedes_invalidate(&fd->f_staging_fd);
287         fd->f_idx       = i;
288         fd->f_stream_id = stream_id;
289         *fd_ret         = fd;
290         inode->i_fds[i] = fd;
291         inode->i_num_opened_fds++;
292         if (lte)
293                 lte->num_opened_fds++;
294         wimfs_inc_num_open_fds();
295         inode->i_next_fd = i + 1;
296         return 0;
297 }
298
299 /*
300  * Close a file descriptor to a data stream in the mounted WIM image.
301  *
302  * Returns 0 or a -errno code.  The file descriptor is always closed.
303  */
304 static int
305 close_wimfs_fd(struct wimfs_fd *fd)
306 {
307         int ret = 0;
308         struct wim_inode *inode;
309
310         /* Close the staging file if open.  */
311         if (filedes_valid(&fd->f_staging_fd))
312                  if (filedes_close(&fd->f_staging_fd))
313                          ret = -errno;
314
315         /* Release this file descriptor from its lookup table entry.  */
316         if (fd->f_lte)
317                 lte_decrement_num_opened_fds(fd->f_lte);
318
319         wimfs_dec_num_open_fds();
320
321         /* Release this file descriptor from its inode.  */
322         inode = fd->f_inode;
323         inode->i_fds[fd->f_idx] = NULL;
324         if (fd->f_idx < inode->i_next_fd)
325                 inode->i_next_fd = fd->f_idx;
326         FREE(fd);
327         if (--inode->i_num_opened_fds == 0) {
328                 /* The last file descriptor to this inode was closed.  */
329                 FREE(inode->i_fds);
330                 inode->i_fds = NULL;
331                 inode->i_num_allocated_fds = 0;
332                 if (inode->i_nlink == 0)
333                         /* No links to this inode remain.  Get rid of it.  */
334                         free_inode(inode);
335         }
336         return ret;
337 }
338
339 /*
340  * Translate a path into the corresponding inode in the mounted WIM image.
341  *
342  * See get_dentry() for more information.
343  *
344  * Returns a pointer to the resulting inode, or NULL with errno set.
345  */
346 static struct wim_inode *
347 wim_pathname_to_inode(WIMStruct *wim, const char *path)
348 {
349         struct wim_dentry *dentry;
350
351         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
352         if (!dentry)
353                 return NULL;
354         return dentry->d_inode;
355 }
356
357 /* Can look up named data stream with colon syntax  */
358 #define LOOKUP_FLAG_ADS_OK              0x01
359
360 /* Can look up directory (otherwise get -ENOTDIR)  */
361 #define LOOKUP_FLAG_DIRECTORY_OK        0x02
362
363 /*
364  * Translate a path into the corresponding dentry, lookup table entry, and
365  * stream index in the mounted WIM image.
366  *
367  * Returns 0 or a -errno code.  All of @dentry_ret, @lte_ret, and
368  * @stream_idx_ret are optional.
369  */
370 static int
371 wim_pathname_to_stream(const struct wimfs_context *ctx, const char *path,
372                        int lookup_flags,
373                        struct wim_dentry **dentry_ret,
374                        struct wim_lookup_table_entry **lte_ret,
375                        u16 *stream_idx_ret)
376 {
377         WIMStruct *wim = ctx->wim;
378         struct wim_dentry *dentry;
379         struct wim_lookup_table_entry *lte;
380         u16 stream_idx;
381         const tchar *stream_name = NULL;
382         struct wim_inode *inode;
383         tchar *p = NULL;
384
385         lookup_flags |= ctx->default_lookup_flags;
386
387         if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
388                 stream_name = path_stream_name(path);
389                 if (stream_name) {
390                         p = (tchar*)stream_name - 1;
391                         *p = T('\0');
392                 }
393         }
394
395         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
396         if (p)
397                 *p = T(':');
398         if (!dentry)
399                 return -errno;
400
401         inode = dentry->d_inode;
402
403         if (!inode->i_resolved)
404                 if (inode_resolve_streams(inode, wim->lookup_table, false))
405                         return -EIO;
406
407         if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
408               && inode_is_directory(inode))
409                 return -EISDIR;
410
411         if (stream_name) {
412                 struct wim_ads_entry *ads_entry;
413
414                 ads_entry = inode_get_ads_entry(inode, stream_name);
415                 if (!ads_entry)
416                         return -errno;
417
418                 stream_idx = ads_entry - inode->i_ads_entries + 1;
419                 lte = ads_entry->lte;
420         } else {
421                 lte = inode_unnamed_stream_resolved(inode, &stream_idx);
422         }
423         if (dentry_ret)
424                 *dentry_ret = dentry;
425         if (lte_ret)
426                 *lte_ret = lte;
427         if (stream_idx_ret)
428                 *stream_idx_ret = stream_idx;
429         return 0;
430 }
431
432 /*
433  * Create a new file in the mounted WIM image.
434  *
435  * @fuse_ctx
436  *      The FUSE context for the mounted image.
437  * @path
438  *      The path at which to create the first link to the new file.  If a file
439  *      already exists at this path, -EEXIST is returned.
440  * @mode
441  *      The UNIX mode for the new file.  This is only honored if
442  *      WIMLIB_MOUNT_FLAG_UNIX_DATA was passed to wimlib_mount_image().
443  * @rdev
444  *      The device ID for the new file, encoding the major and minor device
445  *      numbers.  This is only honored if WIMLIB_MOUNT_FLAG_UNIX_DATA was passed
446  *      to wimlib_mount_image().
447  * @attributes
448  *      Windows file attributes to use for the new file.
449  * @dentry_ret
450  *      On success, a pointer to the new dentry is returned here.  Its d_inode
451  *      member will point to the new inode that was created for it and added to
452  *      the mounted WIM image.
453  *
454  * Returns 0 or a -errno code.
455  */
456 static int
457 create_dentry(struct fuse_context *fuse_ctx, const char *path,
458               mode_t mode, dev_t rdev, u32 attributes,
459               struct wim_dentry **dentry_ret)
460 {
461         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
462         struct wim_dentry *parent;
463         const char *basename;
464         struct wim_dentry *new_dentry;
465         struct wim_inode *new_inode;
466
467         parent = get_parent_dentry(wimfs_ctx->wim, path, WIMLIB_CASE_SENSITIVE);
468         if (!parent)
469                 return -errno;
470
471         if (!dentry_is_directory(parent))
472                 return -ENOTDIR;
473
474         basename = path_basename(path);
475
476         if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE))
477                 return -EEXIST;
478
479         if (new_dentry_with_inode(basename, &new_dentry))
480                 return -ENOMEM;
481
482         new_inode = new_dentry->d_inode;
483
484         new_inode->i_resolved = 1;
485         new_inode->i_ino = wimfs_ctx->next_ino++;
486         new_inode->i_attributes = attributes;
487
488         if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
489                 struct wimlib_unix_data unix_data;
490
491                 unix_data.uid = fuse_ctx->uid;
492                 unix_data.gid = fuse_ctx->gid;
493                 unix_data.mode = fuse_mask_mode(mode, fuse_ctx);
494                 unix_data.rdev = rdev;
495                 if (!inode_set_unix_data(new_inode, &unix_data, UNIX_DATA_ALL))
496                 {
497                         free_dentry(new_dentry);
498                         return -ENOMEM;
499                 }
500         }
501
502         list_add_tail(&new_inode->i_list,
503                       &wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
504
505         dentry_add_child(parent, new_dentry);
506
507         if (dentry_ret)
508                 *dentry_ret = new_dentry;
509         return 0;
510 }
511
512 /*
513  * Remove a dentry from the mounted WIM image; i.e. remove an alias for an
514  * inode.
515  */
516 static void
517 remove_dentry(struct wim_dentry *dentry,
518               struct wim_lookup_table *lookup_table)
519 {
520         /* Drop the reference to each stream the inode contains.  */
521         inode_unref_streams(dentry->d_inode, lookup_table);
522
523         /* Unlink the dentry from the image's dentry tree.  */
524         unlink_dentry(dentry);
525
526         /* Delete the dentry.  This will also decrement the link count of the
527          * corresponding inode, and possibly cause it to be deleted as well.  */
528         free_dentry(dentry);
529 }
530
531 /* Generate UNIX filetype mode bits for the specified WIM inode, based on its
532  * Windows file attributes.  */
533 static mode_t
534 inode_unix_file_type(const struct wim_inode *inode)
535 {
536         if (inode_is_symlink(inode))
537                 return S_IFLNK;
538         else if (inode_is_directory(inode))
539                 return S_IFDIR;
540         else
541                 return S_IFREG;
542 }
543
544 /* Generate a default UNIX mode for the specified WIM inode.  */
545 static mode_t
546 inode_default_unix_mode(const struct wim_inode *inode)
547 {
548         return inode_unix_file_type(inode) | 0777;
549 }
550
551 /*
552  * Retrieve standard UNIX metadata ('struct stat') for a WIM inode.
553  *
554  * @lte specifies the stream of the inode that is being queried.  We mostly
555  * return the same information for all streams, but st_size and st_blocks may be
556  * different for different streams.
557  *
558  * This always returns 0.
559  */
560 static int
561 inode_to_stbuf(const struct wim_inode *inode,
562                const struct wim_lookup_table_entry *lte,
563                struct stat *stbuf)
564 {
565         const struct wimfs_context *ctx = wimfs_get_context();
566         struct wimlib_unix_data unix_data;
567
568         memset(stbuf, 0, sizeof(struct stat));
569         if ((ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) &&
570             inode_get_unix_data(inode, &unix_data))
571         {
572                 /* Use the user ID, group ID, mode, and device ID from the
573                  * inode's extra UNIX metadata information.  */
574                 stbuf->st_uid = unix_data.uid;
575                 stbuf->st_gid = unix_data.gid;
576                 stbuf->st_mode = unix_data.mode;
577                 stbuf->st_rdev = unix_data.rdev;
578         } else {
579                 /* Generate default values for the user ID, group ID, and mode.
580                  *
581                  * Note: in the case of an allow_other mount, fuse_context.uid
582                  * may not be the same as wimfs_context.owner_uid!  */
583                 stbuf->st_uid = ctx->owner_uid;
584                 stbuf->st_gid = ctx->owner_gid;
585                 stbuf->st_mode = inode_default_unix_mode(inode);
586         }
587         stbuf->st_ino = inode->i_ino;
588         stbuf->st_nlink = inode->i_nlink;
589         if (lte)
590                 stbuf->st_size = lte->size;
591 #ifdef HAVE_STAT_NANOSECOND_PRECISION
592         stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time);
593         stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time);
594         stbuf->st_ctim = stbuf->st_mtim;
595 #else
596         stbuf->st_atime = wim_timestamp_to_unix(inode->i_last_access_time);
597         stbuf->st_mtime = wim_timestamp_to_unix(inode->i_last_write_time);
598         stbuf->st_ctime = stbuf->st_mtime;
599 #endif
600         stbuf->st_blocks = (stbuf->st_size + 511) / 512;
601         return 0;
602 }
603
604 /* Update the last access and last write timestamps of a WIM inode.  */
605 static void
606 touch_inode(struct wim_inode *inode)
607 {
608         u64 now = get_wim_timestamp();
609         inode->i_last_access_time = now;
610         inode->i_last_write_time = now;
611 }
612
613 static void
614 touch_parent(struct wim_dentry *dentry)
615 {
616         touch_inode(dentry->d_parent->d_inode);
617 }
618
619 /*
620  * Create a new file in the staging directory for a read-write mounted image.
621  *
622  * On success, returns the file descriptor for the new staging file, opened for
623  * writing.  In addition, stores the allocated name of the staging file in
624  * @name_ret.
625  *
626  * On failure, returns -1 and sets errno.
627  */
628 static int
629 create_staging_file(const struct wimfs_context *ctx, char **name_ret)
630 {
631
632         static const size_t STAGING_FILE_NAME_LEN = 20;
633         char *name;
634         int fd;
635
636         name = MALLOC(STAGING_FILE_NAME_LEN + 1);
637         if (!name)
638                 return -1;
639         name[STAGING_FILE_NAME_LEN] = '\0';
640
641 retry:
642         randomize_char_array_with_alnum(name, STAGING_FILE_NAME_LEN);
643         fd = openat(ctx->staging_dir_fd, name,
644                     O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
645         if (unlikely(fd < 0)) {
646                 if (unlikely(errno == EEXIST))
647                         /* Try again with another name.  */
648                         goto retry;
649                 FREE(name);
650         } else {
651                 *name_ret = name;
652         }
653         return fd;
654 }
655
656 /*
657  * Extract a WIM resource to the staging directory.
658  * This is necessary if a stream using the resource is being opened for writing.
659  *
660  * @inode
661  *      The inode containing the stream being opened for writing.
662  *
663  * @stream_idx
664  *      The index of the stream in @inode being opened for writing.
665  *
666  * @lte_ptr
667  *      *lte_ptr is the lookup table entry for the stream being extracted, or
668  *      NULL if the stream does not have a lookup table entry (which is possible
669  *      if the stream is empty).  On success, *lte_ptr will be set to point to a
670  *      lookup table entry that represents the resource in its new location in a
671  *      staging file.  This may be the same as the old entry in the case that it
672  *      was reused, or it may be a new entry.
673  *
674  * @size
675  *      Number of bytes of the stream to extract and include in the staging file
676  *      resource.  It may be less than the actual stream length, in which case
677  *      only a prefix of the resource will be extracted.  It may also be more
678  *      than the actual stream length, in which case the extra space will be
679  *      zero-filled.
680  *
681  * Returns 0 or a -errno code.
682  */
683 static int
684 extract_resource_to_staging_dir(struct wim_inode *inode,
685                                 u16 stream_idx,
686                                 struct wim_lookup_table_entry **lte_ptr,
687                                 off_t size,
688                                 const struct wimfs_context *ctx)
689 {
690         struct wim_lookup_table_entry *old_lte;
691         struct wim_lookup_table_entry *new_lte;
692         char *staging_file_name;
693         int staging_fd;
694         off_t extract_size;
695         int result;
696         u32 stream_id;
697         int ret;
698
699         old_lte = *lte_ptr;
700
701         /* Create the staging file.  */
702         staging_fd = create_staging_file(ctx, &staging_file_name);
703         if (unlikely(staging_fd < 0))
704                 return -errno;
705
706         /* Extract the stream to the staging file (possibly truncated).  */
707         if (old_lte) {
708                 struct filedes fd;
709
710                 filedes_init(&fd, staging_fd);
711                 errno = 0;
712                 extract_size = min(old_lte->size, size);
713                 result = extract_stream_to_fd(old_lte, &fd, extract_size);
714         } else {
715                 extract_size = 0;
716                 result = 0;
717         }
718
719         /* In the case of truncate() to more than the file length, extend the
720          * staging file with zeroes by calling ftruncate().  */
721         if (!result && size > extract_size)
722                 result = ftruncate(staging_fd, size);
723
724         /* Close the staging file.  */
725         if (close(staging_fd))
726                 result = -1;
727
728         /* If an error occurred, unlink the staging file.  */
729         if (unlikely(result)) {
730                 /* extract_stream_to_fd() should set errno, but if it didn't,
731                  * set a default value.  */
732                 ret = errno ? -errno : -EIO;
733                 goto out_delete_staging_file;
734         }
735
736         /* Now deal with the lookup table entries.  We may be able to re-use the
737          * existing entry, but we may have to create a new one instead.  */
738
739         stream_id = inode_stream_idx_to_id(inode, stream_idx);
740
741         if (old_lte && inode->i_nlink == old_lte->refcnt) {
742                 /* The reference count of the existing lookup table entry is the
743                  * same as the link count of the inode that contains the stream
744                  * we're opening.  Therefore, all the references to the lookup
745                  * table entry correspond to the stream we're trying to extract,
746                  * so the lookup table entry can be re-used.  */
747                 lookup_table_unlink(ctx->wim->lookup_table, old_lte);
748                 lte_put_resource(old_lte);
749                 new_lte = old_lte;
750         } else {
751                 /* We need to split the old lookup table entry because it also
752                  * has other references.  Or, there was no old lookup table
753                  * entry, so we need to create a new one anyway.  */
754
755                 new_lte = new_lookup_table_entry();
756                 if (unlikely(!new_lte)) {
757                         ret = -ENOMEM;
758                         goto out_delete_staging_file;
759                 }
760
761                 /* There may already be open file descriptors to this stream if
762                  * it's previously been opened read-only, but just now we're
763                  * opening it read-write.  Identify those file descriptors and
764                  * change their lookup table entry pointers to point to the new
765                  * lookup table entry, and open staging file descriptors for
766                  * them.
767                  *
768                  * At the same time, we need to count the number of these opened
769                  * file descriptors to the new lookup table entry.  If there's
770                  * an old lookup table entry, this number needs to be subtracted
771                  * from the fd's opened to the old entry.  */
772                 for (u16 i = 0, j = 0; j < inode->i_num_opened_fds; i++) {
773                         struct wimfs_fd *fd;
774                         int raw_fd;
775
776                         fd = inode->i_fds[i];
777                         if (!fd)
778                                 continue;
779
780                         j++;
781
782                         if (fd->f_stream_id != stream_id)
783                                 continue;
784
785                         /* This is a readonly fd for the same stream.  */
786                         fd->f_lte = new_lte;
787                         new_lte->num_opened_fds++;
788                         raw_fd = openat(ctx->staging_dir_fd, staging_file_name,
789                                         O_RDONLY | O_NOFOLLOW);
790                         if (unlikely(raw_fd < 0)) {
791                                 ret = -errno;
792                                 goto out_revert_fd_changes;
793                         }
794                         filedes_init(&fd->f_staging_fd, raw_fd);
795                 }
796                 if (old_lte) {
797                         old_lte->num_opened_fds -= new_lte->num_opened_fds;
798                         old_lte->refcnt -= inode->i_nlink;
799                 }
800         }
801
802         new_lte->refcnt            = inode->i_nlink;
803         new_lte->resource_location = RESOURCE_IN_STAGING_FILE;
804         new_lte->staging_file_name = staging_file_name;
805         new_lte->staging_dir_fd    = ctx->staging_dir_fd;
806         new_lte->size              = size;
807
808         add_unhashed_stream(new_lte, inode, stream_id,
809                             &wim_get_current_image_metadata(ctx->wim)->unhashed_streams);
810         if (stream_idx == 0)
811                 inode->i_lte = new_lte;
812         else
813                 inode->i_ads_entries[stream_idx - 1].lte = new_lte;
814         *lte_ptr = new_lte;
815         return 0;
816
817 out_revert_fd_changes:
818         for (u16 i = 0; new_lte->num_opened_fds; i++) {
819                 struct wimfs_fd *fd = inode->i_fds[i];
820                 if (fd && fd->f_stream_id == stream_id) {
821                         fd->f_lte = old_lte;
822                         if (filedes_valid(&fd->f_staging_fd)) {
823                                 filedes_close(&fd->f_staging_fd);
824                                 filedes_invalidate(&fd->f_staging_fd);
825                         }
826                         new_lte->num_opened_fds--;
827                 }
828         }
829         free_lookup_table_entry(new_lte);
830 out_delete_staging_file:
831         unlinkat(ctx->staging_dir_fd, staging_file_name, 0);
832         FREE(staging_file_name);
833         return ret;
834 }
835
836 /*
837  * Create the staging directory for the WIM file.
838  *
839  * The staging directory will be created in the directory specified by the open
840  * file descriptor @parent_dir_fd.  It will be given a randomly generated name
841  * based on @wim_basename, the name of the WIM file.
842  *
843  * On success, returns a file descriptor to the open staging directory with
844  * O_RDONLY access.  In addition, stores the allocated name of the staging
845  * directory (relative to @parent_dir_fd) in @staging_dir_name_ret.
846  * On failure, returns -1 and sets errno.
847  */
848 static int
849 make_staging_dir_at(int parent_dir_fd, const char *wim_basename,
850                     char **staging_dir_name_ret)
851 {
852         static const char common_suffix[8] = ".staging";
853         static const size_t random_suffix_len = 10;
854         size_t wim_basename_len;
855         size_t staging_dir_name_len;
856         char *staging_dir_name;
857         char *p;
858         int fd;
859
860         wim_basename_len = strlen(wim_basename);
861         staging_dir_name_len = wim_basename_len + sizeof(common_suffix) +
862                                random_suffix_len;
863         staging_dir_name = MALLOC(staging_dir_name_len + 1);
864         if (!staging_dir_name)
865                 return -1;
866
867         p = staging_dir_name;
868         p = mempcpy(p, wim_basename, wim_basename_len);
869         p = mempcpy(p, common_suffix, sizeof(common_suffix));
870         randomize_char_array_with_alnum(p, random_suffix_len);
871         p += random_suffix_len;
872         *p = '\0';
873
874         if (mkdirat(parent_dir_fd, staging_dir_name, 0700))
875                 goto err1;
876
877         fd = openat(parent_dir_fd, staging_dir_name,
878                     O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
879         if (fd < 0)
880                 goto err2;
881
882         *staging_dir_name_ret = staging_dir_name;
883         return fd;
884
885 err2:
886         unlinkat(parent_dir_fd, staging_dir_name, AT_REMOVEDIR);
887 err1:
888         FREE(staging_dir_name);
889         return -1;
890 }
891
892 /*
893  * Create the staging directory and set ctx->staging_dir_fd,
894  * ctx->staging_dir_name, and ctx->parent_dir_fd.
895  */
896 static int
897 make_staging_dir(struct wimfs_context *ctx, const char *parent_dir_path)
898 {
899         const char *wim_basename;
900         char *end = NULL;
901         int ret;
902
903         wim_basename = path_basename(ctx->wim->filename);
904
905         if (!parent_dir_path) {
906                 /* The user did not specify a directory.  Default to creating
907                  * the staging directory alongside the WIM file.  */
908                 if (wim_basename > ctx->wim->filename) {
909                         parent_dir_path = ctx->wim->filename;
910                         end = (char *)(wim_basename - 1);
911                         /* *end must be a slash.  Temporarily overwrite it so we
912                          * can open the parent directory.  */
913                         *end = '\0';
914                 } else {
915                         parent_dir_path = ".";
916                 }
917         }
918
919         /* Open the parent directory (in which we'll create our staging
920          * directory).  */
921         ctx->parent_dir_fd = open(parent_dir_path, O_RDONLY | O_DIRECTORY);
922         if (ctx->parent_dir_fd < 0) {
923                 ERROR_WITH_ERRNO("Can't open directory \"%s\"",
924                                  parent_dir_path);
925                 ret = WIMLIB_ERR_OPENDIR;
926                 goto out_restore_wim_filename;
927         }
928
929         ctx->staging_dir_fd = make_staging_dir_at(ctx->parent_dir_fd,
930                                                   wim_basename,
931                                                   &ctx->staging_dir_name);
932         if (ctx->staging_dir_fd < 0) {
933                 ERROR_WITH_ERRNO("Can't create staging directory in \"%s\"",
934                                  parent_dir_path);
935                 close(ctx->parent_dir_fd);
936                 ret = WIMLIB_ERR_MKDIR;
937                 goto out_restore_wim_filename;
938         }
939         ret = 0;
940 out_restore_wim_filename:
941         if (end)
942                 *end = '/';
943         return ret;
944 }
945
946 /* Deletes the staging directory, undoing the effects of a succesful call to
947  * make_staging_dir().  */
948 static void
949 delete_staging_dir(struct wimfs_context *ctx)
950 {
951         DIR *dir;
952         struct dirent *ent;
953
954         dir = fdopendir(ctx->staging_dir_fd);
955         if (dir) {
956                 while ((ent = readdir(dir)))
957                         unlinkat(ctx->staging_dir_fd, ent->d_name, 0);
958                 closedir(dir);
959         } else {
960                 close(ctx->staging_dir_fd);
961         }
962         if (unlinkat(ctx->parent_dir_fd, ctx->staging_dir_name, AT_REMOVEDIR))
963                 WARNING_WITH_ERRNO("Could not delete staging directory");
964         FREE(ctx->staging_dir_name);
965         close(ctx->parent_dir_fd);
966 }
967
968 static void
969 reassign_inode_numbers(struct wimfs_context *ctx)
970 {
971         struct wim_image_metadata *imd;
972         struct wim_inode *inode;
973
974         ctx->next_ino = 1;
975         imd = wim_get_current_image_metadata(ctx->wim);
976         image_for_each_inode(inode, imd)
977                 inode->i_ino = ctx->next_ino++;
978 }
979
980 static void
981 release_extra_refcnts(struct wimfs_context *ctx)
982 {
983         struct list_head *list = &ctx->orig_stream_list;
984         struct wim_lookup_table *lookup_table = ctx->wim->lookup_table;
985         struct wim_lookup_table_entry *lte, *tmp;
986
987         list_for_each_entry_safe(lte, tmp, list, orig_stream_list) {
988                 u32 n = lte->out_refcnt;
989                 while (n--)
990                         lte_decrement_refcnt(lte, lookup_table);
991         }
992 }
993
994 static void
995 delete_empty_streams(struct wimfs_context *ctx)
996 {
997         struct wim_lookup_table_entry *lte, *tmp;
998         struct wim_image_metadata *imd;
999
1000         imd = wim_get_current_image_metadata(ctx->wim);
1001
1002         image_for_each_unhashed_stream_safe(lte, tmp, imd) {
1003                 if (!lte->size) {
1004                         *retrieve_lte_pointer(lte) = NULL;
1005                         list_del(&lte->unhashed_list);
1006                         free_lookup_table_entry(lte);
1007                 }
1008         }
1009 }
1010
1011 static void
1012 inode_close_fds(struct wim_inode *inode)
1013 {
1014         u16 num_open_fds = inode->i_num_opened_fds;
1015         for (u16 i = 0; num_open_fds; i++) {
1016                 if (inode->i_fds[i]) {
1017                         close_wimfs_fd(inode->i_fds[i]);
1018                         num_open_fds--;
1019                 }
1020         }
1021 }
1022
1023 static void
1024 close_all_fds(struct wimfs_context *ctx)
1025 {
1026         struct wim_inode *inode, *tmp;
1027         struct wim_image_metadata *imd;
1028
1029         imd = wim_get_current_image_metadata(ctx->wim);
1030
1031         list_for_each_entry_safe(inode, tmp, &imd->inode_list, i_list)
1032                 inode_close_fds(inode);
1033 }
1034
1035 /* Moves the currently selected image, which may have been modified, to a new
1036  * index, and sets the original index to refer to a reset (unmodified) copy of
1037  * the image.  */
1038 static int
1039 renew_current_image(struct wimfs_context *ctx)
1040 {
1041         WIMStruct *wim = ctx->wim;
1042         int idx = wim->current_image - 1;
1043         struct wim_image_metadata *imd = wim->image_metadata[idx];
1044         struct wim_image_metadata *replace_imd;
1045         struct wim_lookup_table_entry *new_lte;
1046         int ret;
1047
1048         /* Create 'replace_imd' structure to use for the reset original,
1049          * unmodified image.  */
1050         ret = WIMLIB_ERR_NOMEM;
1051         replace_imd = new_image_metadata();
1052         if (!replace_imd)
1053                 goto err;
1054
1055         /* Create new stream reference for the modified image's metadata
1056          * resource, which doesn't exist yet.  */
1057         ret = WIMLIB_ERR_NOMEM;
1058         new_lte = new_lookup_table_entry();
1059         if (!new_lte)
1060                 goto err_put_replace_imd;
1061         new_lte->flags = WIM_RESHDR_FLAG_METADATA;
1062         new_lte->unhashed = 1;
1063
1064         /* Make the image being moved available at a new index.  Increments the
1065          * WIM's image count, but does not increment the reference count of the
1066          * 'struct image_metadata'.  */
1067         ret = append_image_metadata(wim, imd);
1068         if (ret)
1069                 goto err_free_new_lte;
1070
1071         ret = xml_add_image(wim, T(""));
1072         if (ret)
1073                 goto err_undo_append;
1074
1075         replace_imd->metadata_lte = imd->metadata_lte;
1076         imd->metadata_lte = new_lte;
1077         wim->image_metadata[idx] = replace_imd;
1078         wim->current_image = wim->hdr.image_count;
1079         return 0;
1080
1081 err_undo_append:
1082         wim->hdr.image_count--;
1083 err_free_new_lte:
1084         free_lookup_table_entry(new_lte);
1085 err_put_replace_imd:
1086         put_image_metadata(replace_imd, NULL);
1087 err:
1088         return ret;
1089 }
1090
1091 static enum wimlib_progress_status
1092 commit_progress_func(enum wimlib_progress_msg msg,
1093                      union wimlib_progress_info *info, void *progctx)
1094 {
1095         mqd_t mq = *(mqd_t *)progctx;
1096         struct commit_progress_report report;
1097
1098         memset(&report, 0, sizeof(report));
1099         report.msg = msg;
1100         if (info)
1101                 report.info = *info;
1102         mq_send(mq, (const char *)&report, sizeof(report), 1);
1103         return WIMLIB_PROGRESS_STATUS_CONTINUE;
1104 }
1105
1106 /* Commit the mounted image to the underlying WIM file.  */
1107 static int
1108 commit_image(struct wimfs_context *ctx, int unmount_flags, mqd_t mq)
1109 {
1110         int write_flags;
1111
1112         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS)
1113                 wimlib_register_progress_function(ctx->wim,
1114                                                   commit_progress_func, &mq);
1115         else
1116                 wimlib_register_progress_function(ctx->wim, NULL, NULL);
1117
1118         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_NEW_IMAGE) {
1119                 int ret = renew_current_image(ctx);
1120                 if (ret)
1121                         return ret;
1122         } else {
1123                 release_extra_refcnts(ctx);
1124         }
1125         INIT_LIST_HEAD(&ctx->orig_stream_list);
1126         delete_empty_streams(ctx);
1127         xml_update_image_info(ctx->wim, ctx->wim->current_image);
1128
1129         write_flags = 0;
1130         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY)
1131                 write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
1132         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_REBUILD)
1133                 write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
1134         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_RECOMPRESS)
1135                 write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
1136         return wimlib_overwrite(ctx->wim, write_flags, 0);
1137 }
1138
1139 /* In the case of an allow_other mount, only the owner and root should be
1140  * allowed to unmount the filesystem.  */
1141 static bool
1142 may_unmount_wimfs(void)
1143 {
1144         const struct fuse_context *fuse_ctx = fuse_get_context();
1145         const struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1146
1147         return (fuse_ctx->uid == wimfs_ctx->owner_uid ||
1148                 fuse_ctx->uid == 0);
1149 }
1150
1151 static int
1152 unmount_wimfs(void)
1153 {
1154         struct fuse_context *fuse_ctx = fuse_get_context();
1155         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1156         const struct wimfs_unmount_info *info = &wimfs_ctx->unmount_info;
1157         int unmount_flags = info->unmount_flags;
1158         mqd_t mq = (mqd_t)-1;
1159         int ret;
1160
1161         /* Ignore COMMIT if the image is mounted read-only.  */
1162         if (!(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
1163                 unmount_flags &= ~WIMLIB_UNMOUNT_FLAG_COMMIT;
1164
1165         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS) {
1166                 mq = mq_open(info->mq_name, O_WRONLY | O_NONBLOCK);
1167                 if (mq == (mqd_t)-1) {
1168                         ret = WIMLIB_ERR_MQUEUE;
1169                         goto out;
1170                 }
1171         }
1172
1173         if (wimfs_ctx->num_open_fds) {
1174                 if ((unmount_flags & (WIMLIB_UNMOUNT_FLAG_COMMIT |
1175                                       WIMLIB_UNMOUNT_FLAG_FORCE))
1176                                  == WIMLIB_UNMOUNT_FLAG_COMMIT)
1177                 {
1178                         ret = WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY;
1179                         goto out;
1180                 }
1181                 close_all_fds(wimfs_ctx);
1182         }
1183
1184         if (unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT)
1185                 ret = commit_image(wimfs_ctx, unmount_flags, mq);
1186         else
1187                 ret = 0;
1188 out:
1189         /* Leave the image mounted if commit failed, unless this is a
1190          * forced unmount.  The user can retry without commit if they
1191          * want.  */
1192         if (!ret || (unmount_flags & WIMLIB_UNMOUNT_FLAG_FORCE)) {
1193                 unlock_wim_for_append(wimfs_ctx->wim);
1194                 fuse_exit(fuse_ctx->fuse);
1195         }
1196         if (mq != (mqd_t)-1)
1197                 mq_close(mq);
1198         return ret;
1199 }
1200
1201 static int
1202 wimfs_chmod(const char *path, mode_t mask)
1203 {
1204         const struct wimfs_context *ctx = wimfs_get_context();
1205         struct wim_inode *inode;
1206         struct wimlib_unix_data unix_data;
1207
1208         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1209                 return -EOPNOTSUPP;
1210
1211         inode = wim_pathname_to_inode(ctx->wim, path);
1212         if (!inode)
1213                 return -errno;
1214
1215         unix_data.uid = ctx->owner_uid;
1216         unix_data.gid = ctx->owner_gid;
1217         unix_data.mode = mask;
1218         unix_data.rdev = 0;
1219
1220         if (!inode_set_unix_data(inode, &unix_data, UNIX_DATA_MODE))
1221                 return -ENOMEM;
1222
1223         return 0;
1224 }
1225
1226 static int
1227 wimfs_chown(const char *path, uid_t uid, gid_t gid)
1228 {
1229         const struct wimfs_context *ctx = wimfs_get_context();
1230         struct wim_inode *inode;
1231         struct wimlib_unix_data unix_data;
1232         int which;
1233
1234         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1235                 return -EOPNOTSUPP;
1236
1237         inode = wim_pathname_to_inode(ctx->wim, path);
1238         if (!inode)
1239                 return -errno;
1240
1241         which = 0;
1242
1243         if (uid != (uid_t)-1)
1244                 which |= UNIX_DATA_UID;
1245         else
1246                 uid = ctx->owner_uid;
1247
1248         if (gid != (gid_t)-1)
1249                 which |= UNIX_DATA_GID;
1250         else
1251                 gid = ctx->owner_gid;
1252
1253         unix_data.uid = uid;
1254         unix_data.gid = gid;
1255         unix_data.mode = inode_default_unix_mode(inode);
1256         unix_data.rdev = 0;
1257
1258         if (!inode_set_unix_data(inode, &unix_data, which))
1259                 return -ENOMEM;
1260
1261         return 0;
1262 }
1263
1264 static int
1265 wimfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
1266 {
1267         struct wimfs_fd *fd = WIMFS_FD(fi);
1268         return inode_to_stbuf(fd->f_inode, fd->f_lte, stbuf);
1269 }
1270
1271 static int
1272 wimfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
1273 {
1274         struct wimfs_fd *fd = WIMFS_FD(fi);
1275         if (ftruncate(fd->f_staging_fd.fd, size))
1276                 return -errno;
1277         touch_inode(fd->f_inode);
1278         fd->f_lte->size = size;
1279         return 0;
1280 }
1281
1282 static int
1283 wimfs_getattr(const char *path, struct stat *stbuf)
1284 {
1285         const struct wimfs_context *ctx = wimfs_get_context();
1286         struct wim_dentry *dentry;
1287         struct wim_lookup_table_entry *lte;
1288         int ret;
1289
1290         ret = wim_pathname_to_stream(ctx, path, LOOKUP_FLAG_DIRECTORY_OK,
1291                                      &dentry, &lte, NULL);
1292         if (ret)
1293                 return ret;
1294         return inode_to_stbuf(dentry->d_inode, lte, stbuf);
1295 }
1296
1297 static int
1298 copy_xattr(char *dest, size_t destsize, const void *src, size_t srcsize)
1299 {
1300         if (!destsize)
1301                 return srcsize;
1302         if (destsize < srcsize)
1303                 return -ERANGE;
1304         memcpy(dest, src, srcsize);
1305         return srcsize;
1306 }
1307
1308 static int
1309 wimfs_getxattr(const char *path, const char *name, char *value,
1310                size_t size)
1311 {
1312         const struct wimfs_context *ctx = wimfs_get_context();
1313         struct wim_inode *inode;
1314         struct wim_ads_entry *ads_entry;
1315         struct wim_lookup_table_entry *lte;
1316
1317         if (!strncmp(name, "wimfs.", 6)) {
1318                 /* Handle some magical extended attributes.  These really should
1319                  * be ioctls, but directory ioctls aren't supported until
1320                  * libfuse 2.9, and even then they are broken.  */
1321                 name += 6;
1322                 if (!strcmp(name, "wim_filename")) {
1323                         return copy_xattr(value, size, ctx->wim->filename,
1324                                           strlen(ctx->wim->filename));
1325                 }
1326                 if (!strcmp(name, "wim_info")) {
1327                         struct wimlib_wim_info info;
1328
1329                         wimlib_get_wim_info(ctx->wim, &info);
1330
1331                         return copy_xattr(value, size, &info, sizeof(info));
1332                 }
1333                 if (!strcmp(name, "mounted_image")) {
1334                         return copy_xattr(value, size,
1335                                           &ctx->wim->current_image, sizeof(int));
1336                 }
1337                 if (!strcmp(name, "mount_flags")) {
1338                         return copy_xattr(value, size,
1339                                           &ctx->mount_flags, sizeof(int));
1340                 }
1341                 if (!strcmp(name, "unmount")) {
1342                         if (!may_unmount_wimfs())
1343                                 return -EPERM;
1344                         if (size) {
1345                                 int status;
1346
1347                                 if (size < sizeof(int))
1348                                         return -ERANGE;
1349                                 status = unmount_wimfs();
1350                                 memcpy(value, &status, sizeof(int));
1351                         }
1352                         return sizeof(int);
1353                 }
1354                 return -ENOATTR;
1355         }
1356
1357         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1358                 return -ENOTSUP;
1359
1360         if (strncmp(name, "user.", 5))
1361                 return -ENOATTR;
1362         name += 5;
1363
1364         /* Querying a named data stream  */
1365
1366         inode = wim_pathname_to_inode(ctx->wim, path);
1367         if (!inode)
1368                 return -errno;
1369
1370         ads_entry = inode_get_ads_entry(inode, name);
1371         if (!ads_entry)
1372                 return (errno == ENOENT) ? -ENOATTR : -errno;
1373
1374         lte = ads_entry->lte;
1375         if (!lte)
1376                 return 0;
1377
1378         if (unlikely(lte->size > INT_MAX))
1379                 return -EFBIG;
1380
1381         if (size) {
1382                 if (lte->size > size)
1383                         return -ERANGE;
1384
1385                 if (read_full_stream_into_buf(lte, value))
1386                         return -errno;
1387         }
1388         return lte->size;
1389 }
1390
1391 static int
1392 wimfs_link(const char *existing_path, const char *new_path)
1393 {
1394         WIMStruct *wim = wimfs_get_WIMStruct();
1395         const char *new_name;
1396         struct wim_inode *inode;
1397         struct wim_dentry *dir;
1398         struct wim_dentry *new_alias;
1399
1400         inode = wim_pathname_to_inode(wim, existing_path);
1401         if (!inode)
1402                 return -errno;
1403
1404         if (inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
1405                                    FILE_ATTRIBUTE_REPARSE_POINT))
1406                 return -EPERM;
1407
1408         new_name = path_basename(new_path);
1409
1410         dir = get_parent_dentry(wim, new_path, WIMLIB_CASE_SENSITIVE);
1411         if (!dir)
1412                 return -errno;
1413
1414         if (!dentry_is_directory(dir))
1415                 return -ENOTDIR;
1416
1417         if (get_dentry_child_with_name(dir, new_name, WIMLIB_CASE_SENSITIVE))
1418                 return -EEXIST;
1419
1420         if (new_dentry(new_name, &new_alias))
1421                 return -ENOMEM;
1422
1423         new_alias->d_inode = inode;
1424         inode_add_dentry(new_alias, inode);
1425         dentry_add_child(dir, new_alias);
1426         touch_inode(dir->d_inode);
1427         inode->i_nlink++;
1428         inode_ref_streams(inode);
1429         return 0;
1430 }
1431
1432 static int
1433 wimfs_listxattr(const char *path, char *list, size_t size)
1434 {
1435         const struct wimfs_context *ctx = wimfs_get_context();
1436         const struct wim_inode *inode;
1437         char *p = list;
1438         char *end = list + size;
1439         int total_size = 0;
1440
1441         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1442                 return -ENOTSUP;
1443
1444         /* List named data streams, or get the list size.  We report each named
1445          * data stream "X" as an extended attribute "user.X".  */
1446
1447         inode = wim_pathname_to_inode(ctx->wim, path);
1448         if (!inode)
1449                 return -errno;
1450
1451         for (u16 i = 0; i < inode->i_num_ads; i++) {
1452                 const struct wim_ads_entry *entry;
1453                 char *stream_name_mbs;
1454                 size_t stream_name_mbs_nbytes;
1455
1456                 entry = &inode->i_ads_entries[i];
1457
1458                 if (!entry->stream_name_nbytes)
1459                         continue;
1460
1461                 if (utf16le_to_tstr(entry->stream_name,
1462                                     entry->stream_name_nbytes,
1463                                     &stream_name_mbs,
1464                                     &stream_name_mbs_nbytes))
1465                         return -errno;
1466
1467                 if (unlikely(INT_MAX - total_size < stream_name_mbs_nbytes + 6)) {
1468                         FREE(stream_name_mbs);
1469                         return -EFBIG;
1470                 }
1471
1472                 total_size += stream_name_mbs_nbytes + 6;
1473                 if (size) {
1474                         if (end - p < stream_name_mbs_nbytes + 6) {
1475                                 FREE(stream_name_mbs);
1476                                 return -ERANGE;
1477                         }
1478                         p = mempcpy(p, "user.", 5);
1479                         p = mempcpy(p, stream_name_mbs, stream_name_mbs_nbytes);
1480                         *p++ = '\0';
1481                 }
1482                 FREE(stream_name_mbs);
1483         }
1484         return total_size;
1485 }
1486
1487 static int
1488 wimfs_mkdir(const char *path, mode_t mode)
1489 {
1490         struct wim_dentry *dentry;
1491         int ret;
1492
1493         /* Note: according to fuse.h, mode may not include S_IFDIR  */
1494         ret = create_dentry(fuse_get_context(), path, mode | S_IFDIR, 0,
1495                             FILE_ATTRIBUTE_DIRECTORY, &dentry);
1496         if (ret)
1497                 return ret;
1498         touch_parent(dentry);
1499         return 0;
1500 }
1501
1502 static int
1503 wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
1504 {
1505         struct fuse_context *fuse_ctx = fuse_get_context();
1506         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1507         const char *stream_name;
1508
1509         if ((wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
1510              && (stream_name = path_stream_name(path)))
1511         {
1512                 struct wim_ads_entry *old_entry;
1513                 struct wim_ads_entry *new_entry;
1514                 struct wim_inode *inode;
1515                 char *p;
1516
1517                 /* Create a named data stream.  */
1518
1519                 if (!S_ISREG(mode))
1520                         return -EOPNOTSUPP;
1521
1522                 p = (char *)stream_name - 1;
1523
1524                 *p = '\0';
1525                 inode = wim_pathname_to_inode(wimfs_ctx->wim, path);
1526                 *p = ':';
1527                 if (!inode)
1528                         return -errno;
1529
1530                 old_entry = inode_get_ads_entry(inode, stream_name);
1531                 if (old_entry)
1532                         return -EEXIST;
1533                 if (errno != ENOENT)
1534                         return -errno;
1535
1536                 new_entry = inode_add_ads(inode, stream_name);
1537                 if (!new_entry)
1538                         return -errno;
1539                 return 0;
1540         } else {
1541                 /* Create a regular file, device node, named pipe, or socket.
1542                  */
1543                 struct wim_dentry *dentry;
1544                 int ret;
1545
1546                 if (!S_ISREG(mode) &&
1547                     !(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
1548                         return -EPERM;
1549
1550                 /* Note: we still use FILE_ATTRIBUTE_NORMAL for device nodes,
1551                  * named pipes, and sockets.  The real mode is in the UNIX
1552                  * metadata.  */
1553                 ret = create_dentry(fuse_ctx, path, mode, rdev,
1554                                     FILE_ATTRIBUTE_NORMAL, &dentry);
1555                 if (ret)
1556                         return ret;
1557                 touch_parent(dentry);
1558                 return 0;
1559         }
1560 }
1561
1562 static int
1563 wimfs_open(const char *path, struct fuse_file_info *fi)
1564 {
1565         struct wimfs_context *ctx = wimfs_get_context();
1566         struct wim_dentry *dentry;
1567         struct wim_inode *inode;
1568         struct wim_lookup_table_entry *lte;
1569         u16 stream_idx;
1570         struct wimfs_fd *fd;
1571         int ret;
1572
1573         ret = wim_pathname_to_stream(ctx, path, 0, &dentry, &lte, &stream_idx);
1574         if (ret)
1575                 return ret;
1576
1577         inode = dentry->d_inode;
1578
1579         /* The file resource may be in the staging directory (read-write mounts
1580          * only) or in the WIM.  If it's in the staging directory, we need to
1581          * open a native file descriptor for the corresponding file.  Otherwise,
1582          * we can read the file resource directly from the WIM file if we are
1583          * opening it read-only, but we need to extract the resource to the
1584          * staging directory if we are opening it writable.  */
1585
1586         if (flags_writable(fi->flags) &&
1587             (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) {
1588                 ret = extract_resource_to_staging_dir(inode,
1589                                                       stream_idx,
1590                                                       &lte,
1591                                                       lte ? lte->size : 0,
1592                                                       ctx);
1593                 if (ret)
1594                         return ret;
1595         }
1596
1597         ret = alloc_wimfs_fd(inode, inode_stream_idx_to_id(inode, stream_idx),
1598                              lte, &fd);
1599         if (ret)
1600                 return ret;
1601
1602         if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
1603                 int raw_fd;
1604
1605                 raw_fd = openat(lte->staging_dir_fd, lte->staging_file_name,
1606                                 (fi->flags & O_ACCMODE) | O_NOFOLLOW);
1607                 if (raw_fd < 0) {
1608                         close_wimfs_fd(fd);
1609                         return -errno;
1610                 }
1611                 filedes_init(&fd->f_staging_fd, raw_fd);
1612         }
1613         fi->fh = (uintptr_t)fd;
1614         return 0;
1615 }
1616
1617 static int
1618 wimfs_opendir(const char *path, struct fuse_file_info *fi)
1619 {
1620         WIMStruct *wim = wimfs_get_WIMStruct();
1621         struct wim_inode *inode;
1622         struct wimfs_fd *fd;
1623         int ret;
1624
1625         inode = wim_pathname_to_inode(wim, path);
1626         if (!inode)
1627                 return -errno;
1628         if (!inode_is_directory(inode))
1629                 return -ENOTDIR;
1630         ret = alloc_wimfs_fd(inode, 0, NULL, &fd);
1631         if (ret)
1632                 return ret;
1633         fi->fh = (uintptr_t)fd;
1634         return 0;
1635 }
1636
1637 static int
1638 wimfs_read(const char *path, char *buf, size_t size,
1639            off_t offset, struct fuse_file_info *fi)
1640 {
1641         struct wimfs_fd *fd = WIMFS_FD(fi);
1642         const struct wim_lookup_table_entry *lte;
1643         ssize_t ret;
1644
1645         lte = fd->f_lte;
1646         if (!lte)
1647                 return 0;
1648
1649         if (offset >= lte->size)
1650                 return 0;
1651
1652         if (size > lte->size - offset)
1653                 size = lte->size - offset;
1654
1655         if (!size)
1656                 return 0;
1657
1658         switch (lte->resource_location) {
1659         case RESOURCE_IN_WIM:
1660                 if (read_partial_wim_stream_into_buf(lte, size, offset, buf))
1661                         ret = -errno;
1662                 else
1663                         ret = size;
1664                 break;
1665         case RESOURCE_IN_STAGING_FILE:
1666                 ret = raw_pread(&fd->f_staging_fd, buf, size, offset);
1667                 if (ret < 0)
1668                         ret = -errno;
1669                 break;
1670         case RESOURCE_IN_ATTACHED_BUFFER:
1671                 memcpy(buf, lte->attached_buffer + offset, size);
1672                 ret = size;
1673                 break;
1674         default:
1675                 ret = -EINVAL;
1676                 break;
1677         }
1678         return ret;
1679 }
1680
1681 static int
1682 wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
1683               off_t offset, struct fuse_file_info *fi)
1684 {
1685         struct wimfs_fd *fd = WIMFS_FD(fi);
1686         const struct wim_inode *inode;
1687         const struct wim_dentry *child;
1688         int ret;
1689
1690         inode = fd->f_inode;
1691
1692         ret = filler(buf, ".", NULL, 0);
1693         if (ret)
1694                 return ret;
1695         ret = filler(buf, "..", NULL, 0);
1696         if (ret)
1697                 return ret;
1698
1699         for_inode_child(child, inode) {
1700                 char *file_name_mbs;
1701                 size_t file_name_mbs_nbytes;
1702
1703                 ret = utf16le_to_tstr(child->file_name,
1704                                       child->file_name_nbytes,
1705                                       &file_name_mbs,
1706                                       &file_name_mbs_nbytes);
1707                 if (ret)
1708                         return -errno;
1709
1710                 ret = filler(buf, file_name_mbs, NULL, 0);
1711                 FREE(file_name_mbs);
1712                 if (ret)
1713                         return ret;
1714         }
1715         return 0;
1716 }
1717
1718 static int
1719 wimfs_readlink(const char *path, char *buf, size_t buf_len)
1720 {
1721         WIMStruct *wim = wimfs_get_WIMStruct();
1722         const struct wim_inode *inode;
1723         ssize_t ret;
1724
1725         inode = wim_pathname_to_inode(wim, path);
1726         if (!inode)
1727                 return -errno;
1728         if (!inode_is_symlink(inode))
1729                 return -EINVAL;
1730         if (buf_len == 0)
1731                 return -EINVAL;
1732         ret = wim_inode_readlink(inode, buf, buf_len - 1, NULL);
1733         if (ret >= 0) {
1734                 buf[ret] = '\0';
1735                 ret = 0;
1736         } else if (ret == -ENAMETOOLONG) {
1737                 buf[buf_len - 1] = '\0';
1738         }
1739         return ret;
1740 }
1741
1742 /* We use this for both release() and releasedir(), since in both cases we
1743  * simply need to close the file descriptor.  */
1744 static int
1745 wimfs_release(const char *path, struct fuse_file_info *fi)
1746 {
1747         return close_wimfs_fd(WIMFS_FD(fi));
1748 }
1749
1750 static int
1751 wimfs_removexattr(const char *path, const char *name)
1752 {
1753         struct wimfs_context *ctx = wimfs_get_context();
1754         struct wim_inode *inode;
1755         struct wim_ads_entry *ads_entry;
1756
1757         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1758                 return -ENOTSUP;
1759
1760         if (strncmp(name, "user.", 5))
1761                 return -ENOATTR;
1762         name += 5;
1763
1764         /* Removing a named data stream.  */
1765
1766         inode = wim_pathname_to_inode(ctx->wim, path);
1767         if (!inode)
1768                 return -errno;
1769
1770         ads_entry = inode_get_ads_entry(inode, name);
1771         if (!ads_entry)
1772                 return (errno == ENOENT) ? -ENOATTR : -errno;
1773
1774         inode_remove_ads(inode, ads_entry, ctx->wim->lookup_table);
1775         return 0;
1776 }
1777
1778 static int
1779 wimfs_rename(const char *from, const char *to)
1780 {
1781         return rename_wim_path(wimfs_get_WIMStruct(), from, to,
1782                                WIMLIB_CASE_SENSITIVE, NULL);
1783 }
1784
1785 static int
1786 wimfs_rmdir(const char *path)
1787 {
1788         WIMStruct *wim = wimfs_get_WIMStruct();
1789         struct wim_dentry *dentry;
1790
1791         dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
1792         if (!dentry)
1793                 return -errno;
1794
1795         if (!dentry_is_directory(dentry))
1796                 return -ENOTDIR;
1797
1798         if (dentry_has_children(dentry))
1799                 return -ENOTEMPTY;
1800
1801         touch_parent(dentry);
1802         remove_dentry(dentry, wim->lookup_table);
1803         return 0;
1804 }
1805
1806 static int
1807 wimfs_setxattr(const char *path, const char *name,
1808                const char *value, size_t size, int flags)
1809 {
1810         struct wimfs_context *ctx = wimfs_get_context();
1811         struct wim_inode *inode;
1812         struct wim_ads_entry *existing_entry;
1813
1814         if (!strncmp(name, "wimfs.", 6)) {
1815                 /* Handle some magical extended attributes.  These really should
1816                  * be ioctls, but directory ioctls aren't supported until
1817                  * libfuse 2.9, and even then they are broken.  */
1818                 name += 6;
1819                 if (!strcmp(name, "unmount_info")) {
1820                         if (!may_unmount_wimfs())
1821                                 return -EPERM;
1822                         if (size < sizeof(struct wimfs_unmount_info))
1823                                 return -EINVAL;
1824                         memcpy(&ctx->unmount_info, value,
1825                                sizeof(struct wimfs_unmount_info));
1826                         return 0;
1827                 }
1828                 return -ENOATTR;
1829         }
1830
1831         if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
1832                 return -ENOTSUP;
1833
1834         if (strncmp(name, "user.", 5))
1835                 return -ENOATTR;
1836         name += 5;
1837
1838         /* Setting the contents of a named data stream.  */
1839
1840         inode = wim_pathname_to_inode(ctx->wim, path);
1841         if (!inode)
1842                 return -errno;
1843
1844         existing_entry = inode_get_ads_entry(inode, name);
1845         if (existing_entry) {
1846                 if (flags & XATTR_CREATE)
1847                         return -EEXIST;
1848         } else {
1849                 if (errno != ENOENT)
1850                         return -errno;
1851                 if (flags & XATTR_REPLACE)
1852                         return -ENOATTR;
1853         }
1854
1855         if (!inode_add_ads_with_data(inode, name, value,
1856                                      size, ctx->wim->lookup_table))
1857                 return -errno;
1858         if (existing_entry)
1859                 inode_remove_ads(inode, existing_entry, ctx->wim->lookup_table);
1860         return 0;
1861 }
1862
1863 static int
1864 wimfs_symlink(const char *to, const char *from)
1865 {
1866         struct fuse_context *fuse_ctx = fuse_get_context();
1867         struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
1868         struct wim_dentry *dentry;
1869         int ret;
1870
1871         ret = create_dentry(fuse_ctx, from, S_IFLNK | 0777, 0,
1872                             FILE_ATTRIBUTE_REPARSE_POINT, &dentry);
1873         if (ret)
1874                 return ret;
1875         dentry->d_inode->i_reparse_tag = WIM_IO_REPARSE_TAG_SYMLINK;
1876         ret = wim_inode_set_symlink(dentry->d_inode, to,
1877                                     wimfs_ctx->wim->lookup_table);
1878         if (ret) {
1879                 remove_dentry(dentry, wimfs_ctx->wim->lookup_table);
1880                 if (ret == WIMLIB_ERR_NOMEM)
1881                         ret = -ENOMEM;
1882                 else
1883                         ret = -EINVAL;
1884         } else {
1885                 touch_parent(dentry);
1886         }
1887         return ret;
1888 }
1889
1890 static int
1891 wimfs_truncate(const char *path, off_t size)
1892 {
1893         const struct wimfs_context *ctx = wimfs_get_context();
1894         struct wim_dentry *dentry;
1895         struct wim_lookup_table_entry *lte;
1896         u16 stream_idx;
1897         int ret;
1898         int fd;
1899
1900         ret = wim_pathname_to_stream(ctx, path, 0, &dentry, &lte, &stream_idx);
1901         if (ret)
1902                 return ret;
1903
1904         if (!lte && !size)
1905                 return 0;
1906
1907         if (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE) {
1908                 return extract_resource_to_staging_dir(dentry->d_inode,
1909                                                        stream_idx, &lte,
1910                                                        size, ctx);
1911         }
1912
1913         /* Truncate the staging file.  */
1914         fd = openat(lte->staging_dir_fd, lte->staging_file_name,
1915                     O_WRONLY | O_NOFOLLOW);
1916         if (fd < 0)
1917                 return -errno;
1918         ret = ftruncate(fd, size);
1919         if (close(fd) || ret)
1920                 return -errno;
1921         lte->size = size;
1922         return 0;
1923 }
1924
1925 static int
1926 wimfs_unlink(const char *path)
1927 {
1928         const struct wimfs_context *ctx = wimfs_get_context();
1929         struct wim_dentry *dentry;
1930         u16 stream_idx;
1931         int ret;
1932
1933         ret = wim_pathname_to_stream(ctx, path, 0, &dentry, NULL, &stream_idx);
1934         if (ret)
1935                 return ret;
1936
1937         if (inode_stream_name_nbytes(dentry->d_inode, stream_idx) == 0) {
1938                 touch_parent(dentry);
1939                 remove_dentry(dentry, ctx->wim->lookup_table);
1940         } else {
1941                 inode_remove_ads(dentry->d_inode,
1942                                  &dentry->d_inode->i_ads_entries[stream_idx - 1],
1943                                  ctx->wim->lookup_table);
1944         }
1945         return 0;
1946 }
1947
1948 #ifdef HAVE_UTIMENSAT
1949 /*
1950  * Change the timestamp on a file dentry.
1951  *
1952  * Note that alternate data streams do not have their own timestamps.
1953  */
1954 static int
1955 wimfs_utimens(const char *path, const struct timespec tv[2])
1956 {
1957         WIMStruct *wim = wimfs_get_WIMStruct();
1958         struct wim_inode *inode;
1959
1960         inode = wim_pathname_to_inode(wim, path);
1961         if (!inode)
1962                 return -errno;
1963
1964         if (tv[0].tv_nsec != UTIME_OMIT) {
1965                 if (tv[0].tv_nsec == UTIME_NOW)
1966                         inode->i_last_access_time = get_wim_timestamp();
1967                 else
1968                         inode->i_last_access_time = timespec_to_wim_timestamp(tv[0]);
1969         }
1970         if (tv[1].tv_nsec != UTIME_OMIT) {
1971                 if (tv[1].tv_nsec == UTIME_NOW)
1972                         inode->i_last_write_time = get_wim_timestamp();
1973                 else
1974                         inode->i_last_write_time = timespec_to_wim_timestamp(tv[1]);
1975         }
1976         return 0;
1977 }
1978 #else /* HAVE_UTIMENSAT */
1979 static int
1980 wimfs_utime(const char *path, struct utimbuf *times)
1981 {
1982         WIMStruct *wim = wimfs_get_WIMStruct();
1983         struct wim_inode *inode;
1984
1985         inode = wim_pathname_to_inode(wim, path);
1986         if (!inode)
1987                 return -errno;
1988
1989         inode->i_last_access_time = unix_timestamp_to_wim(times->actime);
1990         inode->i_last_write_time = unix_timestamp_to_wim(times->modtime);
1991         return 0;
1992 }
1993 #endif /* !HAVE_UTIMENSAT */
1994
1995 static int
1996 wimfs_write(const char *path, const char *buf, size_t size,
1997             off_t offset, struct fuse_file_info *fi)
1998 {
1999         struct wimfs_fd *fd = WIMFS_FD(fi);
2000         ssize_t ret;
2001
2002         ret = raw_pwrite(&fd->f_staging_fd, buf, size, offset);
2003         if (ret < 0)
2004                 return -errno;
2005
2006         if (offset + size > fd->f_lte->size)
2007                 fd->f_lte->size = offset + size;
2008
2009         touch_inode(fd->f_inode);
2010         return ret;
2011 }
2012
2013 static struct fuse_operations wimfs_operations = {
2014         .chmod       = wimfs_chmod,
2015         .chown       = wimfs_chown,
2016         .fgetattr    = wimfs_fgetattr,
2017         .ftruncate   = wimfs_ftruncate,
2018         .getattr     = wimfs_getattr,
2019         .getxattr    = wimfs_getxattr,
2020         .link        = wimfs_link,
2021         .listxattr   = wimfs_listxattr,
2022         .mkdir       = wimfs_mkdir,
2023         .mknod       = wimfs_mknod,
2024         .open        = wimfs_open,
2025         .opendir     = wimfs_opendir,
2026         .read        = wimfs_read,
2027         .readdir     = wimfs_readdir,
2028         .readlink    = wimfs_readlink,
2029         .release     = wimfs_release,
2030         .releasedir  = wimfs_release,
2031         .removexattr = wimfs_removexattr,
2032         .rename      = wimfs_rename,
2033         .rmdir       = wimfs_rmdir,
2034         .setxattr    = wimfs_setxattr,
2035         .symlink     = wimfs_symlink,
2036         .truncate    = wimfs_truncate,
2037         .unlink      = wimfs_unlink,
2038 #ifdef HAVE_UTIMENSAT
2039         .utimens     = wimfs_utimens,
2040 #else
2041         .utime       = wimfs_utime,
2042 #endif
2043         .write       = wimfs_write,
2044
2045         /* We keep track of file descriptor structures (struct wimfs_fd), so
2046          * there is no need to have the file path provided on operations such as
2047          * read().  */
2048 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 8)
2049         .flag_nullpath_ok = 1,
2050 #endif
2051 #if FUSE_MAJOR_VERSION > 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 9)
2052         .flag_nopath = 1,
2053         .flag_utime_omit_ok = 1,
2054 #endif
2055 };
2056
2057 /* API function documented in wimlib.h  */
2058 WIMLIBAPI int
2059 wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
2060                    int mount_flags, const char *staging_dir)
2061 {
2062         int ret;
2063         struct wim_image_metadata *imd;
2064         struct wimfs_context ctx;
2065         char *fuse_argv[16];
2066         int fuse_argc;
2067
2068         if (!wim || !dir || !*dir)
2069                 return WIMLIB_ERR_INVALID_PARAM;
2070
2071         if (mount_flags & ~(WIMLIB_MOUNT_FLAG_READWRITE |
2072                             WIMLIB_MOUNT_FLAG_DEBUG |
2073                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
2074                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
2075                             WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS |
2076                             WIMLIB_MOUNT_FLAG_UNIX_DATA |
2077                             WIMLIB_MOUNT_FLAG_ALLOW_OTHER))
2078                 return WIMLIB_ERR_INVALID_PARAM;
2079
2080         /* For read-write mount, check for write access to the WIM.  */
2081         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2082                 ret = can_delete_from_wim(wim);
2083                 if (ret)
2084                         return ret;
2085         }
2086
2087         /* Select the image to mount.  */
2088         ret = select_wim_image(wim, image);
2089         if (ret)
2090                 return ret;
2091
2092         /* Get the metadata for the image to mount.  */
2093         imd = wim_get_current_image_metadata(wim);
2094
2095         if (imd->modified) {
2096                 /* To avoid complicating things, we don't support mounting
2097                  * images to which in-memory modifications have already been
2098                  * made.  */
2099                 ERROR("Cannot mount a modified WIM image!");
2100                 return WIMLIB_ERR_INVALID_PARAM;
2101         }
2102
2103         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2104                 ret = lock_wim_for_append(wim);
2105                 if (ret)
2106                         return ret;
2107         }
2108
2109         /* If the user did not specify an interface for accessing named
2110          * data streams, use the default (extended attributes).  */
2111         if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
2112                              WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
2113                              WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
2114                 mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
2115
2116         /* Start initializing the wimfs_context.  */
2117         memset(&ctx, 0, sizeof(struct wimfs_context));
2118         ctx.wim = wim;
2119         ctx.mount_flags = mount_flags;
2120         if (mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
2121                 ctx.default_lookup_flags = LOOKUP_FLAG_ADS_OK;
2122         /* For read-write mount, create the staging directory.  */
2123         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2124                 ret = make_staging_dir(&ctx, staging_dir);
2125                 if (ret)
2126                         goto out_unlock;
2127         }
2128         ctx.owner_uid = getuid();
2129         ctx.owner_gid = getgid();
2130
2131         /* Add each stream referenced by files in the image to a list and
2132          * preemptively double the number of references to each.  This is done
2133          * to allow implementing the WIMLIB_UNMOUNT_FLAG_NEW_IMAGE semantics.
2134          */
2135         INIT_LIST_HEAD(&ctx.orig_stream_list);
2136         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
2137                 unsigned i;
2138                 struct wim_inode *inode;
2139                 struct wim_lookup_table_entry *lte;
2140
2141                 image_for_each_inode(inode, imd) {
2142                         for (i = 0; i <= inode->i_num_ads; i++) {
2143                                 lte = inode_stream_lte(inode, i,
2144                                                        wim->lookup_table);
2145                                 if (lte)
2146                                         lte->out_refcnt = 0;
2147                         }
2148                 }
2149
2150                 image_for_each_inode(inode, imd) {
2151                         for (i = 0; i <= inode->i_num_ads; i++) {
2152                                 lte = inode_stream_lte(inode, i,
2153                                                        wim->lookup_table);
2154                                 if (lte) {
2155                                         if (lte->out_refcnt == 0)
2156                                                 list_add(&lte->orig_stream_list,
2157                                                          &ctx.orig_stream_list);
2158                                         lte->out_refcnt += inode->i_nlink;
2159                                         lte->refcnt += inode->i_nlink;
2160                                 }
2161                         }
2162                 }
2163         }
2164
2165         /* Assign new inode numbers.  */
2166         reassign_inode_numbers(&ctx);
2167
2168         /* If a read-write mount, mark the image as modified.  */
2169         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
2170                 imd->modified = 1;
2171
2172         /* Build the FUSE command line.  */
2173
2174         fuse_argc = 0;
2175         fuse_argv[fuse_argc++] = "wimlib";
2176         fuse_argv[fuse_argc++] = (char *)dir;
2177
2178         /* Disable multi-threaded operation.  */
2179         fuse_argv[fuse_argc++] = "-s";
2180
2181         /* Enable FUSE debug mode (don't fork) if requested by the user.  */
2182         if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
2183                 fuse_argv[fuse_argc++] = "-d";
2184
2185         /*
2186          * Build the FUSE mount options:
2187          *
2188          * use_ino
2189          *      FUSE will use the inode numbers we provide.  We want this,
2190          *      because we have inodes and will number them ourselves.
2191          *
2192          * subtype=wimfs
2193          *      Name for our filesystem (main type is "fuse").
2194          *
2195          * hard_remove
2196          *      If an open file is unlinked, unlink it for real rather than
2197          *      renaming it to a hidden file.  Our code supports this; an
2198          *      unlinked inode is retained until all its file descriptors have
2199          *      been closed.
2200          *
2201          * default_permissions
2202          *      FUSE will perform permission checking.  Useful when
2203          *      WIMLIB_MOUNT_FLAG_UNIX_DATA is provided and the WIM image
2204          *      contains the UNIX permissions for each file.
2205          *
2206          * kernel_cache
2207          *      Cache the contents of files.  This will speed up repeated access
2208          *      to files on a mounted WIM image, since they won't need to be
2209          *      decompressed repeatedly.  This option is valid because data in
2210          *      the WIM image should never be changed externally.  (Although, if
2211          *      someone really wanted to they could modify the WIM file or mess
2212          *      with the staging directory; but then they're asking for
2213          *      trouble.)
2214          *
2215          * entry_timeout=1000000000
2216          *      Cache positive name lookups indefinitely, since names can only
2217          *      be added, removed, or modified through the mounted filesystem
2218          *      itself.
2219          *
2220          * negative_timeout=1000000000
2221          *      Cache negative name lookups indefinitely, since names can only
2222          *      be added, removed, or modified through the mounted filesystem
2223          *      itself.
2224          *
2225          * attr_timeout=0
2226          *      Don't cache file/directory attributes.  This is needed as a
2227          *      workaround for the fact that when caching attributes, the high
2228          *      level interface to libfuse considers a file which has several
2229          *      hard-linked names as several different files.  (Otherwise, we
2230          *      could cache our file/directory attributes indefinitely, since
2231          *      they can only be changed through the mounted filesystem itself.)
2232          */
2233         char optstring[256] =
2234                 "use_ino"
2235                 ",subtype=wimfs"
2236                 ",attr_timeout=0"
2237                 ",hard_remove"
2238                 ",default_permissions"
2239                 ",kernel_cache"
2240                 ",entry_timeout=1000000000"
2241                 ",negative_timeout=1000000000"
2242                 ",attr_timeout=0"
2243                 ;
2244         fuse_argv[fuse_argc++] = "-o";
2245         fuse_argv[fuse_argc++] = optstring;
2246         if (!(mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
2247                 strcat(optstring, ",ro");
2248         if (mount_flags & WIMLIB_MOUNT_FLAG_ALLOW_OTHER)
2249                 strcat(optstring, ",allow_other");
2250         fuse_argv[fuse_argc] = NULL;
2251
2252         /* Mount our filesystem.  */
2253         ret = fuse_main(fuse_argc, fuse_argv, &wimfs_operations, &ctx);
2254
2255         /* Cleanup and return.  */
2256         if (ret)
2257                 ret = WIMLIB_ERR_FUSE;
2258         release_extra_refcnts(&ctx);
2259         if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE)
2260                 delete_staging_dir(&ctx);
2261 out_unlock:
2262         unlock_wim_for_append(wim);
2263         return ret;
2264 }
2265
2266 struct commit_progress_thread_args {
2267         mqd_t mq;
2268         wimlib_progress_func_t progfunc;
2269         void *progctx;
2270 };
2271
2272 static void *
2273 commit_progress_thread_proc(void *_args)
2274 {
2275         struct commit_progress_thread_args *args = _args;
2276         struct commit_progress_report report;
2277         ssize_t ret;
2278
2279         for (;;) {
2280                 ret = mq_receive(args->mq,
2281                                  (char *)&report, sizeof(report), NULL);
2282                 if (ret == sizeof(report)) {
2283                         call_progress(args->progfunc, report.msg,
2284                                       &report.info, args->progctx);
2285                 } else {
2286                         if (ret == 0 || (ret < 0 && errno != EINTR))
2287                                 break;
2288                 }
2289         }
2290         return NULL;
2291 }
2292
2293 static void
2294 generate_message_queue_name(char name[WIMFS_MQUEUE_NAME_LEN + 1])
2295 {
2296         name[0] = '/';
2297         memcpy(name + 1, "wimfs-", 6);
2298         randomize_char_array_with_alnum(name + 7, WIMFS_MQUEUE_NAME_LEN - 7);
2299         name[WIMFS_MQUEUE_NAME_LEN] = '\0';
2300 }
2301
2302 static mqd_t
2303 create_message_queue(const char *name, bool have_progfunc)
2304 {
2305         bool am_root = (getuid() == 0);
2306         mode_t umask_save = 0;
2307         mode_t mode = 0600;
2308         struct mq_attr attr;
2309         mqd_t mq;
2310
2311         memset(&attr, 0, sizeof(attr));
2312         attr.mq_maxmsg = 8;
2313         if (have_progfunc)
2314                 attr.mq_msgsize = sizeof(struct commit_progress_report);
2315         else
2316                 attr.mq_msgsize = sizeof(int);
2317
2318         if (am_root) {
2319                 /* Filesystem mounted as normal user with --allow-other should
2320                  * be able to send messages to root user, if they're doing the
2321                  * unmount.  */
2322                 umask_save = umask(0);
2323                 mode = 0666;
2324         }
2325         mq = mq_open(name, O_RDWR | O_CREAT | O_EXCL, mode, &attr);
2326         if (am_root)
2327                 umask(umask_save);
2328         return mq;
2329 }
2330
2331 /* Unmount a read-only or read-write mounted WIM image.  */
2332 static int
2333 do_unmount(const char *dir)
2334 {
2335         int status;
2336         ssize_t len;
2337
2338         len = getxattr(dir, "wimfs.unmount", &status, sizeof(int));
2339         if (len == sizeof(int))
2340                 return status;
2341         else if (len < 0 && (errno == EACCES || errno == EPERM))
2342                 return WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT;
2343         else
2344                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2345 }
2346
2347 static int
2348 set_unmount_info(const char *dir, const struct wimfs_unmount_info *unmount_info)
2349 {
2350         if (!setxattr(dir, "wimfs.unmount_info",
2351                       unmount_info, sizeof(struct wimfs_unmount_info), 0))
2352                 return 0;
2353         else if (errno == EROFS)
2354                 return 0;
2355         else if (errno == EACCES || errno == EPERM)
2356                 return WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT;
2357         else
2358                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2359 }
2360
2361 static int
2362 do_unmount_discard(const char *dir)
2363 {
2364         int ret;
2365         struct wimfs_unmount_info unmount_info;
2366
2367         memset(&unmount_info, 0, sizeof(unmount_info));
2368
2369         ret = set_unmount_info(dir, &unmount_info);
2370         if (ret)
2371                 return ret;
2372         return do_unmount(dir);
2373 }
2374
2375 /* Unmount a read-write mounted WIM image, committing the changes.  */
2376 static int
2377 do_unmount_commit(const char *dir, int unmount_flags,
2378                   wimlib_progress_func_t progfunc, void *progctx)
2379 {
2380         struct wimfs_unmount_info unmount_info;
2381         mqd_t mq;
2382         struct commit_progress_thread_args args;
2383         pthread_t commit_progress_tid;
2384         int ret;
2385
2386         memset(&unmount_info, 0, sizeof(unmount_info));
2387         unmount_info.unmount_flags = unmount_flags;
2388
2389         /* The current thread will be stuck in getxattr() until the image is
2390          * committed.  Create a thread to handle the progress messages.  */
2391         if (progfunc) {
2392                 generate_message_queue_name(unmount_info.mq_name);
2393
2394                 mq = create_message_queue(unmount_info.mq_name, progfunc != NULL);
2395                 if (mq == (mqd_t)-1) {
2396                         ERROR_WITH_ERRNO("Can't create POSIX message queue");
2397                         return WIMLIB_ERR_MQUEUE;
2398                 }
2399                 args.mq = mq;
2400                 args.progfunc = progfunc;
2401                 args.progctx = progctx;
2402                 ret = pthread_create(&commit_progress_tid, NULL,
2403                                      commit_progress_thread_proc, &args);
2404                 if (ret) {
2405                         errno = ret;
2406                         ERROR_WITH_ERRNO("Can't create thread");
2407                         ret = WIMLIB_ERR_NOMEM;
2408                         goto out_delete_mq;
2409                 }
2410                 unmount_info.unmount_flags |= WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS;
2411         }
2412
2413         ret = set_unmount_info(dir, &unmount_info);
2414         if (!ret)
2415                 ret = do_unmount(dir);
2416         if (progfunc) {
2417                 /* Terminate the progress thread.  */
2418                 mq_send(mq, NULL, 0, 1);
2419                 pthread_join(commit_progress_tid, NULL);
2420         }
2421 out_delete_mq:
2422         if (progfunc) {
2423                 mq_close(mq);
2424                 mq_unlink(unmount_info.mq_name);
2425         }
2426         return ret;
2427 }
2428
2429 static int
2430 begin_unmount(const char *dir, int unmount_flags, int *mount_flags_ret,
2431               wimlib_progress_func_t progfunc, void *progctx)
2432 {
2433         int mount_flags;
2434         int mounted_image;
2435         int wim_filename_len;
2436         union wimlib_progress_info progress;
2437
2438         if (getxattr(dir, "wimfs.mount_flags",
2439                      &mount_flags, sizeof(int)) != sizeof(int))
2440                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2441
2442         *mount_flags_ret = mount_flags;
2443
2444         if (!progfunc)
2445                 return 0;
2446
2447         if (getxattr(dir, "wimfs.mounted_image",
2448                      &mounted_image, sizeof(int)) != sizeof(int))
2449                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2450
2451         wim_filename_len = getxattr(dir, "wimfs.wim_filename", NULL, 0);
2452         if (wim_filename_len < 0)
2453                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2454
2455         char wim_filename[wim_filename_len + 1];
2456         if (getxattr(dir, "wimfs.wim_filename",
2457                      wim_filename, wim_filename_len) != wim_filename_len)
2458                 return WIMLIB_ERR_NOT_A_MOUNTPOINT;
2459         wim_filename[wim_filename_len] = '\0';
2460
2461         progress.unmount.mountpoint = dir;
2462         progress.unmount.mounted_wim = wim_filename;
2463         progress.unmount.mounted_image = mounted_image;
2464         progress.unmount.mount_flags = mount_flags;
2465         progress.unmount.unmount_flags = unmount_flags;
2466
2467         return call_progress(progfunc, WIMLIB_PROGRESS_MSG_UNMOUNT_BEGIN,
2468                              &progress, progctx);
2469 }
2470
2471 /* API function documented in wimlib.h  */
2472 WIMLIBAPI int
2473 wimlib_unmount_image_with_progress(const char *dir, int unmount_flags,
2474                                    wimlib_progress_func_t progfunc, void *progctx)
2475 {
2476         int mount_flags;
2477         int ret;
2478
2479         wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8);
2480
2481         if (unmount_flags & ~(WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY |
2482                               WIMLIB_UNMOUNT_FLAG_COMMIT |
2483                               WIMLIB_UNMOUNT_FLAG_REBUILD |
2484                               WIMLIB_UNMOUNT_FLAG_RECOMPRESS |
2485                               WIMLIB_UNMOUNT_FLAG_FORCE |
2486                               WIMLIB_UNMOUNT_FLAG_NEW_IMAGE))
2487                 return WIMLIB_ERR_INVALID_PARAM;
2488
2489         ret = begin_unmount(dir, unmount_flags, &mount_flags,
2490                             progfunc, progctx);
2491         if (ret)
2492                 return ret;
2493
2494         if ((unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) &&
2495             (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
2496                 return do_unmount_commit(dir, unmount_flags,
2497                                          progfunc, progctx);
2498         else
2499                 return do_unmount_discard(dir);
2500 }
2501
2502 #else /* WITH_FUSE */
2503
2504
2505 static int
2506 mount_unsupported_error(void)
2507 {
2508 #if defined(__WIN32__)
2509         ERROR("Sorry-- Mounting WIM images is not supported on Windows!");
2510 #else
2511         ERROR("wimlib was compiled with --without-fuse, which disables support "
2512               "for mounting WIMs.");
2513 #endif
2514         return WIMLIB_ERR_UNSUPPORTED;
2515 }
2516
2517 WIMLIBAPI int
2518 wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
2519                                    wimlib_progress_func_t progfunc, void *progctx)
2520 {
2521         return mount_unsupported_error();
2522 }
2523
2524 WIMLIBAPI int
2525 wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
2526                    int mount_flags, const tchar *staging_dir)
2527 {
2528         return mount_unsupported_error();
2529 }
2530
2531 #endif /* !WITH_FUSE */
2532
2533 WIMLIBAPI int
2534 wimlib_unmount_image(const tchar *dir, int unmount_flags)
2535 {
2536         return wimlib_unmount_image_with_progress(dir, unmount_flags, NULL, NULL);
2537 }