Annotation of qemu/roms/openbios/fs/grubfs/fsys_minix.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  GRUB  --  GRand Unified Bootloader
                      3:  *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
                      4:  *
                      5:  *  This program is free software; you can redistribute it and/or modify
                      6:  *  it under the terms of the GNU General Public License as published by
                      7:  *  the Free Software Foundation; either version 2 of the License, or
                      8:  *  (at your option) any later version.
                      9:  *
                     10:  *  This program is distributed in the hope that it will be useful,
                     11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:  *  GNU General Public License for more details.
                     14:  *
                     15:  *  You should have received a copy of the GNU General Public License
                     16:  *  along with this program; if not, write to the Free Software
                     17:  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
                     18:  *  MA 02110-1301, USA.
                     19:  */
                     20: 
                     21: /* Restrictions:
                     22:    This is MINIX V1 only (yet)
                     23:    Disk creation is like:
                     24:    mkfs.minix -c DEVICE
                     25: */
                     26: 
                     27: #ifdef FSYS_MINIX
                     28: 
                     29: #include "shared.h"
                     30: #include "filesys.h"
                     31: 
                     32: /* #define DEBUG_MINIX */
                     33: 
                     34: /* indirect blocks */
                     35: static int mapblock1, mapblock2, namelen;
                     36: 
                     37: /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
                     38: #define DEV_BSIZE 512
                     39: 
                     40: /* include/linux/fs.h */
                     41: #define BLOCK_SIZE_BITS 10
                     42: #define BLOCK_SIZE     (1<<BLOCK_SIZE_BITS)
                     43: 
                     44: /* made up, defaults to 1 but can be passed via mount_opts */
                     45: #define WHICH_SUPER 1
                     46: /* kind of from fs/ext2/super.c (is OK for minix) */
                     47: #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)  /* = 2 */
                     48: 
                     49: /* include/asm-i386/type.h */
                     50: typedef __signed__ char __s8;
                     51: typedef unsigned char __u8;
                     52: typedef __signed__ short __s16;
                     53: typedef unsigned short __u16;
                     54: typedef __signed__ int __s32;
                     55: typedef unsigned int __u32;
                     56: 
                     57: /* include/linux/minix_fs.h */
                     58: #define MINIX_ROOT_INO 1
                     59: 
                     60: /* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
                     61: #define MINIX_LINK_MAX  250
                     62: #define MINIX2_LINK_MAX 65530
                     63: 
                     64: #define MINIX_I_MAP_SLOTS       8
                     65: #define MINIX_Z_MAP_SLOTS       64
                     66: #define MINIX_SUPER_MAGIC       0x137F          /* original minix fs */
                     67: #define MINIX_SUPER_MAGIC2      0x138F          /* minix fs, 30 char names */
                     68: #define MINIX2_SUPER_MAGIC      0x2468          /* minix V2 fs */
                     69: #define MINIX2_SUPER_MAGIC2     0x2478          /* minix V2 fs, 30 char names */
                     70: #define MINIX_VALID_FS          0x0001          /* Clean fs. */
                     71: #define MINIX_ERROR_FS          0x0002          /* fs has errors. */
                     72: 
                     73: #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
                     74: #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
                     75: 
                     76: #define MINIX_V1                0x0001          /* original minix fs */
                     77: #define MINIX_V2                0x0002          /* minix V2 fs */
                     78: 
                     79: /* originally this is :
                     80: #define INODE_VERSION(inode)    inode->i_sb->u.minix_sb.s_version
                     81:    here we have */
                     82: #define INODE_VERSION(inode)   (SUPERBLOCK->s_version)
                     83: 
                     84: /*
                     85:  * This is the original minix inode layout on disk.
                     86:  * Note the 8-bit gid and atime and ctime.
                     87:  */
                     88: struct minix_inode {
                     89:        __u16 i_mode;
                     90:        __u16 i_uid;
                     91:        __u32 i_size;
                     92:        __u32 i_time;
                     93:        __u8  i_gid;
                     94:        __u8  i_nlinks;
                     95:        __u16 i_zone[9];
                     96: };
                     97: 
                     98: /*
                     99:  * The new minix inode has all the time entries, as well as
                    100:  * long block numbers and a third indirect block (7+1+1+1
                    101:  * instead of 7+1+1). Also, some previously 8-bit values are
                    102:  * now 16-bit. The inode is now 64 bytes instead of 32.
                    103:  */
                    104: struct minix2_inode {
                    105:        __u16 i_mode;
                    106:        __u16 i_nlinks;
                    107:        __u16 i_uid;
                    108:        __u16 i_gid;
                    109:        __u32 i_size;
                    110:        __u32 i_atime;
                    111:        __u32 i_mtime;
                    112:        __u32 i_ctime;
                    113:        __u32 i_zone[10];
                    114: };
                    115: 
                    116: /*
                    117:  * minix super-block data on disk
                    118:  */
                    119: struct minix_super_block {
                    120:         __u16 s_ninodes;
                    121:         __u16 s_nzones;
                    122:         __u16 s_imap_blocks;
                    123:         __u16 s_zmap_blocks;
                    124:         __u16 s_firstdatazone;
                    125:         __u16 s_log_zone_size;
                    126:         __u32 s_max_size;
                    127:         __u16 s_magic;
                    128:         __u16 s_state;
                    129:         __u32 s_zones;
                    130: };
                    131: 
                    132: struct minix_dir_entry {
                    133:         __u16 inode;
                    134:         char name[0];
                    135: };
                    136: 
                    137: /* made up, these are pointers into FSYS_BUF */
                    138: /* read once, always stays there: */
                    139: #define SUPERBLOCK \
                    140:     ((struct minix_super_block *)(FSYS_BUF))
                    141: #define INODE \
                    142:     ((struct minix_inode *)((char *) SUPERBLOCK + BLOCK_SIZE))
                    143: #define DATABLOCK1 \
                    144:     ((char *)((char *)INODE + sizeof(struct minix_inode)))
                    145: #define DATABLOCK2 \
                    146:     ((char *)((char *)DATABLOCK1 + BLOCK_SIZE))
                    147: 
                    148: /* linux/stat.h */
                    149: #define S_IFMT  00170000
                    150: #define S_IFLNK  0120000
                    151: #define S_IFREG  0100000
                    152: #define S_IFDIR  0040000
                    153: #define S_ISLNK(m)     (((m) & S_IFMT) == S_IFLNK)
                    154: #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
                    155: #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
                    156: 
                    157: #define PATH_MAX                1024   /* include/linux/limits.h */
                    158: #define MAX_LINK_COUNT             5   /* number of symbolic links to follow */
                    159: 
                    160: /* check filesystem types and read superblock into memory buffer */
                    161: int
                    162: minix_mount (void)
                    163: {
                    164:   if (((current_drive & 0x80) || current_slice != 0)
                    165:       && ! IS_PC_SLICE_TYPE_MINIX (current_slice)
                    166:       && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))
                    167:     return 0;                  /* The partition is not of MINIX type */
                    168: 
                    169:   if (part_length < (SBLOCK +
                    170:                     (sizeof (struct minix_super_block) / DEV_BSIZE)))
                    171:     return 0;                  /* The partition is too short */
                    172: 
                    173:   if (!devread (SBLOCK, 0, sizeof (struct minix_super_block),
                    174:                (char *) SUPERBLOCK))
                    175:     return 0;                  /* Cannot read superblock */
                    176: 
                    177:   switch (SUPERBLOCK->s_magic)
                    178:     {
                    179:     case MINIX_SUPER_MAGIC:
                    180:       namelen = 14;
                    181:       break;
                    182:     case MINIX_SUPER_MAGIC2:
                    183:       namelen = 30;
                    184:       break;
                    185:     default:
                    186:       return 0;                        /* Unsupported type */
                    187:     }
                    188: 
                    189:   return 1;
                    190: }
                    191: 
                    192: /* Takes a file system block number and reads it into BUFFER. */
                    193: static int
                    194: minix_rdfsb (int fsblock, char *buffer)
                    195: {
                    196:   return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0,
                    197:                  BLOCK_SIZE, buffer);
                    198: }
                    199: 
                    200: /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
                    201:    a physical block (the location in the file system) via an inode. */
                    202: static int
                    203: minix_block_map (int logical_block)
                    204: {
                    205:   int i;
                    206: 
                    207:   if (logical_block < 7)
                    208:     return INODE->i_zone[logical_block];
                    209: 
                    210:   logical_block -= 7;
                    211:   if (logical_block < 512)
                    212:     {
                    213:       i = INODE->i_zone[7];
                    214: 
                    215:       if (!i || ((mapblock1 != 1)
                    216:                 && !minix_rdfsb (i, DATABLOCK1)))
                    217:        {
                    218:          errnum = ERR_FSYS_CORRUPT;
                    219:          return -1;
                    220:        }
                    221:       mapblock1 = 1;
                    222:       return ((__u16 *) DATABLOCK1) [logical_block];
                    223:     }
                    224: 
                    225:   logical_block -= 512;
                    226:   i = INODE->i_zone[8];
                    227:   if (!i || ((mapblock1 != 2)
                    228:             && !minix_rdfsb (i, DATABLOCK1)))
                    229:     {
                    230:       errnum = ERR_FSYS_CORRUPT;
                    231:       return -1;
                    232:     }
                    233:   mapblock1 = 2;
                    234:   i = ((__u16 *) DATABLOCK1)[logical_block >> 9];
                    235:   if (!i || ((mapblock2 != i)
                    236:             && !minix_rdfsb (i, DATABLOCK2)))
                    237:     {
                    238:       errnum = ERR_FSYS_CORRUPT;
                    239:       return -1;
                    240:     }
                    241:   mapblock2 = i;
                    242:   return ((__u16 *) DATABLOCK2)[logical_block & 511];
                    243: }
                    244: 
                    245: /* read from INODE into BUF */
                    246: int
                    247: minix_read (char *buf, int len)
                    248: {
                    249:   int logical_block;
                    250:   int offset;
                    251:   int map;
                    252:   int ret = 0;
                    253:   int size = 0;
                    254: 
                    255:   while (len > 0)
                    256:     {
                    257:       /* find the (logical) block component of our location */
                    258:       logical_block = filepos >> BLOCK_SIZE_BITS;
                    259:       offset = filepos & (BLOCK_SIZE - 1);
                    260:       map = minix_block_map (logical_block);
                    261: #ifdef DEBUG_MINIX
                    262:       printf ("map=%d\n", map);
                    263: #endif
                    264:       if (map < 0)
                    265:        break;
                    266: 
                    267:       size = BLOCK_SIZE;
                    268:       size -= offset;
                    269:       if (size > len)
                    270:        size = len;
                    271: 
                    272:       disk_read_func = disk_read_hook;
                    273: 
                    274:       devread (map * (BLOCK_SIZE / DEV_BSIZE),
                    275:               offset, size, buf);
                    276: 
                    277:       disk_read_func = NULL;
                    278: 
                    279:       buf += size;
                    280:       len -= size;
                    281:       filepos += size;
                    282:       ret += size;
                    283:     }
                    284: 
                    285:   if (errnum)
                    286:     ret = 0;
                    287: 
                    288:   return ret;
                    289: }
                    290: 
                    291: /* preconditions: minix_mount already executed, therefore supblk in buffer
                    292:      known as SUPERBLOCK
                    293:    returns: 0 if error, nonzero iff we were able to find the file successfully
                    294:    postconditions: on a nonzero return, buffer known as INODE contains the
                    295:      inode of the file we were trying to look up
                    296:    side effects: none yet  */
                    297: int
                    298: minix_dir (char *dirname)
                    299: {
                    300:   int current_ino = MINIX_ROOT_INO;  /* start at the root */
                    301:   int updir_ino = current_ino;      /* the parent of the current directory */
                    302:   int ino_blk;                      /* fs pointer of the inode's info */
                    303: 
                    304:   int str_chk = 0;                  /* used ot hold the results of a string
                    305:                                        compare */
                    306: 
                    307:   struct minix_inode * raw_inode;    /* inode info for current_ino */
                    308: 
                    309:   char linkbuf[PATH_MAX];           /* buffer for following sym-links */
                    310:   int link_count = 0;
                    311: 
                    312:   char * rest;
                    313:   char ch;
                    314: 
                    315:   int off;                          /* offset within block of directory
                    316:                                        entry */
                    317:   int loc;                          /* location within a directory */
                    318:   int blk;                          /* which data blk within dir entry */
                    319:   long map;                         /* fs pointer of a particular block from
                    320:                                        dir entry */
                    321:   struct minix_dir_entry * dp;      /* pointer to directory entry */
                    322: 
                    323:   /* loop invariants:
                    324:      current_ino = inode to lookup
                    325:      dirname = pointer to filename component we are cur looking up within
                    326:      the directory known pointed to by current_ino (if any) */
                    327: 
                    328: #ifdef DEBUG_MINIX
                    329:   printf ("\n");
                    330: #endif
                    331: 
                    332:   while (1)
                    333:     {
                    334: #ifdef DEBUG_MINIX
                    335:       printf ("inode %d, dirname %s\n", current_ino, dirname);
                    336: #endif
                    337: 
                    338:       ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks
                    339:                 + (current_ino - 1) / MINIX_INODES_PER_BLOCK);
                    340:       if (! minix_rdfsb (ino_blk, (char *) INODE))
                    341:        return 0;
                    342: 
                    343:       /* reset indirect blocks! */
                    344:       mapblock2 = mapblock1 = -1;
                    345: 
                    346:       raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK);
                    347: 
                    348:       /* copy inode to fixed location */
                    349:       memmove ((void *) INODE, (void *) raw_inode,
                    350:               sizeof (struct minix_inode));
                    351: 
                    352:       /* If we've got a symbolic link, then chase it. */
                    353:       if (S_ISLNK (INODE->i_mode))
                    354:        {
                    355:          int len;
                    356: 
                    357:          if (++link_count > MAX_LINK_COUNT)
                    358:            {
                    359:              errnum = ERR_SYMLINK_LOOP;
                    360:              return 0;
                    361:            }
                    362: #ifdef DEBUG_MINIX
                    363:          printf ("S_ISLNK (%s)\n", dirname);
                    364: #endif
                    365: 
                    366:          /* Find out how long our remaining name is. */
                    367:          len = 0;
                    368:          while (dirname[len] && !isspace (dirname[len]))
                    369:            len++;
                    370: 
                    371:          /* Get the symlink size. */
                    372:          filemax = (INODE->i_size);
                    373:          if (filemax + len > sizeof (linkbuf) - 2)
                    374:            {
                    375:              errnum = ERR_FILELENGTH;
                    376:              return 0;
                    377:            }
                    378: 
                    379:          if (len)
                    380:            {
                    381:              /* Copy the remaining name to the end of the symlink data.
                    382:                 Note that DIRNAME and LINKBUF may overlap! */
                    383:              memmove (linkbuf + filemax, dirname, len);
                    384:            }
                    385:          linkbuf[filemax + len] = '\0';
                    386: 
                    387:          /* Read the necessary blocks, and reset the file pointer. */
                    388:          len = grub_read (linkbuf, filemax);
                    389:          filepos = 0;
                    390:          if (!len)
                    391:            return 0;
                    392: 
                    393: #ifdef DEBUG_MINIX
                    394:          printf ("symlink=%s\n", linkbuf);
                    395: #endif
                    396: 
                    397:          dirname = linkbuf;
                    398:          if (*dirname == '/')
                    399:            {
                    400:              /* It's an absolute link, so look it up in root. */
                    401:              current_ino = MINIX_ROOT_INO;
                    402:              updir_ino = current_ino;
                    403:            }
                    404:          else
                    405:            {
                    406:              /* Relative, so look it up in our parent directory. */
                    407:              current_ino = updir_ino;
                    408:            }
                    409: 
                    410:          /* Try again using the new name. */
                    411:          continue;
                    412:        }
                    413: 
                    414:       /* If end of filename, INODE points to the file's inode */
                    415:       if (!*dirname || isspace (*dirname))
                    416:        {
                    417:          if (!S_ISREG (INODE->i_mode))
                    418:            {
                    419:              errnum = ERR_BAD_FILETYPE;
                    420:              return 0;
                    421:            }
                    422: 
                    423:          filemax = (INODE->i_size);
                    424:          return 1;
                    425:        }
                    426: 
                    427:       /* else we have to traverse a directory */
                    428:       updir_ino = current_ino;
                    429: 
                    430:       /* skip over slashes */
                    431:       while (*dirname == '/')
                    432:        dirname++;
                    433: 
                    434:       /* if this isn't a directory of sufficient size to hold our file,
                    435:         abort */
                    436:       if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
                    437:        {
                    438:          errnum = ERR_BAD_FILETYPE;
                    439:          return 0;
                    440:        }
                    441: 
                    442:       /* skip to next slash or end of filename (space) */
                    443:       for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
                    444:           rest++);
                    445: 
                    446:       /* look through this directory and find the next filename component */
                    447:       /* invariant: rest points to slash after the next filename component */
                    448:       *rest = 0;
                    449:       loc = 0;
                    450: 
                    451:       do
                    452:        {
                    453: #ifdef DEBUG_MINIX
                    454:          printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc);
                    455: #endif
                    456: 
                    457:          /* if our location/byte offset into the directory exceeds the size,
                    458:             give up */
                    459:          if (loc >= INODE->i_size)
                    460:            {
                    461:              if (print_possibilities < 0)
                    462:                {
                    463: #if 0
                    464:                  putchar ('\n');
                    465: #endif
                    466:                }
                    467:              else
                    468:                {
                    469:                  errnum = ERR_FILE_NOT_FOUND;
                    470:                  *rest = ch;
                    471:                }
                    472:              return (print_possibilities < 0);
                    473:            }
                    474: 
                    475:          /* else, find the (logical) block component of our location */
                    476:          blk = loc >> BLOCK_SIZE_BITS;
                    477: 
                    478:          /* we know which logical block of the directory entry we are looking
                    479:             for, now we have to translate that to the physical (fs) block on
                    480:             the disk */
                    481:          map = minix_block_map (blk);
                    482: #ifdef DEBUG_MINIX
                    483:          printf ("fs block=%d\n", map);
                    484: #endif
                    485:          mapblock2 = -1;
                    486:          if ((map < 0) || !minix_rdfsb (map, DATABLOCK2))
                    487:            {
                    488:              errnum = ERR_FSYS_CORRUPT;
                    489:              *rest = ch;
                    490:              return 0;
                    491:            }
                    492:          off = loc & (BLOCK_SIZE - 1);
                    493:          dp = (struct minix_dir_entry *) (DATABLOCK2 + off);
                    494:          /* advance loc prematurely to next on-disk directory entry  */
                    495:          loc += sizeof (dp->inode) + namelen;
                    496: 
                    497:          /* NOTE: minix filenames are NULL terminated if < NAMELEN
                    498:             else exact */
                    499: 
                    500: #ifdef DEBUG_MINIX
                    501:          printf ("directory entry ino=%d\n", dp->inode);
                    502:          if (dp->inode)
                    503:            printf ("entry=%s\n", dp->name);
                    504: #endif
                    505: 
                    506:          if (dp->inode)
                    507:            {
                    508:              int saved_c = dp->name[namelen];
                    509: 
                    510:              dp->name[namelen] = 0;
                    511:              str_chk = substring (dirname, dp->name);
                    512: 
                    513: # ifndef STAGE1_5
                    514:              if (print_possibilities && ch != '/'
                    515:                  && (!*dirname || str_chk <= 0))
                    516:                {
                    517:                  if (print_possibilities > 0)
                    518:                    print_possibilities = -print_possibilities;
                    519:                  print_a_completion (dp->name);
                    520:                }
                    521: # endif
                    522: 
                    523:              dp->name[namelen] = saved_c;
                    524:            }
                    525: 
                    526:        }
                    527:       while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
                    528: 
                    529:       current_ino = dp->inode;
                    530:       *(dirname = rest) = ch;
                    531:     }
                    532:   /* never get here */
                    533: }
                    534: 
                    535: #endif /* FSYS_MINIX */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.