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