Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ospfs_dir_readdir(filp, dirent, filldir)
- // This function is called when the kernel reads the contents of a directory
- // (i.e. when file_operations.readdir is called for the inode).
- //
- // Inputs: filp -- The 'struct file' structure correspoding to
- // the open directory.
- // The most important member is 'filp->f_pos', the
- // File POSition. This remembers how far into the
- // directory we are, so if the user calls 'readdir'
- // twice, we don't forget our position.
- // This function must update 'filp->f_pos'.
- // dirent -- Used to pass to 'filldir'.
- // filldir -- A pointer to a callback function.
- // This function should call 'filldir' once for each
- // directory entry, passing it six arguments:
- // (1) 'dirent'.
- // (2) The directory entry's name.
- // (3) The length of the directory entry's name.
- // (4) The 'f_pos' value corresponding to the directory entry.
- // (5) The directory entry's inode number.
- // (6) DT_REG, for regular files; DT_DIR, for subdirectories;
- // or DT_LNK, for symbolic links.
- // This function should stop returning directory
- // entries either when the directory is complete, or
- // when 'filldir' returns < 0, whichever comes first.
- //
- // Returns: 1 at end of directory, 0 if filldir returns < 0 before the end
- // of the directory, and -(error number) on error.
- //
- // EXERCISE: Finish implementing this function.
- static int
- ospfs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
- {
- struct inode *dir_inode = filp->f_dentry->d_inode;
- ospfs_inode_t *dir_oi = ospfs_inode(dir_inode->i_ino);
- uint32_t f_pos = filp->f_pos;
- int r = 0; /* Error return value, if any */
- int ok_so_far = 0; /* Return value from 'filldir' */
- // f_pos is an offset into the directory's data, plus two.
- // The "plus two" is to account for "." and "..".
- if (r == 0 && f_pos == 0) {
- ok_so_far = filldir(dirent, ".", 1, f_pos, dir_inode->i_ino, DT_DIR);
- if (ok_so_far >= 0)
- f_pos++;
- }
- if (r == 0 && ok_so_far >= 0 && f_pos == 1) {
- ok_so_far = filldir(dirent, "..", 2, f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR);
- if (ok_so_far >= 0)
- f_pos++;
- }
- // actual entries
- while (r == 0 && ok_so_far >= 0 && f_pos >= 2) {
- ospfs_direntry_t *od;
- ospfs_inode_t *entry_oi;
- /* If at the end of the directory, set 'r' to 1 and exit
- * the loop. For now we do this all the time.
- *
- * EXERCISE: Your code here */
- if ((f_pos - 2) * OSPFS_DIRENTRY_SIZE >= dir_oi->oi_size) {
- r = 1;
- break;
- }
- /* Get a pointer to the next entry (od) in the directory.
- * The file system interprets the contents of a
- * directory-file as a sequence of ospfs_direntry structures.
- * You will find 'f_pos' and 'ospfs_inode_data' useful.
- *
- * Then use the fields of that file to fill in the directory
- * entry. To figure out whether a file is a regular file or
- * another directory, use 'ospfs_inode' to get the directory
- * entry's corresponding inode, and check out its 'oi_ftype'
- * member.
- *
- * Make sure you ignore blank directory entries! (Which have
- * an inode number of 0.)
- *
- * If the current entry is successfully read (the call to
- * filldir returns >= 0), or the current entry is skipped,
- * your function should advance f_pos by the proper amount to
- * advance to the next directory entry.
- */
- /* EXERCISE: Your code here */
- od = ospfs_inode_data(dir_oi, (f_pos - 2) * OSPFS_DIRENTRY_SIZE);
- entry_oi = ospfs_inode(od->od_ino);
- if (!entry_oi) {
- f_pos++;
- continue;
- }
- ok_so_far = filldir(dirent, od->od_name, strlen(od->od_name), f_pos,
- od->od_ino, entry_oi->oi_ftype == OSPFS_FTYPE_DIR ? DT_DIR :
- entry_oi->oi_ftype == OSPFS_FTYPE_SYMLINK ? DT_LNK : DT_REG);
- f_pos++;
- }
- // Save the file position and return!
- filp->f_pos = f_pos;
- return r;
- }
Add Comment
Please, Sign In to add comment