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