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