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