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