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