Untitled
unknown
plain_text
11 days ago
5.2 kB
7
Indexable
StrongPtr<Node> find(StrongPtr<Node> dir, const char* name) { // Ensure the starting node is either a directory or a symlink. if (!dir->is_dir() && !dir->is_symlink()) { return StrongPtr<Node>(); } // Compute the length of the incoming path. int name_len = 0; while (name[name_len] != '\0') { name_len++; } // Create a mutable copy of the path. char* path_copy = new char[name_len + 1]; for (int i = 0; i < name_len; i++) { path_copy[i] = name[i]; } path_copy[name_len] = '\0'; // Use a separate pointer for traversal. char* curr_ptr = path_copy; // If the path is absolute, start from the root. if (curr_ptr[0] == '/') { dir = root; } // Save the parent directory (for relative symlink resolution). StrongPtr<Node> parent = dir; // Count how many symlinks we have resolved (to avoid infinite loops). int sl_count = 0; while (*curr_ptr != '\0') { // Skip any leading '/' characters. while (*curr_ptr == '/') { curr_ptr++; } if (*curr_ptr == '\0') break; // --- If the current node is a directory --- if (dir->is_dir()) { // Update the parent pointer before descending. parent = dir; // Extract the next path segment into a buffer. char target_name[256]; int j = 0; while (curr_ptr[j] != '/' && curr_ptr[j] != '\0' && j < 255) { target_name[j] = curr_ptr[j]; j++; } target_name[j] = '\0'; // Search through the directory entries for a match. StrongPtr<Node> next_node; uint32_t entry_count = dir->entry_count(); uint32_t offset = 0; bool match_found = false; for (uint32_t k = 0; k < entry_count; k++) { DirEntry entry; dir->read_all(offset, sizeof(DirEntry), (char*)&entry); offset += entry.rec_len; if (entry.name_len == (uint8_t)j) { bool match = true; for (int l = 0; l < j; l++) { if (entry.name[l] != target_name[l]) { match = false; break; } } if (match) { next_node = get_inode(entry.inode); if (next_node == nullptr || next_node->currInode == nullptr) { delete[] path_copy; return StrongPtr<Node>(); } match_found = true; break; } } } if (!match_found) { delete[] path_copy; return StrongPtr<Node>(); } // Advance the traversal pointer by the length of the segment. curr_ptr += j; // Set the current directory to the found node. dir = next_node; continue; } // --- If the current node is a symbolic link --- if (dir->is_symlink()) { sl_count++; if (sl_count > 100) { delete[] path_copy; return StrongPtr<Node>(); } char sl_target[256]; dir->get_symbol(sl_target); // Determine the length of the symlink target. int target_len = 0; while (sl_target[target_len] != '\0') { target_len++; } // Determine the length of the remaining path. int remaining_len = 0; while (curr_ptr[remaining_len] != '\0') { remaining_len++; } // Allocate a new path: symlink target + "/" + remaining path (if any). int new_path_len = target_len + (remaining_len > 0 ? 1 + remaining_len : 0); char* new_path = new char[new_path_len + 1]; for (int i = 0; i < target_len; i++) { new_path[i] = sl_target[i]; } if (remaining_len > 0) { new_path[target_len] = '/'; for (int i = 0; i < remaining_len; i++) { new_path[target_len + 1 + i] = curr_ptr[i]; } new_path[new_path_len] = '\0'; } else { new_path[target_len] = '\0'; } // For absolute symlink targets, start from the root. // For relative targets, interpret them relative to the parent directory. if (sl_target[0] == '/') { dir = root; } else { dir = parent; } // Free the old path copy and update our traversal pointer. delete[] path_copy; path_copy = new_path; curr_ptr = path_copy; continue; } } delete[] path_copy; return dir; }
Editor is loading...
Leave a Comment