2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
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.
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.
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,
22 This is MINIX V1 only (yet)
23 Disk creation is like:
32 /* #define DEBUG_MINIX */
35 static int mapblock1, mapblock2, namelen;
37 /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
40 /* include/linux/fs.h */
41 #define BLOCK_SIZE_BITS 10
42 #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
44 /* made up, defaults to 1 but can be passed via mount_opts */
46 /* kind of from fs/ext2/super.c (is OK for minix) */
47 #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */
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;
57 /* include/linux/minix_fs.h */
58 #define MINIX_ROOT_INO 1
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
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. */
73 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
74 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
76 #define MINIX_V1 0x0001 /* original minix fs */
77 #define MINIX_V2 0x0002 /* minix V2 fs */
79 /* originally this is :
80 #define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version
82 #define INODE_VERSION(inode) (SUPERBLOCK->s_version)
85 * This is the original minix inode layout on disk.
86 * Note the 8-bit gid and atime and ctime.
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.
104 struct minix2_inode {
117 * minix super-block data on disk
119 struct minix_super_block {
124 __u16 s_firstdatazone;
125 __u16 s_log_zone_size;
132 struct minix_dir_entry {
137 /* made up, these are pointers into FSYS_BUF */
138 /* read once, always stays there: */
140 ((struct minix_super_block *)(FSYS_BUF))
142 ((struct minix_inode *)((char *) SUPERBLOCK + BLOCK_SIZE))
144 ((char *)((char *)INODE + sizeof(struct minix_inode)))
146 ((char *)((char *)DATABLOCK1 + BLOCK_SIZE))
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)
157 #define PATH_MAX 1024 /* include/linux/limits.h */
158 #define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
160 /* check filesystem types and read superblock into memory buffer */
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 */
169 if (part_length < (SBLOCK +
170 (sizeof (struct minix_super_block) / DEV_BSIZE)))
171 return 0; /* The partition is too short */
173 if (!devread (SBLOCK, 0, sizeof (struct minix_super_block),
174 (char *) SUPERBLOCK))
175 return 0; /* Cannot read superblock */
177 switch (SUPERBLOCK->s_magic)
179 case MINIX_SUPER_MAGIC:
182 case MINIX_SUPER_MAGIC2:
186 return 0; /* Unsupported type */
192 /* Takes a file system block number and reads it into BUFFER. */
194 minix_rdfsb (int fsblock, char *buffer)
196 return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0,
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. */
203 minix_block_map (int logical_block)
207 if (logical_block < 7)
208 return INODE->i_zone[logical_block];
211 if (logical_block < 512)
213 i = INODE->i_zone[7];
215 if (!i || ((mapblock1 != 1)
216 && !minix_rdfsb (i, DATABLOCK1)))
218 errnum = ERR_FSYS_CORRUPT;
222 return ((__u16 *) DATABLOCK1) [logical_block];
225 logical_block -= 512;
226 i = INODE->i_zone[8];
227 if (!i || ((mapblock1 != 2)
228 && !minix_rdfsb (i, DATABLOCK1)))
230 errnum = ERR_FSYS_CORRUPT;
234 i = ((__u16 *) DATABLOCK1)[logical_block >> 9];
235 if (!i || ((mapblock2 != i)
236 && !minix_rdfsb (i, DATABLOCK2)))
238 errnum = ERR_FSYS_CORRUPT;
242 return ((__u16 *) DATABLOCK2)[logical_block & 511];
245 /* read from INODE into BUF */
247 minix_read (char *buf, int len)
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);
262 printf ("map=%d\n", map);
272 disk_read_func = disk_read_hook;
274 devread (map * (BLOCK_SIZE / DEV_BSIZE),
277 disk_read_func = NULL;
291 /* preconditions: minix_mount already executed, therefore supblk in buffer
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 */
298 minix_dir (char *dirname)
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 */
304 int str_chk = 0; /* used ot hold the results of a string
307 struct minix_inode * raw_inode; /* inode info for current_ino */
309 char linkbuf[PATH_MAX]; /* buffer for following sym-links */
315 int off; /* offset within block of directory
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
321 struct minix_dir_entry * dp; /* pointer to directory entry */
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) */
335 printf ("inode %d, dirname %s\n", current_ino, dirname);
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))
343 /* reset indirect blocks! */
344 mapblock2 = mapblock1 = -1;
346 raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK);
348 /* copy inode to fixed location */
349 memmove ((void *) INODE, (void *) raw_inode,
350 sizeof (struct minix_inode));
352 /* If we've got a symbolic link, then chase it. */
353 if (S_ISLNK (INODE->i_mode))
357 if (++link_count > MAX_LINK_COUNT)
359 errnum = ERR_SYMLINK_LOOP;
363 printf ("S_ISLNK (%s)\n", dirname);
366 /* Find out how long our remaining name is. */
368 while (dirname[len] && !isspace (dirname[len]))
371 /* Get the symlink size. */
372 filemax = (INODE->i_size);
373 if (filemax + len > sizeof (linkbuf) - 2)
375 errnum = ERR_FILELENGTH;
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);
385 linkbuf[filemax + len] = '\0';
387 /* Read the necessary blocks, and reset the file pointer. */
388 len = grub_read (linkbuf, filemax);
394 printf ("symlink=%s\n", linkbuf);
400 /* It's an absolute link, so look it up in root. */
401 current_ino = MINIX_ROOT_INO;
402 updir_ino = current_ino;
406 /* Relative, so look it up in our parent directory. */
407 current_ino = updir_ino;
410 /* Try again using the new name. */
414 /* If end of filename, INODE points to the file's inode */
415 if (!*dirname || isspace (*dirname))
417 if (!S_ISREG (INODE->i_mode))
419 errnum = ERR_BAD_FILETYPE;
423 filemax = (INODE->i_size);
427 /* else we have to traverse a directory */
428 updir_ino = current_ino;
430 /* skip over slashes */
431 while (*dirname == '/')
434 /* if this isn't a directory of sufficient size to hold our file,
436 if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
438 errnum = ERR_BAD_FILETYPE;
442 /* skip to next slash or end of filename (space) */
443 for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
446 /* look through this directory and find the next filename component */
447 /* invariant: rest points to slash after the next filename component */
454 printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc);
457 /* if our location/byte offset into the directory exceeds the size,
459 if (loc >= INODE->i_size)
461 if (print_possibilities < 0)
469 errnum = ERR_FILE_NOT_FOUND;
472 return (print_possibilities < 0);
475 /* else, find the (logical) block component of our location */
476 blk = loc >> BLOCK_SIZE_BITS;
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
481 map = minix_block_map (blk);
483 printf ("fs block=%d\n", map);
486 if ((map < 0) || !minix_rdfsb (map, DATABLOCK2))
488 errnum = ERR_FSYS_CORRUPT;
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;
497 /* NOTE: minix filenames are NULL terminated if < NAMELEN
501 printf ("directory entry ino=%d\n", dp->inode);
503 printf ("entry=%s\n", dp->name);
508 int saved_c = dp->name[namelen];
510 dp->name[namelen] = 0;
511 str_chk = substring (dirname, dp->name);
514 if (print_possibilities && ch != '/'
515 && (!*dirname || str_chk <= 0))
517 if (print_possibilities > 0)
518 print_possibilities = -print_possibilities;
519 print_a_completion (dp->name);
523 dp->name[namelen] = saved_c;
527 while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
529 current_ino = dp->inode;
530 *(dirname = rest) = ch;
535 #endif /* FSYS_MINIX */