bool is_parent_directory (struct dir* directory) { if (!directory) return false; if (ROOT_DIR_SECTOR == get_inumber (directory->inode)) return true; return false; }
bool dir_add (struct dir *directory, block_sector_t block_sec, const char *file) { struct dir_entry directory_element; off_t offset; bool success = false; ASSERT(directory != NULL); ASSERT(file != NULL); acquire_inode_lock (directory->inode); if (*file == '\0' || strlen (file) > MAXIMUM_FILE_NAME_LENGTH) { release_inode_lock (directory->inode); return success; } for (offset = 0; inode_read_at (directory->inode, &directory_element, sizeof directory_element, offset) == sizeof directory_element; offset += sizeof directory_element) if (directory_element.in_use && !strcmp (file, directory_element.name)) { release_inode_lock (directory->inode); return success; } if (!inode_add_parent (get_inumber (directory->inode), block_sec)) { release_inode_lock (directory->inode); return success; } for (offset = 0; inode_read_at (directory->inode, &directory_element, sizeof directory_element, offset) == sizeof directory_element; offset += sizeof directory_element) if (!directory_element.in_use) break; directory_element.in_use = true; strlcpy (directory_element.name, file, sizeof directory_element.name); directory_element.inode_sector = block_sec; success = inode_write_at (directory->inode, &directory_element, sizeof directory_element, offset) == sizeof directory_element; release_inode_lock (directory->inode); return success; }
/* Stores the current working directory, as a null-terminated string, in the CWD_SIZE bytes in CWD. Returns true if successful, false on error. Errors include system errors, directory trees deeper than MAX_LEVEL levels, and insufficient space in CWD. */ static bool getcwd (char *cwd, size_t cwd_size) { size_t cwd_len = 0; #define MAX_LEVEL 20 char name[MAX_LEVEL * 3 + 1 + READDIR_MAX_LEN + 1]; char *namep; int child_inum; /* Make sure there's enough space for at least "/". */ if (cwd_size < 2) return false; /* Get inumber for current directory. */ if (!get_inumber (".", &child_inum)) return false; namep = name; for (;;) { int parent_inum, parent_fd; /* Compose "../../../..", etc., in NAME. */ if ((namep - name) > MAX_LEVEL * 3) return false; *namep++ = '.'; *namep++ = '.'; *namep = '\0'; /* Open directory. */ parent_fd = open (name); if (parent_fd < 0) return false; *namep++ = '/'; /* If parent and child have the same inumber, then we've arrived at the root. */ parent_inum = inumber (parent_fd); if (parent_inum == child_inum) break; /* Find name of file in parent directory with the child's inumber. */ for (;;) { int test_inum; if (!readdir (parent_fd, namep) || !get_inumber (name, &test_inum)) { close (parent_fd); return false; } if (test_inum == child_inum) break; } close (parent_fd); /* Prepend "/name" to CWD. */ if (!prepend (namep - 1, cwd, &cwd_len, cwd_size)) return false; /* Move up. */ child_inum = parent_inum; } /* Finalize CWD. */ if (cwd_len > 0) { /* Move the string to the beginning of CWD, and null-terminate it. */ memmove (cwd, (cwd + cwd_size) - cwd_len, cwd_len); cwd[cwd_len] = '\0'; } else { /* Special case for the root. */ strlcpy (cwd, "/", cwd_size); } return true; }