| 
					
				 | 
			
			
				@@ -54,7 +54,14 @@ fs::vfs::dentry* fs::vfs::dentry::find(const name_type& name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!ind->flags.in.directory) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (ind->flags.in.directory && !flags.in.present) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (name[0] == '.') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!name[1]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (name[1] == '.' && !name[2]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return parent ? parent : this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!flags.in.present) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         ind->fs->load_dentry(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     auto iter = idx_children->find(name); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -80,9 +87,34 @@ void fs::vfs::dentry::invalidate(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     flags.in.present = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fs::vfs::vfs(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    : _root(nullptr, nullptr, "/") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    : _root(nullptr, nullptr, "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void fs::vfs::dentry::path( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const dentry& root, name_type &out_dst) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const dentry* dents[32]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int cnt = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const dentry* cur = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while (cur != &root) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert(cnt < 32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        dents[cnt++] = cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cur = cur->parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (cnt == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        out_dst += '/'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = cnt - 1; i >= 0; --i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        out_dst += '/'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        out_dst += dents[i]->name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fs::inode* fs::vfs::cache_inode(inode_flags flags, uint32_t perm, size_t size, ino_t ino) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     auto [ iter, inserted ] = 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -457,57 +489,56 @@ int fs::vfs_mkdir(fs::vfs::dentry* dir, const char* dirname) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return dir->ind->fs->inode_mkdir(dir, dirname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-fs::vfs::dentry* fs::vfs_open(const char* path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fs::vfs::dentry* fs::vfs_open( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fs::vfs::dentry& root, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const char* pwd, const char* path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (path[0] == '/' && path[1] == 0x00) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return fs::fs_root; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fs::vfs::dentry* cur = nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!*path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    auto* cur = fs::fs_root; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_t n = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    switch (*(path++)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // absolute path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    case '/': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        while (true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (path[n] == 0x00) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                cur = cur->find(string(path, n)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (*path == '/' || !pwd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cur = &root; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cur = vfs_open(root, nullptr, pwd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    size_t n = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    string curpath; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while (true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        switch (path[n]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case '\0': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (n != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                curpath.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                curpath.append(path, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                cur = cur->find(curpath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (path[n] == '/') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                cur = cur->find(string(path, n)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!cur) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (path[n + 1] == 0x00) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    path += (n + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    n = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case '/': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (n == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ++path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            curpath.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            curpath.append(path, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cur = cur->find(curpath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!cur) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            path += (n + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            n = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ++n; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // empty string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    case 0x00: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // relative path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int fs::vfs_stat(const char* filename, stat* stat) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    auto ent = vfs_open(filename); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!ent) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return GB_FAILED; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return vfs_stat(ent, stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int fs::vfs_stat(fs::vfs::dentry* ent, stat* stat) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return ent->ind->fs->inode_stat(ent, stat); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -672,23 +703,14 @@ void init_vfs(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     vfs_mkdir(fs_root, "mnt"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     vfs_mkfile(fs_root, "init"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    auto* init = vfs_open("/init"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    auto* init = vfs_open(*fs_root, nullptr, "/init"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert(init); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const char* str = "#/bin/sh\nexec /bin/sh\n"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     vfs_write(init->ind, str, 0, strlen(str)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    auto* dev = vfs_open("/dev"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    auto* dev = vfs_open(*fs_root, nullptr, "/dev"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert(dev); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     vfs_mknode(dev, "null", { .in { .major = 0, .minor = 0 } }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     vfs_mknode(dev, "console", { .in { .major = 1, .minor = 0 } }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     vfs_mknode(dev, "hda", { .in { .major = 2, .minor = 0 } }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stat _stat {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vfs_stat("/init", &_stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vfs_stat("/", &_stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vfs_stat("/dev", &_stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vfs_stat("/dev/null", &_stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vfs_stat("/dev/console", &_stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vfs_stat("/dev/hda", &_stat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |