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
vstafs_mount(void)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
get_file_info(int sector)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 *
vstafs_readdir(long sector)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 *
vstafs_nextdir(void)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
vstafs_dir(char * dirname)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
vstafs_read(char * addr,int len)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