I want to learn how to write filesystems in Fuse. My idea is to write a filesystem that communicates with pinboard.in (a bookmark service). I have problem with readdir. As far as I understand (which is not very much since this is new stuff for me) readdir is the function that returns what files and folders are in the filesystem.
I have the following code:
def readdir ( self, path, flags ):
print '*** readdir', path, flags
if path == '/':
# Path is root meaning we need to list tags and untagged bookmarks
tags_json=urllib2.urlopen('https://api.pinboard.in/v1/tags/get?format=json&auth_token='+self.apitoken).read()
tags = json.loads(tags_json)
ret = map(lambda k: fuse.Direntry(name=k, type=stat.S_IFDIR), tags.keys())
print ret
return ret
else:
pass
When running this in Fuse with debug flags I get something like
*** getattr /
unique: 2, success, outsize: 120
unique: 3, opcode: OPENDIR (27), nodeid: 1, insize: 48, pid: 6441
unique: 3, success, outsize: 32
unique: 4, opcode: READDIR (28), nodeid: 1, insize: 80, pid: 6441
readdir[0] from 0
*** readdir / 0
[<fuse.Direntry object at 0xb65b8f70>, <fuse.Direntry object at 0xb65b8f90>,........,<fuse.Direntry > object at 0xb65e1670>]
unique: 4, success, outsize: 16
unique: 5, opcode: RELEASEDIR (29), nodeid: 1, insize: 64, pid: 0
unique: 5, success, outsize: 16
but the file system is empty. I tried a little bit of everything but I think that I don't understand the flow of a filesystem. My real questions are, what do I return so ls shows files/directories? Where should I be reading about this?
In case you need more code you can go to my bitbucket and read everything: https://bitbucket.org/aquaplanet/pinboard.in-fuse/commits/38212eb035d3aba163bab9ed5a6b9284ce1dc93c
Thanks very much for your time reading my question, I am looking forward for any answers!
Thanks to @aleatha who told me that I wrote correct but there is a kind of type error in tags.keys(), that normal strings works, I quickly found that tags.keys() was unicode. Despite having sv_SE.UTF-8 in both LANG and LC_CTYPE (working on a raspberry pi) it wants 8 bit strings. This works much better:
def readdir ( self, path, flags ):
print '*** readdir', path, flags
if path == '/':
# Path is root meaning we need to list tags and untagged bookmarks
tags_json=urllib2.urlopen('https://api.pinboard.in/v1/tags/get?format=json&auth_token='+self.apitoken).read()
tags = json.loads(tags_json)
ret = map(lambda k: fuse.Direntry(name=k.encode('iso-8859-1','replace'), type=stat.S_IFDIR), tags.keys())
return ret
else:
pass
You look like you're on the right path... You need to return a series of Direntry objects.
If I replace your API call with a simple array of strings, like so:
tags = ["a", "b", "c"]
ret = map(lambda k: fuse.Direntry(name = k, type = stat.S_IFDIR), tags)
return ret
Then it works fine. So my surmise is that there's something wrong with tags.keys(). I'd start by inspecting the individual Direntry objects and seeing if they look right.