15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GRUB  --  GRand Unified Bootloader
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is free software; you can redistribute it and/or modify
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  it under the terms of the GNU General Public License as published by
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  the Free Software Foundation; either version 2 of the License, or
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  (at your option) any later version.
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is distributed in the hope that it will be useful,
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GNU General Public License for more details.
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  You should have received a copy of the GNU General Public License
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  along with this program; if not, write to the Free Software
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Restrictions:
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   This is MINIX V1 only (yet)
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Disk creation is like:
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   mkfs.minix -c DEVICE
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef FSYS_MINIX
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "shared.h"
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "filesys.h"
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* #define DEBUG_MINIX */
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* indirect blocks */
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int mapblock1, mapblock2, namelen;
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DEV_BSIZE 512
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/linux/fs.h */
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define BLOCK_SIZE_BITS 10
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define BLOCK_SIZE 	(1<<BLOCK_SIZE_BITS)
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* made up, defaults to 1 but can be passed via mount_opts */
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define WHICH_SUPER 1
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* kind of from fs/ext2/super.c (is OK for minix) */
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)	/* = 2 */
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/asm-i386/type.h */
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef __signed__ char __s8;
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned char __u8;
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef __signed__ short __s16;
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned short __u16;
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef __signed__ int __s32;
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned int __u32;
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* include/linux/minix_fs.h */
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_ROOT_INO 1
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_LINK_MAX  250
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX2_LINK_MAX 65530
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_I_MAP_SLOTS       8
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_Z_MAP_SLOTS       64
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_SUPER_MAGIC       0x137F          /* original minix fs */
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_SUPER_MAGIC2      0x138F          /* minix fs, 30 char names */
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX2_SUPER_MAGIC      0x2468          /* minix V2 fs */
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX2_SUPER_MAGIC2     0x2478          /* minix V2 fs, 30 char names */
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_VALID_FS          0x0001          /* Clean fs. */
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_ERROR_FS          0x0002          /* fs has errors. */
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_V1                0x0001          /* original minix fs */
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MINIX_V2                0x0002          /* minix V2 fs */
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* originally this is :
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define INODE_VERSION(inode)    inode->i_sb->u.minix_sb.s_version
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   here we have */
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define INODE_VERSION(inode)	(SUPERBLOCK->s_version)
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * This is the original minix inode layout on disk.
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Note the 8-bit gid and atime and ctime.
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct minix_inode {
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_mode;
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_uid;
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_size;
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_time;
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u8  i_gid;
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u8  i_nlinks;
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_zone[9];
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * The new minix inode has all the time entries, as well as
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * long block numbers and a third indirect block (7+1+1+1
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * instead of 7+1+1). Also, some previously 8-bit values are
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * now 16-bit. The inode is now 64 bytes instead of 32.
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct minix2_inode {
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_mode;
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_nlinks;
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_uid;
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u16 i_gid;
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_size;
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_atime;
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_mtime;
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_ctime;
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	__u32 i_zone[10];
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * minix super-block data on disk
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct minix_super_block {
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_ninodes;
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_nzones;
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_imap_blocks;
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_zmap_blocks;
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_firstdatazone;
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_log_zone_size;
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u32 s_max_size;
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_magic;
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 s_state;
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u32 s_zones;
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct minix_dir_entry {
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        __u16 inode;
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        char name[0];
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* made up, these are pointers into FSYS_BUF */
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* read once, always stays there: */
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define SUPERBLOCK \
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((struct minix_super_block *)(FSYS_BUF))
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define INODE \
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((struct minix_inode *)((int) SUPERBLOCK + BLOCK_SIZE))
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DATABLOCK1 \
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((int)((int)INODE + sizeof(struct minix_inode)))
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DATABLOCK2 \
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ((int)((int)DATABLOCK1 + BLOCK_SIZE))
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* linux/stat.h */
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFMT  00170000
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFLNK  0120000
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFREG  0100000
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_IFDIR  0040000
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define PATH_MAX                1024	/* include/linux/limits.h */
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MAX_LINK_COUNT             5	/* number of symbolic links to follow */
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* check filesystem types and read superblock into memory buffer */
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectminix_mount (void)
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (((current_drive & 0x80) || current_slice != 0)
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      && ! IS_PC_SLICE_TYPE_MINIX (current_slice)
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;			/* The partition is not of MINIX type */
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (part_length < (SBLOCK +
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		     (sizeof (struct minix_super_block) / DEV_BSIZE)))
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;			/* The partition is too short */
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!devread (SBLOCK, 0, sizeof (struct minix_super_block),
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		(char *) SUPERBLOCK))
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;			/* Cannot read superblock */
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  switch (SUPERBLOCK->s_magic)
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case MINIX_SUPER_MAGIC:
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      namelen = 14;
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      break;
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case MINIX_SUPER_MAGIC2:
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      namelen = 30;
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      break;
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    default:
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return 0;			/* Unsupported type */
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 1;
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Takes a file system block number and reads it into BUFFER. */
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectminix_rdfsb (int fsblock, int buffer)
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0,
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  BLOCK_SIZE, (char *) buffer);
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   a physical block (the location in the file system) via an inode. */
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectminix_block_map (int logical_block)
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int i;
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (logical_block < 7)
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return INODE->i_zone[logical_block];
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  logical_block -= 7;
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (logical_block < 512)
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      i = INODE->i_zone[7];
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!i || ((mapblock1 != 1)
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 && !minix_rdfsb (i, DATABLOCK1)))
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_FSYS_CORRUPT;
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return -1;
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock1 = 1;
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return ((__u16 *) DATABLOCK1) [logical_block];
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  logical_block -= 512;
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  i = INODE->i_zone[8];
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!i || ((mapblock1 != 2)
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     && !minix_rdfsb (i, DATABLOCK1)))
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_FSYS_CORRUPT;
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return -1;
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mapblock1 = 2;
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  i = ((__u16 *) DATABLOCK1)[logical_block >> 9];
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!i || ((mapblock2 != i)
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     && !minix_rdfsb (i, DATABLOCK2)))
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_FSYS_CORRUPT;
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return -1;
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mapblock2 = i;
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ((__u16 *) DATABLOCK2)[logical_block & 511];
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* read from INODE into BUF */
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectminix_read (char *buf, int len)
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int logical_block;
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int offset;
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int map;
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ret = 0;
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int size = 0;
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (len > 0)
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* find the (logical) block component of our location */
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      logical_block = filepos >> BLOCK_SIZE_BITS;
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      offset = filepos & (BLOCK_SIZE - 1);
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      map = minix_block_map (logical_block);
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("map=%d\n", map);
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (map < 0)
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	break;
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      size = BLOCK_SIZE;
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      size -= offset;
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (size > len)
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	size = len;
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      disk_read_func = disk_read_hook;
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      devread (map * (BLOCK_SIZE / DEV_BSIZE),
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       offset, size, buf);
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      disk_read_func = NULL;
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      buf += size;
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      len -= size;
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      filepos += size;
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      ret += size;
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (errnum)
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ret = 0;
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ret;
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* preconditions: minix_mount already executed, therefore supblk in buffer
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     known as SUPERBLOCK
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   returns: 0 if error, nonzero iff we were able to find the file successfully
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   postconditions: on a nonzero return, buffer known as INODE contains the
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     inode of the file we were trying to look up
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   side effects: none yet  */
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectminix_dir (char *dirname)
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int current_ino = MINIX_ROOT_INO;  /* start at the root */
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int updir_ino = current_ino;	     /* the parent of the current directory */
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ino_blk;			     /* fs pointer of the inode's info */
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int str_chk = 0;		     /* used ot hold the results of a string
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				        compare */
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct minix_inode * raw_inode;    /* inode info for current_ino */
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char linkbuf[PATH_MAX];	     /* buffer for following sym-links */
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int link_count = 0;
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char * rest;
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char ch;
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int off;			     /* offset within block of directory
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					entry */
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int loc;			     /* location within a directory */
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int blk;			     /* which data blk within dir entry */
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  long map;			     /* fs pointer of a particular block from
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					dir entry */
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct minix_dir_entry * dp;	     /* pointer to directory entry */
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* loop invariants:
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     current_ino = inode to lookup
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     dirname = pointer to filename component we are cur looking up within
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     the directory known pointed to by current_ino (if any) */
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  printf ("\n");
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (1)
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf ("inode %d, dirname %s\n", current_ino, dirname);
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 + (current_ino - 1) / MINIX_INODES_PER_BLOCK);
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! minix_rdfsb (ino_blk, (int) INODE))
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return 0;
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* reset indirect blocks! */
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock2 = mapblock1 = -1;
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK);
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* copy inode to fixed location */
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      memmove ((void *) INODE, (void *) raw_inode,
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       sizeof (struct minix_inode));
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If we've got a symbolic link, then chase it. */
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (S_ISLNK (INODE->i_mode))
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  int len;
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (++link_count > MAX_LINK_COUNT)
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_SYMLINK_LOOP;
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("S_ISLNK (%s)\n", dirname);
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Find out how long our remaining name is. */
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  len = 0;
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  while (dirname[len] && !isspace (dirname[len]))
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    len++;
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Get the symlink size. */
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filemax = (INODE->i_size);
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (filemax + len > sizeof (linkbuf) - 2)
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_FILELENGTH;
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (len)
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Copy the remaining name to the end of the symlink data.
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	         Note that DIRNAME and LINKBUF may overlap! */
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      memmove (linkbuf + filemax, dirname, len);
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  linkbuf[filemax + len] = '\0';
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Read the necessary blocks, and reset the file pointer. */
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  len = grub_read (linkbuf, filemax);
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filepos = 0;
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (!len)
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    return 0;
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("symlink=%s\n", linkbuf);
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  dirname = linkbuf;
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (*dirname == '/')
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* It's an absolute link, so look it up in root. */
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      current_ino = MINIX_ROOT_INO;
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      updir_ino = current_ino;
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Relative, so look it up in our parent directory. */
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      current_ino = updir_ino;
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Try again using the new name. */
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  continue;
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If end of filename, INODE points to the file's inode */
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!*dirname || isspace (*dirname))
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (!S_ISREG (INODE->i_mode))
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_BAD_FILETYPE;
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filemax = (INODE->i_size);
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 1;
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* else we have to traverse a directory */
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      updir_ino = current_ino;
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* skip over slashes */
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      while (*dirname == '/')
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	dirname++;
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* if this isn't a directory of sufficient size to hold our file,
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 abort */
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_BAD_FILETYPE;
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* skip to next slash or end of filename (space) */
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   rest++);
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* look through this directory and find the next filename component */
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* invariant: rest points to slash after the next filename component */
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      *rest = 0;
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      loc = 0;
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      do
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc);
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* if our location/byte offset into the directory exceeds the size,
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     give up */
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (loc >= INODE->i_size)
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (print_possibilities < 0)
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if 0
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  putchar ('\n');
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  errnum = ERR_FILE_NOT_FOUND;
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  *rest = ch;
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return (print_possibilities < 0);
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* else, find the (logical) block component of our location */
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  blk = loc >> BLOCK_SIZE_BITS;
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* we know which logical block of the directory entry we are looking
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     for, now we have to translate that to the physical (fs) block on
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     the disk */
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  map = minix_block_map (blk);
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("fs block=%d\n", map);
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  mapblock2 = -1;
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if ((map < 0) || !minix_rdfsb (map, DATABLOCK2))
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_FSYS_CORRUPT;
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      *rest = ch;
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  off = loc & (BLOCK_SIZE - 1);
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  dp = (struct minix_dir_entry *) (DATABLOCK2 + off);
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* advance loc prematurely to next on-disk directory entry  */
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  loc += sizeof (dp->inode) + namelen;
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* NOTE: minix filenames are NULL terminated if < NAMELEN
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     else exact */
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG_MINIX
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf ("directory entry ino=%d\n", dp->inode);
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (dp->inode)
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    printf ("entry=%s\n", dp->name);
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (dp->inode)
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      int saved_c = dp->name[namelen];
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      dp->name[namelen] = 0;
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str_chk = substring (dirname, dp->name);
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# ifndef STAGE1_5
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (print_possibilities && ch != '/'
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && (!*dirname || str_chk <= 0))
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  if (print_possibilities > 0)
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    print_possibilities = -print_possibilities;
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  print_a_completion (dp->name);
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# endif
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      dp->name[namelen] = saved_c;
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      current_ino = dp->inode;
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      *(dirname = rest) = ch;
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* never get here */
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* FSYS_MINIX */
535