Fuse Filesystem Problem - c

i'm developing a fuse filesystem that stores data in the RAM, but i'm having problems when i write something to a file. The file turns into a blank file.
Here's the code:
#define FUSE_USE_VERSION 26
#include <fuse/fuse.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
char hello_data[200] = {'h', 'e', 'l', 'l', 'o', '\n'};
int hello_size = 6;
int homsifs_getattr(const char* path, struct stat* stbuf)
{
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0)
stbuf->st_mode = S_IFDIR | 0666;
else if (strcmp(path, "/hello") == 0)
{
stbuf->st_mode = S_IFREG | 0666;
stbuf->st_size = hello_size;
}
else
return -ENOENT;
return 0;
}
int homsifs_readdir(const char* path, void* buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info* fi)
{
if (strcmp(path, "/") != 0)
return -ENOENT;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, "hello", NULL, 0);
return 0;
}
int homsifs_open(const char* path, struct fuse_file_info* fi)
{
if (strcmp(path, "/hello") != 0)
return -ENOENT;
return 0;
}
int homsifs_read(const char* path, char* buf, size_t size, off_t offset,
struct fuse_file_info* fi)
{
int offset_size = hello_size - offset;
if (size > offset_size)
size = offset_size;
memcpy(buf, hello_data + offset, size);
return size;
}
int homsifs_truncate(const char* path, off_t size)
{
if (size > 200)
return -ENOMEM;
if (hello_size < size)
memset(hello_data + size, 0, size - hello_size);
hello_size = size;
return 0;
}
int homsifs_write(const char* path, const char* buf, size_t size, off_t offset,
struct fuse_file_info* fi)
{
if (strcmp(path, "/hello") != 0)
return -ENOENT;
memcpy(hello_data + offset, buf, size);
return size;
}
struct fuse_operations homsifs_operations =
{
.getattr = homsifs_getattr,
.readdir = homsifs_readdir,
.open = homsifs_open,
.read = homsifs_read,
.truncate = homsifs_truncate,
.write = homsifs_write
};
int main(int argc, char** argv)
{
return fuse_main(argc, argv, &homsifs_operations, NULL);
}
Anyone knows what's wrong?
Thanks.

When a program opens the file for writing, it gets truncated. After that, any data written is inaccessible because you're not correctly updating hello_size in homsifs_write.

Related

One ioctl not being executed in kernel module

I wrote a kernel module demonstrating on how ioctl works.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
int base_minor = 0;
char *device_name = "msg";
int count = 1;
dev_t devicenumber;
static struct class *class = NULL;
static struct device *device = NULL;
static struct cdev mycdev;
#define MAX_SIZE 1024
char kernel_buffer[MAX_SIZE];
int buffer_index;
MODULE_LICENSE("GPL");
static int device_open(struct inode *inode, struct file *file)
{
pr_info("%s\n", __func__);
file->f_pos = 0;
buffer_index = 0;
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
pr_info("%s\n", __func__);
return 0;
}
static ssize_t device_read(struct file *file, char __user *user_buffer,
size_t read_count, loff_t *offset)
{
int bytes_read;
int available_space;
int bytes_to_read;
pr_info("%s read offset:%lld\n", __func__, *offset);
available_space = MAX_SIZE - *(offset);
if (read_count < available_space)
bytes_to_read = read_count;
else
bytes_to_read = available_space;
pr_info("bytes_to_read:%d\n", bytes_to_read);
if (bytes_to_read == 0) {
pr_err("%s: No available space in the buffer for reading\n",
__func__);
return -ENOSPC;
}
if (buffer_index > *offset)
bytes_to_read = buffer_index - *offset;
else
return 0;
bytes_read = bytes_to_read - copy_to_user(user_buffer, kernel_buffer+*offset, bytes_to_read);
pr_info("%s: Copy to user returned:%d\n", __func__, bytes_to_read);
//update file offset
*offset += bytes_read;
return bytes_read;
}
static ssize_t device_write(struct file *file, const char __user *user_buffer,
size_t write_count, loff_t *offset)
{
int bytes_written;
int available_space;
int bytes_to_write;
pr_info("%s write offset:%lld\n", __func__, *offset);
available_space = MAX_SIZE - *(offset);
if (write_count < available_space)
bytes_to_write = write_count;
else
bytes_to_write = available_space;
if (bytes_to_write == 0) {
pr_err("%s: No available space in the buffer for writing\n",
__func__);
return -ENOSPC;
}
bytes_written = bytes_to_write - copy_from_user(kernel_buffer+*offset, user_buffer, bytes_to_write);
pr_info("%s: Bytes written:%d\n", __func__, bytes_written);
pr_info("%s: kernel_buffer:%s\n", __func__, kernel_buffer);
//update file offset
*offset += bytes_written;
buffer_index += bytes_written;
return bytes_written;
}
static loff_t device_lseek(struct file *file, loff_t offset, int orig)
{
loff_t new_pos = 0;
switch(orig) {
case 0 : /*seek set*/
new_pos = offset;
break;
case 1 : /*seek cur*/
new_pos = file->f_pos + offset;
break;
case 2 : /*seek end*/
new_pos = MAX_SIZE - offset;
break;
}
if(new_pos > MAX_SIZE)
new_pos = MAX_SIZE;
if(new_pos < 0)
new_pos = 0;
file->f_pos = new_pos;
return new_pos;
}
long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned char ch;
pr_info("%s: Cmd:%u\t Arg:%lu\n", __func__, cmd, arg);
switch(cmd)
{
//Get Length of buffer
case 0x01:
pr_info("Get Buffer Length\n");
put_user(MAX_SIZE, (unsigned int *)arg);
break;
//clear buffer
case 0x02:
pr_info("Clear buffer\n");
memset(kernel_buffer, 0, sizeof(kernel_buffer));
break;
//fill character
case 0x03:
get_user(ch, (unsigned char *)arg);
pr_info("Fill Character:%c\n", ch);
memset(kernel_buffer, ch, sizeof(kernel_buffer));
buffer_index = sizeof(kernel_buffer);
break;
default:
pr_info("Unknown Command:%u\n", cmd);
return -EINVAL;
}
return 0;
}
struct file_operations device_fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
.llseek = device_lseek,
.unlocked_ioctl = device_ioctl
};
static int test_hello_init(void)
{
class = class_create(THIS_MODULE, "myclass");
if (!alloc_chrdev_region(&devicenumber, base_minor, count, device_name)) {
printk("Device number registered\n");
printk("Major number received:%d\n", MAJOR(devicenumber));
device = device_create(class, NULL, devicenumber, NULL, device_name);
cdev_init(&mycdev, &device_fops);
mycdev.owner = THIS_MODULE;
cdev_add(&mycdev, devicenumber, count);
}
else
printk("Device number registration Failed\n");
return 0;
}
static void test_hello_exit(void)
{
device_destroy(class, devicenumber);
class_destroy(class);
cdev_del(&mycdev);
unregister_chrdev_region(devicenumber, count);
}
module_init(test_hello_init);
module_exit(test_hello_exit);
Then i wrote a user space code
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
int main(int argc, char *argv[])
{
char buffer[1024];
int fd;
unsigned int length;
unsigned char ch = 'A';
int i = 0;
fd = open("/dev/msg", O_RDWR);
if (fd < 0) {
perror("fd failed");
exit(2);
}
//Get Length - 0x01
ioctl(fd, 0x01, &length);
printf("Length:%u\n", length);
ioctl(fd, 0x02);
//Set Character - 0x03
ioctl(fd, 0x03, &ch);
perror("ioctl");
lseek(fd, 0, SEEK_SET);
perror("lseek");
length = read(fd, buffer, 1024);
perror("Read");
printf("length:%d\n", length);
buffer[1023] = '\0';
printf("Buffer:%s\n", buffer);
close(fd);
}
ioctl commands 1, 3 work but not 2. Can you please provide what's the mistake in the code
You should review the requirements for ioctl on the man page:
DESCRIPTION
The ioctl() system call manipulates the underlying device parameters of
special files. In particular, many operating characteristics of char‐
acter special files (e.g., terminals) may be controlled with ioctl()
requests. The argument fd must be an open file descriptor.
The second argument is a device-dependent request code. The third
argument is an untyped pointer to memory. It's traditionally char
*argp (from the days before void * was valid C), and will be so named
for this discussion.
An ioctl() request has encoded in it whether the argument is an in
parameter or out parameter, and the size of the argument argp in bytes.
Macros and defines used in specifying an ioctl() request are located in
the file <sys/ioctl.h>.

MPI Segmentation Fault while running with 4 processes

I wrote my parallel version of unix grep program. In this program you search for patter in files given as program arguments.
In root process I calculate number of files per process and first file ID for each process. After calculations I send this values to each of root processes.
In not root process I'm receiving num of Files and first file ID and analyzing each file in analyzeFile method. In that method I send back string, which contains all lines with pattern, to root process. After collecting all data from not root precesses I print out final result.
The problem is when I try to run program with more than 3 processes. It ends up with segmentation fault.
I'm out of ideas. Valgrind does not show any error reports on base scanning.
PS. I know that code needs refactoring, but first I want to get rid of this bug.
Thanks for any help.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <mpi.h>
#define YEL "\x1B[33m"
#define BLU "\x1B[34m"
#define MAG "\x1B[35m"
#define RESET "\x1B[0m"
#define send_data_tag 1000
#define return_data_tag 1001
struct linesRange
{
int lineFrom;
int lineTo;
int posFrom;
int posTo;
};
int countNumOfLines(char *str)
{
int numOfLines = 0;
int i = 0;
while(str[i] != '\0')
{
if(str[i] == '\n')
{
++numOfLines;
}
++i;
}
return numOfLines;
}
long int findLinePos(char *str, int lineNumToFind)
{
long int linePos = 0;
long int lineNum = 0;
long int i = 0;
if(lineNumToFind == 0)
{
return linePos;
}
while(str[i] != '\0')
{
if(str[i] == '\n')
{
++lineNum;
if(lineNum == lineNumToFind)
{
linePos = i;
break;
}
}
++i;
}
return linePos;
}
long int findNextLinePos(char *str, int startPos)
{
long int i = startPos;
long int nextLinePos = 0;
while(str[i] != '\0')
{
if(str[i] == '\n')
{
nextLinePos = i;
break;
}
++i;
}
return nextLinePos;
}
bool strstrn(char *str, char *pattern, long int posStart, long int posEnd)
{
long int pos_search = 0;
long int pos_text = 0;
int len_search = strlen(pattern);
for (pos_text = posStart; pos_text < posEnd; ++pos_text)
{
if(str[pos_text] == pattern[pos_search])
{
++pos_search;
if(pos_search == len_search)
{
return true;
}
}
else
{
pos_text -= pos_search;
pos_search = 0;
}
}
return false;
}
char * searchPatternInText(char *text, char *inputPattern, char *fileName, int proc_id)
{
char *bufToAdd;
int lineNum = 0;
char * resultBuf = (char*)malloc(sizeof(char));
memset(resultBuf, 0, sizeof(char));
char * curLine = text;
while(curLine)
{
++lineNum;
char * nextLine = strchr(curLine, '\n');
if (nextLine)
*nextLine = '\0';
if(strstr(curLine, inputPattern))
{
bufToAdd = (char*)malloc(sizeof(char));
memset(bufToAdd, 0, sizeof(char));
asprintf (&bufToAdd, BLU "Ścieżka:%s\tProces:%d\n" MAG "Numer linii:%d\t" RESET "%s\n", fileName, proc_id, lineNum, curLine);
resultBuf = (char*)realloc(resultBuf, strlen(resultBuf) + strlen(bufToAdd) + 1);
strcat(resultBuf, bufToAdd);
free(bufToAdd);
}
if (nextLine)
*nextLine = '\n';
curLine = nextLine ? (nextLine+ 1) : NULL;
}
return resultBuf;
}
void analyzeFile(struct stat sb, int fd, char *fileName, char *pattern, int proc_id)
{
char *text = mmap (0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (text == MAP_FAILED) {
perror ("mmap");
return;
}
if (close (fd) == -1)
{
perror ("close");
return;
}
char *tempTxt;
tempTxt = (char*)malloc(sizeof(char) * (strlen(text) + 1));
strcpy(tempTxt, text);
tempTxt[strlen(text)] = '\0';
//munmap(text, sb.st_size);
char *result;
result = searchPatternInText(tempTxt, pattern, fileName, proc_id);
free(tempTxt);
if(proc_id != 0)
{
MPI_Send(result, strlen(result), MPI_CHAR,
0, return_data_tag, MPI_COMM_WORLD);
}
else
{
printf(result);
}
free(result);
}
int main (int argc, char *argv[])
{
int patternLen = 10;
char pattern [patternLen + 1];
float elapsed;
int numOfFiles = argc - 2;
int proc_id, num_procs, procIterator, filesIterator, root = 0;
int *numOfFilesPerProcess, *firstFileIdPerProcess;
if (argc < 3) {
fprintf (stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
else
{
strncpy(pattern, argv[1], patternLen);
pattern[patternLen] = '\0';
}
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &proc_id);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Barrier(MPI_COMM_WORLD);
double startTime = MPI_Wtime();
if(proc_id == root)
{
MPI_Status statusMaster;
numOfFilesPerProcess = (int*)malloc(sizeof(int) * num_procs);
firstFileIdPerProcess = (int*)malloc(sizeof(int) * num_procs);
for(int i = 0; i < num_procs; ++i)
{
numOfFilesPerProcess[i] = 0;
firstFileIdPerProcess[i] = 0;
}
filesIterator = 0;
procIterator = 0;
while(filesIterator < numOfFiles)
{
if(procIterator == num_procs)
{
procIterator = 0;
}
++numOfFilesPerProcess[procIterator];
++procIterator;
++filesIterator;
}
firstFileIdPerProcess[0] = 2;
//pierwszy numer argumentu argv[] per proces
for(int jj = 1; jj < num_procs; ++jj)
{
firstFileIdPerProcess[jj] = firstFileIdPerProcess[jj - 1] + numOfFilesPerProcess[jj - 1];
}
for(int j = 1; j < num_procs; ++j)
{
MPI_Send(&firstFileIdPerProcess[j], 1, MPI_UNSIGNED,
j, send_data_tag, MPI_COMM_WORLD);
MPI_Send(&numOfFilesPerProcess[j], 1, MPI_UNSIGNED,
j, send_data_tag, MPI_COMM_WORLD);
}
int firstFileIdForProcess = firstFileIdPerProcess[0];
int numOfFilesForProcess = numOfFilesPerProcess[0];
int fd;
struct stat sb;
for(int i = 0; i < numOfFilesForProcess; ++i)
{
fd = open (argv[firstFileIdForProcess + i], O_RDONLY);
if ( fd == -1
|| fstat (fd, &sb) == -1
|| !S_ISREG (sb.st_mode))
{
perror("file");
}
else
{
analyzeFile(sb, fd, argv[firstFileIdForProcess + i], pattern, proc_id);
}
}
for(int ii = numOfFilesPerProcess[0]; ii < numOfFiles; ++ii)
{
int resultLen;
char *result;
MPI_Probe(MPI_ANY_SOURCE, return_data_tag, MPI_COMM_WORLD, &statusMaster);
MPI_Get_count(&statusMaster, MPI_CHAR, &resultLen);
result = (char *)malloc(sizeof(char) * resultLen + 1);
MPI_Recv( result, resultLen, MPI_CHAR,
MPI_ANY_SOURCE, return_data_tag, MPI_COMM_WORLD, &statusMaster);
result[resultLen] = '\0';
printf(result);
free(result);
}
free(numOfFilesPerProcess);
free(firstFileIdPerProcess);
}
else
{
MPI_Status statusSlave;
int firstFileIdForProcess = 0;
int numOfFilesForProcess = 0;
int fd;
struct stat sb;
MPI_Recv( &firstFileIdForProcess, 1, MPI_UNSIGNED,
root, send_data_tag, MPI_COMM_WORLD, &statusSlave);
MPI_Recv( &numOfFilesForProcess, 1, MPI_UNSIGNED,
root, send_data_tag, MPI_COMM_WORLD, &statusSlave);
for(int i = 0; i < numOfFilesForProcess; ++i)
{
fd = open (argv[firstFileIdForProcess + i], O_RDONLY);
if ( fd == -1
|| fstat (fd, &sb) == -1
|| !S_ISREG (sb.st_mode))
{
perror("file");
}
else
{
analyzeFile(sb, fd, argv[firstFileIdForProcess + i], pattern, proc_id);
}
}
}
MPI_Barrier(MPI_COMM_WORLD);
double endTime = MPI_Wtime();
if(proc_id == root)
{
printf("Czas wykonania: %fs\n", endTime - startTime);
}
MPI_Finalize();
return 0;
}

Function in fuse linux in c

I am new in linux, and i have an assignment about FUSE.
My FUSE need to be able open a file, edit, and rename it.
Here is my full code
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/statfs.h>
#include <stdlib.h>
static const char *dirpath = "/home/cync48/Downloads";
static int xmp_getattr(const char *path, struct stat *stbuf)
{
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
res = lstat(fpath, stbuf);
if(res == -1)
return -errno;
return 0;
}
static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
char fpath[1000];
if(strcmp(path,"/")==0)
{
path = dirpath;
sprintf(fpath, "%s", path);
}
else
sprintf(fpath, "%s%s", dirpath, path);
DIR *dp;
struct dirent *de;
(void) offset;
(void) fi;
dp = opendir(fpath);
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 xmp_mknod(const char *path, mode_t mode, dev_t rdev)
{
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
//On Linux this could just be 'mknod(path, mode, rdev)' but thisis more portable
if (S_ISREG(mode)) {
res = open(fpath, O_CREAT | O_EXCL | O_WRONLY, mode);
if (res >= 0)
res = close(res);
} else if (S_ISFIFO(mode))
res = mkfifo(fpath, mode);
else
res = mknod(fpath, mode, rdev);
if (res == -1)
return -errno;
return 0;
}
static int xmp_mkdir(const char *path, mode_t mode)
{
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
res = mkdir(fpath, mode);
if (res == -1)
return -errno;
return 0;
}
static int xmp_unlink(const char *path)
{
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
res = unlink(fpath);
if (res == -1)
return -errno;
return 0;
}
static int xmp_rmdir(const char *path)
{
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
res = rmdir(fpath);
if (res == -1)
return -errno;
return 0;
}
static int xmp_rename(const char *from, const char *to)
{
int res;
res = rename(from, to);
if (res == -1)
return -errno;
return 0;
}
static int xmp_open(const char *path, struct fuse_file_info *fi)
{
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
//(void) fi;
res = open(fpath, fi->flags);
if (res == -1)
return -errno;
close(res);
return 0;
}
static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
int fd;
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
(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 xmp_write(const char *path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *fi)
{
int fd;
int res;
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
(void) fi;
fd = open(fpath, O_WRONLY);
if (fd == -1)
return -errno;
res = pwrite(fd, buf, size, offset);
if (res == -1)
res = -errno;
close(fd);
return res;
}
static int xmp_release(const char *path, struct fuse_file_info *fi)
{
//Just a stub. This method is optional and can safely be left unimplemented
char fpath[1000];
sprintf(fpath, "%s%s", dirpath, path);
(void) fpath;
(void) fi;
return 0;
}
static struct fuse_operations xmp_oper = {
.getattr = xmp_getattr,
.mknod = xmp_mknod,
.mkdir = xmp_mkdir,
.readdir = xmp_readdir,
.unlink = xmp_unlink,
.rmdir = xmp_rmdir,
.rename = xmp_rename,
.open = xmp_open,
.read = xmp_read,
.write = xmp_write,
.release = xmp_release,
};
int main(int argc, char *argv[])
{
umask(0);
return fuse_main(argc, argv, &xmp_oper, NULL);
}
I still cannot open a file, the error is "Too many open files ins system"
I still cannot rename a file, i write the exact syntax to rename a file ( mv name new_name ) but it said about moving a file.
Does my code incorrect?

fuse changes chown to?

i m trying to modify fuse example to mount any directory. I want to mount /home/nikhil in tmp.
i ran it as,
$ ./ni /home/nikhil tmp
It mounts tmp folder, but cannot access it.
$ls -ltr tmp
ls: cannot access tmp: Operation not permitted
$ ls -ltr
ls: cannot access delete: Operation not permitted
total 11716
d????????? ? ? ? ? ? delete
My code is
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#define MAX 100
char *rootpath;
static void ni_fullpath(char fpath[MAX], const char *path){
strcpy(fpath, rootpath);
strncat(fpath, path, MAX);
}
static int ni_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
char fpath[MAX];
memset(stbuf, 0, sizeof(struct stat));
ni_fullpath(fpath, path);
res = lstat(fpath, stbuf);
return res;
}
static int ni_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;
// i didnt understand this
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
ni_fullpath(fpath, path);
filler(buf, fpath + 1, NULL, 0);
return 0;
}
static int ni_open(const char *path, struct fuse_file_info *fi)
{
int fd;
char fpath[MAX];
ni_fullpath(fpath, path);
if ((fi->flags & 3) != O_RDONLY)
return -EACCES;
fd = open(fpath, fi->flags);
return fd;
}
static int ni_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
return pread(fi->fh, buf, size, offset);
}
static struct fuse_operations ni_oper = {
.getattr = ni_getattr,
.readdir = ni_readdir,
.open = ni_open,
.read = ni_read,
};
void ni_usage(){
fprintf(stderr, "usage ni rootDir mountPoint");
abort();
}
int main(int argc, char *argv[])
{
printf("%s %s \n", argv[1], argv[2]);
rootpath = realpath(argv[1], NULL);
argv[1] = argv[2];
argc--;
return fuse_main(argc, argv, &ni_oper, NULL);
}
Can anybody help what i m doing wrong ?
I m using ubuntu 1104 64 bit.
How about using uninitialized var fpath instead of path?
static int ni_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
char fpath[MAX];
memset(stbuf, 0, sizeof(struct stat));
res = lstat(fpath, stbuf);
return res;
}
You probably missed ni_fullpath(fpath, path);
And as far as I understand the 0 should be returned in open callback if success, so it should look like:
....
fd = open(fpath, fi->flags);
if (fd < 0)
return -errno;
fi->fh = fd;
return 0;
}
List operation should uses readdir callback, and in your case it has very limited application. It'd be better to start code on the basis of fusexmp. Check how readdir is implemented there.

FUSE file system crashed at opening file (only in release mode)

I have some problem, and i can't find solution of this :/ I need to open a text file inside my fuse filesystem. In debug everything works fine, but in release system is crashing. I made a simples example, with this. Could anybody tell what's wrong in this code?
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos#szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
gcc -Wall `pkg-config fuse --cflags --libs` hello.c -o hello
*/
# define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}
}
static const char *hello_str = "Hello World!\n";
static const char *hello_path = "/hello";
static int hello_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (strcmp(path, hello_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(hello_str);
} else
res = -ENOENT;
return res;
}
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;
if (strcmp(path, "/") != 0)
return -ENOENT;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, hello_path + 1, NULL, 0);
FILE *infile;
char fname[40];
char line[100];
int lcount;
/* We need to get rid of the newline char. */
stripnl(fname);
/* Open the file. If NULL is returned there was an error */
if((infile = fopen("ex.txt", "r")) == NULL) {
printf("Error Opening File.\n");
}
while( fgets(line, sizeof(line), infile) != NULL ) {
/* Get each line from the infile */
lcount++;
/* print the line number and data */
printf("Line %d: %s", lcount, line);
filler(buf, line, NULL, 0);
}
fclose(infile); /* Close the file */
return 0;
}
static int hello_open(const char *path, struct fuse_file_info *fi)
{
if (strcmp(path, hello_path) != 0)
return -ENOENT;
if ((fi->flags & 3) != O_RDONLY)
return -EACCES;
return 0;
}
static int hello_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
size_t len;
(void) fi;
if(strcmp(path, hello_path) != 0)
return -ENOENT;
len = strlen(hello_str);
if (offset < len) {
if (offset + size > len)
size = len - offset;
memcpy(buf, hello_str + offset, size);
} else
size = 0;
return size;
}
static struct fuse_operations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &hello_oper, NULL);
}
Update
Ok, i've found solution, path must be absolute file path (not sure is this is proper sentence), but here is example code, which is working in release as well as in debug:
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos#szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
gcc -Wall `pkg-config fuse --cflags --libs` hello.c -o hello
*/
# define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}
}
static const char *hello_str = "Hello World!\n";
static const char *hello_path = "/hello";
static int hello_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (strcmp(path, hello_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(hello_str);
} else
res = -ENOENT;
return res;
}
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;
if (strcmp(path, "/") != 0)
return -ENOENT;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, hello_path + 1, NULL, 0);
FILE *infile;
char line[100];
if((infile = fopen("/root/Desktop/fexamples/ex.txt", "rb")) == NULL)
{
return -1;
}
while( fgets(line, sizeof(line), infile) != NULL )
{
filler(buf, line, NULL, 0);
}
fclose(infile); /* Close the file */
return 0;
}
static int hello_open(const char *path, struct fuse_file_info *fi)
{
if (strcmp(path, hello_path) != 0)
return -ENOENT;
if ((fi->flags & 3) != O_RDONLY)
return -EACCES;
return 0;
}
static int hello_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
size_t len;
(void) fi;
if(strcmp(path, hello_path) != 0)
return -ENOENT;
len = strlen(hello_str);
if (offset < len) {
if (offset + size > len)
size = len - offset;
memcpy(buf, hello_str + offset, size);
} else
size = 0;
return size;
}
static struct fuse_operations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &hello_oper, NULL);
}
There are at least two issues in your readdir implementation.
char fname[40];
char line[100];
int lcount;
/* We need to get rid of the newline char. */
stripnl(fname);
You're acting on the contents of fname that you're not initializing anywhere. This could do just about anything. The fact that you're not using fname after that is irrelevant, you could be modifying completely random data with that stripnl call.
/* Open the file. If NULL is returned there was an error */
if((infile = fopen("ex.txt", "r")) == NULL) {
printf("Error Opening File.\n");
}
If fopen fails, you should error out (or just leave) this function. Otherwise the next line will call fgets with NULL as its file argument.
Ok, i've found solution, path must be absolute file path (not sure is this is proper sentence), but here is example code, which is working in release as well as in debug:
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos#szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
gcc -Wall `pkg-config fuse --cflags --libs` hello.c -o hello
*/
# define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
void stripnl(char *str) {
while(strlen(str) && ( (str[strlen(str) - 1] == 13) ||
( str[strlen(str) - 1] == 10 ))) {
str[strlen(str) - 1] = 0;
}
}
static const char *hello_str = "Hello World!\n";
static const char *hello_path = "/hello";
static int hello_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (strcmp(path, hello_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(hello_str);
} else
res = -ENOENT;
return res;
}
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;
if (strcmp(path, "/") != 0)
return -ENOENT;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, hello_path + 1, NULL, 0);
FILE *infile;
char line[100];
if((infile = fopen("/root/Desktop/fexamples/ex.txt", "rb")) == NULL)
{
return -1;
}
while( fgets(line, sizeof(line), infile) != NULL )
{
filler(buf, line, NULL, 0);
}
fclose(infile); /* Close the file */
return 0;
}
static int hello_open(const char *path, struct fuse_file_info *fi)
{
if (strcmp(path, hello_path) != 0)
return -ENOENT;
if ((fi->flags & 3) != O_RDONLY)
return -EACCES;
return 0;
}
static int hello_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
size_t len;
(void) fi;
if(strcmp(path, hello_path) != 0)
return -ENOENT;
len = strlen(hello_str);
if (offset < len) {
if (offset + size > len)
size = len - offset;
memcpy(buf, hello_str + offset, size);
} else
size = 0;
return size;
}
static struct fuse_operations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &hello_oper, NULL);
}

Resources