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

« back to all changes in this revision

Viewing changes to grub-core/fs/affs.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
/* affs.c - Amiga Fast FileSystem.  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2005,2006,2007,2008,2009  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
#include <grub/fshelp.h>
 
28
 
 
29
/* The affs bootblock.  */
 
30
struct grub_affs_bblock
 
31
{
 
32
  grub_uint8_t type[3];
 
33
  grub_uint8_t flags;
 
34
  grub_uint32_t checksum;
 
35
  grub_uint32_t rootblock;
 
36
} __attribute__ ((packed));
 
37
 
 
38
/* Set if the filesystem is a AFFS filesystem.  Otherwise this is an
 
39
   OFS filesystem.  */
 
40
#define GRUB_AFFS_FLAG_FFS      1
 
41
 
 
42
/* The affs rootblock.  */
 
43
struct grub_affs_rblock
 
44
{
 
45
  grub_uint8_t type[4];
 
46
  grub_uint8_t unused1[8];
 
47
  grub_uint32_t htsize;
 
48
  grub_uint32_t unused2;
 
49
  grub_uint32_t checksum;
 
50
  grub_uint32_t hashtable[1];
 
51
} __attribute__ ((packed));
 
52
 
 
53
/* The second part of a file header block.  */
 
54
struct grub_affs_file
 
55
{
 
56
  grub_uint8_t unused1[12];
 
57
  grub_uint32_t size;
 
58
  grub_uint8_t unused2[104];
 
59
  grub_uint8_t namelen;
 
60
  grub_uint8_t name[30];
 
61
  grub_uint8_t unused3[33];
 
62
  grub_uint32_t next;
 
63
  grub_uint32_t parent;
 
64
  grub_uint32_t extension;
 
65
  grub_int32_t type;
 
66
} __attribute__ ((packed));
 
67
 
 
68
/* The location of `struct grub_affs_file' relative to the end of a
 
69
   file header block.  */
 
70
#define GRUB_AFFS_FILE_LOCATION         200
 
71
 
 
72
/* The offset in both the rootblock and the file header block for the
 
73
   hashtable, symlink and block pointers (all synonyms).  */
 
74
#define GRUB_AFFS_HASHTABLE_OFFSET      24
 
75
#define GRUB_AFFS_BLOCKPTR_OFFSET       24
 
76
#define GRUB_AFFS_SYMLINK_OFFSET        24
 
77
 
 
78
#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225)
 
79
 
 
80
#define GRUB_AFFS_FILETYPE_DIR          -3
 
81
#define GRUB_AFFS_FILETYPE_REG          2
 
82
#define GRUB_AFFS_FILETYPE_SYMLINK      3
 
83
 
 
84
 
 
85
struct grub_fshelp_node
 
86
{
 
87
  struct grub_affs_data *data;
 
88
  int block;
 
89
  int size;
 
90
  int parent;
 
91
};
 
92
 
 
93
/* Information about a "mounted" affs filesystem.  */
 
94
struct grub_affs_data
 
95
{
 
96
  struct grub_affs_bblock bblock;
 
97
  struct grub_fshelp_node diropen;
 
98
  grub_disk_t disk;
 
99
 
 
100
  /* Blocksize in sectors.  */
 
101
  int blocksize;
 
102
 
 
103
  /* The number of entries in the hashtable.  */
 
104
  int htsize;
 
105
};
 
106
 
 
107
static grub_dl_t my_mod;
 
108
 
 
109
 
 
110
static grub_disk_addr_t
 
111
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
 
112
{
 
113
  int links;
 
114
  grub_uint32_t pos;
 
115
  int block = node->block;
 
116
  struct grub_affs_file file;
 
117
  struct grub_affs_data *data = node->data;
 
118
  grub_uint32_t mod;
 
119
 
 
120
  /* Find the block that points to the fileblock we are looking up by
 
121
     following the chain until the right table is reached.  */
 
122
  for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
 
123
    {
 
124
      grub_disk_read (data->disk, block + data->blocksize - 1,
 
125
                      data->blocksize * (GRUB_DISK_SECTOR_SIZE
 
126
                                         - GRUB_AFFS_FILE_LOCATION),
 
127
                      sizeof (file), &file);
 
128
      if (grub_errno)
 
129
        return 0;
 
130
 
 
131
      block = grub_be_to_cpu32 (file.extension);
 
132
    }
 
133
 
 
134
  /* Translate the fileblock to the block within the right table.  */
 
135
  fileblock = mod;
 
136
  grub_disk_read (data->disk, block,
 
137
                  GRUB_AFFS_BLOCKPTR_OFFSET
 
138
                  + (data->htsize - fileblock - 1) * sizeof (pos),
 
139
                  sizeof (pos), &pos);
 
140
  if (grub_errno)
 
141
    return 0;
 
142
 
 
143
  return grub_be_to_cpu32 (pos);
 
144
}
 
145
 
 
146
 
 
147
/* Read LEN bytes from the file described by DATA starting with byte
 
148
   POS.  Return the amount of read bytes in READ.  */
 
149
static grub_ssize_t
 
150
grub_affs_read_file (grub_fshelp_node_t node,
 
151
                     void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
 
152
                                        unsigned offset, unsigned length),
 
153
                     int pos, grub_size_t len, char *buf)
 
154
{
 
155
  return grub_fshelp_read_file (node->data->disk, node, read_hook,
 
156
                                pos, len, buf, grub_affs_read_block,
 
157
                                node->size, 0);
 
158
}
 
159
 
 
160
 
 
161
static struct grub_affs_data *
 
162
grub_affs_mount (grub_disk_t disk)
 
163
{
 
164
  struct grub_affs_data *data;
 
165
  grub_uint32_t *rootblock = 0;
 
166
  struct grub_affs_rblock *rblock;
 
167
 
 
168
  int checksum = 0;
 
169
  int checksumr = 0;
 
170
  int blocksize = 0;
 
171
 
 
172
  data = grub_malloc (sizeof (struct grub_affs_data));
 
173
  if (!data)
 
174
    return 0;
 
175
 
 
176
  /* Read the bootblock.  */
 
177
  grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
 
178
                  &data->bblock);
 
179
  if (grub_errno)
 
180
    goto fail;
 
181
 
 
182
  /* Make sure this is an affs filesystem.  */
 
183
  if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3))
 
184
    {
 
185
      grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
 
186
      goto fail;
 
187
    }
 
188
 
 
189
  /* Test if the filesystem is a OFS filesystem.  */
 
190
  if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS))
 
191
    {
 
192
      grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported");
 
193
      goto fail;
 
194
    }
 
195
 
 
196
  /* Read the bootblock.  */
 
197
  grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
 
198
                  &data->bblock);
 
199
  if (grub_errno)
 
200
    goto fail;
 
201
 
 
202
  /* No sane person uses more than 8KB for a block.  At least I hope
 
203
     for that person because in that case this won't work.  */
 
204
  rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
 
205
  if (!rootblock)
 
206
    goto fail;
 
207
 
 
208
  rblock = (struct grub_affs_rblock *) rootblock;
 
209
 
 
210
  /* Read the rootblock.  */
 
211
  grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0,
 
212
                  GRUB_DISK_SECTOR_SIZE * 16, rootblock);
 
213
  if (grub_errno)
 
214
    goto fail;
 
215
 
 
216
  /* The filesystem blocksize is not stored anywhere in the filesystem
 
217
     itself.  One way to determine it is reading blocks for the
 
218
     rootblock until the checksum is correct.  */
 
219
  checksumr = grub_be_to_cpu32 (rblock->checksum);
 
220
  rblock->checksum = 0;
 
221
  for (blocksize = 0; blocksize < 8; blocksize++)
 
222
    {
 
223
      grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize;
 
224
      unsigned int i;
 
225
 
 
226
      for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++)
 
227
        checksum += grub_be_to_cpu32 (currblock[i]);
 
228
 
 
229
      if (checksumr == -checksum)
 
230
        break;
 
231
    }
 
232
  if (-checksum != checksumr)
 
233
    {
 
234
      grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
 
235
      goto fail;
 
236
    }
 
237
  blocksize++;
 
238
 
 
239
  data->blocksize = blocksize;
 
240
  data->disk = disk;
 
241
  data->htsize = grub_be_to_cpu32 (rblock->htsize);
 
242
  data->diropen.data = data;
 
243
  data->diropen.block = (disk->total_sectors >> 1);
 
244
 
 
245
  grub_free (rootblock);
 
246
 
 
247
  return data;
 
248
 
 
249
 fail:
 
250
  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
 
251
    grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
 
252
 
 
253
  grub_free (data);
 
254
  grub_free (rootblock);
 
255
  return 0;
 
256
}
 
257
 
 
258
 
 
259
static char *
 
260
grub_affs_read_symlink (grub_fshelp_node_t node)
 
261
{
 
262
  struct grub_affs_data *data = node->data;
 
263
  char *symlink;
 
264
 
 
265
  symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize));
 
266
  if (!symlink)
 
267
    return 0;
 
268
 
 
269
  grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
 
270
                  GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink);
 
271
  if (grub_errno)
 
272
    {
 
273
      grub_free (symlink);
 
274
      return 0;
 
275
    }
 
276
  grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
 
277
  return symlink;
 
278
}
 
279
 
 
280
 
 
281
static int
 
282
grub_affs_iterate_dir (grub_fshelp_node_t dir,
 
283
                       int NESTED_FUNC_ATTR
 
284
                       (*hook) (const char *filename,
 
285
                                enum grub_fshelp_filetype filetype,
 
286
                                grub_fshelp_node_t node))
 
287
{
 
288
  int i;
 
289
  struct grub_affs_file file;
 
290
  struct grub_fshelp_node *node = 0;
 
291
  struct grub_affs_data *data = dir->data;
 
292
  grub_uint32_t *hashtable;
 
293
 
 
294
  auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
 
295
                                                   int size, int type);
 
296
 
 
297
  int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
 
298
                                              int size, int type)
 
299
    {
 
300
      node = grub_malloc (sizeof (*node));
 
301
      if (!node)
 
302
        {
 
303
          grub_free (hashtable);
 
304
          return 1;
 
305
        }
 
306
 
 
307
      node->data = data;
 
308
      node->size = size;
 
309
      node->block = block;
 
310
      node->parent = grub_be_to_cpu32 (file.parent);
 
311
 
 
312
      if (hook (name, type, node))
 
313
        {
 
314
          grub_free (hashtable);
 
315
          return 1;
 
316
        }
 
317
      return 0;
 
318
    }
 
319
 
 
320
  hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
 
321
  if (!hashtable)
 
322
    return 1;
 
323
 
 
324
  grub_disk_read (data->disk, dir->block, GRUB_AFFS_HASHTABLE_OFFSET,
 
325
                  data->htsize * sizeof (*hashtable), (char *) hashtable);
 
326
  if (grub_errno)
 
327
    goto fail;
 
328
 
 
329
  /* Create the directory entries for `.' and `..'.  */
 
330
  if (grub_affs_create_node (".", dir->block, dir->size, GRUB_FSHELP_DIR))
 
331
    return 1;
 
332
  if (grub_affs_create_node ("..", dir->parent ? dir->parent : dir->block,
 
333
                             dir->size, GRUB_FSHELP_DIR))
 
334
    return 1;
 
335
 
 
336
  for (i = 0; i < data->htsize; i++)
 
337
    {
 
338
      enum grub_fshelp_filetype type;
 
339
      grub_uint64_t next;
 
340
 
 
341
      if (!hashtable[i])
 
342
        continue;
 
343
 
 
344
      /* Every entry in the hashtable can be chained.  Read the entire
 
345
         chain.  */
 
346
      next = grub_be_to_cpu32 (hashtable[i]);
 
347
 
 
348
      while (next)
 
349
        {
 
350
          grub_disk_read (data->disk, next + data->blocksize - 1,
 
351
                          data->blocksize * GRUB_DISK_SECTOR_SIZE
 
352
                          - GRUB_AFFS_FILE_LOCATION,
 
353
                          sizeof (file), (char *) &file);
 
354
          if (grub_errno)
 
355
            goto fail;
 
356
 
 
357
          file.name[file.namelen] = '\0';
 
358
 
 
359
          if ((int) grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_DIR)
 
360
            type = GRUB_FSHELP_REG;
 
361
          else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_REG)
 
362
            type = GRUB_FSHELP_DIR;
 
363
          else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_SYMLINK)
 
364
            type = GRUB_FSHELP_SYMLINK;
 
365
          else
 
366
            type = GRUB_FSHELP_UNKNOWN;
 
367
 
 
368
          if (grub_affs_create_node ((char *) (file.name), next,
 
369
                                     grub_be_to_cpu32 (file.size), type))
 
370
            return 1;
 
371
 
 
372
          next = grub_be_to_cpu32 (file.next);
 
373
        }
 
374
    }
 
375
 
 
376
  grub_free (hashtable);
 
377
  return 0;
 
378
 
 
379
 fail:
 
380
  grub_free (node);
 
381
  grub_free (hashtable);
 
382
  return 0;
 
383
}
 
384
 
 
385
 
 
386
/* Open a file named NAME and initialize FILE.  */
 
387
static grub_err_t
 
388
grub_affs_open (struct grub_file *file, const char *name)
 
389
{
 
390
  struct grub_affs_data *data;
 
391
  struct grub_fshelp_node *fdiro = 0;
 
392
 
 
393
  grub_dl_ref (my_mod);
 
394
 
 
395
  data = grub_affs_mount (file->device->disk);
 
396
  if (!data)
 
397
    goto fail;
 
398
 
 
399
  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_affs_iterate_dir,
 
400
                         grub_affs_read_symlink, GRUB_FSHELP_REG);
 
401
  if (grub_errno)
 
402
    goto fail;
 
403
 
 
404
  file->size = fdiro->size;
 
405
  data->diropen = *fdiro;
 
406
  grub_free (fdiro);
 
407
 
 
408
  file->data = data;
 
409
  file->offset = 0;
 
410
 
 
411
  return 0;
 
412
 
 
413
 fail:
 
414
  if (data && fdiro != &data->diropen)
 
415
    grub_free (fdiro);
 
416
  grub_free (data);
 
417
 
 
418
  grub_dl_unref (my_mod);
 
419
 
 
420
  return grub_errno;
 
421
}
 
422
 
 
423
 
 
424
static grub_err_t
 
425
grub_affs_close (grub_file_t file)
 
426
{
 
427
  grub_free (file->data);
 
428
 
 
429
  grub_dl_unref (my_mod);
 
430
 
 
431
  return GRUB_ERR_NONE;
 
432
}
 
433
 
 
434
 
 
435
/* Read LEN bytes data from FILE into BUF.  */
 
436
static grub_ssize_t
 
437
grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
 
438
{
 
439
  struct grub_affs_data *data =
 
440
    (struct grub_affs_data *) file->data;
 
441
 
 
442
  int size = grub_affs_read_file (&data->diropen, file->read_hook,
 
443
                              file->offset, len, buf);
 
444
 
 
445
  return size;
 
446
}
 
447
 
 
448
 
 
449
static grub_err_t
 
450
grub_affs_dir (grub_device_t device, const char *path,
 
451
               int (*hook) (const char *filename,
 
452
                            const struct grub_dirhook_info *info))
 
453
{
 
454
  struct grub_affs_data *data = 0;
 
455
  struct grub_fshelp_node *fdiro = 0;
 
456
 
 
457
  auto int NESTED_FUNC_ATTR iterate (const char *filename,
 
458
                                     enum grub_fshelp_filetype filetype,
 
459
                                     grub_fshelp_node_t node);
 
460
 
 
461
  int NESTED_FUNC_ATTR iterate (const char *filename,
 
462
                                enum grub_fshelp_filetype filetype,
 
463
                                grub_fshelp_node_t node)
 
464
    {
 
465
      struct grub_dirhook_info info;
 
466
      grub_memset (&info, 0, sizeof (info));
 
467
      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
 
468
      grub_free (node);
 
469
      return hook (filename, &info);
 
470
    }
 
471
 
 
472
  grub_dl_ref (my_mod);
 
473
 
 
474
  data = grub_affs_mount (device->disk);
 
475
  if (!data)
 
476
    goto fail;
 
477
 
 
478
  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_affs_iterate_dir,
 
479
                         grub_affs_read_symlink, GRUB_FSHELP_DIR);
 
480
  if (grub_errno)
 
481
    goto fail;
 
482
 
 
483
  grub_affs_iterate_dir (fdiro, iterate);
 
484
 
 
485
 fail:
 
486
  if (data && fdiro != &data->diropen)
 
487
    grub_free (fdiro);
 
488
  grub_free (data);
 
489
 
 
490
  grub_dl_unref (my_mod);
 
491
 
 
492
  return grub_errno;
 
493
}
 
494
 
 
495
 
 
496
static grub_err_t
 
497
grub_affs_label (grub_device_t device, char **label)
 
498
{
 
499
  struct grub_affs_data *data;
 
500
  struct grub_affs_file file;
 
501
  grub_disk_t disk = device->disk;
 
502
 
 
503
  grub_dl_ref (my_mod);
 
504
 
 
505
  data = grub_affs_mount (disk);
 
506
  if (data)
 
507
    {
 
508
      /* The rootblock maps quite well on a file header block, it's
 
509
         something we can use here.  */
 
510
      grub_disk_read (data->disk, disk->total_sectors >> 1,
 
511
                      data->blocksize * (GRUB_DISK_SECTOR_SIZE
 
512
                                         - GRUB_AFFS_FILE_LOCATION),
 
513
                      sizeof (file), &file);
 
514
      if (grub_errno)
 
515
        return 0;
 
516
 
 
517
      *label = grub_strndup ((char *) (file.name), file.namelen);
 
518
    }
 
519
  else
 
520
    *label = 0;
 
521
 
 
522
  grub_dl_unref (my_mod);
 
523
 
 
524
  grub_free (data);
 
525
 
 
526
  return grub_errno;
 
527
}
 
528
 
 
529
 
 
530
static struct grub_fs grub_affs_fs =
 
531
  {
 
532
    .name = "affs",
 
533
    .dir = grub_affs_dir,
 
534
    .open = grub_affs_open,
 
535
    .read = grub_affs_read,
 
536
    .close = grub_affs_close,
 
537
    .label = grub_affs_label,
 
538
    .next = 0
 
539
  };
 
540
 
 
541
GRUB_MOD_INIT(affs)
 
542
{
 
543
  grub_fs_register (&grub_affs_fs);
 
544
  my_mod = mod;
 
545
}
 
546
 
 
547
GRUB_MOD_FINI(affs)
 
548
{
 
549
  grub_fs_unregister (&grub_affs_fs);
 
550
}