]> git.proxmox.com Git - grub2.git/blame - grub-core/fs/minix.c
minix3fs support
[grub2.git] / grub-core / fs / minix.c
CommitLineData
66e19ef8 1/* minix.c - The minix filesystem, version 1 and 2. */
2/*
3 * GRUB -- GRand Unified Bootloader
f36cc108 4 * Copyright (C) 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
66e19ef8 5 *
5a79f472 6 * GRUB is free software: you can redistribute it and/or modify
66e19ef8 7 * it under the terms of the GNU General Public License as published by
5a79f472 8 * the Free Software Foundation, either version 3 of the License, or
66e19ef8 9 * (at your option) any later version.
10 *
5a79f472 11 * GRUB is distributed in the hope that it will be useful,
66e19ef8 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
5a79f472 17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
66e19ef8 18 */
19
20#include <grub/err.h>
21#include <grub/file.h>
22#include <grub/mm.h>
23#include <grub/misc.h>
24#include <grub/disk.h>
25#include <grub/dl.h>
26#include <grub/types.h>
27
3dd3dd33
FZ
28#ifdef MODE_MINIX3
29#define GRUB_MINIX_MAGIC 0x4D5A
30#elif defined(MODE_MINIX2)
b4a0c915
VS
31#define GRUB_MINIX_MAGIC 0x2468
32#define GRUB_MINIX_MAGIC_30 0x2478
33#else
66e19ef8 34#define GRUB_MINIX_MAGIC 0x137F
66e19ef8 35#define GRUB_MINIX_MAGIC_30 0x138F
b4a0c915 36#endif
3dd3dd33
FZ
37
38#define GRUB_MINIX_INODE_DIR_BLOCKS 7
66e19ef8 39#define GRUB_MINIX_LOG2_BSIZE 1
40#define GRUB_MINIX_ROOT_INODE 1
41#define GRUB_MINIX_MAX_SYMLNK_CNT 8
42#define GRUB_MINIX_SBLOCK 2
43
44#define GRUB_MINIX_IFDIR 0040000U
45#define GRUB_MINIX_IFLNK 0120000U
46
3dd3dd33 47#if defined(MODE_MINIX2) || defined(MODE_MINIX3)
b4a0c915
VS
48typedef grub_uint32_t grub_minix_uintn_t;
49#define grub_minix_le_to_cpu_n grub_le_to_cpu32
50#else
51typedef grub_uint16_t grub_minix_uintn_t;
52#define grub_minix_le_to_cpu_n grub_le_to_cpu16
53#endif
54
55#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
3dd3dd33
FZ
56#ifdef MODE_MINIX3
57typedef grub_uint32_t grub_minix_ino_t;
58#define grub_minix_le_to_cpu_ino grub_le_to_cpu32
59#else
60typedef grub_uint16_t grub_minix_ino_t;
61#define grub_minix_le_to_cpu_ino grub_le_to_cpu16
62#endif
b4a0c915
VS
63
64#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
65#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
66#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \
67 (data->inode.dir_zones[blk]))
68#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \
69 (data->inode.indir_zone))
70#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
71 (data->inode.double_indir_zone))
72
66e19ef8 73#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
74 + grub_le_to_cpu16 (sblock->log2_zone_size))
3dd3dd33 75#define GRUB_MINIX_ZONESZ (data->block_size \
66e19ef8 76 << grub_le_to_cpu16 (sblock->log2_zone_size))
77
3dd3dd33
FZ
78#ifdef MODE_MINIX3
79struct grub_minix_sblock
80{
81 grub_uint32_t inode_cnt;
82 grub_uint16_t zone_cnt;
83 grub_uint16_t inode_bmap_size;
84 grub_uint16_t zone_bmap_size;
85 grub_uint16_t first_data_zone;
86 grub_uint16_t log2_zone_size;
87 grub_uint16_t pad;
88 grub_uint32_t max_file_size;
89 grub_uint32_t zones;
90 grub_uint16_t magic;
91
92 grub_uint16_t pad2;
93 grub_uint16_t block_size;
94 grub_uint8_t disk_version;
95};
96#else
66e19ef8 97struct grub_minix_sblock
98{
99 grub_uint16_t inode_cnt;
100 grub_uint16_t zone_cnt;
101 grub_uint16_t inode_bmap_size;
102 grub_uint16_t zone_bmap_size;
103 grub_uint16_t first_data_zone;
104 grub_uint16_t log2_zone_size;
105 grub_uint32_t max_file_size;
106 grub_uint16_t magic;
107};
3dd3dd33
FZ
108#endif
109
110#if defined(MODE_MINIX3)
111
112struct grub_minix_inode
113{
114 grub_uint16_t mode;
115 grub_uint16_t nlinks;
116 grub_uint16_t uid;
117 grub_uint8_t gid;
118 grub_uint8_t pad;
119 grub_uint32_t size;
120 grub_uint32_t atime;
121 grub_uint32_t mtime;
122 grub_uint32_t ctime;
123 grub_uint32_t dir_zones[7];
124 grub_uint32_t indir_zone;
125 grub_uint32_t double_indir_zone;
126 grub_uint32_t unused;
127};
66e19ef8 128
3dd3dd33 129#elif defined(MODE_MINIX2)
66e19ef8 130struct grub_minix_inode
131{
132 grub_uint16_t mode;
133 grub_uint16_t uid;
134 grub_uint16_t size;
135 grub_uint32_t ctime;
136 grub_uint8_t gid;
137 grub_uint8_t nlinks;
138 grub_uint16_t dir_zones[7];
139 grub_uint16_t indir_zone;
140 grub_uint16_t double_indir_zone;
141};
142
b4a0c915
VS
143#else
144
145struct grub_minix_inode
66e19ef8 146{
147 grub_uint16_t mode;
148 grub_uint16_t nlinks;
149 grub_uint16_t uid;
150 grub_uint16_t gid;
151 grub_uint32_t size;
152 grub_uint32_t atime;
153 grub_uint32_t mtime;
154 grub_uint32_t ctime;
155 grub_uint32_t dir_zones[7];
156 grub_uint32_t indir_zone;
157 grub_uint32_t double_indir_zone;
158 grub_uint32_t unused;
b39f9d20 159
66e19ef8 160};
161
b4a0c915
VS
162#endif
163
66e19ef8 164/* Information about a "mounted" minix filesystem. */
165struct grub_minix_data
166{
167 struct grub_minix_sblock sblock;
168 struct grub_minix_inode inode;
66e19ef8 169 int ino;
170 int linknest;
171 grub_disk_t disk;
66e19ef8 172 int filename_size;
3dd3dd33 173 grub_size_t block_size;
66e19ef8 174};
175
66e19ef8 176static grub_dl_t my_mod;
66e19ef8 177\f
178static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
179 const char *path);
180
181static int
182grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
183{
184 struct grub_minix_sblock *sblock = &data->sblock;
185 int indir;
186
94bc45af 187 auto int grub_get_indir (int, int);
188
66e19ef8 189 /* Read the block pointer in ZONE, on the offset NUM. */
190 int grub_get_indir (int zone, int num)
191 {
b4a0c915
VS
192 grub_minix_uintn_t indirn;
193 grub_disk_read (data->disk,
3dd3dd33
FZ
194#ifdef MODE_MINIX3
195 zone * (data->block_size / GRUB_DISK_SECTOR_SIZE),
196#else
b4a0c915 197 zone << GRUB_MINIX_LOG2_ZONESZ,
3dd3dd33 198#endif
b4a0c915
VS
199 sizeof (grub_minix_uintn_t) * num,
200 sizeof (grub_minix_uintn_t), (char *) &indirn);
201 return grub_minix_le_to_cpu_n (indirn);
66e19ef8 202 }
b39f9d20 203
66e19ef8 204 /* Direct block. */
3dd3dd33 205 if (blk < GRUB_MINIX_INODE_DIR_BLOCKS)
66e19ef8 206 return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
b39f9d20 207
66e19ef8 208 /* Indirect block. */
3dd3dd33 209 blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
66e19ef8 210 if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
211 {
212 indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
213 return indir;
214 }
b39f9d20 215
66e19ef8 216 /* Double indirect block. */
217 blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data);
218 if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
219 * (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
220 {
b39f9d20 221 indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data),
66e19ef8 222 blk / GRUB_MINIX_ZONESZ);
b39f9d20 223
66e19ef8 224 indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ);
b39f9d20 225
66e19ef8 226 return indir;
227 }
b39f9d20 228
66e19ef8 229 /* This should never happen. */
230 grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size");
b39f9d20 231
66e19ef8 232 return 0;
233}
234
235
236/* Read LEN bytes from the file described by DATA starting with byte
237 POS. Return the amount of read bytes in READ. */
238static grub_ssize_t
239grub_minix_read_file (struct grub_minix_data *data,
9959f7db 240 void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
66e19ef8 241 unsigned offset, unsigned length),
3dd3dd33 242 grub_off_t pos, grub_disk_addr_t len, char *buf)
66e19ef8 243{
244 struct grub_minix_sblock *sblock = &data->sblock;
3dd3dd33
FZ
245 grub_disk_addr_t i;
246 grub_disk_addr_t blockcnt;
247 grub_uint64_t posblock;
248 grub_uint32_t blockoff;
66e19ef8 249
250 /* Adjust len so it we can't read past the end of the file. */
6f07b921 251 if (len + pos > GRUB_MINIX_INODE_SIZE (data))
252 len = GRUB_MINIX_INODE_SIZE (data) - pos;
66e19ef8 253
3dd3dd33
FZ
254 blockcnt = grub_divmod64 ((len + pos + data->block_size - 1),
255 data->block_size, 0);
256 posblock = grub_divmod64 (pos, data->block_size, &blockoff);
b39f9d20 257
3dd3dd33 258 for (i = posblock; i < blockcnt; i++)
66e19ef8 259 {
3dd3dd33
FZ
260 grub_disk_addr_t blknr;
261 grub_uint32_t blockend = data->block_size;
262 grub_off_t skipfirst = 0;
b39f9d20 263
66e19ef8 264 blknr = grub_minix_get_file_block (data, i);
265 if (grub_errno)
266 return -1;
b39f9d20 267
66e19ef8 268 /* Last block. */
269 if (i == blockcnt - 1)
270 {
3dd3dd33 271 grub_divmod64 (len + pos, data->block_size, &blockend);
b39f9d20 272
66e19ef8 273 if (!blockend)
3dd3dd33 274 blockend = data->block_size;
66e19ef8 275 }
b39f9d20 276
66e19ef8 277 /* First block. */
3dd3dd33 278 if (i == posblock)
66e19ef8 279 {
280 skipfirst = blockoff;
281 blockend -= skipfirst;
282 }
b39f9d20 283
66e19ef8 284 data->disk->read_hook = read_hook;
3dd3dd33
FZ
285 grub_disk_read (data->disk,
286#ifdef MODE_MINIX3
287 blknr * (sblock->block_size / GRUB_DISK_SECTOR_SIZE),
288#else
289 blknr << GRUB_MINIX_LOG2_ZONESZ,
290#endif
66e19ef8 291 skipfirst, blockend, buf);
66e19ef8 292 data->disk->read_hook = 0;
293 if (grub_errno)
294 return -1;
b39f9d20 295
3dd3dd33 296 buf += data->block_size - skipfirst;
66e19ef8 297 }
b39f9d20 298
66e19ef8 299 return len;
300}
301
302
303/* Read inode INO from the mounted filesystem described by DATA. This
304 inode is used by default now. */
305static grub_err_t
306grub_minix_read_inode (struct grub_minix_data *data, int ino)
307{
308 struct grub_minix_sblock *sblock = &data->sblock;
309
310 /* Block in which the inode is stored. */
3dd3dd33 311 grub_disk_addr_t block;
66e19ef8 312 data->ino = ino;
313
314 /* The first inode in minix is inode 1. */
315 ino--;
3dd3dd33
FZ
316 block = (2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
317 + grub_le_to_cpu16 (sblock->zone_bmap_size));
318#ifndef MODE_MINIX3
319 block <<= GRUB_MINIX_LOG2_BSIZE;
320#else
321 block *= sblock->block_size / GRUB_DISK_SECTOR_SIZE;
322#endif
b4a0c915
VS
323 block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
324 int offs = (ino % (GRUB_DISK_SECTOR_SIZE
325 / sizeof (struct grub_minix_inode))
326 * sizeof (struct grub_minix_inode));
327
328 grub_disk_read (data->disk, block, offs,
329 sizeof (struct grub_minix_inode), &data->inode);
b39f9d20 330
66e19ef8 331 return GRUB_ERR_NONE;
332}
333
334
335/* Lookup the symlink the current inode points to. INO is the inode
336 number of the directory the symlink is relative to. */
337static grub_err_t
338grub_minix_lookup_symlink (struct grub_minix_data *data, int ino)
339{
340 char symlink[GRUB_MINIX_INODE_SIZE (data) + 1];
b39f9d20 341
66e19ef8 342 if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT)
343 return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
b39f9d20 344
66e19ef8 345 if (grub_minix_read_file (data, 0, 0,
346 GRUB_MINIX_INODE_SIZE (data), symlink) < 0)
347 return grub_errno;
348
349 symlink[GRUB_MINIX_INODE_SIZE (data)] = '\0';
b39f9d20 350
66e19ef8 351 /* The symlink is an absolute path, go back to the root inode. */
352 if (symlink[0] == '/')
353 ino = GRUB_MINIX_ROOT_INODE;
b39f9d20 354
66e19ef8 355 /* Now load in the old inode. */
356 if (grub_minix_read_inode (data, ino))
357 return grub_errno;
b39f9d20 358
66e19ef8 359 grub_minix_find_file (data, symlink);
360 if (grub_errno)
61ba42be 361 grub_error (grub_errno, "cannot follow symlink `%s'", symlink);
b39f9d20 362
66e19ef8 363 return grub_errno;
364}
365
366
367/* Find the file with the pathname PATH on the filesystem described by
368 DATA. */
369static grub_err_t
370grub_minix_find_file (struct grub_minix_data *data, const char *path)
371{
78026bce 372 char fpath[grub_strlen (path) + 1];
66e19ef8 373 char *name = fpath;
374 char *next;
375 unsigned int pos = 0;
376 int dirino;
b39f9d20 377
78026bce 378 grub_strcpy (fpath, path);
b39f9d20 379
66e19ef8 380 /* Skip the first slash. */
381 if (name[0] == '/')
382 {
383 name++;
384 if (!*name)
385 return 0;
386 }
387
388 /* Extract the actual part from the pathname. */
389 next = grub_strchr (name, '/');
390 if (next)
391 {
392 next[0] = '\0';
393 next++;
394 }
b39f9d20 395
66e19ef8 396 do
397 {
3dd3dd33 398 grub_minix_ino_t ino;
66e19ef8 399 char filename[data->filename_size + 1];
b39f9d20 400
66e19ef8 401 if (grub_strlen (name) == 0)
402 return GRUB_ERR_NONE;
b39f9d20 403
66e19ef8 404 if (grub_minix_read_file (data, 0, pos, sizeof (ino),
405 (char *) &ino) < 0)
406 return grub_errno;
407 if (grub_minix_read_file (data, 0, pos + sizeof (ino),
408 data->filename_size, (char *) filename)< 0)
409 return grub_errno;
410
411 filename[data->filename_size] = '\0';
b39f9d20 412
66e19ef8 413 /* Check if the current direntry matches the current part of the
414 pathname. */
415 if (!grub_strcmp (name, filename))
416 {
417 dirino = data->ino;
3dd3dd33 418 grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
b39f9d20 419
66e19ef8 420 /* Follow the symlink. */
b39f9d20 421 if ((GRUB_MINIX_INODE_MODE (data)
66e19ef8 422 & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK)
423 {
424 grub_minix_lookup_symlink (data, dirino);
425 if (grub_errno)
426 return grub_errno;
427 }
b39f9d20 428
66e19ef8 429 if (!next)
430 return 0;
b39f9d20 431
66e19ef8 432 pos = 0;
b39f9d20 433
66e19ef8 434 name = next;
435 next = grub_strchr (name, '/');
436 if (next)
437 {
438 next[0] = '\0';
439 next++;
440 }
b39f9d20 441
66e19ef8 442 if ((GRUB_MINIX_INODE_MODE (data)
443 & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR)
444 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
b39f9d20 445
66e19ef8 446 continue;
447 }
b39f9d20 448
66e19ef8 449 pos += sizeof (ino) + data->filename_size;
450 } while (pos < GRUB_MINIX_INODE_SIZE (data));
b39f9d20 451
66e19ef8 452 grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
453 return grub_errno;
454}
455
456
457/* Mount the filesystem on the disk DISK. */
458static struct grub_minix_data *
459grub_minix_mount (grub_disk_t disk)
460{
461 struct grub_minix_data *data;
b39f9d20 462
66e19ef8 463 data = grub_malloc (sizeof (struct grub_minix_data));
464 if (!data)
465 return 0;
b39f9d20 466
66e19ef8 467 /* Read the superblock. */
468 grub_disk_read (disk, GRUB_MINIX_SBLOCK, 0,
238e871f 469 sizeof (struct grub_minix_sblock),&data->sblock);
40fd3a2b 470 if (grub_errno)
471 goto fail;
66e19ef8 472
473 if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
3dd3dd33
FZ
474 {
475#if !defined(MODE_MINIX3)
b4a0c915 476 data->filename_size = 14;
3dd3dd33
FZ
477#else
478 data->filename_size = 60;
479#endif
480 }
481#if !defined(MODE_MINIX3)
66e19ef8 482 else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
b4a0c915 483 data->filename_size = 30;
3dd3dd33 484#endif
66e19ef8 485 else
40fd3a2b 486 goto fail;
487
66e19ef8 488 data->disk = disk;
489 data->linknest = 0;
3dd3dd33
FZ
490#ifdef MODE_MINIX3
491 data->block_size = grub_le_to_cpu16 (data->sblock.block_size);
492#else
493 data->block_size = 1024U;
494#endif
66e19ef8 495
496 return data;
40fd3a2b 497
498 fail:
499 grub_free (data);
3dd3dd33
FZ
500#if defined(MODE_MINIX3)
501 grub_error (GRUB_ERR_BAD_FS, "not a minix3 filesystem");
502#elif defined(MODE_MINIX2)
b4a0c915
VS
503 grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
504#else
40fd3a2b 505 grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
b4a0c915 506#endif
40fd3a2b 507 return 0;
66e19ef8 508}
509\f
510static grub_err_t
b39f9d20 511grub_minix_dir (grub_device_t device, const char *path,
512 int (*hook) (const char *filename,
05aaebfb 513 const struct grub_dirhook_info *info))
66e19ef8 514{
515 struct grub_minix_data *data = 0;
66e19ef8 516 unsigned int pos = 0;
b39f9d20 517
66e19ef8 518 data = grub_minix_mount (device->disk);
519 if (!data)
520 return grub_errno;
b39f9d20 521
66e19ef8 522 grub_minix_read_inode (data, GRUB_MINIX_ROOT_INODE);
523 if (grub_errno)
524 goto fail;
b39f9d20 525
66e19ef8 526 grub_minix_find_file (data, path);
527 if (grub_errno)
528 goto fail;
b39f9d20 529
66e19ef8 530 if ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR)
531 {
532 grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
533 goto fail;
534 }
b39f9d20 535
66e19ef8 536 while (pos < GRUB_MINIX_INODE_SIZE (data))
537 {
3dd3dd33 538 grub_minix_ino_t ino;
66e19ef8 539 char filename[data->filename_size + 1];
540 int dirino = data->ino;
05aaebfb 541 struct grub_dirhook_info info;
542 grub_memset (&info, 0, sizeof (info));
543
b39f9d20 544
66e19ef8 545 if (grub_minix_read_file (data, 0, pos, sizeof (ino),
546 (char *) &ino) < 0)
547 return grub_errno;
b39f9d20 548
66e19ef8 549 if (grub_minix_read_file (data, 0, pos + sizeof (ino),
550 data->filename_size,
551 (char *) filename) < 0)
552 return grub_errno;
553 filename[data->filename_size] = '\0';
3dd3dd33
FZ
554 if (!ino)
555 {
556 pos += sizeof (ino) + data->filename_size;
557 continue;
558 }
b39f9d20 559
3dd3dd33 560 grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
b39f9d20 561 info.dir = ((GRUB_MINIX_INODE_MODE (data)
05aaebfb 562 & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
563 if (hook (filename, &info) ? 1 : 0)
66e19ef8 564 break;
b39f9d20 565
66e19ef8 566 /* Load the old inode back in. */
567 grub_minix_read_inode (data, dirino);
568
569 pos += sizeof (ino) + data->filename_size;
570 }
b39f9d20 571
66e19ef8 572 fail:
573 grub_free (data);
574 return grub_errno;
575}
576
577
578/* Open a file named NAME and initialize FILE. */
579static grub_err_t
580grub_minix_open (struct grub_file *file, const char *name)
581{
582 struct grub_minix_data *data;
583 data = grub_minix_mount (file->device->disk);
584 if (!data)
585 return grub_errno;
586
587 /* Open the inode op the root directory. */
588 grub_minix_read_inode (data, GRUB_MINIX_ROOT_INODE);
589 if (grub_errno)
590 {
591 grub_free (data);
592 return grub_errno;
593 }
b39f9d20 594
66e19ef8 595 if (!name || name[0] != '/')
596 {
597 grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
598 return grub_errno;
599 }
b39f9d20 600
66e19ef8 601 /* Traverse the directory tree to the node that should be
602 opened. */
603 grub_minix_find_file (data, name);
604 if (grub_errno)
605 {
606 grub_free (data);
607 return grub_errno;
608 }
b39f9d20 609
66e19ef8 610 file->data = data;
611 file->size = GRUB_MINIX_INODE_SIZE (data);
b39f9d20 612
66e19ef8 613 return GRUB_ERR_NONE;
614}
615
616
617static grub_ssize_t
524a1e6a 618grub_minix_read (grub_file_t file, char *buf, grub_size_t len)
66e19ef8 619{
b39f9d20 620 struct grub_minix_data *data =
66e19ef8 621 (struct grub_minix_data *) file->data;
b39f9d20 622
66e19ef8 623 return grub_minix_read_file (data, file->read_hook, file->offset, len, buf);
624}
625
626
627static grub_err_t
628grub_minix_close (grub_file_t file)
629{
630 grub_free (file->data);
b39f9d20 631
66e19ef8 632 return GRUB_ERR_NONE;
633}
634
635
66e19ef8 636\f
637static struct grub_fs grub_minix_fs =
638 {
3dd3dd33
FZ
639#if defined(MODE_MINIX3)
640 .name = "minix3",
641#elif defined(MODE_MINIX2)
b4a0c915
VS
642 .name = "minix2",
643#else
66e19ef8 644 .name = "minix",
b4a0c915 645#endif
66e19ef8 646 .dir = grub_minix_dir,
647 .open = grub_minix_open,
648 .read = grub_minix_read,
649 .close = grub_minix_close,
66e19ef8 650 .next = 0
651 };
652
3dd3dd33
FZ
653#if defined(MODE_MINIX3)
654GRUB_MOD_INIT(minix3)
655#elif defined(MODE_MINIX2)
b4a0c915
VS
656GRUB_MOD_INIT(minix2)
657#else
6d099807 658GRUB_MOD_INIT(minix)
b4a0c915 659#endif
66e19ef8 660{
661 grub_fs_register (&grub_minix_fs);
662 my_mod = mod;
663}
664
3dd3dd33
FZ
665#if defined(MODE_MINIX3)
666GRUB_MOD_FINI(minix3)
667#elif defined(MODE_MINIX2)
b4a0c915
VS
668GRUB_MOD_FINI(minix2)
669#else
6d099807 670GRUB_MOD_FINI(minix)
b4a0c915 671#endif
66e19ef8 672{
673 grub_fs_unregister (&grub_minix_fs);
674}