Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / grubfs / fsys_ext2fs.c
1 /*
2  *  GRUB  --  GRand Unified Bootloader
3  *  Copyright (C) 1999, 2001  Free Software Foundation, Inc.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18  *  MA 02110-1301, USA.
19  */
20
21 #ifdef FSYS_EXT2FS
22
23 #include "config.h"
24 #include "shared.h"
25 #include "filesys.h"
26 #include "libc/byteorder.h"
27
28 #ifdef CONFIG_DEBUG_EXT2FS
29 #define E2DEBUG
30 #endif
31
32 static int mapblock1, mapblock2;
33
34 /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
35 #define DEV_BSIZE 512
36
37 /* include/linux/fs.h */
38 #define BLOCK_SIZE 1024         /* initial block size for superblock read */
39 /* made up, defaults to 1 but can be passed via mount_opts */
40 #define WHICH_SUPER 1
41 /* kind of from fs/ext2/super.c */
42 #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)   /* = 2 */
43
44 /* include/asm-i386/types.h */
45 typedef __signed__ char __s8;
46 typedef unsigned char __u8;
47 typedef __signed__ short __s16;
48 typedef unsigned short __u16;
49 typedef __signed__ int __s32;
50 typedef unsigned int __u32;
51
52 /*
53  * Constants relative to the data blocks, from ext2_fs.h
54  */
55 #define EXT2_NDIR_BLOCKS                12
56 #define EXT2_IND_BLOCK                  EXT2_NDIR_BLOCKS
57 #define EXT2_DIND_BLOCK                 (EXT2_IND_BLOCK + 1)
58 #define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
59 #define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
60
61 /* include/linux/ext2_fs.h */
62 struct ext2_super_block
63   {
64     __u32 s_inodes_count;       /* Inodes count */
65     __u32 s_blocks_count;       /* Blocks count */
66     __u32 s_r_blocks_count;     /* Reserved blocks count */
67     __u32 s_free_blocks_count;  /* Free blocks count */
68     __u32 s_free_inodes_count;  /* Free inodes count */
69     __u32 s_first_data_block;   /* First Data Block */
70     __u32 s_log_block_size;     /* Block size */
71     __s32 s_log_frag_size;      /* Fragment size */
72     __u32 s_blocks_per_group;   /* # Blocks per group */
73     __u32 s_frags_per_group;    /* # Fragments per group */
74     __u32 s_inodes_per_group;   /* # Inodes per group */
75     __u32 s_mtime;              /* Mount time */
76     __u32 s_wtime;              /* Write time */
77     __u16 s_mnt_count;          /* Mount count */
78     __s16 s_max_mnt_count;      /* Maximal mount count */
79     __u16 s_magic;              /* Magic signature */
80     __u16 s_state;              /* File system state */
81     __u16 s_errors;             /* Behaviour when detecting errors */
82     __u16 s_pad;
83     __u32 s_lastcheck;          /* time of last check */
84     __u32 s_checkinterval;      /* max. time between checks */
85     __u32 s_creator_os;         /* OS */
86     __u32 s_rev_level;          /* Revision level */
87     __u16 s_def_resuid;         /* Default uid for reserved blocks */
88     __u16 s_def_resgid;         /* Default gid for reserved blocks */
89     __u32 s_reserved[235];      /* Padding to the end of the block */
90   };
91
92 struct ext2_group_desc
93   {
94     __u32 bg_block_bitmap;      /* Blocks bitmap block */
95     __u32 bg_inode_bitmap;      /* Inodes bitmap block */
96     __u32 bg_inode_table;       /* Inodes table block */
97     __u16 bg_free_blocks_count; /* Free blocks count */
98     __u16 bg_free_inodes_count; /* Free inodes count */
99     __u16 bg_used_dirs_count;   /* Directories count */
100     __u16 bg_pad;
101     __u32 bg_reserved[3];
102   };
103
104 struct ext2_inode
105   {
106     __u16 i_mode;               /* File mode */
107     __u16 i_uid;                /* Owner Uid */
108     __u32 i_size;               /* 4: Size in bytes */
109     __u32 i_atime;              /* Access time */
110     __u32 i_ctime;              /* 12: Creation time */
111     __u32 i_mtime;              /* Modification time */
112     __u32 i_dtime;              /* 20: Deletion Time */
113     __u16 i_gid;                /* Group Id */
114     __u16 i_links_count;        /* 24: Links count */
115     __u32 i_blocks;             /* Blocks count */
116     __u32 i_flags;              /* 32: File flags */
117     union
118       {
119         struct
120           {
121             __u32 l_i_reserved1;
122           }
123         linux1;
124         struct
125           {
126             __u32 h_i_translator;
127           }
128         hurd1;
129         struct
130           {
131             __u32 m_i_reserved1;
132           }
133         masix1;
134       }
135     osd1;                       /* OS dependent 1 */
136     __u32 i_block[EXT2_N_BLOCKS];       /* 40: Pointers to blocks */
137     __u32 i_version;            /* File version (for NFS) */
138     __u32 i_file_acl;           /* File ACL */
139     __u32 i_dir_acl;            /* Directory ACL */
140     __u32 i_faddr;              /* Fragment address */
141     union
142       {
143         struct
144           {
145             __u8 l_i_frag;      /* Fragment number */
146             __u8 l_i_fsize;     /* Fragment size */
147             __u16 i_pad1;
148             __u32 l_i_reserved2[2];
149           }
150         linux2;
151         struct
152           {
153             __u8 h_i_frag;      /* Fragment number */
154             __u8 h_i_fsize;     /* Fragment size */
155             __u16 h_i_mode_high;
156             __u16 h_i_uid_high;
157             __u16 h_i_gid_high;
158             __u32 h_i_author;
159           }
160         hurd2;
161         struct
162           {
163             __u8 m_i_frag;      /* Fragment number */
164             __u8 m_i_fsize;     /* Fragment size */
165             __u16 m_pad1;
166             __u32 m_i_reserved2[2];
167           }
168         masix2;
169       }
170     osd2;                       /* OS dependent 2 */
171   };
172
173 /* linux/posix_type.h */
174 typedef long linux_off_t;
175
176 /* linux/ext2fs.h */
177 #define EXT2_NAME_LEN 255
178 struct ext2_dir_entry
179   {
180     __u32 inode;                /* Inode number */
181     __u16 rec_len;              /* Directory entry length */
182     __u8 name_len;              /* Name length */
183     __u8 file_type;
184     char name[EXT2_NAME_LEN];   /* File name */
185   };
186
187 /* ext2/super.c */
188 #define EXT2_SUPER_MAGIC      0xEF53    /* include/linux/ext2_fs.h */
189 #define EXT2_ROOT_INO              2    /* include/linux/ext2_fs.h */
190 #define PATH_MAX                1024    /* include/linux/limits.h */
191 #define MAX_LINK_COUNT             5    /* number of symbolic links to follow */
192
193 /* made up, these are pointers into FSYS_BUF */
194 /* read once, always stays there: */
195 #define SUPERBLOCK \
196     ((struct ext2_super_block *)(FSYS_BUF))
197 #define GROUP_DESC \
198     ((struct ext2_group_desc *) \
199      ((char *)SUPERBLOCK + sizeof(struct ext2_super_block)))
200 #define INODE \
201     ((struct ext2_inode *)((char *)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
202 #define DATABLOCK1 \
203     ((char *)((char *)INODE + sizeof(struct ext2_inode)))
204 #define DATABLOCK2 \
205     ((char *)((char *)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
206
207 /* linux/ext2_fs.h */
208 #define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
209 #define EXT2_ADDR_PER_BLOCK_BITS(s)     (log2(EXT2_ADDR_PER_BLOCK(s)))
210
211 /* linux/ext2_fs.h */
212 #define EXT2_BLOCK_SIZE_BITS(s)        (__le32_to_cpu((s)->s_log_block_size) + 10)
213 /* kind of from ext2/super.c */
214 #define EXT2_BLOCK_SIZE(s)      (1 << EXT2_BLOCK_SIZE_BITS(s))
215 /* linux/ext2fs.h */
216 #define EXT2_DESC_PER_BLOCK(s) \
217      (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
218 /* linux/stat.h */
219 #define S_IFMT  00170000
220 #define S_IFLNK  0120000
221 #define S_IFREG  0100000
222 #define S_IFDIR  0040000
223 #define S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)
224 #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
225 #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
226
227 #ifdef E2DEBUG
228 void
229 dump_super(struct ext2_super_block *s)
230 {
231     printf(" superblock 0x%x:\n", s);
232     printf("  inodes=%d\n", __le32_to_cpu(s->s_inodes_count));
233     printf("  blocks=%d\n", __le32_to_cpu(s->s_blocks_count));
234     printf("  reserved=%d\n", __le32_to_cpu(s->s_r_blocks_count));
235     printf("  i_free=%d\n", __le32_to_cpu(s->s_free_inodes_count));
236     printf("  b_free=%d\n", __le32_to_cpu(s->s_free_blocks_count));
237     printf("  first=%d\n", __le32_to_cpu(s->s_first_data_block));
238     printf("  log_b_size=%d, b_size=%d\n", __le32_to_cpu(s->s_log_block_size), EXT2_BLOCK_SIZE(s));
239     printf("  log_f_size=%d\n", __le32_to_cpu(s->s_log_frag_size));
240     printf("  bpg=%d\n", __le32_to_cpu(s->s_blocks_per_group));
241     printf("  fpg=%d\n", __le32_to_cpu(s->s_frags_per_group));
242     printf("  ipg=%d\n", __le32_to_cpu(s->s_inodes_per_group));
243 }
244
245 void
246 dump_group_desc(struct ext2_group_desc *g)
247 {
248     printf(" group_desc 0x%x:\n", g);
249     printf("  b_bmap block=%d\n", __le32_to_cpu(g->bg_block_bitmap));
250     printf("  i_bmap block=%d\n", __le32_to_cpu(g->bg_inode_bitmap));
251     printf("  i_tab block=%d\n", __le32_to_cpu(g->bg_inode_table));
252     printf("  free_blks=%d\n", __le16_to_cpu(g->bg_free_blocks_count));
253     printf("  free_inodes=%d\n", __le16_to_cpu(g->bg_free_inodes_count));
254     printf("  used_dirs=%d\n", __le16_to_cpu(g->bg_used_dirs_count));
255 }
256
257 void
258 dump_inode(struct ext2_inode *i)
259 {
260     printf(" inode 0x%x:\n", i);
261     printf("  mode=%o\n", __le16_to_cpu(i->i_mode));
262     printf("  uid=%d\n", __le16_to_cpu(i->i_uid));
263     printf("  gid=%d\n", __le16_to_cpu(i->i_gid));
264     printf("  size=%d\n", __le32_to_cpu(i->i_size));
265     printf("  atime=%d\n", __le32_to_cpu(i->i_atime));
266     printf("  ctime=%d\n", __le32_to_cpu(i->i_ctime));
267     printf("  mtime=%d\n", __le32_to_cpu(i->i_mtime));
268     printf("  dtime=%d\n", __le32_to_cpu(i->i_dtime));
269     printf("  links=%d\n", __le16_to_cpu(i->i_links_count));
270     printf("  blocks=%d\n", __le32_to_cpu(i->i_blocks));
271     printf("  flags=%d\n", __le32_to_cpu(i->i_flags));
272 }
273
274 void
275 dump_inode_data(unsigned char *inode, int len)
276 {
277   static char hexdigit[] = "0123456789abcdef";
278   unsigned char *i;
279   for (i = inode;
280        i < (inode + len);
281        i++)
282     {
283       printf ("%c", hexdigit[*i >> 4]);
284       printf ("%c", hexdigit[*i % 16]);
285       if (!((i + 1 - inode) % 16))
286         {
287           printf ("\n");
288         }
289       else
290         {
291           printf (" ");
292         }
293     }
294 }
295 #endif
296
297 /* check filesystem types and read superblock into memory buffer */
298 int
299 ext2fs_mount (void)
300 {
301   int retval = 1;
302
303   if ((((current_drive & 0x80) || (current_slice != 0))
304        && (current_slice != PC_SLICE_TYPE_EXT2FS)
305        && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
306        && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
307        && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
308       || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
309       || !devread (SBLOCK, 0, sizeof (struct ext2_super_block),
310                    (char *) SUPERBLOCK)
311       || __le16_to_cpu(SUPERBLOCK->s_magic) != EXT2_SUPER_MAGIC)
312       retval = 0;
313
314   return retval;
315 }
316
317 /* Takes a file system block number and reads it into BUFFER. */
318 static int
319 ext2_rdfsb (int fsblock, char * buffer)
320 {
321 #ifdef E2DEBUG
322   printf ("ext2_rdfsb: fsblock %d, devblock %d, size %d\n", fsblock,
323           fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
324           EXT2_BLOCK_SIZE (SUPERBLOCK));
325 #endif /* E2DEBUG */
326   return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
327                   EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
328 }
329
330 /* from
331   ext2/inode.c:ext2_bmap()
332 */
333 /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
334    a physical block (the location in the file system) via an inode. */
335 static int
336 ext2fs_block_map (int logical_block)
337 {
338
339 #ifdef E2DEBUG
340   printf ("ext2fs_block_map(%d)\n", logical_block);
341 #endif /* E2DEBUG */
342
343   /* if it is directly pointed to by the inode, return that physical addr */
344   if (logical_block < EXT2_NDIR_BLOCKS)
345     {
346 #ifdef E2DEBUG
347       printf ("ext2fs_block_map: returning %d\n", __le32_to_cpu(INODE->i_block[logical_block]));
348 #endif /* E2DEBUG */
349       return __le32_to_cpu(INODE->i_block[logical_block]);
350     }
351   /* else */
352   logical_block -= EXT2_NDIR_BLOCKS;
353   /* try the indirect block */
354   if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
355     {
356       if (mapblock1 != 1
357           && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_IND_BLOCK]), DATABLOCK1))
358         {
359           errnum = ERR_FSYS_CORRUPT;
360           return -1;
361         }
362       mapblock1 = 1;
363       return __le32_to_cpu(((__u32 *) DATABLOCK1)[logical_block]);
364     }
365   /* else */
366   logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
367   /* now try the double indirect block */
368   if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
369     {
370       int bnum;
371       if (mapblock1 != 2
372           && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_DIND_BLOCK]), DATABLOCK1))
373         {
374           errnum = ERR_FSYS_CORRUPT;
375           return -1;
376         }
377       mapblock1 = 2;
378       if ((bnum = __le32_to_cpu(((__u32 *) DATABLOCK1)
379                    [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
380           != mapblock2
381           && !ext2_rdfsb (bnum, DATABLOCK2))
382         {
383           errnum = ERR_FSYS_CORRUPT;
384           return -1;
385         }
386       mapblock2 = bnum;
387       return __le32_to_cpu(((__u32 *) DATABLOCK2)
388         [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);
389     }
390   /* else */
391   mapblock2 = -1;
392   logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
393   if (mapblock1 != 3
394       && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_TIND_BLOCK]), DATABLOCK1))
395     {
396       errnum = ERR_FSYS_CORRUPT;
397       return -1;
398     }
399   mapblock1 = 3;
400   if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK1)
401                    [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
402                                       * 2)]),
403                    DATABLOCK2))
404     {
405       errnum = ERR_FSYS_CORRUPT;
406       return -1;
407     }
408   if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK2)
409                    [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
410                     & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]),
411                    DATABLOCK2))
412     {
413       errnum = ERR_FSYS_CORRUPT;
414       return -1;
415     }
416   return __le32_to_cpu(((__u32 *) DATABLOCK2)
417     [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);
418 }
419
420 /* preconditions: all preconds of ext2fs_block_map */
421 int
422 ext2fs_read (char *buf, int len)
423 {
424   int logical_block;
425   int offset;
426   int map;
427   int ret = 0;
428   int size = 0;
429
430 #ifdef E2DEBUG
431   printf("ext2fs_read(0x%x, %d)\n", buf, len);
432   dump_inode(INODE);
433   dump_inode_data((unsigned char *)INODE, sizeof (struct ext2_inode));
434 #endif /* E2DEBUG */
435   while (len > 0)
436     {
437       /* find the (logical) block component of our location */
438       logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
439       offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
440       map = ext2fs_block_map (logical_block);
441 #ifdef E2DEBUG
442       printf ("map=%d\n", map);
443 #endif /* E2DEBUG */
444       if (map < 0)
445         break;
446
447       size = EXT2_BLOCK_SIZE (SUPERBLOCK);
448       size -= offset;
449       if (size > len)
450         size = len;
451
452       disk_read_func = disk_read_hook;
453
454       devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
455                offset, size, buf);
456
457       disk_read_func = NULL;
458
459       buf += size;
460       len -= size;
461       filepos += size;
462       ret += size;
463     }
464
465   if (errnum)
466     ret = 0;
467
468   return ret;
469 }
470
471
472 /* Based on:
473    def_blk_fops points to
474    blkdev_open, which calls (I think):
475    sys_open()
476    do_open()
477    open_namei()
478    dir_namei() which accesses current->fs->root
479      fs->root was set during original mount:
480      (something)... which calls (I think):
481      ext2_read_super()
482      iget()
483      __iget()
484      read_inode()
485      ext2_read_inode()
486        uses desc_per_block_bits, which is set in ext2_read_super()
487        also uses group descriptors loaded during ext2_read_super()
488    lookup()
489    ext2_lookup()
490    ext2_find_entry()
491    ext2_getblk()
492
493 */
494
495 /* preconditions: ext2fs_mount already executed, therefore supblk in buffer
496  *   known as SUPERBLOCK
497  * returns: 0 if error, nonzero iff we were able to find the file successfully
498  * postconditions: on a nonzero return, buffer known as INODE contains the
499  *   inode of the file we were trying to look up
500  * side effects: messes up GROUP_DESC buffer area
501  */
502 int
503 ext2fs_dir (char *dirname)
504 {
505   int current_ino = EXT2_ROOT_INO;      /* start at the root */
506   int updir_ino = current_ino;  /* the parent of the current directory */
507   int group_id;                 /* which group the inode is in */
508   int group_desc;               /* fs pointer to that group */
509   int desc;                     /* index within that group */
510   int ino_blk;                  /* fs pointer of the inode's information */
511   int str_chk = 0;              /* used to hold the results of a string compare */
512   struct ext2_group_desc *gdp;
513   struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
514
515   char linkbuf[PATH_MAX];       /* buffer for following symbolic links */
516   int link_count = 0;
517
518   char *rest;
519   char ch;                      /* temp char holder */
520
521   int off;                      /* offset within block of directory entry (off mod blocksize) */
522   int loc;                      /* location within a directory */
523   int blk;                      /* which data blk within dir entry (off div blocksize) */
524   long map;                     /* fs pointer of a particular block from dir entry */
525   struct ext2_dir_entry *dp;    /* pointer to directory entry */
526
527   /* loop invariants:
528      current_ino = inode to lookup
529      dirname = pointer to filename component we are cur looking up within
530      the directory known pointed to by current_ino (if any)
531    */
532
533 #ifdef E2DEBUG
534   printf("****** ext2fs_dir(%s)\n", dirname);
535   dump_super(SUPERBLOCK);
536 #endif /* E2DEBUG */
537
538   while (1)
539     {
540 #ifdef E2DEBUG
541       printf ("ext2fs_dir: inode %d\n", current_ino);
542       printf ("ext2fs_dir: dirname=%s\n", dirname);
543 #endif /* E2DEBUG */
544
545       /* look up an inode */
546       group_id = (current_ino - 1) / __le32_to_cpu(SUPERBLOCK->s_inodes_per_group);
547       group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
548       desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
549 #ifdef E2DEBUG
550       printf ("ext2fs_dir: ipg=%d, dpb=%d\n", __le32_to_cpu(SUPERBLOCK->s_inodes_per_group),
551               EXT2_DESC_PER_BLOCK (SUPERBLOCK));
552       printf ("ext2fs_dir: group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);
553 #endif /* E2DEBUG */
554       if (!ext2_rdfsb (
555                         (WHICH_SUPER + group_desc + __le32_to_cpu(SUPERBLOCK->s_first_data_block)),
556                         (char*) GROUP_DESC))
557         {
558           return 0;
559         }
560
561 #ifdef E2DEBUG
562       dump_group_desc(GROUP_DESC);
563 #endif /* E2DEBUG */
564
565       gdp = GROUP_DESC;
566       ino_blk = __le32_to_cpu(gdp[desc].bg_inode_table) +
567         (((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group))
568          >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
569 #ifdef E2DEBUG
570       printf ("ext2fs_dir: itab_blk=%d, i_in_grp=%d, log2=%d\n",
571          __le32_to_cpu(gdp[desc].bg_inode_table),
572          ((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)),
573          log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
574       printf ("ext2fs_dir: inode table fsblock=%d\n", ino_blk);
575 #endif /* E2DEBUG */
576       if (!ext2_rdfsb (ino_blk, (char *)INODE))
577         {
578           return 0;
579         }
580
581       /* reset indirect blocks! */
582       mapblock2 = mapblock1 = -1;
583
584       raw_inode = INODE +
585         ((current_ino - 1)
586          & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
587 #ifdef E2DEBUG
588       printf ("ext2fs_dir: ipb=%d, sizeof(inode)=%d\n",
589               (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
590               sizeof (struct ext2_inode));
591       printf ("ext2fs_dir: inode=%x, raw_inode=%x\n", INODE, raw_inode);
592       printf ("ext2fs_dir: offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
593       dump_inode(raw_inode);
594       dump_inode_data((unsigned char *)INODE, EXT2_BLOCK_SIZE(SUPERBLOCK));
595       printf ("ext2fs_dir: first word=%x\n", *((int *) raw_inode));
596 #endif /* E2DEBUG */
597
598       /* copy inode to fixed location */
599       memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));
600
601 #ifdef E2DEBUG
602       dump_inode(INODE);
603       printf ("ext2fs_dir: first word=%x\n", *((int *) INODE));
604 #endif /* E2DEBUG */
605
606       /* If we've got a symbolic link, then chase it. */
607       if (S_ISLNK (__le16_to_cpu(INODE->i_mode)))
608         {
609           int len;
610           if (++link_count > MAX_LINK_COUNT)
611             {
612               errnum = ERR_SYMLINK_LOOP;
613               return 0;
614             }
615
616           /* Find out how long our remaining name is. */
617           len = 0;
618           while (dirname[len] && !isspace (dirname[len]))
619             len++;
620
621           /* Get the symlink size. */
622           filemax = __le32_to_cpu(INODE->i_size);
623           if (filemax + len > sizeof (linkbuf) - 2)
624             {
625               errnum = ERR_FILELENGTH;
626               return 0;
627             }
628
629           if (len)
630             {
631               /* Copy the remaining name to the end of the symlink data.
632                  Note that DIRNAME and LINKBUF may overlap! */
633               memmove (linkbuf + filemax, dirname, len);
634             }
635           linkbuf[filemax + len] = '\0';
636
637           /* Read the symlink data. */
638           if (__le32_to_cpu(INODE->i_blocks))
639             {
640               /* Read the necessary blocks, and reset the file pointer. */
641               len = file_read (linkbuf, filemax);
642               filepos = 0;
643               if (!len)
644                 return 0;
645             }
646           else
647             {
648               /* Copy the data directly from the inode. */
649               len = filemax;
650               memmove (linkbuf, (char *) INODE->i_block, len);
651             }
652
653 #ifdef E2DEBUG
654           printf ("ext2fs_dir: symlink=%s\n", linkbuf);
655 #endif
656
657           dirname = linkbuf;
658           if (*dirname == '/')
659             {
660               /* It's an absolute link, so look it up in root. */
661               current_ino = EXT2_ROOT_INO;
662               updir_ino = current_ino;
663             }
664           else
665             {
666               /* Relative, so look it up in our parent directory. */
667               current_ino = updir_ino;
668             }
669
670           /* Try again using the new name. */
671           continue;
672         }
673
674       /* if end of filename, INODE points to the file's inode */
675       if (!*dirname || isspace (*dirname))
676         {
677           if (!S_ISREG (__le16_to_cpu(INODE->i_mode)))
678             {
679               errnum = ERR_BAD_FILETYPE;
680               return 0;
681             }
682
683           filemax = __le32_to_cpu(INODE->i_size);
684           return 1;
685         }
686
687       /* else we have to traverse a directory */
688       updir_ino = current_ino;
689
690       /* skip over slashes */
691       while (*dirname == '/')
692         dirname++;
693
694       /* if this isn't a directory of sufficient size to hold our file, abort */
695       if (!(__le32_to_cpu(INODE->i_size)) || !S_ISDIR (__le16_to_cpu(INODE->i_mode)))
696         {
697           errnum = ERR_BAD_FILETYPE;
698           return 0;
699         }
700
701       /* skip to next slash or end of filename (space) */
702       for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
703            rest++);
704
705       /* look through this directory and find the next filename component */
706       /* invariant: rest points to slash after the next filename component */
707       *rest = 0;
708       loc = 0;
709
710       do
711         {
712
713 #ifdef E2DEBUG
714           printf ("ext2fs_dir: dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);
715 #endif /* E2DEBUG */
716
717           /* if our location/byte offset into the directory exceeds the size,
718              give up */
719           if (loc >= __le32_to_cpu(INODE->i_size))
720             {
721               if (print_possibilities < 0)
722                 {
723 # if 0
724                   putchar ('\n');
725 # endif
726                 }
727               else
728                 {
729                   errnum = ERR_FILE_NOT_FOUND;
730                   *rest = ch;
731                 }
732               return (print_possibilities < 0);
733             }
734
735           /* else, find the (logical) block component of our location */
736           blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
737
738           /* we know which logical block of the directory entry we are looking
739              for, now we have to translate that to the physical (fs) block on
740              the disk */
741           map = ext2fs_block_map (blk);
742 #ifdef E2DEBUG
743           printf ("ext2fs_dir: fs block=%d\n", map);
744 #endif /* E2DEBUG */
745           mapblock2 = -1;
746           if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
747             {
748               errnum = ERR_FSYS_CORRUPT;
749               *rest = ch;
750               return 0;
751             }
752           off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
753           dp = (struct ext2_dir_entry *) (DATABLOCK2 + off);
754           /* advance loc prematurely to next on-disk directory entry  */
755           loc += __le16_to_cpu(dp->rec_len);
756
757           /* NOTE: ext2fs filenames are NOT null-terminated */
758
759 #ifdef E2DEBUG
760           printf ("ext2fs_dir: directory entry ino=%d\n", __le32_to_cpu(dp->inode));
761           if (__le32_to_cpu(dp->inode))
762             printf ("entry=%s\n", dp->name);
763 #endif /* E2DEBUG */
764
765           if (__le32_to_cpu(dp->inode))
766             {
767               int saved_c = dp->name[dp->name_len];
768
769               dp->name[dp->name_len] = 0;
770               str_chk = substring (dirname, dp->name);
771
772 # ifndef STAGE1_5
773               if (print_possibilities && ch != '/'
774                   && (!*dirname || str_chk <= 0))
775                 {
776                   if (print_possibilities > 0)
777                     print_possibilities = -print_possibilities;
778                   print_a_completion (dp->name);
779                 }
780 # endif
781
782               dp->name[dp->name_len] = saved_c;
783             }
784
785         }
786       while (!__le32_to_cpu(dp->inode) || (str_chk || (print_possibilities && ch != '/')));
787
788       current_ino = __le32_to_cpu(dp->inode);
789       *(dirname = rest) = ch;
790     }
791   /* never get here */
792 }
793
794 #endif /* FSYS_EXT2_FS */