|
|
@ -0,0 +1,419 @@ |
|
|
|
/* |
|
|
|
* --- SDE-COPYRIGHT-NOTE-BEGIN --- |
|
|
|
* This copyright note is auto-generated by ./scripts/Create-CopyPatch. |
|
|
|
* |
|
|
|
* Filename: src/tools-source/fl_fuse/fl_fuse.c |
|
|
|
* Copyright (C) 2013 The OpenSDE Project |
|
|
|
* Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org> |
|
|
|
* Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> |
|
|
|
* |
|
|
|
* More information can be found in the files COPYING and README. |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or modify |
|
|
|
* it under the terms of the GNU General Public License as published by |
|
|
|
* the Free Software Foundation; version 2 of the License. A copy of the |
|
|
|
* GNU General Public License can be found in the file COPYING. |
|
|
|
* --- SDE-COPYRIGHT-NOTE-END --- |
|
|
|
*/ |
|
|
|
|
|
|
|
#define FUSE_USE_VERSION 26 |
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H |
|
|
|
#include <config.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifdef linux |
|
|
|
/* For pread()/pwrite()/utimensat() */ |
|
|
|
#define _XOPEN_SOURCE 700 |
|
|
|
#endif |
|
|
|
|
|
|
|
#include <fuse.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <string.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
#include <dirent.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <sys/time.h> |
|
|
|
#ifdef HAVE_SETXATTR |
|
|
|
#include <sys/xattr.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
static int fl_getattr(const char *path, struct stat *stbuf) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = lstat(path, stbuf); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_access(const char *path, int mask) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = access(path, mask); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_readlink(const char *path, char *buf, size_t size) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = readlink(path, buf, size - 1); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
buf[res] = '\0'; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int fl_readdir(const char *path, void *buf, fuse_fill_dir_t filler, |
|
|
|
off_t offset, struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
DIR *dp; |
|
|
|
struct dirent *de; |
|
|
|
|
|
|
|
(void) offset; |
|
|
|
(void) fi; |
|
|
|
|
|
|
|
dp = opendir(path); |
|
|
|
if (dp == NULL) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
while ((de = readdir(dp)) != NULL) { |
|
|
|
struct stat st; |
|
|
|
memset(&st, 0, sizeof(st)); |
|
|
|
st.st_ino = de->d_ino; |
|
|
|
st.st_mode = de->d_type << 12; |
|
|
|
if (filler(buf, de->d_name, &st, 0)) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
closedir(dp); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_mknod(const char *path, mode_t mode, dev_t rdev) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
/* On Linux this could just be 'mknod(path, mode, rdev)' but this |
|
|
|
is more portable */ |
|
|
|
if (S_ISREG(mode)) { |
|
|
|
res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); |
|
|
|
if (res >= 0) |
|
|
|
res = close(res); |
|
|
|
} else if (S_ISFIFO(mode)) |
|
|
|
res = mkfifo(path, mode); |
|
|
|
else |
|
|
|
res = mknod(path, mode, rdev); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_mkdir(const char *path, mode_t mode) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = mkdir(path, mode); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_unlink(const char *path) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = unlink(path); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_rmdir(const char *path) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = rmdir(path); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_symlink(const char *from, const char *to) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = symlink(from, to); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_rename(const char *from, const char *to) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = rename(from, to); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_link(const char *from, const char *to) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = link(from, to); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_chmod(const char *path, mode_t mode) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = chmod(path, mode); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_chown(const char *path, uid_t uid, gid_t gid) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = lchown(path, uid, gid); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_truncate(const char *path, off_t size) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = truncate(path, size); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef HAVE_UTIMENSAT |
|
|
|
static int fl_utimens(const char *path, const struct timespec ts[2]) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
/* don't use utime/utimes since they follow symlinks */ |
|
|
|
res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
static int fl_open(const char *path, struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = open(path, fi->flags); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
close(res); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_read(const char *path, char *buf, size_t size, off_t offset, |
|
|
|
struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
int fd; |
|
|
|
int res; |
|
|
|
|
|
|
|
(void) fi; |
|
|
|
fd = open(path, O_RDONLY); |
|
|
|
if (fd == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
res = pread(fd, buf, size, offset); |
|
|
|
if (res == -1) |
|
|
|
res = -errno; |
|
|
|
|
|
|
|
close(fd); |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_write(const char *path, const char *buf, size_t size, |
|
|
|
off_t offset, struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
int fd; |
|
|
|
int res; |
|
|
|
|
|
|
|
(void) fi; |
|
|
|
fd = open(path, O_WRONLY); |
|
|
|
if (fd == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
res = pwrite(fd, buf, size, offset); |
|
|
|
if (res == -1) |
|
|
|
res = -errno; |
|
|
|
|
|
|
|
close(fd); |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_statfs(const char *path, struct statvfs *stbuf) |
|
|
|
{ |
|
|
|
int res; |
|
|
|
|
|
|
|
res = statvfs(path, stbuf); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_release(const char *path, struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
/* Just a stub. This method is optional and can safely be left |
|
|
|
unimplemented */ |
|
|
|
|
|
|
|
(void) path; |
|
|
|
(void) fi; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_fsync(const char *path, int isdatasync, |
|
|
|
struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
/* Just a stub. This method is optional and can safely be left |
|
|
|
unimplemented */ |
|
|
|
|
|
|
|
(void) path; |
|
|
|
(void) isdatasync; |
|
|
|
(void) fi; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef HAVE_POSIX_FALLOCATE |
|
|
|
static int fl_fallocate(const char *path, int mode, |
|
|
|
off_t offset, off_t length, struct fuse_file_info *fi) |
|
|
|
{ |
|
|
|
int fd; |
|
|
|
int res; |
|
|
|
|
|
|
|
(void) fi; |
|
|
|
|
|
|
|
if (mode) |
|
|
|
return -EOPNOTSUPP; |
|
|
|
|
|
|
|
fd = open(path, O_WRONLY); |
|
|
|
if (fd == -1) |
|
|
|
return -errno; |
|
|
|
|
|
|
|
res = -posix_fallocate(fd, offset, length); |
|
|
|
|
|
|
|
close(fd); |
|
|
|
return res; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifdef HAVE_SETXATTR |
|
|
|
/* xattr operations are optional and can safely be left unimplemented */ |
|
|
|
static int fl_setxattr(const char *path, const char *name, const char *value, |
|
|
|
size_t size, int flags) |
|
|
|
{ |
|
|
|
int res = lsetxattr(path, name, value, size, flags); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_getxattr(const char *path, const char *name, char *value, |
|
|
|
size_t size) |
|
|
|
{ |
|
|
|
int res = lgetxattr(path, name, value, size); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_listxattr(const char *path, char *list, size_t size) |
|
|
|
{ |
|
|
|
int res = llistxattr(path, list, size); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
static int fl_removexattr(const char *path, const char *name) |
|
|
|
{ |
|
|
|
int res = lremovexattr(path, name); |
|
|
|
if (res == -1) |
|
|
|
return -errno; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif /* HAVE_SETXATTR */ |
|
|
|
|
|
|
|
static struct fuse_operations fl_oper = { |
|
|
|
.getattr = fl_getattr, |
|
|
|
.access = fl_access, |
|
|
|
.readlink = fl_readlink, |
|
|
|
.readdir = fl_readdir, |
|
|
|
.mknod = fl_mknod, |
|
|
|
.mkdir = fl_mkdir, |
|
|
|
.symlink = fl_symlink, |
|
|
|
.unlink = fl_unlink, |
|
|
|
.rmdir = fl_rmdir, |
|
|
|
.rename = fl_rename, |
|
|
|
.link = fl_link, |
|
|
|
.chmod = fl_chmod, |
|
|
|
.chown = fl_chown, |
|
|
|
.truncate = fl_truncate, |
|
|
|
#ifdef HAVE_UTIMENSAT |
|
|
|
.utimens = fl_utimens, |
|
|
|
#endif |
|
|
|
.open = fl_open, |
|
|
|
.read = fl_read, |
|
|
|
.write = fl_write, |
|
|
|
.statfs = fl_statfs, |
|
|
|
.release = fl_release, |
|
|
|
.fsync = fl_fsync, |
|
|
|
#ifdef HAVE_POSIX_FALLOCATE |
|
|
|
.fallocate = fl_fallocate, |
|
|
|
#endif |
|
|
|
#ifdef HAVE_SETXATTR |
|
|
|
.setxattr = fl_setxattr, |
|
|
|
.getxattr = fl_getxattr, |
|
|
|
.listxattr = fl_listxattr, |
|
|
|
.removexattr = fl_removexattr, |
|
|
|
#endif |
|
|
|
}; |
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
{ |
|
|
|
umask(0); |
|
|
|
return fuse_main(argc, argv, &fl_oper, NULL); |
|
|
|
} |