libfuse examples linked with OSXFUSE does not show up in Finder after mounted

152 views
Skip to first unread message

pjhades

unread,
Jul 10, 2016, 4:53:00 PM7/10/16
to OSXFUSE
I tried to compile the simplest libfuse example "hello.c" and link it with OSXFUSE. After mounting it, I cannot see the file system in Finder. However, I can see other file systems like YoutubeFS and in Finder. The implementation of "hello.c" is quite simple (I made some changes to let it work with OSXFUSE):

#include <osxfuse/fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

static const char *hello_str = "Hello World!\n";
static const char *hello_path = "/hello";

static int hello_getattr(const char *path, struct stat *stbuf)
{
    printf("getattr, path: %s\n", path);
int res = 0;

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;
    printf("readdir, path: %s\n", path);

if (strcmp(path, "/") != 0)
return -ENOENT;

filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, hello_path + 1, NULL, 0);

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 void *hello_init(struct fuse_conn_info *conn)
{
    printf("init\n");
    return NULL;
}

static struct fuse_operations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
    .init       = hello_init,
};

int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &hello_oper, NULL);
}

I build the executable with command

clang -D_FILE_OFFSET_BITS=64 hello.c -losxfuse -o hello

How to make this simple toy show up in Finder?

Sam Moffatt

unread,
Jul 10, 2016, 7:34:17 PM7/10/16
to osxfus...@googlegroups.com
Finder can be picky about what it thinks is legit or not. In the past I’ve had plenty of issues with Finder deciding to not show anything because the data it got back from my file system was inconsistent.

What I’d personally do is run your file system in debug mode and see exactly what FS operations are being called and what is being returned. It’s possible that there is a call to your filesystem for some folder metadata that is being returned in such a way that Finder is assuming it doesn’t exist. 

Also keep in mind that Mac OS X’s VFS layer is slightly different to the Linux VFS layer and there are different behaviours that aren’t 100% compatible. IMHO OSXFUSE does a good job of isolating a lot of that but there are various system calls that outright behave differently on the two OS’s that makes development a pain.


I copied your code and tried to compile as is with the latest non developer version of OSXFUSE however I got the standard FUSE version error. I modified it slightly to fix that (adding a def for FUSE_USE_VERSION ahead of the fuse.h import) and it compiled.

Running in debug mode there are a lot of failed calls:

pancake:osxfuse_hello pasamio$ ./hello -d -s mount
unique: 0, opcode: INIT (26), nodeid: 0, insize: 56
INIT: 7.8
flags=0x00000000
max_readahead=0x00100000
init
   INIT: 7.8
   flags=0x00000000
   max_readahead=0x00100000
   max_write=0x01000000
   unique: 0, error: 0 (Undefined error: 0), outsize: 40
unique: 0, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 0, error: 0 (Undefined error: 0), outsize: 96
unique: 0, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 0, error: 0 (Undefined error: 0), outsize: 96
unique: 0, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 0, error: 0 (Undefined error: 0), outsize: 96
unique: 0, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 0, error: 0 (Undefined error: 0), outsize: 96
unique: 0, opcode: ACCESS (34), nodeid: 1, insize: 48
ACCESS / 00
   unique: 0, error: -78 (Function not implemented), outsize: 16
unique: 0, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 0, error: 0 (Undefined error: 0), outsize: 96
unique: 1, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 1, error: 0 (Undefined error: 0), outsize: 96
unique: 0, opcode: GETATTR (3), nodeid: 1, insize: 40
getattr, path: /
   unique: 0, error: -2 (No such file or directory), outsize: 16
unique: 1, opcode: STATFS (17), nodeid: 1, insize: 40
   unique: 1, error: 0 (Undefined error: 0), outsize: 96
(repeated a lot more times)



What is probably actually causing the problems is that there is a getattr call on the root path that returns it doesn’t exist (repeating below):
unique: 0, opcode: GETATTR (3), nodeid: 1, insize: 40
getattr, path: /
   unique: 0, error: -2 (No such file or directory), outsize: 16


Now if I’m Finder (or really the OS) and go “Hey, what’s at the root” and the FS goes “nothing” then I’m going to pretend it doesn’t exist. My guess is this is what is happening with Finder.

Let’s implement a basic getattr for / to see if this makes a difference:

static int hello_getattr(const char *path, struct stat *stbuf)
{
    printf("getattr, path: %s\n", path);
int res = 0;

if (strcmp(path, hello_path) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(hello_str);
} else if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 3;
stbuf->st_size = 0;
} else
res = -ENOENT;

return res;
}


My include lines are also modified to look like this:

#define FUSE_USE_VERSION 26
#include <osxfuse/fuse.h>


Now when I compile and run this, the new mount point shows up in Finder. The command line also likes it better as well. 

Before:

pancake:osxfuse_hello pasamio$ ls mount
ls: mount: Device not configured


After:

pancake:osxfuse_hello pasamio$ ls mount
hello


Running your filesystem in debug mode and single threaded are great ways to debug your file system and see what is going on. Single threaded mode isn’t always necessary but I’ve found it useful in the past to determine if the bug is the result of a race condition in my filesystem (if it works in single threaded mode but Finder pukes otherwise then my FS is behaving inconsistently).

Best of luck!

Cheers,

Sam


--
You received this message because you are subscribed to the Google Groups "OSXFUSE" group.
To unsubscribe from this group and stop receiving emails from it, send an email to osxfuse-grou...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

pjhades

unread,
Jul 25, 2016, 10:13:47 PM7/25/16
to OSXFUSE
Thank you so much for your detailed reply Samuel! And I'm sorry for my late return since I forgot to check the email notification.
I've tested with the editions you mentioned and it works.
I'll try to use the debug mode more :)

在 2016年7月10日星期日 UTC-4下午7:34:17,Samuel Moffatt写道:
Reply all
Reply to author
Forward
0 new messages