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