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