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