]> git.proxmox.com Git - grub2.git/blob - fs/afs.c
merge mtrunk into xnu
[grub2.git] / fs / afs.c
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 }