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

« back to all changes in this revision

Viewing changes to fs/afs.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
 
/* afs.c - The native AtheOS file-system.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 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
 
#ifdef MODE_BIGENDIAN
30
 
#define GRUB_AFS_FSNAME_SUFFIX "_be"
31
 
#else
32
 
#define GRUB_AFS_FSNAME_SUFFIX ""
33
 
#endif
34
 
 
35
 
#ifdef MODE_BFS
36
 
#define GRUB_AFS_FSNAME "befs" GRUB_AFS_FSNAME_SUFFIX
37
 
#else
38
 
#define GRUB_AFS_FSNAME "afs" GRUB_AFS_FSNAME_SUFFIX
39
 
#endif
40
 
 
41
 
#define GRUB_AFS_DIRECT_BLOCK_COUNT     12
42
 
#define GRUB_AFS_BLOCKS_PER_DI_RUN      4
43
 
 
44
 
#ifdef MODE_BFS
45
 
#define GRUB_AFS_SBLOCK_SECTOR 1
46
 
#define GRUB_AFS_SBLOCK_MAGIC1  0x42465331 /* BFS1.  */
47
 
#else
48
 
#define GRUB_AFS_SBLOCK_SECTOR 2
49
 
#define GRUB_AFS_SBLOCK_MAGIC1  0x41465331 /* AFS1.  */
50
 
#endif
51
 
 
52
 
#define GRUB_AFS_SBLOCK_MAGIC2  0xdd121031
53
 
#define GRUB_AFS_SBLOCK_MAGIC3  0x15b6830e
54
 
 
55
 
#define GRUB_AFS_INODE_MAGIC    0x64358428
56
 
 
57
 
#ifdef MODE_BFS
58
 
#define GRUB_AFS_BTREE_MAGIC    0x69f6c2e8
59
 
#else
60
 
#define GRUB_AFS_BTREE_MAGIC    0x65768995
61
 
#endif
62
 
 
63
 
#define GRUB_AFS_BNODE_SIZE     1024
64
 
 
65
 
#define GRUB_AFS_S_IFMT         00170000
66
 
#define GRUB_AFS_S_IFLNK        0120000
67
 
 
68
 
#define GRUB_AFS_S_IFREG        0100000
69
 
#define GRUB_AFS_S_IFDIR        0040000
70
 
#define GRUB_AFS_S_IFIFO        0010000
71
 
 
72
 
#define GRUB_AFS_NULL_VAL       ((grub_afs_bvalue_t)-1)
73
 
 
74
 
#ifdef MODE_BIGENDIAN
75
 
#define grub_afs_to_cpu16(x) grub_be_to_cpu16 (x)
76
 
#define grub_afs_to_cpu32(x) grub_be_to_cpu32 (x)
77
 
#define grub_afs_to_cpu64(x) grub_be_to_cpu64 (x)
78
 
#else
79
 
#define grub_afs_to_cpu16(x) grub_le_to_cpu16 (x)
80
 
#define grub_afs_to_cpu32(x) grub_le_to_cpu32 (x)
81
 
#define grub_afs_to_cpu64(x) grub_le_to_cpu64 (x)
82
 
#endif
83
 
 
84
 
#ifdef MODE_BFS
85
 
#define B_KEY_INDEX_ALIGN 8
86
 
#else
87
 
#define B_KEY_INDEX_ALIGN 4
88
 
#endif
89
 
 
90
 
#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \
91
 
                                  ((char *) (node) \
92
 
                                   + ALIGN_UP (sizeof (struct grub_afs_bnode) \
93
 
                                               + node->key_size, \
94
 
                                               B_KEY_INDEX_ALIGN)))
95
 
 
96
 
#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \
97
 
                                   ((char *) B_KEY_INDEX_OFFSET (node) + \
98
 
                                    node->key_count * 2))
99
 
 
100
 
typedef grub_uint64_t grub_afs_off_t;
101
 
typedef grub_uint64_t grub_afs_bigtime;
102
 
typedef grub_uint64_t grub_afs_bvalue_t;
103
 
 
104
 
struct grub_afs_blockrun
105
 
{
106
 
  grub_uint32_t group;
107
 
  grub_uint16_t start;
108
 
  grub_uint16_t len;
109
 
} __attribute__ ((packed));
110
 
 
111
 
struct grub_afs_datastream
112
 
{
113
 
  struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT];
114
 
  grub_afs_off_t max_direct_range;
115
 
  struct grub_afs_blockrun indirect;
116
 
  grub_afs_off_t max_indirect_range;
117
 
  struct grub_afs_blockrun double_indirect;
118
 
  grub_afs_off_t max_double_indirect_range;
119
 
  grub_afs_off_t size;
120
 
} __attribute__ ((packed));
121
 
 
122
 
struct grub_afs_bnode
123
 
{
124
 
  grub_afs_bvalue_t left;
125
 
  grub_afs_bvalue_t right;
126
 
  grub_afs_bvalue_t overflow;
127
 
#ifdef MODE_BFS
128
 
  grub_uint16_t key_count;
129
 
  grub_uint16_t key_size;
130
 
#else
131
 
  grub_uint32_t key_count;
132
 
  grub_uint32_t key_size;
133
 
#endif
134
 
  char key_data[0];
135
 
} __attribute__ ((packed));
136
 
 
137
 
#ifdef MODE_BFS
138
 
struct grub_afs_btree
139
 
{
140
 
  grub_uint32_t magic;
141
 
  grub_uint32_t unused1;
142
 
  grub_uint32_t tree_depth;
143
 
  grub_uint32_t unused2;
144
 
  grub_afs_bvalue_t root;
145
 
  grub_uint32_t unused3[4];
146
 
} __attribute__ ((packed));
147
 
#else
148
 
struct grub_afs_btree
149
 
{
150
 
  grub_uint32_t magic;
151
 
  grub_afs_bvalue_t root;
152
 
  grub_uint32_t tree_depth;
153
 
  grub_afs_bvalue_t last_node;
154
 
  grub_afs_bvalue_t first_free;
155
 
} __attribute__ ((packed));
156
 
#endif
157
 
 
158
 
/* Beware that following structure describes AtheFS and if you write code
159
 
   which uses currently unused fields check it with both AtheFS and BeFS.
160
 
 */
161
 
struct grub_afs_sblock
162
 
{
163
 
  char name[32];
164
 
  grub_uint32_t magic1;
165
 
  grub_uint32_t byte_order;
166
 
  grub_uint32_t block_size;
167
 
  grub_uint32_t block_shift;
168
 
  grub_afs_off_t num_blocks;
169
 
  grub_afs_off_t used_blocks;
170
 
  grub_uint32_t inode_size;
171
 
  grub_uint32_t magic2;
172
 
  grub_uint32_t block_per_group; /* Number of blocks per allocation
173
 
                                    group. (Max 65536)  */
174
 
  grub_uint32_t alloc_group_shift; /* Number of bits to shift a group
175
 
                                      number to get a byte address.  */
176
 
  grub_uint32_t alloc_group_count;
177
 
  grub_uint32_t flags;
178
 
  struct grub_afs_blockrun log_block;
179
 
  grub_afs_off_t log_start;
180
 
  grub_uint32_t valid_log_blocks;
181
 
  grub_uint32_t log_size;
182
 
  grub_uint32_t magic3;
183
 
  struct grub_afs_blockrun root_dir; /* Root dir inode.  */
184
 
  struct grub_afs_blockrun deleted_files; /* Directory containing files
185
 
                                             scheduled for deletion.  */
186
 
  struct grub_afs_blockrun index_dir; /* Directory of index files.  */
187
 
  grub_uint32_t boot_loader_size;
188
 
  grub_uint32_t pad[7];
189
 
}  __attribute__ ((packed));
190
 
 
191
 
struct grub_afs_inode
192
 
{
193
 
  grub_uint32_t magic1;
194
 
  struct grub_afs_blockrun inode_num;
195
 
  grub_uint32_t uid;
196
 
  grub_uint32_t gid;
197
 
  grub_uint32_t mode;
198
 
  grub_uint32_t flags;
199
 
#ifndef MODE_BFS
200
 
  grub_uint32_t link_count;
201
 
#endif
202
 
  grub_afs_bigtime create_time;
203
 
  grub_afs_bigtime modified_time;
204
 
  struct grub_afs_blockrun parent;
205
 
  struct grub_afs_blockrun attrib_dir;
206
 
  grub_uint32_t index_type; /* Key data-key only used for index files. */
207
 
  grub_uint32_t inode_size;
208
 
  grub_uint32_t unused;
209
 
  struct grub_afs_datastream stream;
210
 
  grub_uint32_t pad[4];
211
 
  grub_uint32_t small_data[1];
212
 
} __attribute__ ((packed));
213
 
 
214
 
struct grub_fshelp_node
215
 
{
216
 
  struct grub_afs_data *data;
217
 
  struct grub_afs_inode inode;
218
 
};
219
 
 
220
 
struct grub_afs_data
221
 
{
222
 
  grub_disk_t disk;
223
 
  struct grub_afs_sblock sblock;
224
 
  struct grub_afs_inode *inode;
225
 
  struct grub_fshelp_node diropen;
226
 
};
227
 
 
228
 
static grub_dl_t my_mod;
229
 
 
230
 
static grub_afs_off_t
231
 
grub_afs_run_to_num (struct grub_afs_sblock *sb,
232
 
                     struct grub_afs_blockrun *run)
233
 
{
234
 
  return ((grub_afs_off_t) grub_afs_to_cpu32 (run->group)
235
 
          * sb->block_per_group + grub_afs_to_cpu16 (run->start));
236
 
}
237
 
 
238
 
static grub_err_t
239
 
grub_afs_read_inode (struct grub_afs_data *data,
240
 
                     grub_uint32_t ino, struct grub_afs_inode *inode)
241
 
{
242
 
  return grub_disk_read (data->disk,
243
 
                         ino *
244
 
                         (data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
245
 
                         0, sizeof (struct grub_afs_inode),
246
 
                         inode);
247
 
}
248
 
 
249
 
static grub_disk_addr_t
250
 
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
251
 
{
252
 
  struct grub_afs_sblock *sb = &node->data->sblock;
253
 
  struct grub_afs_datastream *ds = &node->inode.stream;
254
 
 
255
 
  if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range))
256
 
    {
257
 
      int i;
258
 
 
259
 
      for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++)
260
 
        {
261
 
          if (fileblock < grub_afs_to_cpu16 (ds->direct[i].len))
262
 
            return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
263
 
          fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
264
 
        }
265
 
    }
266
 
  else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range))
267
 
    {
268
 
      int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
269
 
      struct grub_afs_blockrun indir[ptrs_per_blk];
270
 
      grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
271
 
      int i;
272
 
 
273
 
      fileblock -= grub_afs_to_cpu64 (ds->max_direct_range);
274
 
      for (i = 0; i < ds->indirect.len; i++, blk++)
275
 
        {
276
 
          int j;
277
 
 
278
 
          if (grub_disk_read (node->data->disk,
279
 
                              blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
280
 
                              0, sizeof (indir),
281
 
                              indir))
282
 
            return 0;
283
 
 
284
 
          for (j = 0; j < ptrs_per_blk; j++)
285
 
            {
286
 
              if (fileblock < grub_afs_to_cpu16 (indir[j].len))
287
 
                return grub_afs_run_to_num (sb, &indir[j]) + fileblock;
288
 
 
289
 
              fileblock -= grub_afs_to_cpu16 (indir[j].len);
290
 
            }
291
 
        }
292
 
    }
293
 
  else
294
 
    {
295
 
      int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
296
 
      struct grub_afs_blockrun indir[ptrs_per_blk];
297
 
 
298
 
      /* ([idblk][idptr]) ([dblk][dptr]) [blk]  */
299
 
      int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range);
300
 
 
301
 
      int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
302
 
      int dblk_size = dptr_size * ptrs_per_blk;
303
 
      int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
304
 
      int idblk_size = idptr_size * ptrs_per_blk;
305
 
 
306
 
      int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
307
 
      int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
308
 
      int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
309
 
      int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
310
 
      int idblk = (cur_pos / idblk_size);
311
 
 
312
 
      if (grub_disk_read (node->data->disk,
313
 
                          (grub_afs_run_to_num (sb, &ds->double_indirect)
314
 
                           + idblk) *
315
 
                          (sb->block_size >> GRUB_DISK_SECTOR_BITS),
316
 
                          0, sizeof (indir),
317
 
                          indir))
318
 
        return 0;
319
 
 
320
 
      if (grub_disk_read (node->data->disk,
321
 
                          (grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
322
 
                          (sb->block_size >> GRUB_DISK_SECTOR_BITS),
323
 
                          0, sizeof (indir),
324
 
                          indir))
325
 
        return 0;
326
 
 
327
 
      return grub_afs_run_to_num (sb, &indir[dptr]) + off;
328
 
    }
329
 
 
330
 
  return 0;
331
 
}
332
 
 
333
 
static grub_ssize_t
334
 
grub_afs_read_file (grub_fshelp_node_t node,
335
 
                    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
336
 
                                                        unsigned offset, unsigned length),
337
 
                    int pos, grub_size_t len, char *buf)
338
 
{
339
 
  return grub_fshelp_read_file (node->data->disk, node, read_hook,
340
 
                                pos, len, buf, grub_afs_read_block,
341
 
                                grub_afs_to_cpu64 (node->inode.stream.size),
342
 
                                node->data->sblock.block_shift
343
 
                                - GRUB_DISK_SECTOR_BITS);
344
 
}
345
 
 
346
 
static char *
347
 
grub_afs_read_symlink (grub_fshelp_node_t node)
348
 
{
349
 
  char *ret;
350
 
  grub_afs_off_t size = grub_afs_to_cpu64 (node->inode.stream.size);
351
 
 
352
 
  if (size == 0)
353
 
    {
354
 
      size = sizeof (node->inode.stream);
355
 
      ret = grub_zalloc (size + 1);
356
 
      if (! ret)
357
 
        return 0;
358
 
      grub_memcpy (ret, (char *) &(node->inode.stream),
359
 
                   sizeof (node->inode.stream));
360
 
      return ret;
361
 
    }
362
 
  ret = grub_zalloc (size + 1);
363
 
  if (! ret)
364
 
    return 0;
365
 
  grub_afs_read_file (node, 0, 0, size, ret);
366
 
  return ret;
367
 
}
368
 
 
369
 
static int
370
 
grub_afs_iterate_dir (grub_fshelp_node_t dir,
371
 
                      int NESTED_FUNC_ATTR
372
 
                      (*hook) (const char *filename,
373
 
                               enum grub_fshelp_filetype filetype,
374
 
                               grub_fshelp_node_t node))
375
 
{
376
 
  struct grub_afs_btree head;
377
 
  char node_data [GRUB_AFS_BNODE_SIZE];
378
 
  struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data;
379
 
  int i;
380
 
 
381
 
  if ((dir->inode.stream.size == 0)
382
 
      || ((grub_afs_to_cpu32 (dir->inode.mode) & GRUB_AFS_S_IFMT)
383
 
          != GRUB_AFS_S_IFDIR))
384
 
    return 0;
385
 
 
386
 
  grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head);
387
 
  if (grub_errno)
388
 
    return 0;
389
 
 
390
 
  grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (head.root),
391
 
                      GRUB_AFS_BNODE_SIZE, (char *) node);
392
 
  if (grub_errno)
393
 
    return 0;
394
 
 
395
 
  for (i = 0; i < (int) grub_afs_to_cpu32 (head.tree_depth) - 1; i++)
396
 
    {
397
 
      grub_afs_bvalue_t blk;
398
 
 
399
 
      blk = grub_afs_to_cpu64(B_KEY_VALUE_OFFSET (node) [0]);
400
 
      grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node);
401
 
      if (grub_errno)
402
 
        return 0;
403
 
    }
404
 
 
405
 
  if (node->key_count)
406
 
    {
407
 
      grub_uint32_t cur_key = 0;
408
 
 
409
 
      while (1)
410
 
        {
411
 
          int key_start, key_size;
412
 
          grub_uint16_t *index;
413
 
 
414
 
          index = B_KEY_INDEX_OFFSET (node);
415
 
 
416
 
          key_start = (cur_key > 0)
417
 
            ? grub_afs_to_cpu16 (index[cur_key - 1]) : 0;
418
 
          key_size = grub_afs_to_cpu16 (index[cur_key]) - key_start;
419
 
          if (key_size > 0)
420
 
            {
421
 
              char filename [key_size + 1];
422
 
              struct grub_fshelp_node *fdiro;
423
 
              int mode, type;
424
 
 
425
 
              fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
426
 
              if (! fdiro)
427
 
                return 0;
428
 
 
429
 
              fdiro->data = dir->data;
430
 
              if (grub_afs_read_inode (dir->data,
431
 
                                       grub_afs_to_cpu64
432
 
                                       (B_KEY_VALUE_OFFSET (node) [cur_key]),
433
 
                                       &fdiro->inode))
434
 
                return 0;
435
 
 
436
 
              grub_memcpy (filename, &node->key_data[key_start], key_size);
437
 
              filename [key_size] = 0;
438
 
 
439
 
              mode = (grub_afs_to_cpu32 (fdiro->inode.mode) & GRUB_AFS_S_IFMT);
440
 
              if (mode == GRUB_AFS_S_IFDIR)
441
 
                type = GRUB_FSHELP_DIR;
442
 
              else if (mode == GRUB_AFS_S_IFREG)
443
 
                type = GRUB_FSHELP_REG;
444
 
              else if (mode == GRUB_AFS_S_IFLNK)
445
 
                type = GRUB_FSHELP_SYMLINK;
446
 
              else
447
 
                type = GRUB_FSHELP_UNKNOWN;
448
 
 
449
 
              if (hook (filename, type, fdiro))
450
 
                return 1;
451
 
            }
452
 
 
453
 
          cur_key++;
454
 
          if (cur_key >= grub_afs_to_cpu32 (node->key_count))
455
 
            {
456
 
              if (node->right == GRUB_AFS_NULL_VAL)
457
 
                break;
458
 
 
459
 
              grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (node->right),
460
 
                                  GRUB_AFS_BNODE_SIZE, (char *) node);
461
 
              if (grub_errno)
462
 
                return 0;
463
 
 
464
 
              cur_key = 0;
465
 
            }
466
 
        }
467
 
    }
468
 
 
469
 
  return 0;
470
 
}
471
 
 
472
 
static int
473
 
grub_afs_validate_sblock (struct grub_afs_sblock *sb)
474
 
{
475
 
  if (grub_afs_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
476
 
    {
477
 
      sb->magic2 = grub_afs_to_cpu32 (sb->magic2);
478
 
      sb->magic3 = grub_afs_to_cpu32 (sb->magic3);
479
 
      sb->block_shift = grub_afs_to_cpu32 (sb->block_shift);
480
 
      sb->block_size = grub_afs_to_cpu32 (sb->block_size);
481
 
      sb->used_blocks = grub_afs_to_cpu64 (sb->used_blocks);
482
 
      sb->num_blocks = grub_afs_to_cpu64 (sb->num_blocks);
483
 
      sb->inode_size = grub_afs_to_cpu32 (sb->inode_size);
484
 
      sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
485
 
      sb->alloc_group_shift = grub_afs_to_cpu32 (sb->alloc_group_shift);
486
 
      sb->block_per_group = grub_afs_to_cpu32 (sb->block_per_group);
487
 
      sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
488
 
      sb->log_size = grub_afs_to_cpu32 (sb->log_size);
489
 
    }
490
 
  else
491
 
    return 0;
492
 
 
493
 
  if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) ||
494
 
      (sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3))
495
 
    return 0;
496
 
 
497
 
#ifdef MODE_BFS
498
 
  sb->block_per_group = 1 << (sb->alloc_group_shift);
499
 
#endif
500
 
 
501
 
  if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size)
502
 
      || (sb->used_blocks > sb->num_blocks )
503
 
      || (sb->inode_size != sb->block_size)
504
 
      || (0 == sb->block_size)
505
 
#ifndef MODE_BFS
506
 
      || ((grub_uint32_t) (1 << sb->alloc_group_shift) !=
507
 
          sb->block_per_group * sb->block_size)
508
 
      || (sb->alloc_group_count * sb->block_per_group < sb->num_blocks)
509
 
      || (grub_afs_to_cpu16 (sb->log_block.len) != sb->log_size)
510
 
      || (grub_afs_to_cpu32 (sb->valid_log_blocks) > sb->log_size)
511
 
#endif
512
 
      )
513
 
    return 0;
514
 
 
515
 
  return 1;
516
 
}
517
 
 
518
 
static struct grub_afs_data *
519
 
grub_afs_mount (grub_disk_t disk)
520
 
{
521
 
  struct grub_afs_data *data = 0;
522
 
 
523
 
  data = grub_malloc (sizeof (struct grub_afs_data));
524
 
  if (!data)
525
 
    return 0;
526
 
 
527
 
  /* Read the superblock.  */
528
 
  if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
529
 
                      sizeof (struct grub_afs_sblock), &data->sblock))
530
 
    goto fail;
531
 
 
532
 
  if (! grub_afs_validate_sblock (&data->sblock))
533
 
    goto fail;
534
 
 
535
 
  data->diropen.data = data;
536
 
  data->inode = &data->diropen.inode;
537
 
  data->disk = disk;
538
 
 
539
 
  if (grub_afs_read_inode (data,
540
 
                           grub_afs_run_to_num (&data->sblock,
541
 
                                                &data->sblock.root_dir),
542
 
                           data->inode))
543
 
    goto fail;
544
 
 
545
 
  return data;
546
 
 
547
 
fail:
548
 
  grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
549
 
 
550
 
  grub_free (data);
551
 
  return 0;
552
 
}
553
 
 
554
 
static grub_err_t
555
 
grub_afs_open (struct grub_file *file, const char *name)
556
 
{
557
 
  struct grub_afs_data *data;
558
 
  struct grub_fshelp_node *fdiro = 0;
559
 
 
560
 
  grub_dl_ref (my_mod);
561
 
 
562
 
  data = grub_afs_mount (file->device->disk);
563
 
  if (! data)
564
 
    goto fail;
565
 
 
566
 
  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir,
567
 
                         grub_afs_read_symlink, GRUB_FSHELP_REG);
568
 
  if (grub_errno)
569
 
    goto fail;
570
 
 
571
 
  grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode));
572
 
  grub_free (fdiro);
573
 
 
574
 
  file->size = grub_afs_to_cpu64 (data->inode->stream.size);
575
 
  file->data = data;
576
 
  file->offset = 0;
577
 
 
578
 
  return 0;
579
 
 
580
 
fail:
581
 
  grub_free (data);
582
 
 
583
 
  grub_dl_unref (my_mod);
584
 
 
585
 
  return grub_errno;
586
 
}
587
 
 
588
 
static grub_ssize_t
589
 
grub_afs_read (grub_file_t file, char *buf, grub_size_t len)
590
 
{
591
 
  struct grub_afs_data *data = (struct grub_afs_data *) file->data;
592
 
 
593
 
  return grub_afs_read_file (&data->diropen, file->read_hook,
594
 
                             file->offset, len, buf);
595
 
}
596
 
 
597
 
static grub_err_t
598
 
grub_afs_close (grub_file_t file)
599
 
{
600
 
  grub_free (file->data);
601
 
 
602
 
  grub_dl_unref (my_mod);
603
 
 
604
 
  return GRUB_ERR_NONE;
605
 
}
606
 
 
607
 
static grub_err_t
608
 
grub_afs_dir (grub_device_t device, const char *path,
609
 
              int (*hook) (const char *filename,
610
 
                           const struct grub_dirhook_info *info))
611
 
{
612
 
  struct grub_afs_data *data = 0;
613
 
  struct grub_fshelp_node *fdiro = 0;
614
 
 
615
 
  auto int NESTED_FUNC_ATTR iterate (const char *filename,
616
 
                                     enum grub_fshelp_filetype filetype,
617
 
                                     grub_fshelp_node_t node);
618
 
 
619
 
  int NESTED_FUNC_ATTR iterate (const char *filename,
620
 
                                enum grub_fshelp_filetype filetype,
621
 
                                grub_fshelp_node_t node)
622
 
    {
623
 
      struct grub_dirhook_info info;
624
 
      grub_memset (&info, 0, sizeof (info));
625
 
      info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
626
 
      info.mtimeset = 1;
627
 
#ifdef MODE_BFS
628
 
      info.mtime = grub_afs_to_cpu64 (node->inode.modified_time) >> 16;
629
 
#else
630
 
      info.mtime = grub_divmod64 (grub_afs_to_cpu64 (node->inode.modified_time),
631
 
                                  1000000, 0);
632
 
#endif
633
 
      grub_free (node);
634
 
      return hook (filename, &info);
635
 
    }
636
 
 
637
 
  grub_dl_ref (my_mod);
638
 
 
639
 
  data = grub_afs_mount (device->disk);
640
 
  if (! data)
641
 
    goto fail;
642
 
 
643
 
  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir,
644
 
                         grub_afs_read_symlink, GRUB_FSHELP_DIR);
645
 
  if (grub_errno)
646
 
    goto fail;
647
 
 
648
 
  grub_afs_iterate_dir (fdiro, iterate);
649
 
 
650
 
  if (fdiro != &data->diropen)
651
 
    grub_free (fdiro);
652
 
 
653
 
 fail:
654
 
  grub_free (data);
655
 
 
656
 
  grub_dl_unref (my_mod);
657
 
 
658
 
  return grub_errno;
659
 
}
660
 
 
661
 
static grub_err_t
662
 
grub_afs_label (grub_device_t device, char **label)
663
 
{
664
 
  struct grub_afs_data *data;
665
 
  grub_disk_t disk = device->disk;
666
 
 
667
 
  grub_dl_ref (my_mod);
668
 
 
669
 
  data = grub_afs_mount (disk);
670
 
  if (data)
671
 
    *label = grub_strndup (data->sblock.name, sizeof (data->sblock.name));
672
 
  else
673
 
    *label = NULL;
674
 
 
675
 
  grub_dl_unref (my_mod);
676
 
 
677
 
  grub_free (data);
678
 
 
679
 
  return grub_errno;
680
 
}
681
 
 
682
 
 
683
 
static struct grub_fs grub_afs_fs = {
684
 
  .name = GRUB_AFS_FSNAME,
685
 
  .dir = grub_afs_dir,
686
 
  .open = grub_afs_open,
687
 
  .read = grub_afs_read,
688
 
  .close = grub_afs_close,
689
 
  .label = grub_afs_label,
690
 
  .next = 0
691
 
};
692
 
 
693
 
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
694
 
GRUB_MOD_INIT (befs_be)
695
 
#elif defined (MODE_BFS)
696
 
GRUB_MOD_INIT (befs)
697
 
#elif defined (MODE_BIGENDIAN)
698
 
GRUB_MOD_INIT (afs_be)
699
 
#else
700
 
GRUB_MOD_INIT (afs)
701
 
#endif
702
 
{
703
 
  grub_fs_register (&grub_afs_fs);
704
 
  my_mod = mod;
705
 
}
706
 
 
707
 
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
708
 
GRUB_MOD_FINI (befs_be)
709
 
#elif defined (MODE_BFS)
710
 
GRUB_MOD_FINI (befs)
711
 
#elif defined (MODE_BIGENDIAN)
712
 
GRUB_MOD_FINI (afs_be)
713
 
#else
714
 
GRUB_MOD_FINI (afs)
715
 
#endif
716
 
{
717
 
  grub_fs_unregister (&grub_afs_fs);
718
 
}