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