Fork me on GitHub

root/fs/procfs/dir.c

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

DEFINITIONS

This source file includes following definitions.
  1. proc_listdir
  2. dir_read
  3. procfs_dir_open
  4. procfs_dir_close
  5. procfs_dir_read
  6. procfs_dir_readdir

   1 /*
   2  * fiwix/fs/procfs/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/fs.h>
  11 #include <fiwix/filesystems.h>
  12 #include <fiwix/fs_proc.h>
  13 #include <fiwix/dirent.h>
  14 #include <fiwix/stat.h>
  15 #include <fiwix/mm.h>
  16 #include <fiwix/stdio.h>
  17 #include <fiwix/string.h>
  18 
  19 struct fs_operations procfs_dir_fsop = {
  20         0,
  21         0,
  22 
  23         procfs_dir_open,
  24         procfs_dir_close,
  25         procfs_dir_read,
  26         NULL,                   /* write */
  27         NULL,                   /* ioctl */
  28         NULL,                   /* lseek */
  29         procfs_dir_readdir,
  30         NULL,                   /* mmap */
  31         NULL,                   /* select */
  32 
  33         NULL,                   /* readlink */
  34         NULL,                   /* followlink */
  35         procfs_bmap,
  36         procfs_lookup,
  37         NULL,                   /* rmdir */
  38         NULL,                   /* link */
  39         NULL,                   /* unlink */
  40         NULL,                   /* symlink */
  41         NULL,                   /* mkdir */
  42         NULL,                   /* mknod */
  43         NULL,                   /* truncate */
  44         NULL,                   /* create */
  45         NULL,                   /* 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 static int proc_listdir(char *buffer, int count)
  62 {
  63         int n;
  64         struct proc *p;
  65         struct procfs_dir_entry *pd;
  66         struct procfs_dir_entry d;
  67         int size;
  68 
  69         size = 0;
  70         pd = (struct procfs_dir_entry *)buffer;
  71 
  72         FOR_EACH_PROCESS(p) {
  73                 d.inode = PROC_PID_INO + (p->pid << 12);
  74                 d.mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
  75                 d.nlink = 1;
  76                 d.lev = -1;
  77                 d.name_len = 1;
  78                 n = p->pid;
  79                 while(n / 10) {
  80                         n /= 10;
  81                         d.name_len++;
  82                 }
  83                 d.name = p->pidstr;
  84                 d.data_fn = NULL;
  85 
  86                 if(size + sizeof(struct procfs_dir_entry) > (count - 1)) {
  87                         printk("WARNING: kmalloc() is limited to 4096 bytes.\n");
  88                         break;
  89                 }
  90 
  91                 size += sizeof(struct procfs_dir_entry);
  92                 memcpy_b((void *)pd, (void *)&d, sizeof(struct procfs_dir_entry));
  93                 pd++;
  94                 p = p->next;
  95         }
  96         return size;
  97 }
  98 
  99 /*
 100 static int proc_listfd(struct inode *i, char *buffer, int count)
 101 {
 102         int n;
 103         struct proc *p;
 104         struct procfs_dir_entry *pd;
 105         struct procfs_dir_entry d;
 106         int size;
 107 
 108         size = 0;
 109         pd = (struct procfs_dir_entry *)buffer;
 110 
 111         p = get_proc_by_pid((i->inode >> 12) & 0xFFFF);
 112         for(n = 0; n < OPEN_MAX; n++) {
 113                 if(p->fd[n]) {
 114                         d.inode = PROC_PID_INO + (p->pid << 12) + n;
 115                         d.mode = S_IFREG | S_IRWXU;
 116                         d.nlink = 1;
 117                         d.lev = -1;
 118                         d.name_len = sprintk(d.name, "%d", n);
 119                         d.data_fn = NULL;
 120 
 121                         if(size + sizeof(struct procfs_dir_entry) > (count - 1)) {
 122                                 printk("WARNING: kmalloc() is limited to 4096 bytes.\n");
 123                                 break;
 124                         }
 125 
 126                         size += sizeof(struct procfs_dir_entry);
 127                         memcpy_b((void *)pd, (void *)&d, sizeof(struct procfs_dir_entry));
 128                         pd++;
 129                 }
 130         }
 131         memset_b((void *)pd + size, NULL, sizeof(struct procfs_dir_entry));
 132         return size;
 133 }
 134 */
 135 
 136 static int dir_read(struct inode *i, struct fd *fd_table, char *buffer, __size_t count)
 137 {
 138         __off_t total_read;
 139         unsigned int bytes;
 140         int len, lev;
 141         char *buf;
 142 
 143         if(!(buf = (void *)kmalloc())) {
 144                 return -ENOMEM;
 145         }
 146 
 147         /* create the list of directories for each process */
 148         len = 0;
 149         if(i->inode == PROC_ROOT_INO) {
 150                 len = proc_listdir(buf, count);
 151         }
 152 
 153         /* TODO: create the list of fds used for each process
 154         if((i->inode & 0xF0000FFF) == PROC_PID_FD) {
 155                 len = proc_listfd(i, buf, count);
 156         }
 157         */
 158 
 159         /* add the rest of static files in the main directory */
 160         lev = i->u.procfs.i_lev;
 161 
 162         /* assigns the size of the level without the last entry (NULL) */
 163         bytes = sizeof(procfs_array[lev]) - sizeof(struct procfs_dir_entry);
 164 
 165         if((len + bytes) > (count - 1)) {
 166                 printk("WARNING: %s(): len (%d) > count (%d).\n", __FUNCTION__, len, count);
 167                 kfree((unsigned int)buf);
 168                 return 0;
 169         }
 170         memcpy_b(buf + len, (char *)&procfs_array[lev], bytes);
 171         len += bytes;
 172         total_read = fd_table->offset = len;
 173         memcpy_b(buffer, buf, len);
 174         kfree((unsigned int)buf);
 175         return total_read;
 176 }
 177 
 178 int procfs_dir_open(struct inode *i, struct fd *fd_table)
 179 {
 180         fd_table->offset = 0;
 181         return 0;
 182 }
 183 
 184 int procfs_dir_close(struct inode *i, struct fd *fd_table)
 185 {
 186         return 0;
 187 }
 188 
 189 int procfs_dir_read(struct inode *i, struct fd *fd_table, char *buffer, __size_t count)
 190 {
 191         return -EISDIR;
 192 }
 193 
 194 int procfs_dir_readdir(struct inode *i, struct fd *fd_table, struct dirent *dirent, unsigned int count)
 195 {
 196         unsigned int offset, boffset, dirent_offset, doffset;
 197         int dirent_len;
 198         unsigned int total_read;
 199         struct procfs_dir_entry *d;
 200         int base_dirent_len;
 201         char *buffer;
 202         int lev;
 203 
 204         if(!(buffer = (void *)kmalloc())) {
 205                 return -ENOMEM;
 206         }
 207 
 208         lev = i->u.procfs.i_lev;
 209         base_dirent_len = sizeof(dirent->d_ino) + sizeof(dirent->d_off) + sizeof(dirent->d_reclen);
 210 
 211         offset = fd_table->offset;
 212         boffset = dirent_offset = doffset = 0;
 213 
 214         boffset = offset % PAGE_SIZE;
 215 
 216         total_read = dir_read(i, fd_table, buffer, PAGE_SIZE);
 217         if((count = MIN(total_read, count)) == 0) {
 218                 kfree((unsigned int)buffer);
 219                 return dirent_offset;
 220         }
 221 
 222         while(boffset < fd_table->offset) {
 223                 d = (struct procfs_dir_entry *)(buffer + boffset);
 224                 if(!d->inode) {
 225                         break;
 226                 }
 227                 dirent_len = (base_dirent_len + (d->name_len + 1)) + 3;
 228                 dirent_len &= ~3;       /* round up */
 229                 if((doffset + dirent_len) <= count) {
 230                         boffset += sizeof(struct procfs_dir_entry);
 231                         offset += sizeof(struct procfs_dir_entry);
 232                         doffset += dirent_len;
 233                         dirent->d_ino = d->inode;
 234                         dirent->d_off = offset;
 235                         dirent->d_reclen = dirent_len;
 236                         memcpy_b(dirent->d_name, d->name, d->name_len);
 237                         dirent->d_name[d->name_len] = NULL;
 238                         dirent = (struct dirent *)((char *)dirent + dirent_len);
 239                         dirent_offset += dirent_len;
 240                 } else {
 241                         break;
 242                 }
 243         }
 244         fd_table->offset = boffset;
 245         kfree((unsigned int)buffer);
 246         return dirent_offset;
 247 }

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