~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/fs/minix.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

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