gerryg400 wrote:Hmm, you're right. So I checked my code...
Code: Select all
while (*p) {
if (*p == '/') {
++p;
continue;
}
/* Look in the current dir for the entry and walk the tree as far
* as we can
*/
n = search_dir(curr_node, p);
if (n == NULL)
break;
/* We continue to the next level */
p = nameskip(p);
curr_node = n;
}
It goes as far as it can finding the deepest match. I didn't know that anyone read my posts !! I'll have to be more careful from now on.
That's actually very similar to the code I whipped up earlier today. Here is what I wrote (untested, more like psuedo):
Code: Select all
/*! find a node within a specified node (node must be a directory) */
struct fs_node* find_node(struct fs_node* node, const char* path)
{
if( !(node->flags & FS_DIRECTORY) ) return 0;
char name[64] = {0};
const char* next = strchr(path, '/');
while( next ){
memcpy(name, path, int(next-path));
name[int(next-path)] = 0;
if( !(node->flags & FS_DIRECTORY) ) return 0;
node = check_mount(finddir_fs(node, name)); // Find the item, and check if it is a mount point!
if( !node ) return 0;
path = next+1;
next = strchr(path, '/');
}
/*! No more slashes. All that's left is the last name, or there was a leading slash. */
if( path[0] == '\0' ) return node;
else{
if( !(node->flags & FS_DIRECTORY) ) return 0;
node = finddir_fs(node, path); // This could return null, if so just return it
}
return node;
}
Edit yes I know, the memcpy of the name isn't good. I was thinking of changing so that it just changes the '/' pointed to by 'next' to a '\0' then finds the node, and changes it back to a '/'. That way finddir could use path like a normal null terminated string with no '/'s.
in that, the initial node would be a directory to search for a file/directory in. It goes down the path (from the start) and searches "node" for that file/directory, until it either can't find it (that file/directory doesn't exist) or there are no more "/"s in which case, we just need to check the last file in the path to make sure the requested file/directory exists. All of this is done through the node->finddir function (here we use finddir_fs which is a wrapper in case 1. finddir isn't implemented and 2. so you don't have to write node twice (node->finddir(node, path)) ) which should return the struct fs_node* for a given file name in a given directory.
In that code, check_mount checks to see if the new directory node matches any mount points. If it doesn't, it returns the node as returned by finddir_fs, but if the node is a mount point, it returns the node that was mounted there (see struct mount_point above). Here is the source to that function:
Code: Select all
/*! Check all the mount points to see if this node should redirect
This might be a slow way, but there should never be many mount points
anyway. (On my current slackware machine, there are 6 mount points */
struct fs_node* check_mount(struct fs_node* node)
{
if( !node ) return 0;
if( !(node->flags & FS_DIRECTORY) ) return node; // Not a directory, just return the node
struct list_head* iter = 0;
struct mount_point* mp = 0;
list_for_each(iter, &mount_list){
mp = list_value(iter, struct mount_point, link);
if( mp->dst == node ) return mp->src; // if the mount point is this node, return the mounted node
}
return node; // Otherwise return the original node
}
How does that look?
jnc100 wrote:I find the quickest way to search for these is to keep your list of mount points as a hash table, indexed on the path of the mount-point (as a string).
well then I'd need to implement a hash table...
lol
Your way does make sense if I wanted a device and path, but I don't want to deal with devices. Only fs_node's so (for the sake of abstraction), there is really no need to have any path left at all is there? If I keep a list of what node is mounted where, then if I really do need the device, there should be a way to get it through the driver and node.
Actually... if, using your method, instead of returning a device, I just return a node for that device (that might be what you meant). So it would be a hash table of strings, which point to fs_node's. On a side note, wouldn't that make it (theoretically) possible to mount a device/directory on a completely bogus path. Like lets say we did this:
mount /dev/sda1 /these/dont/exist
and it didn't check to see if the path "/these/dont/exist" was valid, and just put the string and node in the hash. Then when you did something like:
cat /these/dont/exist/text.txt
it would just look for "/these/dont/exist" in the mount hash table, and give you a valid fs_node. I don't see the usefulness of this, and I assume there would be a lot of problems but it's interesting to think about.