16881f68fSopenharmony_ci/* 26881f68fSopenharmony_ci FUSE: Filesystem in Userspace 36881f68fSopenharmony_ci Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 46881f68fSopenharmony_ci Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org> 56881f68fSopenharmony_ci 66881f68fSopenharmony_ci This program can be distributed under the terms of the GNU GPLv2. 76881f68fSopenharmony_ci See the file COPYING. 86881f68fSopenharmony_ci*/ 96881f68fSopenharmony_ci 106881f68fSopenharmony_ci/** @file 116881f68fSopenharmony_ci * 126881f68fSopenharmony_ci * This file system mirrors the existing file system hierarchy of the 136881f68fSopenharmony_ci * system, starting at the root file system. This is implemented by 146881f68fSopenharmony_ci * just "passing through" all requests to the corresponding user-space 156881f68fSopenharmony_ci * libc functions. Its performance is terrible. 166881f68fSopenharmony_ci * 176881f68fSopenharmony_ci * Compile with 186881f68fSopenharmony_ci * 196881f68fSopenharmony_ci * gcc -Wall passthrough.c `pkg-config fuse3 --cflags --libs` -o passthrough 206881f68fSopenharmony_ci * 216881f68fSopenharmony_ci * ## Source code ## 226881f68fSopenharmony_ci * \include passthrough.c 236881f68fSopenharmony_ci */ 246881f68fSopenharmony_ci 256881f68fSopenharmony_ci 266881f68fSopenharmony_ci#define FUSE_USE_VERSION 31 276881f68fSopenharmony_ci 286881f68fSopenharmony_ci#define _GNU_SOURCE 296881f68fSopenharmony_ci 306881f68fSopenharmony_ci#ifdef linux 316881f68fSopenharmony_ci/* For pread()/pwrite()/utimensat() */ 326881f68fSopenharmony_ci#define _XOPEN_SOURCE 700 336881f68fSopenharmony_ci#endif 346881f68fSopenharmony_ci 356881f68fSopenharmony_ci#include <fuse.h> 366881f68fSopenharmony_ci#include <stdio.h> 376881f68fSopenharmony_ci#include <string.h> 386881f68fSopenharmony_ci#include <unistd.h> 396881f68fSopenharmony_ci#include <fcntl.h> 406881f68fSopenharmony_ci#include <sys/stat.h> 416881f68fSopenharmony_ci#include <dirent.h> 426881f68fSopenharmony_ci#include <errno.h> 436881f68fSopenharmony_ci#ifdef __FreeBSD__ 446881f68fSopenharmony_ci#include <sys/socket.h> 456881f68fSopenharmony_ci#include <sys/un.h> 466881f68fSopenharmony_ci#endif 476881f68fSopenharmony_ci#include <sys/time.h> 486881f68fSopenharmony_ci#ifdef HAVE_SETXATTR 496881f68fSopenharmony_ci#include <sys/xattr.h> 506881f68fSopenharmony_ci#endif 516881f68fSopenharmony_ci 526881f68fSopenharmony_ci#include "passthrough_helpers.h" 536881f68fSopenharmony_ci 546881f68fSopenharmony_cistatic int fill_dir_plus = 0; 556881f68fSopenharmony_ci 566881f68fSopenharmony_cistatic void *xmp_init(struct fuse_conn_info *conn, 576881f68fSopenharmony_ci struct fuse_config *cfg) 586881f68fSopenharmony_ci{ 596881f68fSopenharmony_ci (void) conn; 606881f68fSopenharmony_ci cfg->use_ino = 1; 616881f68fSopenharmony_ci 626881f68fSopenharmony_ci /* Pick up changes from lower filesystem right away. This is 636881f68fSopenharmony_ci also necessary for better hardlink support. When the kernel 646881f68fSopenharmony_ci calls the unlink() handler, it does not know the inode of 656881f68fSopenharmony_ci the to-be-removed entry and can therefore not invalidate 666881f68fSopenharmony_ci the cache of the associated inode - resulting in an 676881f68fSopenharmony_ci incorrect st_nlink value being reported for any remaining 686881f68fSopenharmony_ci hardlinks to this inode. */ 696881f68fSopenharmony_ci cfg->entry_timeout = 0; 706881f68fSopenharmony_ci cfg->attr_timeout = 0; 716881f68fSopenharmony_ci cfg->negative_timeout = 0; 726881f68fSopenharmony_ci 736881f68fSopenharmony_ci return NULL; 746881f68fSopenharmony_ci} 756881f68fSopenharmony_ci 766881f68fSopenharmony_cistatic int xmp_getattr(const char *path, struct stat *stbuf, 776881f68fSopenharmony_ci struct fuse_file_info *fi) 786881f68fSopenharmony_ci{ 796881f68fSopenharmony_ci (void) fi; 806881f68fSopenharmony_ci int res; 816881f68fSopenharmony_ci 826881f68fSopenharmony_ci res = lstat(path, stbuf); 836881f68fSopenharmony_ci if (res == -1) 846881f68fSopenharmony_ci return -errno; 856881f68fSopenharmony_ci 866881f68fSopenharmony_ci return 0; 876881f68fSopenharmony_ci} 886881f68fSopenharmony_ci 896881f68fSopenharmony_cistatic int xmp_access(const char *path, int mask) 906881f68fSopenharmony_ci{ 916881f68fSopenharmony_ci int res; 926881f68fSopenharmony_ci 936881f68fSopenharmony_ci res = access(path, mask); 946881f68fSopenharmony_ci if (res == -1) 956881f68fSopenharmony_ci return -errno; 966881f68fSopenharmony_ci 976881f68fSopenharmony_ci return 0; 986881f68fSopenharmony_ci} 996881f68fSopenharmony_ci 1006881f68fSopenharmony_cistatic int xmp_readlink(const char *path, char *buf, size_t size) 1016881f68fSopenharmony_ci{ 1026881f68fSopenharmony_ci int res; 1036881f68fSopenharmony_ci 1046881f68fSopenharmony_ci res = readlink(path, buf, size - 1); 1056881f68fSopenharmony_ci if (res == -1) 1066881f68fSopenharmony_ci return -errno; 1076881f68fSopenharmony_ci 1086881f68fSopenharmony_ci buf[res] = '\0'; 1096881f68fSopenharmony_ci return 0; 1106881f68fSopenharmony_ci} 1116881f68fSopenharmony_ci 1126881f68fSopenharmony_ci 1136881f68fSopenharmony_cistatic int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 1146881f68fSopenharmony_ci off_t offset, struct fuse_file_info *fi, 1156881f68fSopenharmony_ci enum fuse_readdir_flags flags) 1166881f68fSopenharmony_ci{ 1176881f68fSopenharmony_ci DIR *dp; 1186881f68fSopenharmony_ci struct dirent *de; 1196881f68fSopenharmony_ci 1206881f68fSopenharmony_ci (void) offset; 1216881f68fSopenharmony_ci (void) fi; 1226881f68fSopenharmony_ci (void) flags; 1236881f68fSopenharmony_ci 1246881f68fSopenharmony_ci dp = opendir(path); 1256881f68fSopenharmony_ci if (dp == NULL) 1266881f68fSopenharmony_ci return -errno; 1276881f68fSopenharmony_ci 1286881f68fSopenharmony_ci while ((de = readdir(dp)) != NULL) { 1296881f68fSopenharmony_ci struct stat st; 1306881f68fSopenharmony_ci memset(&st, 0, sizeof(st)); 1316881f68fSopenharmony_ci st.st_ino = de->d_ino; 1326881f68fSopenharmony_ci st.st_mode = de->d_type << 12; 1336881f68fSopenharmony_ci if (filler(buf, de->d_name, &st, 0, fill_dir_plus)) 1346881f68fSopenharmony_ci break; 1356881f68fSopenharmony_ci } 1366881f68fSopenharmony_ci 1376881f68fSopenharmony_ci closedir(dp); 1386881f68fSopenharmony_ci return 0; 1396881f68fSopenharmony_ci} 1406881f68fSopenharmony_ci 1416881f68fSopenharmony_cistatic int xmp_mknod(const char *path, mode_t mode, dev_t rdev) 1426881f68fSopenharmony_ci{ 1436881f68fSopenharmony_ci int res; 1446881f68fSopenharmony_ci 1456881f68fSopenharmony_ci res = mknod_wrapper(AT_FDCWD, path, NULL, mode, rdev); 1466881f68fSopenharmony_ci if (res == -1) 1476881f68fSopenharmony_ci return -errno; 1486881f68fSopenharmony_ci 1496881f68fSopenharmony_ci return 0; 1506881f68fSopenharmony_ci} 1516881f68fSopenharmony_ci 1526881f68fSopenharmony_cistatic int xmp_mkdir(const char *path, mode_t mode) 1536881f68fSopenharmony_ci{ 1546881f68fSopenharmony_ci int res; 1556881f68fSopenharmony_ci 1566881f68fSopenharmony_ci res = mkdir(path, mode); 1576881f68fSopenharmony_ci if (res == -1) 1586881f68fSopenharmony_ci return -errno; 1596881f68fSopenharmony_ci 1606881f68fSopenharmony_ci return 0; 1616881f68fSopenharmony_ci} 1626881f68fSopenharmony_ci 1636881f68fSopenharmony_cistatic int xmp_unlink(const char *path) 1646881f68fSopenharmony_ci{ 1656881f68fSopenharmony_ci int res; 1666881f68fSopenharmony_ci 1676881f68fSopenharmony_ci res = unlink(path); 1686881f68fSopenharmony_ci if (res == -1) 1696881f68fSopenharmony_ci return -errno; 1706881f68fSopenharmony_ci 1716881f68fSopenharmony_ci return 0; 1726881f68fSopenharmony_ci} 1736881f68fSopenharmony_ci 1746881f68fSopenharmony_cistatic int xmp_rmdir(const char *path) 1756881f68fSopenharmony_ci{ 1766881f68fSopenharmony_ci int res; 1776881f68fSopenharmony_ci 1786881f68fSopenharmony_ci res = rmdir(path); 1796881f68fSopenharmony_ci if (res == -1) 1806881f68fSopenharmony_ci return -errno; 1816881f68fSopenharmony_ci 1826881f68fSopenharmony_ci return 0; 1836881f68fSopenharmony_ci} 1846881f68fSopenharmony_ci 1856881f68fSopenharmony_cistatic int xmp_symlink(const char *from, const char *to) 1866881f68fSopenharmony_ci{ 1876881f68fSopenharmony_ci int res; 1886881f68fSopenharmony_ci 1896881f68fSopenharmony_ci res = symlink(from, to); 1906881f68fSopenharmony_ci if (res == -1) 1916881f68fSopenharmony_ci return -errno; 1926881f68fSopenharmony_ci 1936881f68fSopenharmony_ci return 0; 1946881f68fSopenharmony_ci} 1956881f68fSopenharmony_ci 1966881f68fSopenharmony_cistatic int xmp_rename(const char *from, const char *to, unsigned int flags) 1976881f68fSopenharmony_ci{ 1986881f68fSopenharmony_ci int res; 1996881f68fSopenharmony_ci 2006881f68fSopenharmony_ci if (flags) 2016881f68fSopenharmony_ci return -EINVAL; 2026881f68fSopenharmony_ci 2036881f68fSopenharmony_ci res = rename(from, to); 2046881f68fSopenharmony_ci if (res == -1) 2056881f68fSopenharmony_ci return -errno; 2066881f68fSopenharmony_ci 2076881f68fSopenharmony_ci return 0; 2086881f68fSopenharmony_ci} 2096881f68fSopenharmony_ci 2106881f68fSopenharmony_cistatic int xmp_link(const char *from, const char *to) 2116881f68fSopenharmony_ci{ 2126881f68fSopenharmony_ci int res; 2136881f68fSopenharmony_ci 2146881f68fSopenharmony_ci res = link(from, to); 2156881f68fSopenharmony_ci if (res == -1) 2166881f68fSopenharmony_ci return -errno; 2176881f68fSopenharmony_ci 2186881f68fSopenharmony_ci return 0; 2196881f68fSopenharmony_ci} 2206881f68fSopenharmony_ci 2216881f68fSopenharmony_cistatic int xmp_chmod(const char *path, mode_t mode, 2226881f68fSopenharmony_ci struct fuse_file_info *fi) 2236881f68fSopenharmony_ci{ 2246881f68fSopenharmony_ci (void) fi; 2256881f68fSopenharmony_ci int res; 2266881f68fSopenharmony_ci 2276881f68fSopenharmony_ci res = chmod(path, mode); 2286881f68fSopenharmony_ci if (res == -1) 2296881f68fSopenharmony_ci return -errno; 2306881f68fSopenharmony_ci 2316881f68fSopenharmony_ci return 0; 2326881f68fSopenharmony_ci} 2336881f68fSopenharmony_ci 2346881f68fSopenharmony_cistatic int xmp_chown(const char *path, uid_t uid, gid_t gid, 2356881f68fSopenharmony_ci struct fuse_file_info *fi) 2366881f68fSopenharmony_ci{ 2376881f68fSopenharmony_ci (void) fi; 2386881f68fSopenharmony_ci int res; 2396881f68fSopenharmony_ci 2406881f68fSopenharmony_ci res = lchown(path, uid, gid); 2416881f68fSopenharmony_ci if (res == -1) 2426881f68fSopenharmony_ci return -errno; 2436881f68fSopenharmony_ci 2446881f68fSopenharmony_ci return 0; 2456881f68fSopenharmony_ci} 2466881f68fSopenharmony_ci 2476881f68fSopenharmony_cistatic int xmp_truncate(const char *path, off_t size, 2486881f68fSopenharmony_ci struct fuse_file_info *fi) 2496881f68fSopenharmony_ci{ 2506881f68fSopenharmony_ci int res; 2516881f68fSopenharmony_ci 2526881f68fSopenharmony_ci if (fi != NULL) 2536881f68fSopenharmony_ci res = ftruncate(fi->fh, size); 2546881f68fSopenharmony_ci else 2556881f68fSopenharmony_ci res = truncate(path, size); 2566881f68fSopenharmony_ci if (res == -1) 2576881f68fSopenharmony_ci return -errno; 2586881f68fSopenharmony_ci 2596881f68fSopenharmony_ci return 0; 2606881f68fSopenharmony_ci} 2616881f68fSopenharmony_ci 2626881f68fSopenharmony_ci#ifdef HAVE_UTIMENSAT 2636881f68fSopenharmony_cistatic int xmp_utimens(const char *path, const struct timespec ts[2], 2646881f68fSopenharmony_ci struct fuse_file_info *fi) 2656881f68fSopenharmony_ci{ 2666881f68fSopenharmony_ci (void) fi; 2676881f68fSopenharmony_ci int res; 2686881f68fSopenharmony_ci 2696881f68fSopenharmony_ci /* don't use utime/utimes since they follow symlinks */ 2706881f68fSopenharmony_ci res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW); 2716881f68fSopenharmony_ci if (res == -1) 2726881f68fSopenharmony_ci return -errno; 2736881f68fSopenharmony_ci 2746881f68fSopenharmony_ci return 0; 2756881f68fSopenharmony_ci} 2766881f68fSopenharmony_ci#endif 2776881f68fSopenharmony_ci 2786881f68fSopenharmony_cistatic int xmp_create(const char *path, mode_t mode, 2796881f68fSopenharmony_ci struct fuse_file_info *fi) 2806881f68fSopenharmony_ci{ 2816881f68fSopenharmony_ci int res; 2826881f68fSopenharmony_ci 2836881f68fSopenharmony_ci res = open(path, fi->flags, mode); 2846881f68fSopenharmony_ci if (res == -1) 2856881f68fSopenharmony_ci return -errno; 2866881f68fSopenharmony_ci 2876881f68fSopenharmony_ci fi->fh = res; 2886881f68fSopenharmony_ci return 0; 2896881f68fSopenharmony_ci} 2906881f68fSopenharmony_ci 2916881f68fSopenharmony_cistatic int xmp_open(const char *path, struct fuse_file_info *fi) 2926881f68fSopenharmony_ci{ 2936881f68fSopenharmony_ci int res; 2946881f68fSopenharmony_ci 2956881f68fSopenharmony_ci res = open(path, fi->flags); 2966881f68fSopenharmony_ci if (res == -1) 2976881f68fSopenharmony_ci return -errno; 2986881f68fSopenharmony_ci 2996881f68fSopenharmony_ci fi->fh = res; 3006881f68fSopenharmony_ci return 0; 3016881f68fSopenharmony_ci} 3026881f68fSopenharmony_ci 3036881f68fSopenharmony_cistatic int xmp_read(const char *path, char *buf, size_t size, off_t offset, 3046881f68fSopenharmony_ci struct fuse_file_info *fi) 3056881f68fSopenharmony_ci{ 3066881f68fSopenharmony_ci int fd; 3076881f68fSopenharmony_ci int res; 3086881f68fSopenharmony_ci 3096881f68fSopenharmony_ci if(fi == NULL) 3106881f68fSopenharmony_ci fd = open(path, O_RDONLY); 3116881f68fSopenharmony_ci else 3126881f68fSopenharmony_ci fd = fi->fh; 3136881f68fSopenharmony_ci 3146881f68fSopenharmony_ci if (fd == -1) 3156881f68fSopenharmony_ci return -errno; 3166881f68fSopenharmony_ci 3176881f68fSopenharmony_ci res = pread(fd, buf, size, offset); 3186881f68fSopenharmony_ci if (res == -1) 3196881f68fSopenharmony_ci res = -errno; 3206881f68fSopenharmony_ci 3216881f68fSopenharmony_ci if(fi == NULL) 3226881f68fSopenharmony_ci close(fd); 3236881f68fSopenharmony_ci return res; 3246881f68fSopenharmony_ci} 3256881f68fSopenharmony_ci 3266881f68fSopenharmony_cistatic int xmp_write(const char *path, const char *buf, size_t size, 3276881f68fSopenharmony_ci off_t offset, struct fuse_file_info *fi) 3286881f68fSopenharmony_ci{ 3296881f68fSopenharmony_ci int fd; 3306881f68fSopenharmony_ci int res; 3316881f68fSopenharmony_ci 3326881f68fSopenharmony_ci (void) fi; 3336881f68fSopenharmony_ci if(fi == NULL) 3346881f68fSopenharmony_ci fd = open(path, O_WRONLY); 3356881f68fSopenharmony_ci else 3366881f68fSopenharmony_ci fd = fi->fh; 3376881f68fSopenharmony_ci 3386881f68fSopenharmony_ci if (fd == -1) 3396881f68fSopenharmony_ci return -errno; 3406881f68fSopenharmony_ci 3416881f68fSopenharmony_ci res = pwrite(fd, buf, size, offset); 3426881f68fSopenharmony_ci if (res == -1) 3436881f68fSopenharmony_ci res = -errno; 3446881f68fSopenharmony_ci 3456881f68fSopenharmony_ci if(fi == NULL) 3466881f68fSopenharmony_ci close(fd); 3476881f68fSopenharmony_ci return res; 3486881f68fSopenharmony_ci} 3496881f68fSopenharmony_ci 3506881f68fSopenharmony_cistatic int xmp_statfs(const char *path, struct statvfs *stbuf) 3516881f68fSopenharmony_ci{ 3526881f68fSopenharmony_ci int res; 3536881f68fSopenharmony_ci 3546881f68fSopenharmony_ci res = statvfs(path, stbuf); 3556881f68fSopenharmony_ci if (res == -1) 3566881f68fSopenharmony_ci return -errno; 3576881f68fSopenharmony_ci 3586881f68fSopenharmony_ci return 0; 3596881f68fSopenharmony_ci} 3606881f68fSopenharmony_ci 3616881f68fSopenharmony_cistatic int xmp_release(const char *path, struct fuse_file_info *fi) 3626881f68fSopenharmony_ci{ 3636881f68fSopenharmony_ci (void) path; 3646881f68fSopenharmony_ci close(fi->fh); 3656881f68fSopenharmony_ci return 0; 3666881f68fSopenharmony_ci} 3676881f68fSopenharmony_ci 3686881f68fSopenharmony_cistatic int xmp_fsync(const char *path, int isdatasync, 3696881f68fSopenharmony_ci struct fuse_file_info *fi) 3706881f68fSopenharmony_ci{ 3716881f68fSopenharmony_ci /* Just a stub. This method is optional and can safely be left 3726881f68fSopenharmony_ci unimplemented */ 3736881f68fSopenharmony_ci 3746881f68fSopenharmony_ci (void) path; 3756881f68fSopenharmony_ci (void) isdatasync; 3766881f68fSopenharmony_ci (void) fi; 3776881f68fSopenharmony_ci return 0; 3786881f68fSopenharmony_ci} 3796881f68fSopenharmony_ci 3806881f68fSopenharmony_ci#ifdef HAVE_POSIX_FALLOCATE 3816881f68fSopenharmony_cistatic int xmp_fallocate(const char *path, int mode, 3826881f68fSopenharmony_ci off_t offset, off_t length, struct fuse_file_info *fi) 3836881f68fSopenharmony_ci{ 3846881f68fSopenharmony_ci int fd; 3856881f68fSopenharmony_ci int res; 3866881f68fSopenharmony_ci 3876881f68fSopenharmony_ci (void) fi; 3886881f68fSopenharmony_ci 3896881f68fSopenharmony_ci if (mode) 3906881f68fSopenharmony_ci return -EOPNOTSUPP; 3916881f68fSopenharmony_ci 3926881f68fSopenharmony_ci if(fi == NULL) 3936881f68fSopenharmony_ci fd = open(path, O_WRONLY); 3946881f68fSopenharmony_ci else 3956881f68fSopenharmony_ci fd = fi->fh; 3966881f68fSopenharmony_ci 3976881f68fSopenharmony_ci if (fd == -1) 3986881f68fSopenharmony_ci return -errno; 3996881f68fSopenharmony_ci 4006881f68fSopenharmony_ci res = -posix_fallocate(fd, offset, length); 4016881f68fSopenharmony_ci 4026881f68fSopenharmony_ci if(fi == NULL) 4036881f68fSopenharmony_ci close(fd); 4046881f68fSopenharmony_ci return res; 4056881f68fSopenharmony_ci} 4066881f68fSopenharmony_ci#endif 4076881f68fSopenharmony_ci 4086881f68fSopenharmony_ci#ifdef HAVE_SETXATTR 4096881f68fSopenharmony_ci/* xattr operations are optional and can safely be left unimplemented */ 4106881f68fSopenharmony_cistatic int xmp_setxattr(const char *path, const char *name, const char *value, 4116881f68fSopenharmony_ci size_t size, int flags) 4126881f68fSopenharmony_ci{ 4136881f68fSopenharmony_ci int res = lsetxattr(path, name, value, size, flags); 4146881f68fSopenharmony_ci if (res == -1) 4156881f68fSopenharmony_ci return -errno; 4166881f68fSopenharmony_ci return 0; 4176881f68fSopenharmony_ci} 4186881f68fSopenharmony_ci 4196881f68fSopenharmony_cistatic int xmp_getxattr(const char *path, const char *name, char *value, 4206881f68fSopenharmony_ci size_t size) 4216881f68fSopenharmony_ci{ 4226881f68fSopenharmony_ci int res = lgetxattr(path, name, value, size); 4236881f68fSopenharmony_ci if (res == -1) 4246881f68fSopenharmony_ci return -errno; 4256881f68fSopenharmony_ci return res; 4266881f68fSopenharmony_ci} 4276881f68fSopenharmony_ci 4286881f68fSopenharmony_cistatic int xmp_listxattr(const char *path, char *list, size_t size) 4296881f68fSopenharmony_ci{ 4306881f68fSopenharmony_ci int res = llistxattr(path, list, size); 4316881f68fSopenharmony_ci if (res == -1) 4326881f68fSopenharmony_ci return -errno; 4336881f68fSopenharmony_ci return res; 4346881f68fSopenharmony_ci} 4356881f68fSopenharmony_ci 4366881f68fSopenharmony_cistatic int xmp_removexattr(const char *path, const char *name) 4376881f68fSopenharmony_ci{ 4386881f68fSopenharmony_ci int res = lremovexattr(path, name); 4396881f68fSopenharmony_ci if (res == -1) 4406881f68fSopenharmony_ci return -errno; 4416881f68fSopenharmony_ci return 0; 4426881f68fSopenharmony_ci} 4436881f68fSopenharmony_ci#endif /* HAVE_SETXATTR */ 4446881f68fSopenharmony_ci 4456881f68fSopenharmony_ci#ifdef HAVE_COPY_FILE_RANGE 4466881f68fSopenharmony_cistatic ssize_t xmp_copy_file_range(const char *path_in, 4476881f68fSopenharmony_ci struct fuse_file_info *fi_in, 4486881f68fSopenharmony_ci off_t offset_in, const char *path_out, 4496881f68fSopenharmony_ci struct fuse_file_info *fi_out, 4506881f68fSopenharmony_ci off_t offset_out, size_t len, int flags) 4516881f68fSopenharmony_ci{ 4526881f68fSopenharmony_ci int fd_in, fd_out; 4536881f68fSopenharmony_ci ssize_t res; 4546881f68fSopenharmony_ci 4556881f68fSopenharmony_ci if(fi_in == NULL) 4566881f68fSopenharmony_ci fd_in = open(path_in, O_RDONLY); 4576881f68fSopenharmony_ci else 4586881f68fSopenharmony_ci fd_in = fi_in->fh; 4596881f68fSopenharmony_ci 4606881f68fSopenharmony_ci if (fd_in == -1) 4616881f68fSopenharmony_ci return -errno; 4626881f68fSopenharmony_ci 4636881f68fSopenharmony_ci if(fi_out == NULL) 4646881f68fSopenharmony_ci fd_out = open(path_out, O_WRONLY); 4656881f68fSopenharmony_ci else 4666881f68fSopenharmony_ci fd_out = fi_out->fh; 4676881f68fSopenharmony_ci 4686881f68fSopenharmony_ci if (fd_out == -1) { 4696881f68fSopenharmony_ci close(fd_in); 4706881f68fSopenharmony_ci return -errno; 4716881f68fSopenharmony_ci } 4726881f68fSopenharmony_ci 4736881f68fSopenharmony_ci res = copy_file_range(fd_in, &offset_in, fd_out, &offset_out, len, 4746881f68fSopenharmony_ci flags); 4756881f68fSopenharmony_ci if (res == -1) 4766881f68fSopenharmony_ci res = -errno; 4776881f68fSopenharmony_ci 4786881f68fSopenharmony_ci if (fi_out == NULL) 4796881f68fSopenharmony_ci close(fd_out); 4806881f68fSopenharmony_ci if (fi_in == NULL) 4816881f68fSopenharmony_ci close(fd_in); 4826881f68fSopenharmony_ci 4836881f68fSopenharmony_ci return res; 4846881f68fSopenharmony_ci} 4856881f68fSopenharmony_ci#endif 4866881f68fSopenharmony_ci 4876881f68fSopenharmony_cistatic off_t xmp_lseek(const char *path, off_t off, int whence, struct fuse_file_info *fi) 4886881f68fSopenharmony_ci{ 4896881f68fSopenharmony_ci int fd; 4906881f68fSopenharmony_ci off_t res; 4916881f68fSopenharmony_ci 4926881f68fSopenharmony_ci if (fi == NULL) 4936881f68fSopenharmony_ci fd = open(path, O_RDONLY); 4946881f68fSopenharmony_ci else 4956881f68fSopenharmony_ci fd = fi->fh; 4966881f68fSopenharmony_ci 4976881f68fSopenharmony_ci if (fd == -1) 4986881f68fSopenharmony_ci return -errno; 4996881f68fSopenharmony_ci 5006881f68fSopenharmony_ci res = lseek(fd, off, whence); 5016881f68fSopenharmony_ci if (res == -1) 5026881f68fSopenharmony_ci res = -errno; 5036881f68fSopenharmony_ci 5046881f68fSopenharmony_ci if (fi == NULL) 5056881f68fSopenharmony_ci close(fd); 5066881f68fSopenharmony_ci return res; 5076881f68fSopenharmony_ci} 5086881f68fSopenharmony_ci 5096881f68fSopenharmony_cistatic const struct fuse_operations xmp_oper = { 5106881f68fSopenharmony_ci .init = xmp_init, 5116881f68fSopenharmony_ci .getattr = xmp_getattr, 5126881f68fSopenharmony_ci .access = xmp_access, 5136881f68fSopenharmony_ci .readlink = xmp_readlink, 5146881f68fSopenharmony_ci .readdir = xmp_readdir, 5156881f68fSopenharmony_ci .mknod = xmp_mknod, 5166881f68fSopenharmony_ci .mkdir = xmp_mkdir, 5176881f68fSopenharmony_ci .symlink = xmp_symlink, 5186881f68fSopenharmony_ci .unlink = xmp_unlink, 5196881f68fSopenharmony_ci .rmdir = xmp_rmdir, 5206881f68fSopenharmony_ci .rename = xmp_rename, 5216881f68fSopenharmony_ci .link = xmp_link, 5226881f68fSopenharmony_ci .chmod = xmp_chmod, 5236881f68fSopenharmony_ci .chown = xmp_chown, 5246881f68fSopenharmony_ci .truncate = xmp_truncate, 5256881f68fSopenharmony_ci#ifdef HAVE_UTIMENSAT 5266881f68fSopenharmony_ci .utimens = xmp_utimens, 5276881f68fSopenharmony_ci#endif 5286881f68fSopenharmony_ci .open = xmp_open, 5296881f68fSopenharmony_ci .create = xmp_create, 5306881f68fSopenharmony_ci .read = xmp_read, 5316881f68fSopenharmony_ci .write = xmp_write, 5326881f68fSopenharmony_ci .statfs = xmp_statfs, 5336881f68fSopenharmony_ci .release = xmp_release, 5346881f68fSopenharmony_ci .fsync = xmp_fsync, 5356881f68fSopenharmony_ci#ifdef HAVE_POSIX_FALLOCATE 5366881f68fSopenharmony_ci .fallocate = xmp_fallocate, 5376881f68fSopenharmony_ci#endif 5386881f68fSopenharmony_ci#ifdef HAVE_SETXATTR 5396881f68fSopenharmony_ci .setxattr = xmp_setxattr, 5406881f68fSopenharmony_ci .getxattr = xmp_getxattr, 5416881f68fSopenharmony_ci .listxattr = xmp_listxattr, 5426881f68fSopenharmony_ci .removexattr = xmp_removexattr, 5436881f68fSopenharmony_ci#endif 5446881f68fSopenharmony_ci#ifdef HAVE_COPY_FILE_RANGE 5456881f68fSopenharmony_ci .copy_file_range = xmp_copy_file_range, 5466881f68fSopenharmony_ci#endif 5476881f68fSopenharmony_ci .lseek = xmp_lseek, 5486881f68fSopenharmony_ci}; 5496881f68fSopenharmony_ci 5506881f68fSopenharmony_ciint main(int argc, char *argv[]) 5516881f68fSopenharmony_ci{ 5526881f68fSopenharmony_ci enum { MAX_ARGS = 10 }; 5536881f68fSopenharmony_ci int i,new_argc; 5546881f68fSopenharmony_ci char *new_argv[MAX_ARGS]; 5556881f68fSopenharmony_ci 5566881f68fSopenharmony_ci umask(0); 5576881f68fSopenharmony_ci /* Process the "--plus" option apart */ 5586881f68fSopenharmony_ci for (i=0, new_argc=0; (i<argc) && (new_argc<MAX_ARGS); i++) { 5596881f68fSopenharmony_ci if (!strcmp(argv[i], "--plus")) { 5606881f68fSopenharmony_ci fill_dir_plus = FUSE_FILL_DIR_PLUS; 5616881f68fSopenharmony_ci } else { 5626881f68fSopenharmony_ci new_argv[new_argc++] = argv[i]; 5636881f68fSopenharmony_ci } 5646881f68fSopenharmony_ci } 5656881f68fSopenharmony_ci return fuse_main(new_argc, new_argv, &xmp_oper, NULL); 5666881f68fSopenharmony_ci} 567