blob: ae1322549f88b6309c7dbcc41e75a80d323831ce [file] [log] [blame]
Miklos Szeredif830a7f2001-11-16 17:46:45 +00001/*
Miklos Szeredicdb8b792007-12-12 14:25:40 +00002 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
Sebastian Pippingc605b5f2011-06-25 19:14:29 +02004 Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
Miklos Szeredif830a7f2001-11-16 17:46:45 +00005
Dr. David Alan Gilbert252e9782020-03-13 16:46:44 +00006 This program can be distributed under the terms of the GNU GPLv2.
Miklos Szeredicdb8b792007-12-12 14:25:40 +00007 See the file COPYING.
Miklos Szeredif830a7f2001-11-16 17:46:45 +00008*/
9
Joachim Schieleea7227d2013-06-20 19:18:18 +020010/** @file
Joachim Schieleea7227d2013-06-20 19:18:18 +020011 *
Nikolaus Rath463189c2016-10-09 19:22:57 -070012 * This file system mirrors the existing file system hierarchy of the
13 * system, starting at the root file system. This is implemented by
14 * just "passing through" all requests to the corresponding user-space
Jay Hankinsd6d3e502016-12-04 12:13:25 -050015 * libc functions. Its performance is terrible.
Joachim Schieleea7227d2013-06-20 19:18:18 +020016 *
Nikolaus Rath79834142016-10-28 20:44:39 -070017 * Compile with
Joachim Schieleea7227d2013-06-20 19:18:18 +020018 *
Nikolaus Rath79834142016-10-28 20:44:39 -070019 * gcc -Wall passthrough.c `pkg-config fuse3 --cflags --libs` -o passthrough
Joachim Schieleea7227d2013-06-20 19:18:18 +020020 *
Nikolaus Rath79834142016-10-28 20:44:39 -070021 * ## Source code ##
Nikolaus Rath463189c2016-10-09 19:22:57 -070022 * \include passthrough.c
Joachim Schieleea7227d2013-06-20 19:18:18 +020023 */
24
25
Nikolaus Rathe870a042017-07-07 15:25:41 +020026#define FUSE_USE_VERSION 31
Miklos Szeredi4003dfa2006-10-01 13:46:02 +000027
Miklos Szerediea8fdc02007-05-17 12:41:46 +000028#ifdef HAVE_CONFIG_H
Miklos Szeredi03cebae2004-03-31 10:19:18 +000029#include <config.h>
Miklos Szerediea8fdc02007-05-17 12:41:46 +000030#endif
Miklos Szeredi03cebae2004-03-31 10:19:18 +000031
Niels de Vos2548c4b2018-06-26 21:40:21 +020032#define _GNU_SOURCE
33
Miklos Szeredi2df1c042001-11-06 15:07:17 +000034#ifdef linux
Sebastian Pippingc605b5f2011-06-25 19:14:29 +020035/* For pread()/pwrite()/utimensat() */
36#define _XOPEN_SOURCE 700
Miklos Szeredi2df1c042001-11-06 15:07:17 +000037#endif
38
Miklos Szeredi2df1c042001-11-06 15:07:17 +000039#include <fuse.h>
40#include <stdio.h>
Miklos Szeredi074b4b92002-01-11 08:25:52 +000041#include <string.h>
Miklos Szeredi2df1c042001-11-06 15:07:17 +000042#include <unistd.h>
Miklos Szeredicc8c9752001-11-21 10:03:39 +000043#include <fcntl.h>
Sebastian Pippingc605b5f2011-06-25 19:14:29 +020044#include <sys/stat.h>
Miklos Szeredi2df1c042001-11-06 15:07:17 +000045#include <dirent.h>
46#include <errno.h>
Alan Somers1f842c92019-05-15 14:35:57 -060047#ifdef __FreeBSD__
48#include <sys/socket.h>
49#include <sys/un.h>
50#endif
Miklos Szeredifa440772006-09-02 09:51:08 +000051#include <sys/time.h>
Miklos Szeredi03cebae2004-03-31 10:19:18 +000052#ifdef HAVE_SETXATTR
53#include <sys/xattr.h>
54#endif
Miklos Szeredi2df1c042001-11-06 15:07:17 +000055
Alan Somers1f842c92019-05-15 14:35:57 -060056#include "passthrough_helpers.h"
57
Jean-Pierre Andrébdd2d412021-03-18 10:52:30 +010058static int fill_dir_plus = 0;
59
Nikolaus Rath8ee553d2016-10-18 21:23:22 -070060static void *xmp_init(struct fuse_conn_info *conn,
61 struct fuse_config *cfg)
62{
63 (void) conn;
64 cfg->use_ino = 1;
Nikolaus Rathf7c5d102017-04-06 11:47:06 -070065
66 /* Pick up changes from lower filesystem right away. This is
67 also necessary for better hardlink support. When the kernel
68 calls the unlink() handler, it does not know the inode of
69 the to-be-removed entry and can therefore not invalidate
70 the cache of the associated inode - resulting in an
71 incorrect st_nlink value being reported for any remaining
72 hardlinks to this inode. */
73 cfg->entry_timeout = 0;
74 cfg->attr_timeout = 0;
75 cfg->negative_timeout = 0;
76
Nikolaus Rath8ee553d2016-10-18 21:23:22 -070077 return NULL;
78}
79
Nikolaus Rath73b6ff42016-10-15 18:46:27 -070080static int xmp_getattr(const char *path, struct stat *stbuf,
81 struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +000082{
Nikolaus Rath73b6ff42016-10-15 18:46:27 -070083 (void) fi;
Miklos Szeredicdb8b792007-12-12 14:25:40 +000084 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +000085
Miklos Szeredicdb8b792007-12-12 14:25:40 +000086 res = lstat(path, stbuf);
Nikolaus Rathe6dd8ce2017-05-31 12:35:16 -070087 if (res == -1)
88 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +000089
Miklos Szeredicdb8b792007-12-12 14:25:40 +000090 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +000091}
92
Miklos Szeredib0b13d12005-10-26 12:53:25 +000093static int xmp_access(const char *path, int mask)
94{
Miklos Szeredicdb8b792007-12-12 14:25:40 +000095 int res;
Miklos Szeredib0b13d12005-10-26 12:53:25 +000096
Miklos Szeredicdb8b792007-12-12 14:25:40 +000097 res = access(path, mask);
98 if (res == -1)
99 return -errno;
Miklos Szeredib0b13d12005-10-26 12:53:25 +0000100
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000101 return 0;
Miklos Szeredib0b13d12005-10-26 12:53:25 +0000102}
103
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000104static int xmp_readlink(const char *path, char *buf, size_t size)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000105{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000106 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000107
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000108 res = readlink(path, buf, size - 1);
109 if (res == -1)
110 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000111
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000112 buf[res] = '\0';
113 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000114}
115
116
Miklos Szerediab974562005-04-07 15:40:21 +0000117static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
Eric Wong6bf2e6f2014-03-05 14:45:44 +0100118 off_t offset, struct fuse_file_info *fi,
119 enum fuse_readdir_flags flags)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000120{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000121 DIR *dp;
122 struct dirent *de;
Miklos Szerediab974562005-04-07 15:40:21 +0000123
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000124 (void) offset;
125 (void) fi;
Eric Wong6bf2e6f2014-03-05 14:45:44 +0100126 (void) flags;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000127
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000128 dp = opendir(path);
129 if (dp == NULL)
130 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000131
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000132 while ((de = readdir(dp)) != NULL) {
133 struct stat st;
134 memset(&st, 0, sizeof(st));
135 st.st_ino = de->d_ino;
136 st.st_mode = de->d_type << 12;
Jean-Pierre Andrébdd2d412021-03-18 10:52:30 +0100137 if (filler(buf, de->d_name, &st, 0, fill_dir_plus))
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000138 break;
139 }
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000140
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000141 closedir(dp);
142 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000143}
144
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000145static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000146{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000147 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000148
Alan Somers1f842c92019-05-15 14:35:57 -0600149 res = mknod_wrapper(AT_FDCWD, path, NULL, mode, rdev);
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000150 if (res == -1)
151 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000152
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000153 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000154}
155
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000156static int xmp_mkdir(const char *path, mode_t mode)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000157{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000158 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000159
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000160 res = mkdir(path, mode);
161 if (res == -1)
162 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000163
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000164 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000165}
166
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000167static int xmp_unlink(const char *path)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000168{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000169 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000170
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000171 res = unlink(path);
172 if (res == -1)
173 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000174
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000175 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000176}
177
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000178static int xmp_rmdir(const char *path)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000179{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000180 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000181
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000182 res = rmdir(path);
183 if (res == -1)
184 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000185
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000186 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000187}
188
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000189static int xmp_symlink(const char *from, const char *to)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000190{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000191 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000192
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000193 res = symlink(from, to);
194 if (res == -1)
195 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000196
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000197 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000198}
199
Miklos Szeredib49cf752014-07-15 18:02:19 +0200200static int xmp_rename(const char *from, const char *to, unsigned int flags)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000201{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000202 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000203
Miklos Szeredib49cf752014-07-15 18:02:19 +0200204 if (flags)
205 return -EINVAL;
206
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000207 res = rename(from, to);
208 if (res == -1)
209 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000210
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000211 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000212}
213
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000214static int xmp_link(const char *from, const char *to)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000215{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000216 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000217
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000218 res = link(from, to);
219 if (res == -1)
220 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000221
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000222 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000223}
224
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700225static int xmp_chmod(const char *path, mode_t mode,
226 struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000227{
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700228 (void) fi;
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000229 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000230
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000231 res = chmod(path, mode);
232 if (res == -1)
233 return -errno;
Miklos Szeredie5183742005-02-02 11:14:04 +0000234
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000235 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000236}
237
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700238static int xmp_chown(const char *path, uid_t uid, gid_t gid,
239 struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000240{
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700241 (void) fi;
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000242 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000243
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000244 res = lchown(path, uid, gid);
245 if (res == -1)
246 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000247
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000248 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000249}
250
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700251static int xmp_truncate(const char *path, off_t size,
252 struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000253{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000254 int res;
Miklos Szeredie5183742005-02-02 11:14:04 +0000255
Nikolaus Rath76218eb2017-04-07 16:27:59 -0700256 if (fi != NULL)
257 res = ftruncate(fi->fh, size);
258 else
259 res = truncate(path, size);
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000260 if (res == -1)
261 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000262
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000263 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000264}
265
Emmanuel Dreyfus40a47ed2011-12-08 10:55:27 +0000266#ifdef HAVE_UTIMENSAT
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700267static int xmp_utimens(const char *path, const struct timespec ts[2],
268 struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000269{
Nikolaus Rath73b6ff42016-10-15 18:46:27 -0700270 (void) fi;
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000271 int res;
Miklos Szeredie5183742005-02-02 11:14:04 +0000272
Emmanuel Dreyfus40a47ed2011-12-08 10:55:27 +0000273 /* don't use utime/utimes since they follow symlinks */
Sebastian Pippingc605b5f2011-06-25 19:14:29 +0200274 res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000275 if (res == -1)
276 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000277
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000278 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000279}
Emmanuel Dreyfus40a47ed2011-12-08 10:55:27 +0000280#endif
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000281
Nikolaus Rath20b24a12017-04-07 16:36:52 -0700282static int xmp_create(const char *path, mode_t mode,
283 struct fuse_file_info *fi)
284{
285 int res;
286
287 res = open(path, fi->flags, mode);
288 if (res == -1)
289 return -errno;
290
291 fi->fh = res;
292 return 0;
293}
294
Miklos Szeredifb28c5e2004-11-26 12:15:06 +0000295static int xmp_open(const char *path, struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000296{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000297 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000298
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000299 res = open(path, fi->flags);
300 if (res == -1)
301 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000302
Nikolaus Rathdb1c6ad2017-04-07 16:27:33 -0700303 fi->fh = res;
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000304 return 0;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000305}
306
Miklos Szeredifb28c5e2004-11-26 12:15:06 +0000307static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000308 struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000309{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000310 int fd;
311 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000312
Nikolaus Rath09862552017-04-07 16:31:07 -0700313 if(fi == NULL)
314 fd = open(path, O_RDONLY);
315 else
316 fd = fi->fh;
317
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000318 if (fd == -1)
319 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000320
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000321 res = pread(fd, buf, size, offset);
322 if (res == -1)
323 res = -errno;
Miklos Szeredie5183742005-02-02 11:14:04 +0000324
Nikolaus Rath09862552017-04-07 16:31:07 -0700325 if(fi == NULL)
326 close(fd);
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000327 return res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000328}
329
Miklos Szeredi0a7077f2001-11-11 18:20:17 +0000330static int xmp_write(const char *path, const char *buf, size_t size,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000331 off_t offset, struct fuse_file_info *fi)
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000332{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000333 int fd;
334 int res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000335
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000336 (void) fi;
Nikolaus Rath09862552017-04-07 16:31:07 -0700337 if(fi == NULL)
338 fd = open(path, O_WRONLY);
339 else
340 fd = fi->fh;
341
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000342 if (fd == -1)
343 return -errno;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000344
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000345 res = pwrite(fd, buf, size, offset);
346 if (res == -1)
347 res = -errno;
Miklos Szeredie5183742005-02-02 11:14:04 +0000348
Nikolaus Rath09862552017-04-07 16:31:07 -0700349 if(fi == NULL)
350 close(fd);
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000351 return res;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000352}
353
Miklos Szeredi52cb09d2005-11-07 11:59:00 +0000354static int xmp_statfs(const char *path, struct statvfs *stbuf)
Mark Glinesd84b39a2002-01-07 16:32:02 +0000355{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000356 int res;
Miklos Szeredi18e75e42004-02-19 14:23:27 +0000357
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000358 res = statvfs(path, stbuf);
359 if (res == -1)
360 return -errno;
Miklos Szeredi18e75e42004-02-19 14:23:27 +0000361
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000362 return 0;
Mark Glinesd84b39a2002-01-07 16:32:02 +0000363}
364
Miklos Szeredifb28c5e2004-11-26 12:15:06 +0000365static int xmp_release(const char *path, struct fuse_file_info *fi)
David McNab7a19caf2003-12-13 02:05:46 +0000366{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000367 (void) path;
Nikolaus Rathdb1c6ad2017-04-07 16:27:33 -0700368 close(fi->fh);
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000369 return 0;
David McNab7a19caf2003-12-13 02:05:46 +0000370}
371
Miklos Szeredifb28c5e2004-11-26 12:15:06 +0000372static int xmp_fsync(const char *path, int isdatasync,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000373 struct fuse_file_info *fi)
David McNab7a19caf2003-12-13 02:05:46 +0000374{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000375 /* Just a stub. This method is optional and can safely be left
376 unimplemented */
Miklos Szeredi2f3d9402003-12-15 12:11:33 +0000377
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000378 (void) path;
379 (void) isdatasync;
380 (void) fi;
381 return 0;
David McNab7a19caf2003-12-13 02:05:46 +0000382}
383
Anatol Pomozov96ac0e52012-04-22 18:49:35 -0700384#ifdef HAVE_POSIX_FALLOCATE
385static int xmp_fallocate(const char *path, int mode,
386 off_t offset, off_t length, struct fuse_file_info *fi)
387{
388 int fd;
389 int res;
390
391 (void) fi;
392
393 if (mode)
394 return -EOPNOTSUPP;
395
Nikolaus Rath09862552017-04-07 16:31:07 -0700396 if(fi == NULL)
397 fd = open(path, O_WRONLY);
398 else
399 fd = fi->fh;
400
Anatol Pomozov96ac0e52012-04-22 18:49:35 -0700401 if (fd == -1)
402 return -errno;
403
404 res = -posix_fallocate(fd, offset, length);
405
Nikolaus Rath09862552017-04-07 16:31:07 -0700406 if(fi == NULL)
407 close(fd);
Anatol Pomozov96ac0e52012-04-22 18:49:35 -0700408 return res;
409}
410#endif
411
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000412#ifdef HAVE_SETXATTR
413/* xattr operations are optional and can safely be left unimplemented */
414static int xmp_setxattr(const char *path, const char *name, const char *value,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000415 size_t size, int flags)
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000416{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000417 int res = lsetxattr(path, name, value, size, flags);
418 if (res == -1)
419 return -errno;
420 return 0;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000421}
422
423static int xmp_getxattr(const char *path, const char *name, char *value,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000424 size_t size)
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000425{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000426 int res = lgetxattr(path, name, value, size);
427 if (res == -1)
428 return -errno;
429 return res;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000430}
431
432static int xmp_listxattr(const char *path, char *list, size_t size)
433{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000434 int res = llistxattr(path, list, size);
435 if (res == -1)
436 return -errno;
437 return res;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000438}
439
440static int xmp_removexattr(const char *path, const char *name)
441{
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000442 int res = lremovexattr(path, name);
443 if (res == -1)
444 return -errno;
445 return 0;
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000446}
447#endif /* HAVE_SETXATTR */
448
Niels de Vos2548c4b2018-06-26 21:40:21 +0200449#ifdef HAVE_COPY_FILE_RANGE
450static ssize_t xmp_copy_file_range(const char *path_in,
451 struct fuse_file_info *fi_in,
452 off_t offset_in, const char *path_out,
453 struct fuse_file_info *fi_out,
454 off_t offset_out, size_t len, int flags)
455{
456 int fd_in, fd_out;
457 ssize_t res;
458
459 if(fi_in == NULL)
460 fd_in = open(path_in, O_RDONLY);
461 else
462 fd_in = fi_in->fh;
463
464 if (fd_in == -1)
465 return -errno;
466
467 if(fi_out == NULL)
468 fd_out = open(path_out, O_WRONLY);
469 else
470 fd_out = fi_out->fh;
471
472 if (fd_out == -1) {
473 close(fd_in);
474 return -errno;
475 }
476
477 res = copy_file_range(fd_in, &offset_in, fd_out, &offset_out, len,
478 flags);
479 if (res == -1)
480 res = -errno;
481
Alan Somersccba27f2021-01-01 12:34:58 -0700482 if (fi_out == NULL)
483 close(fd_out);
484 if (fi_in == NULL)
485 close(fd_in);
Niels de Vos2548c4b2018-06-26 21:40:21 +0200486
487 return res;
488}
489#endif
490
Yuri Perd735af92019-11-03 11:44:31 +0200491static off_t xmp_lseek(const char *path, off_t off, int whence, struct fuse_file_info *fi)
492{
493 int fd;
494 off_t res;
495
496 if (fi == NULL)
497 fd = open(path, O_RDONLY);
498 else
499 fd = fi->fh;
500
501 if (fd == -1)
502 return -errno;
503
504 res = lseek(fd, off, whence);
505 if (res == -1)
506 res = -errno;
507
508 if (fi == NULL)
509 close(fd);
510 return res;
511}
512
zsugabubus81ab7d82020-01-30 16:17:25 +0000513static const struct fuse_operations xmp_oper = {
Nikolaus Rath8ee553d2016-10-18 21:23:22 -0700514 .init = xmp_init,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000515 .getattr = xmp_getattr,
516 .access = xmp_access,
517 .readlink = xmp_readlink,
518 .readdir = xmp_readdir,
519 .mknod = xmp_mknod,
520 .mkdir = xmp_mkdir,
521 .symlink = xmp_symlink,
522 .unlink = xmp_unlink,
523 .rmdir = xmp_rmdir,
524 .rename = xmp_rename,
525 .link = xmp_link,
526 .chmod = xmp_chmod,
527 .chown = xmp_chown,
528 .truncate = xmp_truncate,
Emmanuel Dreyfus40a47ed2011-12-08 10:55:27 +0000529#ifdef HAVE_UTIMENSAT
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000530 .utimens = xmp_utimens,
Emmanuel Dreyfus40a47ed2011-12-08 10:55:27 +0000531#endif
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000532 .open = xmp_open,
Nikolaus Rath20b24a12017-04-07 16:36:52 -0700533 .create = xmp_create,
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000534 .read = xmp_read,
535 .write = xmp_write,
536 .statfs = xmp_statfs,
537 .release = xmp_release,
538 .fsync = xmp_fsync,
Anatol Pomozov96ac0e52012-04-22 18:49:35 -0700539#ifdef HAVE_POSIX_FALLOCATE
540 .fallocate = xmp_fallocate,
541#endif
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000542#ifdef HAVE_SETXATTR
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000543 .setxattr = xmp_setxattr,
544 .getxattr = xmp_getxattr,
545 .listxattr = xmp_listxattr,
546 .removexattr = xmp_removexattr,
Miklos Szeredi03cebae2004-03-31 10:19:18 +0000547#endif
Niels de Vos2548c4b2018-06-26 21:40:21 +0200548#ifdef HAVE_COPY_FILE_RANGE
549 .copy_file_range = xmp_copy_file_range,
550#endif
Yuri Perd735af92019-11-03 11:44:31 +0200551 .lseek = xmp_lseek,
Miklos Szeredi680a69a2001-11-16 13:31:14 +0000552};
553
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000554int main(int argc, char *argv[])
555{
Jean-Pierre Andrébdd2d412021-03-18 10:52:30 +0100556 enum { MAX_ARGS = 10 };
557 int i,new_argc;
558 char *new_argv[MAX_ARGS];
559
Miklos Szeredicdb8b792007-12-12 14:25:40 +0000560 umask(0);
Jean-Pierre Andrébdd2d412021-03-18 10:52:30 +0100561 /* Process the "--plus" option apart */
562 for (i=0, new_argc=0; (i<argc) && (new_argc<MAX_ARGS); i++) {
563 if (!strcmp(argv[i], "--plus")) {
564 fill_dir_plus = FUSE_FILL_DIR_PLUS;
565 } else {
566 new_argv[new_argc++] = argv[i];
567 }
568 }
569 return fuse_main(new_argc, new_argv, &xmp_oper, NULL);
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000570}