~ilya-yanok/ubuntu/precise/grub2/fix-for-948716

« back to all changes in this revision

Viewing changes to fs/ext2.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2006-01-05 15:20:40 UTC
  • mto: (17.3.1 squeeze) (1.9.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20060105152040-b72i5pq1a82z22yi
Tags: upstream-1.92
ImportĀ upstreamĀ versionĀ 1.92

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ext2.c - Second Extended filesystem */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
 
5
 *
 
6
 *  This program 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 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program 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 this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 */
 
20
 
 
21
/* Magic value used to identify an ext2 filesystem.  */
 
22
#define EXT2_MAGIC              0xEF53
 
23
/* Amount of indirect blocks in an inode.  */
 
24
#define INDIRECT_BLOCKS         12
 
25
/* Maximum lenght of a pathname.  */
 
26
#define EXT2_PATH_MAX           4096
 
27
/* Maximum nesting of symlinks, used to prevent a loop.  */
 
28
#define EXT2_MAX_SYMLINKCNT     8
 
29
 
 
30
/* Filetype used in directory entry.  */
 
31
#define FILETYPE_UNKNOWN        0
 
32
#define FILETYPE_REG            1
 
33
#define FILETYPE_DIRECTORY      2
 
34
#define FILETYPE_SYMLINK        7
 
35
 
 
36
/* Filetype information as used in inodes.  */
 
37
#define FILETYPE_INO_MASK       0170000
 
38
#define FILETYPE_INO_REG        0100000
 
39
#define FILETYPE_INO_DIRECTORY  0040000
 
40
#define FILETYPE_INO_SYMLINK    0120000
 
41
 
 
42
#include <grub/err.h>
 
43
#include <grub/file.h>
 
44
#include <grub/mm.h>
 
45
#include <grub/misc.h>
 
46
#include <grub/disk.h>
 
47
#include <grub/dl.h>
 
48
#include <grub/types.h>
 
49
#include <grub/fshelp.h>
 
50
 
 
51
/* Log2 size of ext2 block in 512 blocks.  */
 
52
#define LOG2_EXT2_BLOCK_SIZE(data)                      \
 
53
        (grub_le_to_cpu32 (data->sblock.log2_block_size) + 1)
 
54
     
 
55
/* Log2 size of ext2 block in bytes.  */
 
56
#define LOG2_BLOCK_SIZE(data)                                   \
 
57
        (grub_le_to_cpu32 (data->sblock.log2_block_size) + 10)
 
58
 
 
59
/* The size of an ext2 block in bytes.  */
 
60
#define EXT2_BLOCK_SIZE(data)           (1 << LOG2_BLOCK_SIZE(data))
 
61
 
 
62
/* The ext2 superblock.  */
 
63
struct grub_ext2_sblock
 
64
{
 
65
  grub_uint32_t total_inodes;
 
66
  grub_uint32_t total_blocks;
 
67
  grub_uint32_t reserved_blocks;
 
68
  grub_uint32_t free_blocks;
 
69
  grub_uint32_t free_inodes;
 
70
  grub_uint32_t first_data_block;
 
71
  grub_uint32_t log2_block_size;
 
72
  grub_uint32_t log2_fragment_size;
 
73
  grub_uint32_t blocks_per_group;
 
74
  grub_uint32_t fragments_per_group;
 
75
  grub_uint32_t inodes_per_group;
 
76
  grub_uint32_t mtime;
 
77
  grub_uint32_t utime;
 
78
  grub_uint16_t mnt_count;
 
79
  grub_uint16_t max_mnt_count;
 
80
  grub_uint16_t magic;
 
81
  grub_uint16_t fs_state;
 
82
  grub_uint16_t error_handling;
 
83
  grub_uint16_t minor_revision_level;
 
84
  grub_uint32_t lastcheck;
 
85
  grub_uint32_t checkinterval;
 
86
  grub_uint32_t creator_os;
 
87
  grub_uint32_t revision_level;
 
88
  grub_uint16_t uid_reserved;
 
89
  grub_uint16_t gid_reserved;
 
90
  grub_uint32_t first_inode;
 
91
  grub_uint16_t inode_size;
 
92
  grub_uint16_t block_group_number;
 
93
  grub_uint32_t feature_compatibility;
 
94
  grub_uint32_t feature_incompat;
 
95
  grub_uint32_t feature_ro_compat;
 
96
  grub_uint32_t unique_id[4];
 
97
  char volume_name[16];
 
98
  char last_mounted_on[64];
 
99
  grub_uint32_t compression_info;
 
100
};
 
101
 
 
102
/* The ext2 blockgroup.  */
 
103
struct grub_ext2_block_group
 
104
{
 
105
  grub_uint32_t block_id;
 
106
  grub_uint32_t inode_id;
 
107
  grub_uint32_t inode_table_id;
 
108
  grub_uint16_t free_blocks;
 
109
  grub_uint16_t free_inodes;
 
110
  grub_uint16_t pad;
 
111
  grub_uint32_t reserved[3];
 
112
};
 
113
 
 
114
/* The ext2 inode.  */
 
115
struct grub_ext2_inode
 
116
{
 
117
  grub_uint16_t mode;
 
118
  grub_uint16_t uid;
 
119
  grub_uint32_t size;
 
120
  grub_uint32_t atime;
 
121
  grub_uint32_t ctime;
 
122
  grub_uint32_t mtime;
 
123
  grub_uint32_t dtime;
 
124
  grub_uint16_t gid;
 
125
  grub_uint16_t nlinks;
 
126
  grub_uint32_t blockcnt;  /* Blocks of 512 bytes!! */
 
127
  grub_uint32_t flags;
 
128
  grub_uint32_t osd1;
 
129
  union
 
130
  {
 
131
    struct datablocks
 
132
    {
 
133
      grub_uint32_t dir_blocks[INDIRECT_BLOCKS];
 
134
      grub_uint32_t indir_block;
 
135
      grub_uint32_t double_indir_block;
 
136
      grub_uint32_t tripple_indir_block;
 
137
    } blocks;
 
138
    char symlink[60];
 
139
  };
 
140
  grub_uint32_t version;
 
141
  grub_uint32_t acl;
 
142
  grub_uint32_t dir_acl;
 
143
  grub_uint32_t fragment_addr;
 
144
  grub_uint32_t osd2[3];
 
145
};
 
146
 
 
147
/* The header of an ext2 directory entry.  */
 
148
struct ext2_dirent
 
149
{
 
150
  grub_uint32_t inode;
 
151
  grub_uint16_t direntlen;
 
152
  grub_uint8_t namelen;
 
153
  grub_uint8_t filetype;
 
154
};
 
155
 
 
156
struct grub_fshelp_node
 
157
{
 
158
  struct grub_ext2_data *data;
 
159
  struct grub_ext2_inode inode;
 
160
  int ino;
 
161
  int inode_read;
 
162
};
 
163
 
 
164
/* Information about a "mounted" ext2 filesystem.  */
 
165
struct grub_ext2_data
 
166
{
 
167
  struct grub_ext2_sblock sblock;
 
168
  grub_disk_t disk;
 
169
  struct grub_ext2_inode *inode;
 
170
  struct grub_fshelp_node diropen;
 
171
};
 
172
 
 
173
#ifndef GRUB_UTIL
 
174
static grub_dl_t my_mod;
 
175
#endif
 
176
 
 
177
/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
 
178
   the mounted filesystem DATA.  */
 
179
inline static grub_err_t
 
180
grub_ext2_blockgroup (struct grub_ext2_data *data, int group, 
 
181
                      struct grub_ext2_block_group *blkgrp)
 
182
{
 
183
  return grub_disk_read (data->disk,
 
184
                         ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
 
185
                          << LOG2_EXT2_BLOCK_SIZE (data)),
 
186
                         group * sizeof (struct grub_ext2_block_group), 
 
187
                         sizeof (struct grub_ext2_block_group), (char *) blkgrp);
 
188
}
 
189
 
 
190
 
 
191
static int
 
192
grub_ext2_read_block (grub_fshelp_node_t node, int fileblock)
 
193
{
 
194
  struct grub_ext2_data *data = node->data;
 
195
  struct grub_ext2_inode *inode = &node->inode;
 
196
  int blknr;
 
197
  int blksz = EXT2_BLOCK_SIZE (data);
 
198
  int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
 
199
  
 
200
  /* Direct blocks.  */
 
201
  if (fileblock < INDIRECT_BLOCKS)
 
202
    blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
 
203
  /* Indirect.  */
 
204
  else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
 
205
    {
 
206
      grub_uint32_t indir[blksz / 4];
 
207
 
 
208
      if (grub_disk_read (data->disk, 
 
209
                          grub_le_to_cpu32 (inode->blocks.indir_block)
 
210
                          << log2_blksz,
 
211
                          0, blksz, (char *) indir))
 
212
        return grub_errno;
 
213
          
 
214
      blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
 
215
    }
 
216
  /* Double indirect.  */
 
217
  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz  / 4 + 1))
 
218
    {
 
219
      unsigned int perblock = blksz / 4;
 
220
      unsigned int rblock = fileblock - (INDIRECT_BLOCKS 
 
221
                                         + blksz / 4);
 
222
      grub_uint32_t indir[blksz / 4];
 
223
 
 
224
      if (grub_disk_read (data->disk, 
 
225
                          grub_le_to_cpu32 (inode->blocks.double_indir_block) 
 
226
                          << log2_blksz,
 
227
                          0, blksz, (char *) indir))
 
228
        return grub_errno;
 
229
 
 
230
      if (grub_disk_read (data->disk,
 
231
                          grub_le_to_cpu32 (indir[rblock / perblock])
 
232
                          << log2_blksz,
 
233
                          0, blksz, (char *) indir))
 
234
        return grub_errno;
 
235
 
 
236
      
 
237
      blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
 
238
    }
 
239
  /* Tripple indirect.  */
 
240
  else
 
241
    {
 
242
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
 
243
                  "ext2fs doesn't support tripple indirect blocks");
 
244
      return grub_errno;
 
245
    }
 
246
 
 
247
  return blknr;
 
248
}
 
249
 
 
250
 
 
251
/* Read LEN bytes from the file described by DATA starting with byte
 
252
   POS.  Return the amount of read bytes in READ.  */
 
253
static grub_ssize_t
 
254
grub_ext2_read_file (grub_fshelp_node_t node,
 
255
                     void (*read_hook) (unsigned long sector,
 
256
                                        unsigned offset, unsigned length),
 
257
                     int pos, unsigned int len, char *buf)
 
258
{
 
259
  return grub_fshelp_read_file (node->data->disk, node, read_hook,
 
260
                                pos, len, buf, grub_ext2_read_block,
 
261
                                node->inode.size,
 
262
                                LOG2_EXT2_BLOCK_SIZE (node->data));
 
263
    
 
264
}
 
265
 
 
266
 
 
267
/* Read the inode INO for the file described by DATA into INODE.  */
 
268
static grub_err_t
 
269
grub_ext2_read_inode (struct grub_ext2_data *data,
 
270
                      int ino, struct grub_ext2_inode *inode)
 
271
{
 
272
  struct grub_ext2_block_group blkgrp;
 
273
  struct grub_ext2_sblock *sblock = &data->sblock;
 
274
  int inodes_per_block;
 
275
  
 
276
  unsigned int blkno;
 
277
  unsigned int blkoff;
 
278
 
 
279
  /* It is easier to calculate if the first inode is 0.  */
 
280
  ino--;
 
281
  
 
282
  grub_ext2_blockgroup (data, ino / grub_le_to_cpu32 (sblock->inodes_per_group),
 
283
                        &blkgrp);
 
284
  if (grub_errno)
 
285
    return grub_errno;
 
286
 
 
287
  inodes_per_block = EXT2_BLOCK_SIZE (data) / 128;
 
288
  blkno = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
 
289
    / inodes_per_block;
 
290
  blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
 
291
    % inodes_per_block;
 
292
  
 
293
  /* Read the inode.  */
 
294
  if (grub_disk_read (data->disk, 
 
295
                      ((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
 
296
                       << LOG2_EXT2_BLOCK_SIZE (data)),
 
297
                      sizeof (struct grub_ext2_inode) * blkoff,
 
298
                      sizeof (struct grub_ext2_inode), (char *) inode))
 
299
    return grub_errno;
 
300
  
 
301
  return 0;
 
302
}
 
303
 
 
304
static struct grub_ext2_data *
 
305
grub_ext2_mount (grub_disk_t disk)
 
306
{
 
307
  struct grub_ext2_data *data;
 
308
 
 
309
  data = grub_malloc (sizeof (struct grub_ext2_data));
 
310
  if (!data)
 
311
    return 0;
 
312
 
 
313
  /* Read the superblock.  */
 
314
  grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_ext2_sblock),
 
315
                        (char *) &data->sblock);
 
316
  if (grub_errno)
 
317
    goto fail;
 
318
 
 
319
  /* Make sure this is an ext2 filesystem.  */
 
320
  if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC)
 
321
    goto fail;
 
322
  
 
323
  data->diropen.data = data;
 
324
  data->diropen.ino = 2;
 
325
  data->diropen.inode_read = 1;
 
326
 
 
327
  data->inode = &data->diropen.inode;
 
328
  data->disk = disk;
 
329
 
 
330
  grub_ext2_read_inode (data, 2, data->inode);
 
331
  if (grub_errno)
 
332
    goto fail;
 
333
  
 
334
  return data;
 
335
 
 
336
 fail:
 
337
  grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
 
338
  grub_free (data);
 
339
  return 0;
 
340
}
 
341
 
 
342
static char *
 
343
grub_ext2_read_symlink (grub_fshelp_node_t node)
 
344
{
 
345
  char *symlink;
 
346
  struct grub_fshelp_node *diro = node;
 
347
  
 
348
  if (!diro->inode_read)
 
349
    {
 
350
      grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
 
351
      if (grub_errno)
 
352
        return 0;
 
353
    }
 
354
  
 
355
  symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
 
356
  if (!symlink)
 
357
    return 0;
 
358
  
 
359
  /* If the filesize of the symlink is bigger than
 
360
     60 the symlink is stored in a separate block,
 
361
     otherwise it is stored in the inode.  */
 
362
  if (grub_le_to_cpu32 (diro->inode.size) <= 60)
 
363
    grub_strncpy (symlink, 
 
364
                  diro->inode.symlink,
 
365
                  grub_le_to_cpu32 (diro->inode.size));
 
366
  else
 
367
    {
 
368
      grub_ext2_read_file (diro, 0, 0,
 
369
                           grub_le_to_cpu32 (diro->inode.size),
 
370
                           symlink);
 
371
      if (grub_errno)
 
372
        {
 
373
          grub_free (symlink);
 
374
          return 0;
 
375
        }
 
376
    }
 
377
  
 
378
  symlink[grub_le_to_cpu32 (diro->inode.size)] = '\0';
 
379
  return symlink;
 
380
}
 
381
 
 
382
static int
 
383
grub_ext2_iterate_dir (grub_fshelp_node_t dir,
 
384
                       int NESTED_FUNC_ATTR
 
385
                       (*hook) (const char *filename,
 
386
                                enum grub_fshelp_filetype filetype,
 
387
                                grub_fshelp_node_t node))
 
388
{
 
389
  unsigned int fpos = 0;
 
390
  struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
 
391
  
 
392
  if (!diro->inode_read)
 
393
    {
 
394
      grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
 
395
      if (grub_errno)
 
396
        return 0;
 
397
    }
 
398
  
 
399
  /* Search the file.  */
 
400
  while (fpos < grub_le_to_cpu32 (diro->inode.size))
 
401
    {
 
402
      struct ext2_dirent dirent;
 
403
 
 
404
      grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent),
 
405
                           (char *) &dirent);
 
406
      if (grub_errno)
 
407
        return 0;
 
408
      
 
409
      if (dirent.namelen != 0)
 
410
        {
 
411
          char filename[dirent.namelen + 1];
 
412
          struct grub_fshelp_node *fdiro;
 
413
          enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
 
414
          
 
415
          grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent),
 
416
                               dirent.namelen, filename);
 
417
          if (grub_errno)
 
418
            return 0;
 
419
          
 
420
          fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
 
421
          if (!fdiro)
 
422
            return 0;
 
423
          
 
424
          fdiro->data = diro->data;
 
425
          fdiro->ino = grub_le_to_cpu32 (dirent.inode);
 
426
          
 
427
          filename[dirent.namelen] = '\0';
 
428
 
 
429
          if (dirent.filetype != FILETYPE_UNKNOWN)
 
430
            {
 
431
              fdiro->inode_read = 0;
 
432
 
 
433
              if (dirent.filetype == FILETYPE_DIRECTORY)
 
434
                type = GRUB_FSHELP_DIR;
 
435
              else if (dirent.filetype == FILETYPE_SYMLINK)
 
436
                type = GRUB_FSHELP_SYMLINK;
 
437
              else if (dirent.filetype == FILETYPE_REG)
 
438
                type = GRUB_FSHELP_REG;
 
439
            }
 
440
          else
 
441
            {
 
442
              /* The filetype can not be read from the dirent, read
 
443
                 the inode to get more information.  */
 
444
              grub_ext2_read_inode (diro->data, grub_le_to_cpu32 (dirent.inode),
 
445
                                    &fdiro->inode);
 
446
              if (grub_errno)
 
447
                {
 
448
                  grub_free (fdiro);
 
449
                  return 0;
 
450
                }
 
451
              
 
452
              fdiro->inode_read = 1;
 
453
              
 
454
              if ((grub_le_to_cpu16 (fdiro->inode.mode)
 
455
                   & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
 
456
                type = GRUB_FSHELP_DIR;
 
457
              else if ((grub_le_to_cpu16 (fdiro->inode.mode)
 
458
                        & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
 
459
                type = GRUB_FSHELP_SYMLINK;
 
460
              else if ((grub_le_to_cpu16 (fdiro->inode.mode)
 
461
                        & FILETYPE_INO_MASK) == FILETYPE_INO_REG)
 
462
                type = GRUB_FSHELP_REG;
 
463
            }
 
464
          
 
465
          if (hook (filename, type, fdiro))
 
466
            return 1;
 
467
        }
 
468
      
 
469
      fpos += grub_le_to_cpu16 (dirent.direntlen);
 
470
    }
 
471
  
 
472
  return 0;
 
473
}
 
474
 
 
475
/* Open a file named NAME and initialize FILE.  */
 
476
static grub_err_t
 
477
grub_ext2_open (struct grub_file *file, const char *name)
 
478
{
 
479
  struct grub_ext2_data *data;
 
480
  struct grub_fshelp_node *fdiro = 0;
 
481
  
 
482
#ifndef GRUB_UTIL
 
483
  grub_dl_ref (my_mod);
 
484
#endif
 
485
  
 
486
  data = grub_ext2_mount (file->device->disk);
 
487
  if (!data)
 
488
    goto fail;
 
489
  
 
490
  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir,
 
491
                         grub_ext2_read_symlink, GRUB_FSHELP_REG);
 
492
  if (grub_errno)
 
493
    goto fail;
 
494
  
 
495
  if (!fdiro->inode_read)
 
496
    {
 
497
      grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
 
498
      if (grub_errno)
 
499
        goto fail;
 
500
    }
 
501
  
 
502
  grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
 
503
  grub_free (fdiro);
 
504
 
 
505
  file->size = grub_le_to_cpu32 (data->inode->size);
 
506
  file->data = data;
 
507
  file->offset = 0;
 
508
 
 
509
  return 0;
 
510
 
 
511
 fail:
 
512
  if (fdiro != &data->diropen)
 
513
    grub_free (fdiro);
 
514
  grub_free (data);
 
515
  
 
516
#ifndef GRUB_UTIL
 
517
  grub_dl_unref (my_mod);
 
518
#endif
 
519
 
 
520
  return grub_errno;
 
521
}
 
522
 
 
523
static grub_err_t
 
524
grub_ext2_close (grub_file_t file)
 
525
{
 
526
  grub_free (file->data);
 
527
 
 
528
#ifndef GRUB_UTIL
 
529
  grub_dl_unref (my_mod);
 
530
#endif
 
531
 
 
532
  return GRUB_ERR_NONE;
 
533
}
 
534
 
 
535
/* Read LEN bytes data from FILE into BUF.  */
 
536
static grub_ssize_t
 
537
grub_ext2_read (grub_file_t file, char *buf, grub_ssize_t len)
 
538
{
 
539
  struct grub_ext2_data *data = 
 
540
    (struct grub_ext2_data *) file->data;
 
541
  
 
542
  return grub_ext2_read_file (&data->diropen, file->read_hook,
 
543
                              file->offset, len, buf);
 
544
}
 
545
 
 
546
 
 
547
static grub_err_t
 
548
grub_ext2_dir (grub_device_t device, const char *path, 
 
549
               int (*hook) (const char *filename, int dir))
 
550
{
 
551
  struct grub_ext2_data *data = 0;;
 
552
  struct grub_fshelp_node *fdiro = 0;
 
553
  
 
554
  auto int NESTED_FUNC_ATTR iterate (const char *filename,
 
555
                                     enum grub_fshelp_filetype filetype,
 
556
                                     grub_fshelp_node_t node);
 
557
 
 
558
  int NESTED_FUNC_ATTR iterate (const char *filename,
 
559
                                enum grub_fshelp_filetype filetype,
 
560
                                grub_fshelp_node_t node)
 
561
    {
 
562
      grub_free (node);
 
563
      
 
564
      if (filetype == GRUB_FSHELP_DIR)
 
565
        return hook (filename, 1);
 
566
      else 
 
567
        return hook (filename, 0);
 
568
      
 
569
      return 0;
 
570
    }
 
571
 
 
572
#ifndef GRUB_UTIL
 
573
  grub_dl_ref (my_mod);
 
574
#endif
 
575
  
 
576
  data = grub_ext2_mount (device->disk);
 
577
  if (!data)
 
578
    goto fail;
 
579
  
 
580
  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir,
 
581
                         grub_ext2_read_symlink, GRUB_FSHELP_DIR);
 
582
  if (grub_errno)
 
583
    goto fail;
 
584
  
 
585
  grub_ext2_iterate_dir (fdiro, iterate);
 
586
  
 
587
 fail:
 
588
  if (fdiro != &data->diropen)
 
589
    grub_free (fdiro);
 
590
  grub_free (data);
 
591
 
 
592
#ifndef GRUB_UTIL
 
593
  grub_dl_unref (my_mod);
 
594
#endif
 
595
 
 
596
  return grub_errno;
 
597
}
 
598
 
 
599
static grub_err_t
 
600
grub_ext2_label (grub_device_t device, char **label)
 
601
{
 
602
  struct grub_ext2_data *data;
 
603
  grub_disk_t disk = device->disk;
 
604
 
 
605
#ifndef GRUB_UTIL
 
606
  grub_dl_ref (my_mod);
 
607
#endif
 
608
 
 
609
  data = grub_ext2_mount (disk);
 
610
  if (data)
 
611
    *label = grub_strndup (data->sblock.volume_name, 14);
 
612
  else
 
613
    *label = 0;
 
614
 
 
615
#ifndef GRUB_UTIL
 
616
  grub_dl_unref (my_mod);
 
617
#endif
 
618
 
 
619
  grub_free (data);
 
620
 
 
621
  return grub_errno;
 
622
}
 
623
 
 
624
 
 
625
static struct grub_fs grub_ext2_fs =
 
626
  {
 
627
    .name = "ext2",
 
628
    .dir = grub_ext2_dir,
 
629
    .open = grub_ext2_open,
 
630
    .read = grub_ext2_read,
 
631
    .close = grub_ext2_close,
 
632
    .label = grub_ext2_label,
 
633
    .next = 0
 
634
  };
 
635
 
 
636
GRUB_MOD_INIT(ext2)
 
637
{
 
638
  grub_fs_register (&grub_ext2_fs);
 
639
#ifndef GRUB_UTIL
 
640
  my_mod = mod;
 
641
#endif
 
642
}
 
643
 
 
644
GRUB_MOD_FINI(ext2)
 
645
{
 
646
  grub_fs_unregister (&grub_ext2_fs);
 
647
}