The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/boot/rawfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      rawfs.c - Raw Minix file system support.        Author: Kees J. Bot
    2  *                                                              23 Dec 1991
    3  *                                           Based on readfs by Paul Polderman
    4  */
    5 #define nil 0
    6 #define _POSIX_SOURCE   1
    7 #define _MINIX          1
    8 #include <sys/types.h>
    9 #include <sys/stat.h>
   10 #include <stdlib.h>
   11 #include <limits.h>
   12 #include <string.h>
   13 #include <errno.h>
   14 #include <minix/config.h>
   15 #include <minix/const.h>
   16 #include <minix/type.h>
   17 #include <servers/fs/const.h>
   18 #include <servers/fs/type.h>
   19 #include <servers/fs/buf.h>
   20 #include <servers/fs/super.h>
   21 #include <servers/fs/inode.h>
   22 #include "rawfs.h"
   23 
   24 void readblock(off_t blockno, char *buf, int);
   25 
   26 /* The following code handles two file system types: Version 1 with small
   27  * inodes and 16-bit disk addresses and Version 2 with big inodes and 32-bit
   28  * disk addresses.
   29 #ifdef FLEX
   30  * To make matters worse, Minix-vmd knows about the normal Unix Version 7
   31  * directories and directories with flexible entries.
   32 #endif
   33  */
   34 
   35 /* File system parameters. */
   36 static unsigned nr_dzones;      /* Fill these in after reading superblock. */
   37 static unsigned nr_indirects;
   38 static unsigned inodes_per_block;
   39 static int block_size;
   40 #ifdef FLEX
   41 #include <dirent.h>
   42 #define direct _v7_direct
   43 #else
   44 #include <sys/dir.h>
   45 #endif
   46 
   47 #if __minix_vmd
   48 static struct v12_super_block super;    /* Superblock of file system */
   49 #define s_log_zone_size s_dummy         /* Zones are obsolete. */
   50 #else
   51 static struct super_block super;        /* Superblock of file system */
   52 #define SUPER_V1 SUPER_MAGIC            /* V1 magic has a weird name. */
   53 #endif
   54 
   55 static struct inode curfil;             /* Inode of file under examination */
   56 static char indir[MAX_BLOCK_SIZE];      /* Single indirect block. */
   57 static char dindir[MAX_BLOCK_SIZE];     /* Double indirect block. */
   58 static char dirbuf[MAX_BLOCK_SIZE];     /* Scratch/Directory block. */
   59 #define scratch dirbuf
   60 
   61 static block_t a_indir, a_dindir;       /* Addresses of the indirects. */
   62 static off_t dirpos;                    /* Reading pos in a dir. */
   63 
   64 #define fsbuf(b)        (* (struct buf *) (b))
   65 
   66 #define zone_shift      (super.s_log_zone_size) /* zone to block ratio */
   67 
   68 off_t r_super(int *bs)
   69 /* Initialize variables, return size of file system in blocks,
   70  * (zero on error).
   71  */
   72 {
   73         /* Read superblock. (The superblock is always at 1kB offset,
   74          * that's why we lie to readblock and say the block size is 1024
   75          * and we want block number 1 (the 'second block', at offset 1kB).)
   76          */
   77         readblock(1, scratch, 1024);
   78 
   79         memcpy(&super, scratch, sizeof(super));
   80 
   81         /* Is it really a MINIX file system ? */
   82         if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
   83                 if(super.s_magic == SUPER_V2)
   84                         super.s_block_size = 1024;
   85                 *bs = block_size = super.s_block_size;
   86                 if(block_size < MIN_BLOCK_SIZE ||
   87                         block_size > MAX_BLOCK_SIZE) {
   88                         return 0;
   89                 }
   90                 nr_dzones= V2_NR_DZONES;
   91                 nr_indirects= V2_INDIRECTS(block_size);
   92                 inodes_per_block= V2_INODES_PER_BLOCK(block_size);
   93                 return (off_t) super.s_zones << zone_shift;
   94         } else
   95         if (super.s_magic == SUPER_V1) {
   96                 *bs = block_size = 1024;
   97                 nr_dzones= V1_NR_DZONES;
   98                 nr_indirects= V1_INDIRECTS;
   99                 inodes_per_block= V1_INODES_PER_BLOCK;
  100                 return (off_t) super.s_nzones << zone_shift;
  101         } else {
  102                 /* Filesystem not recognized as Minix. */
  103                 return 0;
  104         }
  105 }
  106 
  107 void r_stat(Ino_t inum, struct stat *stp)
  108 /* Return information about a file like stat(2) and remember it. */
  109 {
  110         block_t block;
  111         block_t ino_block;
  112         ino_t ino_offset;
  113 
  114         /* Calculate start of i-list */
  115         block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
  116 
  117         /* Calculate block with inode inum */
  118         ino_block = ((inum - 1) / inodes_per_block);
  119         ino_offset = ((inum - 1) % inodes_per_block);
  120         block += ino_block;
  121 
  122         /* Fetch the block */
  123         readblock(block, scratch, block_size);
  124 
  125         if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
  126                 d2_inode *dip;
  127                 int i;
  128 
  129                 dip= &fsbuf(scratch).b_v2_ino[ino_offset];
  130 
  131                 curfil.i_mode= dip->d2_mode;
  132                 curfil.i_nlinks= dip->d2_nlinks;
  133                 curfil.i_uid= dip->d2_uid;
  134                 curfil.i_gid= dip->d2_gid;
  135                 curfil.i_size= dip->d2_size;
  136                 curfil.i_atime= dip->d2_atime;
  137                 curfil.i_mtime= dip->d2_mtime;
  138                 curfil.i_ctime= dip->d2_ctime;
  139                 for (i= 0; i < V2_NR_TZONES; i++)
  140                         curfil.i_zone[i]= dip->d2_zone[i];
  141         } else {
  142                 d1_inode *dip;
  143                 int i;
  144 
  145                 dip= &fsbuf(scratch).b_v1_ino[ino_offset];
  146 
  147                 curfil.i_mode= dip->d1_mode;
  148                 curfil.i_nlinks= dip->d1_nlinks;
  149                 curfil.i_uid= dip->d1_uid;
  150                 curfil.i_gid= dip->d1_gid;
  151                 curfil.i_size= dip->d1_size;
  152                 curfil.i_atime= dip->d1_mtime;
  153                 curfil.i_mtime= dip->d1_mtime;
  154                 curfil.i_ctime= dip->d1_mtime;
  155                 for (i= 0; i < V1_NR_TZONES; i++)
  156                         curfil.i_zone[i]= dip->d1_zone[i];
  157         }
  158         curfil.i_dev= -1;       /* Can't fill this in alas. */
  159         curfil.i_num= inum;
  160 
  161         stp->st_dev= curfil.i_dev;
  162         stp->st_ino= curfil.i_num;
  163         stp->st_mode= curfil.i_mode;
  164         stp->st_nlink= curfil.i_nlinks;
  165         stp->st_uid= curfil.i_uid;
  166         stp->st_gid= curfil.i_gid;
  167         stp->st_rdev= (dev_t) curfil.i_zone[0];
  168         stp->st_size= curfil.i_size;
  169         stp->st_atime= curfil.i_atime;
  170         stp->st_mtime= curfil.i_mtime;
  171         stp->st_ctime= curfil.i_ctime;
  172 
  173         a_indir= a_dindir= 0;
  174         dirpos= 0;
  175 }
  176 
  177 ino_t r_readdir(char *name)
  178 /* Read next directory entry at "dirpos" from file "curfil". */
  179 {
  180         ino_t inum= 0;
  181         int blkpos;
  182         struct direct *dp;
  183 
  184         if (!S_ISDIR(curfil.i_mode)) { errno= ENOTDIR; return -1; }
  185 
  186         if(!block_size) { errno = 0; return -1; }
  187 
  188         while (inum == 0 && dirpos < curfil.i_size) {
  189                 if ((blkpos= (int) (dirpos % block_size)) == 0) {
  190                         /* Need to fetch a new directory block. */
  191 
  192                         readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
  193                 }
  194 #ifdef FLEX
  195                 if (super.s_flags & S_FLEX) {
  196                         struct _fl_direct *dp;
  197 
  198                         dp= (struct _fl_direct *) (dirbuf + blkpos);
  199                         if ((inum= dp->d_ino) != 0) strcpy(name, dp->d_name);
  200 
  201                         dirpos+= (1 + dp->d_extent) * FL_DIR_ENTRY_SIZE;
  202                         continue;
  203                 }
  204 #endif
  205                 /* Let dp point to the next entry. */
  206                 dp= (struct direct *) (dirbuf + blkpos);
  207 
  208                 if ((inum= dp->d_ino) != 0) {
  209                         /* This entry is occupied, return name. */
  210                         strncpy(name, dp->d_name, sizeof(dp->d_name));
  211                         name[sizeof(dp->d_name)]= 0;
  212                 }
  213                 dirpos+= DIR_ENTRY_SIZE;
  214         }
  215         return inum;
  216 }
  217 
  218 off_t r_vir2abs(off_t virblk)
  219 /* Translate a block number in a file to an absolute disk block number.
  220  * Returns 0 for a hole and -1 if block is past end of file.
  221  */
  222 {
  223         block_t b= virblk;
  224         zone_t zone, ind_zone;
  225         block_t z, zone_index;
  226         int i;
  227 
  228         if(!block_size) return -1;
  229 
  230         /* Check if virblk within file. */
  231         if (virblk * block_size >= curfil.i_size) return -1;
  232 
  233         /* Calculate zone in which the datablock number is contained */
  234         zone = (zone_t) (b >> zone_shift);
  235 
  236         /* Calculate index of the block number in the zone */
  237         zone_index = b - ((block_t) zone << zone_shift);
  238 
  239         /* Go get the zone */
  240         if (zone < (zone_t) nr_dzones) {        /* direct block */
  241                 zone = curfil.i_zone[(int) zone];
  242                 z = ((block_t) zone << zone_shift) + zone_index;
  243                 return z;
  244         }
  245 
  246         /* The zone is not a direct one */
  247         zone -= (zone_t) nr_dzones;
  248 
  249         /* Is it single indirect ? */
  250         if (zone < (zone_t) nr_indirects) {     /* single indirect block */
  251                 ind_zone = curfil.i_zone[nr_dzones];
  252         } else {                        /* double indirect block */
  253                 /* Fetch the double indirect block */
  254                 if ((ind_zone = curfil.i_zone[nr_dzones + 1]) == 0) return 0;
  255 
  256                 z = (block_t) ind_zone << zone_shift;
  257                 if (a_dindir != z) {
  258                         readblock(z, dindir, block_size);
  259                         a_dindir= z;
  260                 }
  261                 /* Extract the indirect zone number from it */
  262                 zone -= (zone_t) nr_indirects;
  263 
  264                 i = zone / (zone_t) nr_indirects;
  265                 ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
  266                                 ? fsbuf(dindir).b_v2_ind[i]
  267                                 : fsbuf(dindir).b_v1_ind[i];
  268                 zone %= (zone_t) nr_indirects;
  269         }
  270         if (ind_zone == 0) return 0;
  271 
  272         /* Extract the datablock number from the indirect zone */
  273         z = (block_t) ind_zone << zone_shift;
  274         if (a_indir != z) {
  275                 readblock(z, indir, block_size);
  276                 a_indir= z;
  277         }
  278         zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
  279                 ? fsbuf(indir).b_v2_ind[(int) zone]
  280                 : fsbuf(indir).b_v1_ind[(int) zone];
  281 
  282         /* Calculate absolute datablock number */
  283         z = ((block_t) zone << zone_shift) + zone_index;
  284         return z;
  285 }
  286 
  287 ino_t r_lookup(Ino_t cwd, char *path)
  288 /* Translates a pathname to an inode number.  This is just a nice utility
  289  * function, it only needs r_stat and r_readdir.
  290  */
  291 {
  292         char name[NAME_MAX+1], r_name[NAME_MAX+1];
  293         char *n;
  294         struct stat st;
  295         ino_t ino;
  296 
  297         ino= path[0] == '/' ? ROOT_INO : cwd;
  298 
  299         for (;;) {
  300                 if (ino == 0) {
  301                         errno= ENOENT;
  302                         return 0;
  303                 }
  304 
  305                 while (*path == '/') path++;
  306 
  307                 if (*path == 0) return ino;
  308 
  309                 r_stat(ino, &st);
  310 
  311                 if (!S_ISDIR(st.st_mode)) {
  312                         errno= ENOTDIR;
  313                         return 0;
  314                 }
  315 
  316                 n= name;
  317                 while (*path != 0 && *path != '/')
  318                         if (n < name + NAME_MAX) *n++ = *path++;
  319                 *n= 0;
  320 
  321                 while ((ino= r_readdir(r_name)) != 0
  322                                         && strcmp(name, r_name) != 0) {
  323                 }
  324         }
  325 }
  326 
  327 /*
  328  * $PchId: rawfs.c,v 1.8 1999/11/05 23:14:15 philip Exp $
  329  */

Cache object: c1827abce3a03471bc48592266196616


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.