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);
}
Related
In my code C, I have **line and I need check if *line is NULL, I wrote following code can crash the program and I don't know why
How I can check if *line is NULL or not ?
( I have 0 warnings, 0 errors: -Wall -Werror -Wextra )
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "libft/libft.h"
# define BUFF_SIZE 16
int read_buffer(int const fd, int ret, char **endl, char **buffer)
{
char buff[BUFF_SIZE + 1];
ret = read(fd, buff, BUFF_SIZE);
buff[ret] = '\0';
if (ret > 0)
{
*buffer = ft_strjoin(*buffer, buff);
*endl = ft_strchr(*buffer, '\n');
}
return (ret);
}
int get_next_line(int const fd, char **line)
{
static char *buffer;
char *endl;
int ret;
if (!buffer && !(buffer = ft_memalloc(BUFF_SIZE + 1)))
return (-1);
if (!*line) // HERE, program crash
*line = my_strdup("");
ret = 1;
endl = ft_strchr(buffer, '\n');
while (ret > 0)
{
ret = read_buffer(fd, ret, &endl, &buffer);
if (endl)
{
buffer[endl - buffer] = '\0';
*line = my_strdup(buffer);
buffer = my_strdup(endl + 1);
return (1);
}
if (ret == 0)
{
if (ft_strcmp("", *line) == 0)
{
*line = my_strdup(buffer);
return (1);
}
return (0);
}
}
return (ret);
}
int main(void)
{
int fd;
int ret;
char *line;
if ((fd = open("b.txt", O_RDONLY)) < 3 && fd != 0)
return (-1);
printf("%d\n", fd);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
return (0);
}
You're testing whether *line is null correctly in get_next_line(). The problem is that you never initialized line to NULL in main(). Since it's uninitialized, you get undefined behavior when trying to use it.
Change
char *line;
to
char *line = NULL;
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?
I would like to obtain a behavior similar to this:
Server run
Client run
Client type a command like "help" or other
Server responds appropriately
go to 3
The problem is that when my function excCommand("help") run just a little text is received and printed.
My text file is this:
COMMAND HELP:
help - Display help
quit - Shutdown client
only COMMAND HELP is printed.
Another problem is that when i type a command nothing is printed and after 2 command client exit.
This is the piece in particular:
while (quit)
{
getLine("client> ", command, 10);
if (strcmp(command, "quit") == 0)
quit = 0;
else
excCommand(command);
}
This is the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
int main(int argc, char *argv[])
{
if (argc != 2)
ErrorWithUserMessage("Parameter(s)", "<Server Port>");
char *service = argv[1];
int servSock = SetupTCPServerSocket(service);
if (servSock < 0)
ErrorWithUserMessage("SetupTCPServerSocket() failed: ", "unable to establish");
unsigned int childProcessCount = 0;
while (1)
{
int clntSock = AcceptTCPConnection(servSock);
pid_t processID = fork();
if (processID < 0)
ErrorWithSystemMessage("fork() failed");
else if (processID == 0)
{
close(servSock);
HandleTCPClient(clntSock);
exit(EXIT_SUCCESS);
}
printf("with child process: %d\n", processID);
close(clntSock);
childProcessCount++;
//clean up zombies
while (childProcessCount)
{
processID = waitpid((pid_t) - 1, NULL, WNOHANG);
if (processID < 0)
ErrorWithSystemMessage("waitpid() failed");
else if (processID == 0)
break;
else
childProcessCount--;
}
}
}
Handler:
void HandleTCPClient(int clntSock)
{
char buffer[BUFSIZE];
ssize_t numBytesRcvd = recv(clntSock, buffer, BUFSIZE, 0);
buffer[numBytesRcvd] = '\0';
if (numBytesRcvd < 0)
ErrorWithSystemMessage("recv() failed");
if (strcmp(buffer, "help") == 0)
{
FILE *fp = fopen("help.txt", "r");
if (fp)
{
char line[128];
while (fgets(line, sizeof(line), fp) != NULL)
{
if (send(clntSock, line, sizeof(line), 0) < 0)
ErrorWithSystemMessage("send() failed");
}
fclose(fp);
}
}
close(clntSock);
}
and this is my client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "common.h"
int sock;
void getLine(char *message, char *buf, int maxLen)
{
printf("%s", message);
fgets(buf, maxLen, stdin);
buf[strlen(buf) - 1] = 0;
}
void excCommand(char *command)
{
if ( send(sock, command, strlen(command), 0) < 0)
ErrorWithSystemMessage("send() failed");
char replyMessage[BUFSIZE];
ssize_t numBytesRecv = 0;
do
{
numBytesRecv = recv(sock, replyMessage, BUFSIZE, 0);
if ( numBytesRecv < 0)
ErrorWithSystemMessage("recv() failed");
printf("%s\n", replyMessage);
memset(&replyMessage, 0, sizeof(replyMessage));
}
while (numBytesRecv > 0);
}
void PrintFile(const char *filename)
{
FILE *fp;
fp = fopen(filename, "r");
if (fp)
{
char line[128];
while (fgets(line, sizeof(line), fp) != NULL)
fputs(line, stdout);
fputs("\n", stdout);
fclose(fp);
}
}
int main(int argc, char *argv[])
{
int quit = 1;
char command[10];
if (argc < 2 || argc > 3)
{
ErrorWithUserMessage("Parameter(s)", "<Server Address> <Server Port>");
}
char *server = argv[1];
char *service = argv[2];
sock = SetupTCPClientSocket(server, service);
if (sock < 0)
ErrorWithUserMessage("SetupTCPClientSocket() failed: ", "unable to connect");
printf("Connection established!\n\n");
PrintFile("menu.txt");
excCommand("help");
while (quit)
{
getLine("client> ", command, 10);
if (strcmp(command, "quit") == 0)
quit = 0;
else
excCommand(command);
}
fputs("\n", stdout);
close(sock);
exit(EXIT_SUCCESS);
}
sorry for being so long-winded
The recv() and send() functions do not guarantee to send/recv all data (see man recv, man send)
You need to implement your own send_all() and recv_all(), something like
bool send_all(int socket, void *buffer, size_t length)
{
char *ptr = (char*) buffer;
while (length > 0)
{
int i = send(socket, ptr, length);
if (i < 1) return false;
ptr += i;
length -= i;
}
return true;
}
The following guide may help you Beej's Guide to Network Programming
Usual problems.
void excCommand(char *command)
{
if ( send(sock, command, strlen(command), 0) < 0)
ErrorWithSystemMessage("send() failed");
char replyMessage[BUFSIZE];
ssize_t numBytesRecv = 0;
do
{
numBytesRecv = recv(sock, replyMessage, BUFSIZE, 0);
if ( numBytesRecv < 0)
ErrorWithSystemMessage("recv() failed");
printf("%s\n", replyMessage);
Invalid. numBytesRecv could have been zero, in which case there is no message at all, otherwise at this point must be positive, as you've already tested for negative, and it indicates the actual length of the message, which isn't necessarily null-terminated. Change to:
if (numBytesRecv == 0)
break;
printf("%.*s\n", numBytesRecv, replyMessage);
and then:
memset(&replyMessage, 0, sizeof(replyMessage));
Pointless. Remove.
}
while (numBytesRecv > 0);
At this point you should check for numBytesRecv < 0 and call perror() or one of its friends.
I choose to send before each send() if i have to continue or not.
so i first have 3 define
#define BUFFSIZE 1024
#define CONT "CONT"
#define DONE "DONE"
Then to send my data
int send_to_socket(int sock, char *msg)
{
size_t len;
int ret[2];
len = strlen(msg);
ret[0] = send(sock, (len <= BUFFSIZE) ? DONE : CONT, 4, 0);
ret[1] = send(sock, msg, BUFFSIZE, 0);
if (ret[0] <= 0 || ret[1] <= 0)
{
perror("send_to_socket");
return (-1);
}
if (len > BUFFSIZE)
return (send_to_socket(sock, msg + BUFFSIZE));
return (1);
}
And to receive it :
char *recv_from_socket(int cs)
{
char state[5];
char buff[BUFFSIZE+1];
char *msg;
int ret[2];
msg = NULL;
while (42)
{
bzero(state, 5);
bzero(buff, BUFFSIZE+1);
ret[0] = recv(cs, state, 4, 0);
ret[1] = recv(cs, buff, BUFFSIZE, 0);
if (ret[0] <= 0 || ret[1] <= 0)
{
perror("recv_from_socket");
return (NULL);
}
// strfljoin() is selfmade
// join the string and free the left argument to prevent memory leaks.
// return fresh new string
msg = (msg) ? ft_strfljoin(msg, buff) : strdup(buff);
if (strncmp(state, DONE, 4) == 0)
break ;
i++;
}
return (msg);
}
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.
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.