Приветствую. Разбираюсь с ФС. Спроектировал свою FAT подобную систему, использую FUSE.
Библиотека основных функций ФС уже написана. Но... Не получается до конца прикрутить FUSE. И я даже как-то в недоумении, как отлаживать, это и не Kernel object, где можно использовать kprintf, и обычное логирование у меня почему-то не вышло, хотя по идее должно работать. Возможно, потому что ошибка сегметации возникает раньше того, как я вывожу сообщение в лог.
Код fuse модуля:
#define _USE_GNU
#define _POSIX_C_SOURCE 199309
#define FUSE_USE_VERSION 26
#define USERDATA ((struct user_data*)(fuse_get_context()->private_data))
#define LOGFILE USERDATA->logfile
#include <fuse.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdarg.h>
#include "libdfat.h"
/******************************************************/
struct user_data {
FILE *logfile;
};
FILE* log_open()
{
FILE *logfile = fopen("fusedfat.log", "w");
setvbuf(logfile, NULL, _IOLBF, 0);;
return logfile;
}
void log_msg(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf( LOGFILE, format, ap);
fflush(LOGFILE);
}
/******************************************************/
int dfuse_usage()
{
printf("dfuse_fuse <device> <mountpoint>\n\n");
return 0;
}
void *dfuse_init(struct fuse_conn_info *conn)
{
return NULL;
}
void dfuse_destroy(void *userdata)
{
fflush(LOGFILE);
fclose(LOGFILE);
dfat_close();
}
static int dfuse_getattr(const char *path, struct stat *stbuf)
{
int res = 0; /* temporary result */
memset(stbuf, 0, sizeof(struct stat));
dir_record_t r;
if( !dfat_find_dir_record(path, &r) )
return -ENOENT;
if(r.flags & 0x80 == 1) {
stbuf->st_mode = 0x4000 | 0777;
stbuf->st_size = 0;
}
else {
stbuf->st_mode = 0777;
stbuf->st_size = r.size;
}
}
static int dfuse_error(char *str)
{
int ret = -errno;
log_msg(" ERROR %s: %s\n", str, strerror(errno));
return ret;
}
int dfuse_mkdir(const char *path, mode_t mode)
{
int retstat = 0;
log_msg("\ndfuse_mkdir(path=\"%s\", mode=0%3o)\n", path, mode);
retstat = dfat_create(path, 0x80, NULL);
if (retstat < 0)
retstat = dfuse_error("dfuse_mkdir mkdir");
return retstat;
}
int dfuse_unlink(const char *path)
{
int retstat = 0;
log_msg("dfuse_unlink(path=\"%s\")\n", path);
retstat = dfat_unlink(path);
if (retstat < 0)
retstat = dfuse_error("unlink");
return retstat;
}
int dfuse_rmdir(const char *path)
{
int retstat = 0;
log_msg("dfuse_rmdir(path=\"%s\")\n", path);
retstat = dfat_unlink(path);
if (retstat < 0)
retstat = dfuse_error("rmdir");
return retstat;
}
int dfuse_rename(const char *path, const char *newpath)
{
return dfat_rename(path, newpath);
}
int dfuse_open(const char *path, struct fuse_file_info *fi)
{
if(!dfat_exist(path))
{
return -ENOENT;
}
return 0;
}
int dfuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
int readed = 0;
return readed;
}
int dfuse_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
int writed = 0;
return writed = 0;
}
int dfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
struct fuse_file_info *fi)
{
log_msg("dfuse_readdir()\n");
int retstat = 0;
struct list l;
list_clear(&l);
dfat_read_folder_by_path(path, &l);
filler(buf, "." , NULL, 0);
filler(buf, ".." , NULL, 0);
for(unsigned int i=0; i<l.count; i++) {
filler(buf, l.array[i].name , NULL, 0);
log_msg("\t%s\n", l.array[i].name);
}
fflush(stderr);
return retstat;
}
/******************************************************************/
/* The fuse struct for storing FS operations functions addresses */
struct fuse_operations dfuse_oper = {
.getattr = dfuse_getattr,
.mkdir = dfuse_mkdir,
.unlink = dfuse_unlink,
.readdir = dfuse_readdir,
.rmdir = dfuse_rmdir,
.rename = dfuse_rename,
.open = dfuse_open,
.read = dfuse_read,
.write = dfuse_write,
.destroy = dfuse_destroy,
};
int main(int argc, char *argv[])
{
if ((argc < 3))
return dfuse_usage();
struct user_data *data = (struct user_data*) malloc(sizeof(struct user_data));
data->logfile = log_open();
dfat_load(argv[1]);
argv[1] = argv[2];
argv[2] = NULL;
argc--;
return fuse_main(argc, argv, &dfuse_oper, data);
}
Все собирается. Монтируется без ошибок. Но:
dmesg | tail
[101513.954108] fusedfat[21784]: segfault at c000c20 ip 00007f9312f72137 sp 00007f9312a458f8 error 4 in libc-2.16.so[7f9312e55000+19d000]
[101514.754521] systemd-journald[127]: Failed to write entry, ignoring: Argument list too long
А при попытке прочитать содержимое дирректории:
% ls mountpoint/*
ls: cannot access mountpoint/*: Transport endpoint is not connected
Поддтолкните в нужное направление пожалуйста.