1

I'm trying to write a custom filesystem for Tcl using the Tclapi (it's work related, won't go into details), but I'm stuck trying to figure out why this is not working.

In this code segment I'm getting the original/native Tcl_Filesystem, copying over all its contents (function pointers) to my_fs, and then calling Tcl_FSRegister on my_fs. Very simple, thought it should work.

// global scope
const Tcl_Filesystem *ori_fs;
Tcl_Filesystem *my_fs;

...

// in Init

// Get the original Tcl_Filesystem.
Tcl_Obj *root_obj = Tcl_NewStringObj("/", -1);
Tcl_IncrRefCount(root_obj);
ori_fs = Tcl_FSGetFileSystemForPath(root_obj);
Tcl_DecrRefCount(root_obj);

// create a duplicate of the original Tcl_Filesystem struct.
my_fs = malloc(sizeof(Tcl_Filesystem));
memmove(my_fs, ori_fs, ori_fs->structureLength);

int ret = Tcl_FSRegister((ClientData)1, my_fs);
if (ret == TCL_ERROR) {
...

When I ran

load <path to .so>/my_fs[info sharedlibextension]

# sanity check
puts [pwd]

set fp [open test.txt]

however, I get this

<my current directory>

while executing
"open test.txt"
    invoked from within
"set fp [open test.txt]"
    (file "test.tcl" line 3)

Notice how "puts [pwd]" works but not "open test.txt" ?

Replacing "my_fs" with "ori_fs" in the call to Tcl_FSRegister seems to work... I've already spent far too much time trying to figure this out. I would appreciate if anyone could help me with this!

lennoxho
  • 21
  • 2

1 Answers1

1

The native filesystem is special. In particular, there's some places where its identity is used directly: for example, it's the only FS that can have temporary files made on it, it's assumed to own the roots, and it is handled specially in path management. (Well, according to where in the source code there are direct references to the Tcl internal variable tclNativeFilesystem, which isn't something you can cheat at. It's also possibly in read-only memory, so you can't hack around this.)

For most sane uses of a Tcl virtual filesystem, this doesn't matter. Temp files have to be native because you may well be passing them to the OS (e.g., for loading libraries or running programs that were inside the VFS; with these, they have to be copied out or the OS will think “what are you talking about?!”) and you put the things that you are mounting somewhere other than the native root. So long as you're not trying to use a VFS as a security measure (not recommended; there are safe interpreters for that as they offer a stronger sandboxing solution) it shouldn't be a problem as you can just make your code know that it needs to work below a particular location to get things done. (FWIW, it's a bad idea to cd anyway, except in response to user requests, since it changes the meaning of user-supplied relative paths, so good code handles “make everything relative to a defined location” from the start.)

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215