1N/A/*
1N/A * GRUB -- GRand Unified Bootloader
1N/A * Copyright (C) 2001 Free Software Foundation, Inc.
1N/A *
1N/A * This program is free software; you can redistribute it and/or modify
1N/A * it under the terms of the GNU General Public License as published by
1N/A * the Free Software Foundation; either version 2 of the License, or
1N/A * (at your option) any later version.
1N/A *
1N/A * This program is distributed in the hope that it will be useful,
1N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
1N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1N/A * GNU General Public License for more details.
1N/A *
1N/A * You should have received a copy of the GNU General Public License
1N/A * along with this program; if not, write to the Free Software
1N/A * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1N/A */
1N/A
1N/A#ifdef FSYS_VSTAFS
1N/A
1N/A#include "shared.h"
1N/A#include "filesys.h"
1N/A#include "vstafs.h"
1N/A
1N/A
1N/Astatic void get_file_info (int sector);
1N/Astatic struct dir_entry *vstafs_readdir (long sector);
1N/Astatic struct dir_entry *vstafs_nextdir (void);
1N/A
1N/A
1N/A#define FIRST_SECTOR ((struct first_sector *) FSYS_BUF)
1N/A#define FILE_INFO ((struct fs_file *) (int) FIRST_SECTOR + 8192)
1N/A#define DIRECTORY_BUF ((struct dir_entry *) (int) FILE_INFO + 512)
1N/A
1N/A#define ROOT_SECTOR 1
1N/A
1N/A/*
1N/A * In f_sector we store the sector number in which the information about
1N/A * the found file is.
1N/A */
1N/Aextern int filepos;
1N/Astatic int f_sector;
1N/A
1N/Aint
1N/Avstafs_mount (void)
1N/A{
1N/A int retval = 1;
1N/A
1N/A if( (((current_drive & 0x80) || (current_slice != 0))
1N/A && current_slice != PC_SLICE_TYPE_VSTAFS)
1N/A || ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF)
1N/A || FIRST_SECTOR->fs_magic != 0xDEADFACE)
1N/A retval = 0;
1N/A
1N/A return retval;
1N/A}
1N/A
1N/Astatic void
1N/Aget_file_info (int sector)
1N/A{
1N/A devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO);
1N/A}
1N/A
1N/Astatic int curr_ext, current_direntry, current_blockpos;
1N/Astatic struct alloc *a;
1N/A
1N/Astatic struct dir_entry *
1N/Avstafs_readdir (long sector)
1N/A{
1N/A /*
1N/A * Get some information from the current directory
1N/A */
1N/A get_file_info (sector);
1N/A if (FILE_INFO->type != 2)
1N/A {
1N/A errnum = ERR_FILE_NOT_FOUND;
1N/A return 0;
1N/A }
1N/A
1N/A a = FILE_INFO->blocks;
1N/A curr_ext = 0;
1N/A devread (a[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF);
1N/A current_direntry = 11;
1N/A current_blockpos = 0;
1N/A
1N/A return &DIRECTORY_BUF[10];
1N/A}
1N/A
1N/Astatic struct dir_entry *
1N/Avstafs_nextdir (void)
1N/A{
1N/A if (current_direntry > 15)
1N/A {
1N/A current_direntry = 0;
1N/A if (++current_blockpos > (a[curr_ext].a_len - 1))
1N/A {
1N/A current_blockpos = 0;
1N/A curr_ext++;
1N/A }
1N/A
1N/A if (curr_ext < FILE_INFO->extents)
1N/A {
1N/A devread (a[curr_ext].a_start + current_blockpos, 0,
1N/A 512, (char *) DIRECTORY_BUF);
1N/A }
1N/A else
1N/A {
1N/A /* errnum =ERR_FILE_NOT_FOUND; */
1N/A return 0;
1N/A }
1N/A }
1N/A
1N/A return &DIRECTORY_BUF[current_direntry++];
1N/A}
1N/A
1N/Aint
1N/Avstafs_dir (char *dirname)
1N/A{
1N/A char *fn, ch;
1N/A struct dir_entry *d;
1N/A /* int l, i, s; */
1N/A
1N/A /*
1N/A * Read in the entries of the current directory.
1N/A */
1N/A f_sector = ROOT_SECTOR;
1N/A do
1N/A {
1N/A if (! (d = vstafs_readdir (f_sector)))
1N/A {
1N/A return 0;
1N/A }
1N/A
1N/A /*
1N/A * Find the file in the path
1N/A */
1N/A while (*dirname == '/') dirname++;
1N/A fn = dirname;
1N/A while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++;
1N/A *fn = 0;
1N/A
1N/A do
1N/A {
1N/A if (d->name[0] == 0 || d->name[0] & 0x80)
1N/A continue;
1N/A
1N/A#ifndef STAGE1_5
1N/A if (print_possibilities && ch != '/'
1N/A && (! *dirname || strcmp (dirname, d->name) <= 0))
1N/A {
1N/A if (print_possibilities > 0)
1N/A print_possibilities = -print_possibilities;
1N/A
1N/A printf (" %s", d->name);
1N/A }
1N/A#endif
1N/A if (! grub_strcmp (dirname, d->name))
1N/A {
1N/A f_sector = d->start;
1N/A get_file_info (f_sector);
1N/A filemax = FILE_INFO->len;
1N/A break;
1N/A }
1N/A }
1N/A while ((d =vstafs_nextdir ()));
1N/A
1N/A *(dirname = fn) = ch;
1N/A if (! d)
1N/A {
1N/A if (print_possibilities < 0)
1N/A {
1N/A putchar ('\n');
1N/A return 1;
1N/A }
1N/A
1N/A errnum = ERR_FILE_NOT_FOUND;
1N/A return 0;
1N/A }
1N/A }
1N/A while (*dirname && ! isspace (ch));
1N/A
1N/A return 1;
1N/A}
1N/A
1N/Aint
1N/Avstafs_read (char *addr, int len)
1N/A{
1N/A struct alloc *a;
1N/A int size, ret = 0, offset, curr_len = 0;
1N/A int curr_ext;
1N/A char extent;
1N/A int ext_size;
1N/A char *curr_pos;
1N/A
1N/A get_file_info (f_sector);
1N/A size = FILE_INFO->len-VSTAFS_START_DATA;
1N/A a = FILE_INFO->blocks;
1N/A
1N/A if (filepos > 0)
1N/A {
1N/A if (filepos < a[0].a_len * 512 - VSTAFS_START_DATA)
1N/A {
1N/A offset = filepos + VSTAFS_START_DATA;
1N/A extent = 0;
1N/A curr_len = a[0].a_len * 512 - offset - filepos;
1N/A }
1N/A else
1N/A {
1N/A ext_size = a[0].a_len * 512 - VSTAFS_START_DATA;
1N/A offset = filepos - ext_size;
1N/A extent = 1;
1N/A do
1N/A {
1N/A curr_len -= ext_size;
1N/A offset -= ext_size;
1N/A ext_size = a[extent+1].a_len * 512;
1N/A }
1N/A while (extent < FILE_INFO->extents && offset>ext_size);
1N/A }
1N/A }
1N/A else
1N/A {
1N/A offset = VSTAFS_START_DATA;
1N/A extent = 0;
1N/A curr_len = a[0].a_len * 512 - offset;
1N/A }
1N/A
1N/A curr_pos = addr;
1N/A if (curr_len > len)
1N/A curr_len = len;
1N/A
1N/A for (curr_ext=extent;
1N/A curr_ext < FILE_INFO->extents;
1N/A curr_len = a[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext++)
1N/A {
1N/A ret += curr_len;
1N/A size -= curr_len;
1N/A if (size < 0)
1N/A {
1N/A ret += size;
1N/A curr_len += size;
1N/A }
1N/A
1N/A devread (a[curr_ext].a_start,offset, curr_len, curr_pos);
1N/A offset = 0;
1N/A }
1N/A
1N/A return ret;
1N/A}
1N/A
1N/A#endif /* FSYS_VSTAFS */