~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to fs/minix.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

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