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

« back to all changes in this revision

Viewing changes to fs/afs.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
 
/* 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
 
}