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