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; }
/* Adds a file named NAME to DIR, which must not already contain a file by that name. The file's inode is in sector INODE_SECTOR. Returns true if successful, false on failure. Fails if NAME is invalid (i.e. too long) or a disk or memory error occurs. */ bool dir_add (struct dir *dir, const char *name, block_sector_t inode_sector) { struct dir_entry e; off_t ofs; bool success = false; ASSERT (dir != NULL); ASSERT (name != NULL); inode_lock(dir_get_inode (dir)); /* Check NAME for validity. */ if (*name == '\0' || strlen (name) > NAME_MAX) { inode_unlock (dir_get_inode(dir)); return false; } /* Check that NAME is not in use. */ if (lookup (dir, name, NULL, NULL)) goto done; if (!inode_add_parent (inode_get_inumber (dir_get_inode(dir)),inode_sector)) { goto done; } /* Set OFS to offset of free slot. If there are no free slots, then it will be set to the current end-of-file. inode_read_at() will only return a short read at end of file. Otherwise, we'd need to verify that we didn't get a short read due to something intermittent such as low memory. */ for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e; ofs += sizeof e) if (!e.in_use) break; /* Write slot. */ e.in_use = true; strlcpy (e.name, name, sizeof e.name); e.inode_sector = inode_sector; success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e; done: inode_unlock (dir_get_inode(dir)); return success; }