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