Annotation of qemu/roms/openbios/fs/grubfs/fsys_minix.c, revision 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.