|
|
1.1 root 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.