Home | History | Annotate | Download | only in stage2
      1 /*
      2  *  GRUB  --  GRand Unified Bootloader
      3  *  Copyright (C) 2001   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., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 
     20 #ifdef FSYS_VSTAFS
     21 
     22 #include "shared.h"
     23 #include "filesys.h"
     24 #include "vstafs.h"
     25 
     26 
     27 static void get_file_info (int sector);
     28 static struct dir_entry *vstafs_readdir (long sector);
     29 static struct dir_entry *vstafs_nextdir (void);
     30 
     31 
     32 #define FIRST_SECTOR	((struct first_sector *) FSYS_BUF)
     33 #define FILE_INFO	((struct fs_file *) (int) FIRST_SECTOR + 8192)
     34 #define DIRECTORY_BUF	((struct dir_entry *) (int) FILE_INFO + 512)
     35 
     36 #define ROOT_SECTOR	1
     37 
     38 /*
     39  * In f_sector we store the sector number in which the information about
     40  * the found file is.
     41  */
     42 extern int filepos;
     43 static int f_sector;
     44 
     45 int
     46 vstafs_mount (void)
     47 {
     48   int retval = 1;
     49 
     50   if( (((current_drive & 0x80) || (current_slice != 0))
     51        && current_slice != PC_SLICE_TYPE_VSTAFS)
     52       ||  ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF)
     53       ||  FIRST_SECTOR->fs_magic != 0xDEADFACE)
     54     retval = 0;
     55 
     56   return retval;
     57 }
     58 
     59 static void
     60 get_file_info (int sector)
     61 {
     62   devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO);
     63 }
     64 
     65 static int curr_ext, current_direntry, current_blockpos;
     66 static struct alloc *a;
     67 
     68 static struct dir_entry *
     69 vstafs_readdir (long sector)
     70 {
     71   /*
     72    * Get some information from the current directory
     73    */
     74   get_file_info (sector);
     75   if (FILE_INFO->type != 2)
     76     {
     77       errnum = ERR_FILE_NOT_FOUND;
     78       return 0;
     79     }
     80 
     81   a = FILE_INFO->blocks;
     82   curr_ext = 0;
     83   devread (a[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF);
     84   current_direntry = 11;
     85   current_blockpos = 0;
     86 
     87   return &DIRECTORY_BUF[10];
     88 }
     89 
     90 static struct dir_entry *
     91 vstafs_nextdir (void)
     92 {
     93   if (current_direntry > 15)
     94     {
     95       current_direntry = 0;
     96       if (++current_blockpos > (a[curr_ext].a_len - 1))
     97 	{
     98 	  current_blockpos = 0;
     99 	  curr_ext++;
    100 	}
    101 
    102       if (curr_ext < FILE_INFO->extents)
    103 	{
    104 	  devread (a[curr_ext].a_start + current_blockpos, 0,
    105 		   512, (char *) DIRECTORY_BUF);
    106 	}
    107       else
    108 	{
    109 	  /* errnum =ERR_FILE_NOT_FOUND; */
    110 	  return 0;
    111 	}
    112     }
    113 
    114   return &DIRECTORY_BUF[current_direntry++];
    115 }
    116 
    117 int
    118 vstafs_dir (char *dirname)
    119 {
    120   char *fn, ch;
    121   struct dir_entry *d;
    122   /* int l, i, s; */
    123 
    124   /*
    125    * Read in the entries of the current directory.
    126    */
    127   f_sector = ROOT_SECTOR;
    128   do
    129     {
    130       if (! (d = vstafs_readdir (f_sector)))
    131 	{
    132 	  return 0;
    133 	}
    134 
    135       /*
    136        * Find the file in the path
    137        */
    138       while (*dirname == '/') dirname++;
    139       fn = dirname;
    140       while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++;
    141       *fn = 0;
    142 
    143       do
    144 	{
    145 	  if (d->name[0] == 0 || d->name[0] & 0x80)
    146 	    continue;
    147 
    148 #ifndef STAGE1_5
    149 	  if (print_possibilities && ch != '/'
    150 	      && (! *dirname || strcmp (dirname, d->name) <= 0))
    151 	    {
    152 	      if (print_possibilities > 0)
    153 		print_possibilities = -print_possibilities;
    154 
    155 	      printf ("  %s", d->name);
    156 	    }
    157 #endif
    158 	  if (! grub_strcmp (dirname, d->name))
    159 	    {
    160 	      f_sector = d->start;
    161 	      get_file_info (f_sector);
    162 	      filemax = FILE_INFO->len;
    163 	      break;
    164 	    }
    165 	}
    166       while ((d =vstafs_nextdir ()));
    167 
    168       *(dirname = fn) = ch;
    169       if (! d)
    170 	{
    171 	  if (print_possibilities < 0)
    172 	    {
    173 	      putchar ('\n');
    174 	      return 1;
    175 	    }
    176 
    177 	  errnum = ERR_FILE_NOT_FOUND;
    178 	  return 0;
    179 	}
    180     }
    181   while (*dirname && ! isspace (ch));
    182 
    183   return 1;
    184 }
    185 
    186 int
    187 vstafs_read (char *addr, int len)
    188 {
    189   struct alloc *a;
    190   int size, ret = 0, offset, curr_len = 0;
    191   int curr_ext;
    192   char extent;
    193   int ext_size;
    194   char *curr_pos;
    195 
    196   get_file_info (f_sector);
    197   size = FILE_INFO->len-VSTAFS_START_DATA;
    198   a = FILE_INFO->blocks;
    199 
    200   if (filepos > 0)
    201     {
    202       if (filepos < a[0].a_len * 512 - VSTAFS_START_DATA)
    203 	{
    204 	  offset = filepos + VSTAFS_START_DATA;
    205 	  extent = 0;
    206 	  curr_len = a[0].a_len * 512 - offset - filepos;
    207 	}
    208       else
    209 	{
    210 	  ext_size = a[0].a_len * 512 - VSTAFS_START_DATA;
    211 	  offset = filepos - ext_size;
    212 	  extent = 1;
    213 	  do
    214 	    {
    215 	      curr_len -= ext_size;
    216 	      offset -= ext_size;
    217 	      ext_size = a[extent+1].a_len * 512;
    218 	    }
    219 	  while (extent < FILE_INFO->extents && offset>ext_size);
    220 	}
    221     }
    222   else
    223     {
    224       offset = VSTAFS_START_DATA;
    225       extent = 0;
    226       curr_len = a[0].a_len * 512 - offset;
    227     }
    228 
    229   curr_pos = addr;
    230   if (curr_len > len)
    231     curr_len = len;
    232 
    233   for (curr_ext=extent;
    234        curr_ext < FILE_INFO->extents;
    235        curr_len = a[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext++)
    236     {
    237       ret += curr_len;
    238       size -= curr_len;
    239       if (size < 0)
    240 	{
    241 	  ret += size;
    242 	  curr_len += size;
    243 	}
    244 
    245       devread (a[curr_ext].a_start,offset, curr_len, curr_pos);
    246       offset = 0;
    247     }
    248 
    249   return ret;
    250 }
    251 
    252 #endif /* FSYS_VSTAFS */
    253