Fork me on GitHub

root/fs/ext2/dir.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ext2_dir_open
  2. ext2_dir_close
  3. ext2_dir_read
  4. ext2_dir_write
  5. ext2_dir_readdir

   1 /*
   2  * fiwix/fs/ext2/dir.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/types.h>
   9 #include <fiwix/errno.h>
  10 #include <fiwix/buffer.h>
  11 #include <fiwix/fs.h>
  12 #include <fiwix/filesystems.h>
  13 #include <fiwix/stat.h>
  14 #include <fiwix/dirent.h>
  15 #include <fiwix/mm.h>
  16 #include <fiwix/stdio.h>
  17 #include <fiwix/string.h>
  18 
  19 struct fs_operations ext2_dir_fsop = {
  20         0,
  21         0,
  22 
  23         ext2_dir_open,
  24         ext2_dir_close,
  25         ext2_dir_read,
  26         ext2_dir_write,
  27         NULL,                   /* ioctl */
  28         NULL,                   /* lseek */
  29         ext2_dir_readdir,
  30         NULL,                   /* mmap */
  31         NULL,                   /* select */
  32 
  33         NULL,                   /* readlink */
  34         NULL,                   /* followlink */
  35         ext2_bmap,
  36         ext2_lookup,
  37         ext2_rmdir,
  38         ext2_link,
  39         ext2_unlink,
  40         ext2_symlink,
  41         ext2_mkdir,
  42         ext2_mknod,
  43         NULL,                   /* truncate */
  44         ext2_create,
  45         ext2_rename,
  46 
  47         NULL,                   /* read_block */
  48         NULL,                   /* write_block */
  49 
  50         NULL,                   /* read_inode */
  51         NULL,                   /* write_inode */
  52         NULL,                   /* ialloc */
  53         NULL,                   /* ifree */
  54         NULL,                   /* statfs */
  55         NULL,                   /* read_superblock */
  56         NULL,                   /* remount_fs */
  57         NULL,                   /* write_superblock */
  58         NULL                    /* release_superblock */
  59 };
  60 
  61 int ext2_dir_open(struct inode *i, struct fd *fd_table)
  62 {
  63         fd_table->offset = 0;
  64         return 0;
  65 }
  66 
  67 int ext2_dir_close(struct inode *i, struct fd *fd_table)
  68 {
  69         return 0;
  70 }
  71 
  72 int ext2_dir_read(struct inode *i, struct fd *fd_table, char *buffer, __size_t count)
  73 {
  74         return -EISDIR;
  75 }
  76 
  77 int ext2_dir_write(struct inode *i, struct fd *fd_table, const char *buffer, __size_t count)
  78 {
  79         return -EBADF;
  80 }
  81 
  82 int ext2_dir_readdir(struct inode *i, struct fd *fd_table, struct dirent *dirent, unsigned int count)
  83 {
  84         __blk_t block;
  85         unsigned int doffset, offset;
  86         unsigned int size, dirent_len;
  87         struct ext2_dir_entry_2 *d;
  88         int base_dirent_len;
  89         int blksize;
  90         struct buffer *buf;
  91 
  92         if(!(S_ISDIR(i->i_mode))) {
  93                 return -EBADF;
  94         }
  95 
  96         blksize = i->sb->s_blocksize;
  97         if(fd_table->offset > i->i_size) {
  98                 fd_table->offset = i->i_size;
  99         }
 100 
 101         base_dirent_len = sizeof(dirent->d_ino) + sizeof(dirent->d_off) + sizeof(dirent->d_reclen);
 102         doffset = offset = size = 0;
 103 
 104         while(fd_table->offset < i->i_size && count > 0) {
 105                 if((block = bmap(i, fd_table->offset, FOR_READING)) < 0) {
 106                         return block;
 107                 }
 108                 if(block) {
 109                         if(!(buf = bread(i->dev, block, blksize))) {
 110                                 return -EIO;
 111                         }
 112 
 113                         doffset = fd_table->offset;
 114                         offset = fd_table->offset % blksize;
 115                         while(offset < blksize) {
 116                                 d = (struct ext2_dir_entry_2 *)(buf->data + offset);
 117                                 if(d->inode) {
 118                                         dirent_len = (base_dirent_len + (d->name_len + 1)) + 3;
 119                                         dirent_len &= ~3;       /* round up */
 120                                         dirent->d_ino = d->inode;
 121                                         if((size + dirent_len) < count) {
 122                                                 dirent->d_off = doffset;
 123                                                 dirent->d_reclen = dirent_len;
 124                                                 memcpy_b(dirent->d_name, d->name, d->name_len);
 125                                                 dirent->d_name[d->name_len] = NULL;
 126                                                 dirent = (struct dirent *)((char *)dirent + dirent_len);
 127                                                 size += dirent_len;
 128                                                 count -= size;
 129                                         } else {
 130                                                 count = 0;
 131                                                 break;
 132                                         }
 133                                 }
 134                                 doffset += d->rec_len;
 135                                 offset += d->rec_len;
 136                                 if(!d->rec_len) {
 137                                         break;
 138                                 }
 139                         }
 140                         brelse(buf);
 141                 }
 142                 fd_table->offset &= ~(blksize - 1);
 143                 doffset = fd_table->offset;
 144                 fd_table->offset += offset;
 145                 doffset += blksize;
 146         }
 147 
 148         return size;
 149 }

/* [previous][next][first][last][top][bottom][index][help] */