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