2023-11-03 22:56:54 +00:00
|
|
|
/*
|
2020-05-19 02:13:51 +00:00
|
|
|
* Copyright (c) 2020 Adler Neves <adlerosn@gmail.com>
|
2023-11-03 22:56:54 +00:00
|
|
|
* Copyright (c) 2023 Bruno Gazotti <bgazotti@gmail.com>
|
2020-05-19 02:13:51 +00:00
|
|
|
*
|
2023-11-03 22:56:54 +00:00
|
|
|
* CICPOFFS 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.
|
2020-05-19 02:13:51 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cicpoffs.hpp"
|
|
|
|
#include "cicpps.hpp"
|
|
|
|
extern "C"{
|
2023-11-04 00:54:26 +00:00
|
|
|
#include <ulockmgr.h>
|
2020-05-19 02:13:51 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/xattr.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
}
|
|
|
|
|
2023-11-04 00:54:26 +00:00
|
|
|
#define VERSION "0.0.2"
|
2020-05-19 02:13:51 +00:00
|
|
|
|
|
|
|
static struct fuse_operations operations = {
|
|
|
|
.getattr = fuse_fn_getattr,
|
|
|
|
.readlink = fuse_fn_readlink,
|
|
|
|
// .getdir = <unimplemented> - deprecated,
|
|
|
|
.mknod = fuse_fn_mknod,
|
|
|
|
.mkdir = fuse_fn_mkdir,
|
|
|
|
.unlink = fuse_fn_unlink,
|
|
|
|
.rmdir = fuse_fn_rmdir,
|
|
|
|
.symlink = fuse_fn_symlink,
|
|
|
|
.rename = fuse_fn_rename,
|
|
|
|
.link = fuse_fn_link,
|
|
|
|
.chmod = fuse_fn_chmod,
|
|
|
|
.chown = fuse_fn_chown,
|
|
|
|
.truncate = fuse_fn_truncate,
|
2023-10-30 03:16:37 +00:00
|
|
|
//.utime = fuse_fn_utime,
|
2020-05-19 02:13:51 +00:00
|
|
|
.open = fuse_fn_open,
|
|
|
|
.read = fuse_fn_read,
|
|
|
|
.write = fuse_fn_write,
|
|
|
|
.statfs = fuse_fn_statfs,
|
|
|
|
.flush = fuse_fn_flush,
|
|
|
|
.release = fuse_fn_release,
|
|
|
|
.fsync = fuse_fn_fsync,
|
|
|
|
.setxattr = fuse_fn_setxattr,
|
|
|
|
.getxattr = fuse_fn_getxattr,
|
|
|
|
.listxattr = fuse_fn_listxattr,
|
|
|
|
.removexattr = fuse_fn_removexattr,
|
|
|
|
.opendir = fuse_fn_opendir,
|
|
|
|
.readdir = fuse_fn_readdir,
|
|
|
|
.releasedir = fuse_fn_releasedir,
|
|
|
|
// .fsyncdir = fuse_fn_fsyncdir,
|
|
|
|
.init = fuse_fn_init,
|
|
|
|
.destroy = fuse_fn_destroy,
|
|
|
|
.access = fuse_fn_access,
|
|
|
|
.create = fuse_fn_create,
|
2023-10-30 03:16:37 +00:00
|
|
|
//.ftruncate = fuse_fn_ftruncate,
|
|
|
|
//.fgetattr = fuse_fn_fgetattr,
|
2020-05-19 02:13:51 +00:00
|
|
|
.lock = fuse_fn_lock,
|
|
|
|
.utimens = fuse_fn_utimens,
|
|
|
|
//.bmap = <unimplemented> - not for block devices,
|
|
|
|
//.ioctl = fuse_fn_ioctl,
|
|
|
|
//.poll = fuse_fn_poll,
|
|
|
|
//.flock = fuse_fn_flock,
|
|
|
|
.fallocate = fuse_fn_fallocate,
|
|
|
|
};
|
|
|
|
|
|
|
|
static char* read_source_directory = NULL;
|
|
|
|
|
|
|
|
static char* argv0 = NULL;
|
|
|
|
|
|
|
|
static void stderr_print(const char* msg){
|
|
|
|
fprintf(stderr, "[%s] %s\n", argv0, msg);
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ignore_print(const char* msg){};
|
|
|
|
|
|
|
|
static void (*logmsg) (const char* msg) = ignore_print;
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
void* (fuse_fn_init) (struct fuse_conn_info* conn, struct fuse_config* cfg){
|
2020-05-19 02:13:51 +00:00
|
|
|
struct stat st;
|
|
|
|
if(stat(read_source_directory, &st)){
|
|
|
|
logmsg("Source does not exist.");
|
|
|
|
exit(ENOENT);
|
|
|
|
}
|
|
|
|
if(read_source_directory[0]!='/'){
|
|
|
|
logmsg("Path must be absolute.");
|
|
|
|
exit(ENOENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
};
|
|
|
|
|
|
|
|
void (fuse_fn_destroy) (void* private_data){
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
int (fuse_fn_getattr) (const char* path, struct stat* stbuf, struct fuse_file_info* fi){
|
2020-05-19 02:13:51 +00:00
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = stat(correctpath, stbuf);
|
|
|
|
free((void*) correctpath);
|
|
|
|
if(retval==-1) return -errno;
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_readlink) (const char* path, char* buf, size_t size){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = readlink(correctpath, buf, size);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_mknod) (const char* path, mode_t mode, dev_t rdev){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = mknod(correctpath, mode, rdev);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_mkdir) (const char* path, mode_t mode){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = mkdir(correctpath, mode);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_unlink) (const char* path){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = unlink(correctpath);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_rmdir) (const char* path){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = rmdir(correctpath);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_symlink) (const char* to, const char* from){
|
|
|
|
const char* correctfrom = correct_case_sensitivity_for(read_source_directory, from);
|
|
|
|
int retval = symlink(to, correctfrom);
|
|
|
|
free((void*) correctfrom);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
// flag behavior is absolutely ignored
|
|
|
|
int (fuse_fn_rename) (const char* from, const char* to, unsigned int flags){
|
2020-05-19 02:13:51 +00:00
|
|
|
const char* correctfrom = correct_case_sensitivity_for(read_source_directory, from);
|
|
|
|
const char* correctto = correct_case_sensitivity_for(read_source_directory, to);
|
|
|
|
int retval = rename(correctfrom, correctto);
|
|
|
|
free((void*) correctfrom);
|
|
|
|
free((void*) correctto);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_link) (const char* from, const char* to){
|
|
|
|
const char* correctfrom = correct_case_sensitivity_for(read_source_directory, from);
|
|
|
|
const char* correctto = correct_case_sensitivity_for(read_source_directory, to);
|
|
|
|
int retval = link(correctfrom, correctto);
|
|
|
|
free((void*) correctfrom);
|
|
|
|
free((void*) correctto);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
int (fuse_fn_chmod) (const char* path, mode_t mode, struct fuse_file_info* fi){
|
2020-05-19 02:13:51 +00:00
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = chmod(correctpath, mode);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
int (fuse_fn_chown) (const char* path, uid_t uid, gid_t gid, struct fuse_file_info*){
|
2020-05-19 02:13:51 +00:00
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = chown(correctpath, uid, gid);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
int (fuse_fn_truncate) (const char* path, off_t off, struct fuse_file_info*){
|
2020-05-19 02:13:51 +00:00
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = truncate(correctpath, off);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
/** int (fuse_fn_utime) (const char* path, struct utimbuf* buf){
|
|
|
|
* const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
* int retval = utime(correctpath, buf);
|
|
|
|
* free((void*) correctpath);
|
|
|
|
* return retval;
|
|
|
|
};*/
|
2020-05-19 02:13:51 +00:00
|
|
|
|
|
|
|
int (fuse_fn_open) (const char* path, struct fuse_file_info* ffi){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int fd = open(correctpath, ffi->flags);
|
|
|
|
free((void*) correctpath);
|
|
|
|
ffi->fh = fd;
|
|
|
|
return (fd==-1) ? -errno : 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_read) (const char* path, char* buf, size_t size, off_t off, struct fuse_file_info* ffi){
|
|
|
|
return pread(ffi->fh, buf, size, off);
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_write) (const char* path, const char* buf, size_t size, off_t off, struct fuse_file_info* ffi){
|
|
|
|
return pwrite(ffi->fh, buf, size, off);
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_statfs) (const char* path, struct statvfs* svfs){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = statvfs(correctpath, svfs);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_flush) (const char* path, struct fuse_file_info* ffi){
|
|
|
|
return close(dup(ffi->fh));
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_release) (const char* path, struct fuse_file_info* ffi){
|
|
|
|
return close(ffi->fh);
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_fsync) (const char* path, int data_sync, struct fuse_file_info* ffi){
|
|
|
|
#ifdef HAVE_FDATASYNC
|
|
|
|
if(data_sync)
|
|
|
|
return fdatasync(ffi->fh);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
return fsync(ffi->fh);
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_setxattr) (const char* path, const char* key, const char* value, size_t size, int flags){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = lsetxattr(correctpath, key, value, size, flags);
|
|
|
|
free((void*) correctpath);
|
|
|
|
if(retval==-1) return -errno;
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_getxattr) (const char* path, const char* key, char* value, size_t size){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = lgetxattr(correctpath, key, value, size);
|
|
|
|
free((void*) correctpath);
|
|
|
|
if(retval==-1) return -errno;
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_listxattr) (const char* path, char* list, size_t size){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = llistxattr(correctpath, list, size);
|
|
|
|
free((void*) correctpath);
|
|
|
|
if(retval==-1) return -errno;
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_removexattr) (const char* path, const char* key){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = lremovexattr(correctpath, key);
|
|
|
|
free((void*) correctpath);
|
|
|
|
if(retval==-1) return -errno;
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_opendir) (const char* path, struct fuse_file_info* ffi){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
DIR* dp = opendir(correctpath);
|
|
|
|
free((void*) correctpath);
|
|
|
|
ffi->fh = (uintptr_t) dp;
|
|
|
|
return dp==NULL ? -errno : 0;
|
|
|
|
};
|
|
|
|
|
2023-10-30 03:16:37 +00:00
|
|
|
int (fuse_fn_readdir) (const char* path, void* buf, fuse_fill_dir_t filler, off_t off, struct fuse_file_info* ffi, enum fuse_readdir_flags flags){
|
2020-05-19 02:13:51 +00:00
|
|
|
DIR* dp = (DIR*) ffi->fh;
|
|
|
|
if(!dp) return -EBADF;
|
|
|
|
seekdir(dp, off);
|
|
|
|
struct dirent *de;
|
|
|
|
while((de = readdir(dp)) != NULL){
|
|
|
|
struct stat st;
|
|
|
|
st.st_ino = de->d_ino;
|
|
|
|
st.st_mode = de->d_type << 12;
|
2023-10-30 03:16:37 +00:00
|
|
|
if (filler(buf, de->d_name, &st, telldir(dp), FUSE_FILL_DIR_PLUS)) break;
|
2020-05-19 02:13:51 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_releasedir) (const char* path, struct fuse_file_info* ffi){
|
|
|
|
if(ffi->fh)
|
|
|
|
closedir((DIR*)(uintptr_t) ffi->fh);
|
|
|
|
ffi->fh = 0;
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// int (fuse_fn_fsyncdir) (const char* path, int isdatasync, struct fuse_file_info* ffi){
|
|
|
|
// return ENOSYS;
|
|
|
|
// };
|
|
|
|
|
|
|
|
int (fuse_fn_access) (const char* path, int mode){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = access(correctpath, mode);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_create) (const char* path, mode_t mode, struct fuse_file_info* ffi){
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int fd = open(correctpath, ffi->flags, mode);
|
|
|
|
free((void*) correctpath);
|
|
|
|
if(fd==-1) return -errno;
|
|
|
|
ffi->fh = fd;
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_ftruncate) (const char* path, off_t off, struct fuse_file_info* ffi){
|
|
|
|
return ftruncate(ffi->fh, off);
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_fgetattr) (const char* path, struct stat* st, struct fuse_file_info* ffi){
|
|
|
|
int retval = fstat(ffi->fh, st);
|
|
|
|
if(retval==-1) return -errno;
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
int (fuse_fn_lock) (const char* path, struct fuse_file_info* ffi, int cmd, struct flock* lock){
|
|
|
|
return ulockmgr_op(ffi->fh, cmd, lock, &ffi->lock_owner, sizeof(ffi->lock_owner));
|
|
|
|
};
|
|
|
|
|
2023-11-04 00:54:26 +00:00
|
|
|
int (fuse_fn_utimens) (const char* path, const struct timespec ts[2], struct fuse_file_info* ffi){
|
2020-05-19 02:13:51 +00:00
|
|
|
struct timeval tv[2];
|
|
|
|
tv[0].tv_sec = ts[0].tv_sec;
|
|
|
|
tv[0].tv_usec = ts[0].tv_nsec / 1000;
|
|
|
|
tv[1].tv_sec = ts[1].tv_sec;
|
|
|
|
tv[1].tv_usec = ts[1].tv_nsec / 1000;
|
|
|
|
const char* correctpath = correct_case_sensitivity_for(read_source_directory, path);
|
|
|
|
int retval = utimes(correctpath, tv);
|
|
|
|
free((void*) correctpath);
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
// int (fuse_fn_ioctl) (const char* path, int cmd, void* arg, struct fuse_file_info* ffi, unsigned int flags, void* data){
|
|
|
|
// return ENOSYS;
|
|
|
|
// };
|
|
|
|
|
|
|
|
// int (fuse_fn_poll) (const char* path, struct fuse_file_info* ffi, struct fuse_pollhandle* ph, unsigned* reventsp){
|
|
|
|
// return ENOSYS;
|
|
|
|
// };
|
|
|
|
|
|
|
|
// int (fuse_fn_write_buf) (const char* path, struct fuse_bufvec* buf, off_t off, struct fuse_file_info* ffi){
|
|
|
|
// return ENOSYS;
|
|
|
|
// };
|
|
|
|
|
|
|
|
// int (fuse_fn_read_buf) (const char* path, struct fuse_bufvec** buf, size_t size, off_t off, struct fuse_file_info* ffi){
|
|
|
|
// return ENOSYS;
|
|
|
|
// };
|
|
|
|
|
|
|
|
// int (fuse_fn_flock) (const char* path, struct fuse_file_info*, int){
|
|
|
|
// return ENOSYS;
|
|
|
|
// };
|
|
|
|
|
|
|
|
int (fuse_fn_fallocate) (const char* path, int mode, off_t off, off_t len, struct fuse_file_info* ffi){
|
|
|
|
return fallocate(ffi->fh, mode, off, len);
|
|
|
|
};
|