|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.