Fork me on GitHub

root/fs/iso9660/dir.c

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

DEFINITIONS

This source file includes following definitions.
  1. iso9660_dir_open
  2. iso9660_dir_close
  3. iso9660_dir_read
  4. iso9660_dir_readdir

   1 /*
   2  * fiwix/fs/iso9660/dir.c
   3  *
   4  * Copyright 2018-2021, 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/stdio.h>
  16 #include <fiwix/string.h>
  17 
  18 struct fs_operations iso9660_dir_fsop = {
  19         0,
  20         0,
  21 
  22         iso9660_dir_open,
  23         iso9660_dir_close,
  24         iso9660_dir_read,
  25         NULL,                   /* write */
  26         NULL,                   /* ioctl */
  27         NULL,                   /* lseek */
  28         iso9660_dir_readdir,
  29         NULL,                   /* mmap */
  30         NULL,                   /* select */
  31 
  32         NULL,                   /* readlink */
  33         NULL,                   /* followlink */
  34         iso9660_bmap,
  35         iso9660_lookup,
  36         NULL,                   /* rmdir */
  37         NULL,                   /* link */
  38         NULL,                   /* unlink */
  39         NULL,                   /* symlink */
  40         NULL,                   /* mkdir */
  41         NULL,                   /* mknod */
  42         NULL,                   /* truncate */
  43         NULL,                   /* create */
  44         NULL,                   /* rename */
  45 
  46         NULL,                   /* read_block */
  47         NULL,                   /* write_block */
  48 
  49         NULL,                   /* read_inode */
  50         NULL,                   /* write_inode */
  51         NULL,                   /* ialloc */
  52         NULL,                   /* ifree */
  53         NULL,                   /* statsfs */
  54         NULL,                   /* read_superblock */
  55         NULL,                   /* remount_fs */
  56         NULL,                   /* write_superblock */
  57         NULL                    /* release_superblock */
  58 };
  59 
  60 int iso9660_dir_open(struct inode *i, struct fd *fd_table)
  61 {
  62         fd_table->offset = 0;
  63         return 0;
  64 }
  65 
  66 int iso9660_dir_close(struct inode *i, struct fd *fd_table)
  67 {
  68         return 0;
  69 }
  70 
  71 int iso9660_dir_read(struct inode *i, struct fd *fd_table, char *buffer, __size_t count)
  72 {
  73         return -EISDIR;
  74 }
  75 
  76 int iso9660_dir_readdir(struct inode *i, struct fd *fd_table, struct dirent *dirent, unsigned int count)
  77 {
  78         __blk_t block;
  79         unsigned int doffset, offset;
  80         unsigned int size, dirent_len;
  81         struct iso9660_directory_record *d;
  82         int base_dirent_len;
  83         int blksize;
  84         struct buffer *buf;
  85         int nm_len;
  86         char nm_name[NAME_MAX + 1];
  87 
  88         if(!(S_ISDIR(i->i_mode))) {
  89                 return -EBADF;
  90         }
  91 
  92         blksize = i->sb->s_blocksize;
  93         if(fd_table->offset > i->i_size) {
  94                 fd_table->offset = i->i_size;
  95         }
  96 
  97         base_dirent_len = sizeof(dirent->d_ino) + sizeof(dirent->d_off) + sizeof(dirent->d_reclen);
  98         doffset = size = 0;
  99 
 100         while(doffset < count) {
 101                 if((block = bmap(i, fd_table->offset, FOR_READING)) < 0) {
 102                         return block;
 103                 }
 104                 if(block) {
 105                         if(!(buf = bread(i->dev, block, blksize))) {
 106                                 return -EIO;
 107                         }
 108 
 109                         doffset = fd_table->offset;
 110                         offset = fd_table->offset % blksize;
 111 
 112                         while(doffset < i->i_size && offset < blksize) {
 113                                 d = (struct iso9660_directory_record *)(buf->data + offset);
 114                                 if(isonum_711(d->length)) {
 115                                         dirent_len = (base_dirent_len + (isonum_711(d->name_len) + 1)) + 3;
 116                                         dirent_len &= ~3;       /* round up */
 117                                         if((size + dirent_len) < count) {
 118                                                 dirent->d_ino = (block << ISO9660_INODE_BITS) + (doffset & ISO9660_INODE_MASK);
 119                                                 dirent->d_off = doffset;
 120                                                 dirent->d_reclen = dirent_len;
 121                                                 if(isonum_711(d->name_len) == 1 && d->name[0] == 0) {
 122                                                         dirent->d_name[0] = '.';
 123                                                         dirent->d_name[1] = NULL;
 124                                                 } else if(isonum_711(d->name_len) == 1 && d->name[0] == 1) {
 125                                                         dirent->d_name[0] = '.';
 126                                                         dirent->d_name[1] = '.';
 127                                                         dirent->d_name[2] = NULL;
 128                                                         dirent_len = 16;
 129                                                         dirent->d_reclen = 16;
 130                                                         if(i->u.iso9660.i_parent) {
 131                                                                 dirent->d_ino = i->u.iso9660.i_parent->inode;
 132                                                         } else {
 133                                                                 dirent->d_ino = i->inode;
 134                                                         }
 135                                                 } else {
 136                                                         nm_len = 0;
 137                                                         if(i->sb->u.iso9660.rrip) {
 138                                                                 nm_len = get_rrip_filename(d, i, nm_name);
 139                                                         }
 140                                                         if(nm_len) {
 141                                                                 dirent->d_reclen = (base_dirent_len + nm_len + 1) + 3;
 142                                                                 dirent->d_reclen &= ~3; /* round up */
 143                                                                 dirent_len = dirent->d_reclen;
 144                                                                 if((size + dirent_len) < count) {
 145                                                                         dirent->d_name[nm_len] = NULL;
 146                                                                         memcpy_b(dirent->d_name, nm_name, nm_len);
 147                                                                 } else {
 148                                                                         break;
 149                                                                 }
 150                                                         } else {
 151                                                                 memcpy_b(dirent->d_name, d->name, isonum_711(d->name_len));
 152                                                                 dirent->d_name[isonum_711(d->name_len)] = NULL;
 153                                                         }
 154                                                 }
 155                                                 if(!((char)d->flags[0] & ISO9660_FILE_ISDIR)) {
 156                                                         iso9660_cleanfilename(dirent->d_name, isonum_711(d->name_len));
 157                                                 }
 158                                                 dirent = (struct dirent *)((char *)dirent + dirent_len);
 159                                                 size += dirent_len;
 160                                         } else {
 161                                                 break;
 162                                         }
 163                                         doffset += isonum_711(d->length);
 164                                         offset += isonum_711(d->length);
 165                                 } else {
 166                                         doffset &= ~(blksize - 1);
 167                                         doffset += blksize;
 168                                         break;
 169                                 }
 170                         }
 171                         brelse(buf);
 172                 }
 173                 fd_table->offset = doffset;
 174         }
 175         return size;
 176 }

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