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., 675 Mass Ave, Cambridge, MA 02139, USA.
21 This is MINIX V1 only (yet)
22 Disk creation is like:
31 /* #define DEBUG_MINIX */
34 static int mapblock1
, mapblock2
, namelen
;
36 /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
39 /* include/linux/fs.h */
40 #define BLOCK_SIZE_BITS 10
41 #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
43 /* made up, defaults to 1 but can be passed via mount_opts */
45 /* kind of from fs/ext2/super.c (is OK for minix) */
46 #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */
48 /* include/asm-i386/type.h */
49 typedef __signed__
char __s8
;
50 typedef unsigned char __u8
;
51 typedef __signed__
short __s16
;
52 typedef unsigned short __u16
;
53 typedef __signed__
int __s32
;
54 typedef unsigned int __u32
;
56 /* include/linux/minix_fs.h */
57 #define MINIX_ROOT_INO 1
59 /* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
60 #define MINIX_LINK_MAX 250
61 #define MINIX2_LINK_MAX 65530
63 #define MINIX_I_MAP_SLOTS 8
64 #define MINIX_Z_MAP_SLOTS 64
65 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
66 #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
67 #define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */
68 #define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
69 #define MINIX_VALID_FS 0x0001 /* Clean fs. */
70 #define MINIX_ERROR_FS 0x0002 /* fs has errors. */
72 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
73 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
75 #define MINIX_V1 0x0001 /* original minix fs */
76 #define MINIX_V2 0x0002 /* minix V2 fs */
78 /* originally this is :
79 #define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version
81 #define INODE_VERSION(inode) (SUPERBLOCK->s_version)
84 * This is the original minix inode layout on disk.
85 * Note the 8-bit gid and atime and ctime.
98 * The new minix inode has all the time entries, as well as
99 * long block numbers and a third indirect block (7+1+1+1
100 * instead of 7+1+1). Also, some previously 8-bit values are
101 * now 16-bit. The inode is now 64 bytes instead of 32.
103 struct minix2_inode
{
116 * minix super-block data on disk
118 struct minix_super_block
{
123 __u16 s_firstdatazone
;
124 __u16 s_log_zone_size
;
131 struct minix_dir_entry
{
136 /* made up, these are pointers into FSYS_BUF */
137 /* read once, always stays there: */
139 ((struct minix_super_block *)(FSYS_BUF))
141 ((struct minix_inode *)((int) SUPERBLOCK + BLOCK_SIZE))
143 ((int)((int)INODE + sizeof(struct minix_inode)))
145 ((int)((int)DATABLOCK1 + BLOCK_SIZE))
148 #define S_IFMT 00170000
149 #define S_IFLNK 0120000
150 #define S_IFREG 0100000
151 #define S_IFDIR 0040000
152 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
153 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
154 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
156 #define PATH_MAX 1024 /* include/linux/limits.h */
157 #define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
159 /* check filesystem types and read superblock into memory buffer */
163 if (((current_drive
& 0x80) || current_slice
!= 0)
164 && ! IS_PC_SLICE_TYPE_MINIX (current_slice
)
165 && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice
, FS_OTHER
))
166 return 0; /* The partition is not of MINIX type */
168 if (part_length
< (SBLOCK
+
169 (sizeof (struct minix_super_block
) / DEV_BSIZE
)))
170 return 0; /* The partition is too short */
172 if (!devread (SBLOCK
, 0, sizeof (struct minix_super_block
),
173 (char *) SUPERBLOCK
))
174 return 0; /* Cannot read superblock */
176 switch (SUPERBLOCK
->s_magic
)
178 case MINIX_SUPER_MAGIC
:
181 case MINIX_SUPER_MAGIC2
:
185 return 0; /* Unsupported type */
191 /* Takes a file system block number and reads it into BUFFER. */
193 minix_rdfsb (int fsblock
, int buffer
)
195 return devread (fsblock
* (BLOCK_SIZE
/ DEV_BSIZE
), 0,
196 BLOCK_SIZE
, (char *) buffer
);
199 /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
200 a physical block (the location in the file system) via an inode. */
202 minix_block_map (int logical_block
)
206 if (logical_block
< 7)
207 return INODE
->i_zone
[logical_block
];
210 if (logical_block
< 512)
212 i
= INODE
->i_zone
[7];
214 if (!i
|| ((mapblock1
!= 1)
215 && !minix_rdfsb (i
, DATABLOCK1
)))
217 errnum
= ERR_FSYS_CORRUPT
;
221 return ((__u16
*) DATABLOCK1
) [logical_block
];
224 logical_block
-= 512;
225 i
= INODE
->i_zone
[8];
226 if (!i
|| ((mapblock1
!= 2)
227 && !minix_rdfsb (i
, DATABLOCK1
)))
229 errnum
= ERR_FSYS_CORRUPT
;
233 i
= ((__u16
*) DATABLOCK1
)[logical_block
>> 9];
234 if (!i
|| ((mapblock2
!= i
)
235 && !minix_rdfsb (i
, DATABLOCK2
)))
237 errnum
= ERR_FSYS_CORRUPT
;
241 return ((__u16
*) DATABLOCK2
)[logical_block
& 511];
244 /* read from INODE into BUF */
246 minix_read (char *buf
, int len
)
256 /* find the (logical) block component of our location */
257 logical_block
= filepos
>> BLOCK_SIZE_BITS
;
258 offset
= filepos
& (BLOCK_SIZE
- 1);
259 map
= minix_block_map (logical_block
);
261 printf ("map=%d\n", map
);
271 disk_read_func
= disk_read_hook
;
273 devread (map
* (BLOCK_SIZE
/ DEV_BSIZE
),
276 disk_read_func
= NULL
;
290 /* preconditions: minix_mount already executed, therefore supblk in buffer
292 returns: 0 if error, nonzero iff we were able to find the file successfully
293 postconditions: on a nonzero return, buffer known as INODE contains the
294 inode of the file we were trying to look up
295 side effects: none yet */
297 minix_dir (char *dirname
)
299 int current_ino
= MINIX_ROOT_INO
; /* start at the root */
300 int updir_ino
= current_ino
; /* the parent of the current directory */
301 int ino_blk
; /* fs pointer of the inode's info */
303 int str_chk
= 0; /* used ot hold the results of a string
306 struct minix_inode
* raw_inode
; /* inode info for current_ino */
308 char linkbuf
[PATH_MAX
]; /* buffer for following sym-links */
314 int off
; /* offset within block of directory
316 int loc
; /* location within a directory */
317 int blk
; /* which data blk within dir entry */
318 long map
; /* fs pointer of a particular block from
320 struct minix_dir_entry
* dp
; /* pointer to directory entry */
323 current_ino = inode to lookup
324 dirname = pointer to filename component we are cur looking up within
325 the directory known pointed to by current_ino (if any) */
334 printf ("inode %d, dirname %s\n", current_ino
, dirname
);
337 ino_blk
= (2 + SUPERBLOCK
->s_imap_blocks
+ SUPERBLOCK
->s_zmap_blocks
338 + (current_ino
- 1) / MINIX_INODES_PER_BLOCK
);
339 if (! minix_rdfsb (ino_blk
, (int) INODE
))
342 /* reset indirect blocks! */
343 mapblock2
= mapblock1
= -1;
345 raw_inode
= INODE
+ ((current_ino
- 1) % MINIX_INODES_PER_BLOCK
);
347 /* copy inode to fixed location */
348 memmove ((void *) INODE
, (void *) raw_inode
,
349 sizeof (struct minix_inode
));
351 /* If we've got a symbolic link, then chase it. */
352 if (S_ISLNK (INODE
->i_mode
))
356 if (++link_count
> MAX_LINK_COUNT
)
358 errnum
= ERR_SYMLINK_LOOP
;
362 printf ("S_ISLNK (%s)\n", dirname
);
365 /* Find out how long our remaining name is. */
367 while (dirname
[len
] && !isspace (dirname
[len
]))
370 /* Get the symlink size. */
371 filemax
= (INODE
->i_size
);
372 if (filemax
+ len
> sizeof (linkbuf
) - 2)
374 errnum
= ERR_FILELENGTH
;
380 /* Copy the remaining name to the end of the symlink data.
381 Note that DIRNAME and LINKBUF may overlap! */
382 memmove (linkbuf
+ filemax
, dirname
, len
);
384 linkbuf
[filemax
+ len
] = '\0';
386 /* Read the necessary blocks, and reset the file pointer. */
387 len
= grub_read (linkbuf
, filemax
);
393 printf ("symlink=%s\n", linkbuf
);
399 /* It's an absolute link, so look it up in root. */
400 current_ino
= MINIX_ROOT_INO
;
401 updir_ino
= current_ino
;
405 /* Relative, so look it up in our parent directory. */
406 current_ino
= updir_ino
;
409 /* Try again using the new name. */
413 /* If end of filename, INODE points to the file's inode */
414 if (!*dirname
|| isspace (*dirname
))
416 if (!S_ISREG (INODE
->i_mode
))
418 errnum
= ERR_BAD_FILETYPE
;
422 filemax
= (INODE
->i_size
);
426 /* else we have to traverse a directory */
427 updir_ino
= current_ino
;
429 /* skip over slashes */
430 while (*dirname
== '/')
433 /* if this isn't a directory of sufficient size to hold our file,
435 if (!(INODE
->i_size
) || !S_ISDIR (INODE
->i_mode
))
437 errnum
= ERR_BAD_FILETYPE
;
441 /* skip to next slash or end of filename (space) */
442 for (rest
= dirname
; (ch
= *rest
) && !isspace (ch
) && ch
!= '/';
445 /* look through this directory and find the next filename component */
446 /* invariant: rest points to slash after the next filename component */
453 printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname
, rest
, loc
);
456 /* if our location/byte offset into the directory exceeds the size,
458 if (loc
>= INODE
->i_size
)
460 if (print_possibilities
< 0)
468 errnum
= ERR_FILE_NOT_FOUND
;
471 return (print_possibilities
< 0);
474 /* else, find the (logical) block component of our location */
475 blk
= loc
>> BLOCK_SIZE_BITS
;
477 /* we know which logical block of the directory entry we are looking
478 for, now we have to translate that to the physical (fs) block on
480 map
= minix_block_map (blk
);
482 printf ("fs block=%d\n", map
);
485 if ((map
< 0) || !minix_rdfsb (map
, DATABLOCK2
))
487 errnum
= ERR_FSYS_CORRUPT
;
491 off
= loc
& (BLOCK_SIZE
- 1);
492 dp
= (struct minix_dir_entry
*) (DATABLOCK2
+ off
);
493 /* advance loc prematurely to next on-disk directory entry */
494 loc
+= sizeof (dp
->inode
) + namelen
;
496 /* NOTE: minix filenames are NULL terminated if < NAMELEN
500 printf ("directory entry ino=%d\n", dp
->inode
);
502 printf ("entry=%s\n", dp
->name
);
507 int saved_c
= dp
->name
[namelen
];
509 dp
->name
[namelen
] = 0;
510 str_chk
= substring (dirname
, dp
->name
);
513 if (print_possibilities
&& ch
!= '/'
514 && (!*dirname
|| str_chk
<= 0))
516 if (print_possibilities
> 0)
517 print_possibilities
= -print_possibilities
;
518 print_a_completion (dp
->name
);
522 dp
->name
[namelen
] = saved_c
;
526 while (!dp
->inode
|| (str_chk
|| (print_possibilities
&& ch
!= '/')));
528 current_ino
= dp
->inode
;
529 *(dirname
= rest
) = ch
;
534 #endif /* FSYS_MINIX */