~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): Mario Limonciello
  • Date: 2008-05-27 11:32:41 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20080527113241-033nau9g4yfsr5ps
Tags: 1.96+20080512-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Adjust debian/default/grub for default Ubuntu boot options.

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