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