Warning, cross-references for /kernel/fs/ext2/fsys_ext2fs.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #include "kernel.h"
0042 #include "fs/filesys.h"
0043 #include "arch/i386.h"
0044 #include "util/printf.h"
0045
0046 extern void ReadSector (void *offset, int cylinder, int head, int sector);
0047 extern void WriteSector (void *offset, int cylinder, int head, int sector);
0048 extern void ReadSectorLBA (void *offset, uint32 lba);
0049 extern void WriteSectorLBA (void *offset, uint32 lba);
0050
0051 static int mapblock1, mapblock2;
0052 static int errnum;
0053 static char fsys_buf[0x8000];
0054 static int filepos;
0055 static int filemax;
0056
0057
0058 #define DEV_BSIZE 512
0059
0060
0061 #define BLOCK_SIZE 1024
0062
0063 #define WHICH_SUPER 1
0064
0065 #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)
0066
0067
0068 typedef __signed__ char __s8;
0069 typedef uint8 __u8;
0070 typedef __signed__ short __s16;
0071 typedef uint16 __u16;
0072 typedef __signed__ int __s32;
0073 typedef unsigned int __u32;
0074
0075
0076
0077
0078 #define EXT2_NDIR_BLOCKS 12
0079 #define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
0080 #define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
0081 #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
0082 #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
0083
0084 #define SECTOR_BITS 9
0085
0086
0087 struct ext2_super_block
0088 {
0089 __u32 s_inodes_count;
0090 __u32 s_blocks_count;
0091 __u32 s_r_blocks_count;
0092 __u32 s_free_blocks_count;
0093 __u32 s_free_inodes_count;
0094 __u32 s_first_data_block;
0095 __u32 s_log_block_size;
0096 __s32 s_log_frag_size;
0097 __u32 s_blocks_per_group;
0098 __u32 s_frags_per_group;
0099 __u32 s_inodes_per_group;
0100 __u32 s_mtime;
0101 __u32 s_wtime;
0102 __u16 s_mnt_count;
0103 __s16 s_max_mnt_count;
0104 __u16 s_magic;
0105 __u16 s_state;
0106 __u16 s_errors;
0107 __u16 s_pad;
0108 __u32 s_lastcheck;
0109 __u32 s_checkinterval;
0110 __u32 s_creator_os;
0111 __u32 s_rev_level;
0112 __u16 s_def_resuid;
0113 __u16 s_def_resgid;
0114 __u32 s_reserved[235];
0115 };
0116
0117 struct ext2_group_desc
0118 {
0119 __u32 bg_block_bitmap;
0120 __u32 bg_inode_bitmap;
0121 __u32 bg_inode_table;
0122 __u16 bg_free_blocks_count;
0123 __u16 bg_free_inodes_count;
0124 __u16 bg_used_dirs_count;
0125 __u16 bg_pad;
0126 __u32 bg_reserved[3];
0127 };
0128
0129 struct ext2_inode
0130 {
0131 __u16 i_mode;
0132 __u16 i_uid;
0133 __u32 i_size;
0134 __u32 i_atime;
0135 __u32 i_ctime;
0136 __u32 i_mtime;
0137 __u32 i_dtime;
0138 __u16 i_gid;
0139 __u16 i_links_count;
0140 __u32 i_blocks;
0141 __u32 i_flags;
0142 union
0143 {
0144 struct
0145 {
0146 __u32 l_i_reserved1;
0147 }
0148 linux1;
0149 struct
0150 {
0151 __u32 h_i_translator;
0152 }
0153 hurd1;
0154 struct
0155 {
0156 __u32 m_i_reserved1;
0157 }
0158 masix1;
0159 }
0160 osd1;
0161 __u32 i_block[EXT2_N_BLOCKS];
0162 __u32 i_version;
0163 __u32 i_file_acl;
0164 __u32 i_dir_acl;
0165 __u32 i_faddr;
0166 union
0167 {
0168 struct
0169 {
0170 __u8 l_i_frag;
0171 __u8 l_i_fsize;
0172 __u16 i_pad1;
0173 __u32 l_i_reserved2[2];
0174 }
0175 linux2;
0176 struct
0177 {
0178 __u8 h_i_frag;
0179 __u8 h_i_fsize;
0180 __u16 h_i_mode_high;
0181 __u16 h_i_uid_high;
0182 __u16 h_i_gid_high;
0183 __u32 h_i_author;
0184 }
0185 hurd2;
0186 struct
0187 {
0188 __u8 m_i_frag;
0189 __u8 m_i_fsize;
0190 __u16 m_pad1;
0191 __u32 m_i_reserved2[2];
0192 }
0193 masix2;
0194 }
0195 osd2;
0196 };
0197
0198
0199 #define NAME_MAX 255
0200
0201
0202 typedef long linux_off_t;
0203
0204
0205 #define EXT2_NAME_LEN 255
0206 struct ext2_dir_entry
0207 {
0208 __u32 inode;
0209 __u16 rec_len;
0210 __u8 name_len;
0211 __u8 file_type;
0212 char name[EXT2_NAME_LEN];
0213 };
0214
0215
0216
0217
0218
0219
0220
0221 #define EXT2_DIR_PAD 4
0222 #define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
0223 #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
0224 ~EXT2_DIR_ROUND)
0225
0226
0227
0228 #define log2(n) ffz(~(n))
0229
0230 #define EXT2_SUPER_MAGIC 0xEF53
0231 #define EXT2_ROOT_INO 2
0232 #define PATH_MAX 1024
0233 #define MAX_LINK_COUNT 5
0234
0235
0236
0237 #define SUPERBLOCK \
0238 ((struct ext2_super_block *)(fsys_buf))
0239 #define GROUP_DESC \
0240 ((struct ext2_group_desc *) \
0241 ((int)SUPERBLOCK + sizeof(struct ext2_super_block)))
0242 #define INODE \
0243 ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
0244 #define DATABLOCK1 \
0245 ((int)((int)INODE + sizeof(struct ext2_inode)))
0246 #define DATABLOCK2 \
0247 ((int)((int)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
0248
0249
0250 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
0251 #define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
0252
0253
0254 #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
0255
0256 #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
0257
0258 #define EXT2_DESC_PER_BLOCK(s) \
0259 (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
0260
0261 #define S_IFMT 00170000
0262 #define S_IFLNK 0120000
0263 #define S_IFREG 0100000
0264 #define S_IFDIR 0040000
0265 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
0266 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
0267 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
0268
0269
0270
0271
0272 void
0273 itoa (char *buf, int base, int d)
0274 {
0275 char *p = buf;
0276 char *p1, *p2;
0277 uint32 ud = d;
0278 int divisor = 10;
0279
0280
0281 if (base == 'd' && d < 0) {
0282 *p++ = '-';
0283 buf++;
0284 ud = -d;
0285 } else if (base == 'x')
0286 divisor = 16;
0287
0288
0289 do {
0290 int remainder = ud % divisor;
0291
0292 *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
0293 }
0294 while (ud /= divisor);
0295
0296
0297 *p = 0;
0298
0299
0300 p1 = buf;
0301 p2 = p - 1;
0302 while (p1 < p2) {
0303 char tmp = *p1;
0304 *p1 = *p2;
0305 *p2 = tmp;
0306 p1++;
0307 p2--;
0308 }
0309 }
0310
0311
0312
0313
0314
0315 #if 0
0316 void
0317 printf (const char *format, ...)
0318 {
0319 char **arg = (char **) &format;
0320 int c;
0321 char buf[20];
0322
0323 arg++;
0324
0325 while ((c = *format++) != 0) {
0326 if (c != '%')
0327 putchar (c);
0328 else {
0329 char *p;
0330
0331 c = *format++;
0332 switch (c) {
0333 case 'd':
0334 case 'u':
0335 case 'x':
0336 itoa (buf, c, *((int *) arg++));
0337 p = buf;
0338 goto string;
0339 break;
0340
0341 case 's':
0342 p = *arg++;
0343 if (!p)
0344 p = "(null)";
0345
0346 string:
0347 while (*p)
0348 putchar (*p++);
0349 break;
0350
0351 default:
0352 putchar (*((int *) arg++));
0353 break;
0354 }
0355 }
0356 }
0357 }
0358 #endif
0359
0360
0361 int
0362 substring (const char *s1, const char *s2)
0363 {
0364 while (*s1 == *s2) {
0365
0366 if (!*(s1++))
0367 return 0;
0368 s2++;
0369 }
0370
0371
0372 if (*s1 == 0)
0373 return -1;
0374
0375
0376 return 1;
0377 }
0378
0379 int
0380 isspace (int c)
0381 {
0382 switch (c) {
0383 case ' ':
0384 case '\t':
0385 case '\r':
0386 case '\n':
0387 return 1;
0388 default:
0389 break;
0390 }
0391
0392 return 0;
0393 }
0394
0395 void *
0396 memmove (void *to, const void *from, int len)
0397 {
0398
0399
0400
0401
0402 int d0, d1, d2;
0403
0404 if (to < from) {
0405 asm volatile ("cld\n\t"
0406 "rep\n\t" "movsb":"=&c" (d0), "=&S" (d1), "=&D" (d2)
0407 :"0" (len), "1" (from), "2" (to)
0408 :"memory");
0409 } else {
0410 asm volatile ("std\n\t"
0411 "rep\n\t"
0412 "movsb\n\t" "cld":"=&c" (d0), "=&S" (d1), "=&D" (d2)
0413 :"0" (len),
0414 "1" (len - 1 + (const char *) from),
0415 "2" (len - 1 + (char *) to)
0416 :"memory");
0417 }
0418 return to;
0419 }
0420
0421
0422
0423
0424 void
0425 LBAtoCHS (int LBA, int *cylinder, int *head, int *sector)
0426 {
0427
0428 int temp;
0429
0430
0431
0432
0433
0434 *cylinder = LBA / (16 * 63);
0435 temp = LBA % (16 * 63);
0436 *head = temp / 63;
0437 *sector = temp % 63 + 1;
0438 }
0439
0440
0441 int
0442 devread (int sector, int byte_offset, int byte_len, char *buf)
0443 {
0444
0445 char sector_buf[SECTOR_SIZE];
0446 int partial_bytes;
0447 int cyl, hd, sect;
0448
0449 int CHS = 0;
0450
0451
0452
0453
0454 sector += 63;
0455
0456 #if 0
0457
0458
0459
0460 if (sector < 0 || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
0461 >= part_length)) {
0462 errnum = ERR_OUTSIDE_PART;
0463 return 0;
0464 }
0465 #endif
0466
0467
0468
0469
0470
0471 sector += byte_offset >> SECTOR_BITS;
0472 byte_offset &= SECTOR_SIZE - 1;
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488 if (byte_offset) {
0489 partial_bytes = SECTOR_SIZE - byte_offset;
0490
0491 if (CHS) {
0492 LBAtoCHS (sector, &cyl, &hd, §);
0493 ReadSector (sector_buf, cyl, hd, sect);
0494 } else
0495 ReadSectorLBA (sector_buf, sector);
0496
0497 memcpy (buf, sector_buf + byte_offset, partial_bytes);
0498 buf += partial_bytes;
0499 byte_len -= partial_bytes;
0500 sector++;
0501 }
0502
0503 for (; byte_len >= SECTOR_SIZE; byte_len -= SECTOR_SIZE) {
0504 if (CHS) {
0505 LBAtoCHS (sector, &cyl, &hd, §);
0506 ReadSector (buf, cyl, hd, sect);
0507 } else
0508 ReadSectorLBA (buf, sector);
0509
0510 buf += SECTOR_SIZE;
0511 sector++;
0512 }
0513
0514 if (byte_len) {
0515 if (CHS) {
0516 LBAtoCHS (sector, &cyl, &hd, §);
0517 ReadSector (sector_buf, cyl, hd, sect);
0518 } else
0519 ReadSectorLBA (sector_buf, sector);
0520
0521 memcpy (buf, sector_buf, byte_len);
0522 }
0523
0524 return 1;
0525 }
0526
0527
0528
0529
0530
0531
0532
0533 static __inline__ uint32
0534 ffz (uint32 word)
0535 {
0536 asm volatile ("bsfl %1,%0":"=r" (word):"r" (~word));
0537 return word;
0538 }
0539
0540
0541 int
0542 ext2fs_mount (void)
0543 {
0544 int retval = 1;
0545
0546 if (!devread (SBLOCK, 0, sizeof (struct ext2_super_block),
0547 (char *) SUPERBLOCK)
0548 || SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC)
0549 retval = 0;
0550
0551 return retval;
0552 }
0553
0554
0555 static int
0556 ext2_rdfsb (int fsblock, int buffer)
0557 {
0558 #ifdef E2DEBUG
0559 printf ("fsblock %d buffer %d\n", fsblock, buffer);
0560 #endif
0561 return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
0562 EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
0563 }
0564
0565
0566
0567
0568
0569
0570 static int
0571 ext2fs_block_map (int logical_block)
0572 {
0573
0574 #ifdef E2DEBUG
0575 uint8 *i;
0576 for (i = (uint8 *) INODE;
0577 i < ((uint8 *) INODE + sizeof (struct ext2_inode)); i++) {
0578 printf ("%c", "0123456789abcdef"[*i >> 4]);
0579 printf ("%c", "0123456789abcdef"[*i % 16]);
0580 if (!((i + 1 - (uint8 *) INODE) % 16)) {
0581 printf ("\n");
0582 } else {
0583 printf (" ");
0584 }
0585 }
0586 printf ("logical block %d\n", logical_block);
0587 #endif
0588
0589
0590 if (logical_block < EXT2_NDIR_BLOCKS) {
0591 #ifdef E2DEBUG
0592 printf ("returning %d\n", (uint8 *) (INODE->i_block[logical_block]));
0593 printf ("returning %d\n", INODE->i_block[logical_block]);
0594 #endif
0595 return INODE->i_block[logical_block];
0596 }
0597
0598 logical_block -= EXT2_NDIR_BLOCKS;
0599
0600 if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) {
0601 if (mapblock1 != 1
0602 && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) {
0603 errnum = ERR_FSYS_CORRUPT;
0604 return -1;
0605 }
0606 mapblock1 = 1;
0607 return ((__u32 *) DATABLOCK1)[logical_block];
0608 }
0609
0610 logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
0611
0612 if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) {
0613 int bnum;
0614 if (mapblock1 != 2
0615 && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) {
0616 errnum = ERR_FSYS_CORRUPT;
0617 return -1;
0618 }
0619 mapblock1 = 2;
0620 if ((bnum = (((__u32 *) DATABLOCK1)
0621 [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
0622 != mapblock2 && !ext2_rdfsb (bnum, DATABLOCK2)) {
0623 errnum = ERR_FSYS_CORRUPT;
0624 return -1;
0625 }
0626 mapblock2 = bnum;
0627 return ((__u32 *) DATABLOCK2)
0628 [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
0629 }
0630
0631 mapblock2 = -1;
0632 logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
0633 if (mapblock1 != 3
0634 && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) {
0635 errnum = ERR_FSYS_CORRUPT;
0636 return -1;
0637 }
0638 mapblock1 = 3;
0639 if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
0640 [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
0641 * 2)], DATABLOCK2)) {
0642 errnum = ERR_FSYS_CORRUPT;
0643 return -1;
0644 }
0645 if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
0646 [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
0647 & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], DATABLOCK2)) {
0648 errnum = ERR_FSYS_CORRUPT;
0649 return -1;
0650 }
0651 return ((__u32 *) DATABLOCK2)
0652 [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
0653 }
0654
0655
0656 int
0657 ext2fs_read (char *buf, int len)
0658 {
0659 int logical_block;
0660 int offset;
0661 int map;
0662 int ret = 0;
0663 int size = 0;
0664
0665 #ifdef E2DEBUG
0666 static char hexdigit[] = "0123456789abcdef";
0667 uint8 *i;
0668 for (i = (uint8 *) INODE;
0669 i < ((uint8 *) INODE + sizeof (struct ext2_inode)); i++) {
0670 printf ("%c", hexdigit[*i >> 4]);
0671 printf ("%c", hexdigit[*i % 16]);
0672 if (!((i + 1 - (uint8 *) INODE) % 16)) {
0673 printf ("\n");
0674 } else {
0675 printf (" ");
0676 }
0677 }
0678 #endif
0679 while (len > 0) {
0680
0681 logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
0682 offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
0683 map = ext2fs_block_map (logical_block);
0684 #ifdef E2DEBUG
0685 printf ("map=%d\n", map);
0686 #endif
0687 if (map < 0)
0688 break;
0689
0690 size = EXT2_BLOCK_SIZE (SUPERBLOCK);
0691 size -= offset;
0692 if (size > len)
0693 size = len;
0694
0695 if (map == 0) {
0696 memset ((char *) buf, 0, size);
0697 } else {
0698 devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
0699 offset, size, buf);
0700 }
0701
0702 buf += size;
0703 len -= size;
0704 filepos += size;
0705 ret += size;
0706 }
0707
0708 if (errnum)
0709 ret = 0;
0710
0711 return ret;
0712 }
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738 static inline int
0739 ext2_is_fast_symlink (void)
0740 {
0741 int ea_blocks;
0742 ea_blocks =
0743 INODE->i_file_acl ? EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE : 0;
0744 return INODE->i_blocks == ea_blocks;
0745 }
0746
0747
0748
0749
0750
0751
0752
0753
0754 int
0755 ext2fs_dir (char *dirname)
0756 {
0757 int current_ino = EXT2_ROOT_INO;
0758 int updir_ino = current_ino;
0759 int group_id;
0760 int group_desc;
0761 int desc;
0762 int ino_blk;
0763 int str_chk = 0;
0764 struct ext2_group_desc *gdp;
0765 struct ext2_inode *raw_inode;
0766
0767 char linkbuf[PATH_MAX];
0768 int link_count = 0;
0769
0770 char *rest;
0771 char ch;
0772
0773 int off;
0774 int loc;
0775 int blk;
0776 long map;
0777 struct ext2_dir_entry *dp;
0778 #ifdef E2DEBUG
0779 uint8 *i;
0780 #endif
0781
0782
0783
0784
0785
0786
0787
0788 filepos = 0;
0789 filemax = 0;
0790 errnum = 0;
0791
0792 while (1) {
0793 #ifdef E2DEBUG
0794 printf ("inode %d\n", current_ino);
0795 printf ("dirname=%s\n", dirname);
0796 #endif
0797
0798
0799 group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group);
0800 group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
0801 desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
0802 #ifdef E2DEBUG
0803 printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group,
0804 EXT2_DESC_PER_BLOCK (SUPERBLOCK));
0805 printf ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc,
0806 desc);
0807 #endif
0808 if (!ext2_rdfsb ((WHICH_SUPER + group_desc +
0809 SUPERBLOCK->s_first_data_block), (int) GROUP_DESC)) {
0810 return -1;
0811 }
0812 gdp = GROUP_DESC;
0813 ino_blk = gdp[desc].bg_inode_table +
0814 (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
0815 >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
0816 #ifdef E2DEBUG
0817 printf ("inode table fsblock=%d\n", ino_blk);
0818 #endif
0819 if (!ext2_rdfsb (ino_blk, (int) INODE)) {
0820 return -1;
0821 }
0822
0823
0824 mapblock2 = mapblock1 = -1;
0825
0826 raw_inode = INODE + ((current_ino - 1)
0827 & (EXT2_BLOCK_SIZE (SUPERBLOCK) /
0828 sizeof (struct ext2_inode) - 1));
0829 #ifdef E2DEBUG
0830 printf ("ipb=%d, sizeof(inode)=%d\n",
0831 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
0832 sizeof (struct ext2_inode));
0833 printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
0834 printf ("offset into inode table block=%d\n",
0835 (int) raw_inode - (int) INODE);
0836 for (i = (uint8 *) INODE; i <= (uint8 *) raw_inode; i++) {
0837 printf ("%c", "0123456789abcdef"[*i >> 4]);
0838 printf ("%c", "0123456789abcdef"[*i % 16]);
0839 if (!((i + 1 - (uint8 *) INODE) % 16)) {
0840 printf ("\n");
0841 } else {
0842 printf (" ");
0843 }
0844 }
0845 printf ("first word=%x\n", *((int *) raw_inode));
0846 #endif
0847
0848
0849 memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));
0850
0851 #ifdef E2DEBUG
0852 printf ("first word=%x\n", *((int *) INODE));
0853 #endif
0854
0855
0856 if (S_ISLNK (INODE->i_mode)) {
0857 int len;
0858 if (++link_count > MAX_LINK_COUNT) {
0859 errnum = ERR_SYMLINK_LOOP;
0860 return -1;
0861 }
0862
0863
0864 len = 0;
0865 while (dirname[len] && !isspace (dirname[len]))
0866 len++;
0867
0868
0869 filemax = (INODE->i_size);
0870 if (filemax + len > sizeof (linkbuf) - 2) {
0871 errnum = ERR_FILELENGTH;
0872 return -1;
0873 }
0874
0875 if (len) {
0876
0877
0878 memmove (linkbuf + filemax, dirname, len);
0879 }
0880 linkbuf[filemax + len] = '\0';
0881
0882
0883 if (!ext2_is_fast_symlink ()) {
0884 #if 0
0885
0886
0887 len = grub_read (linkbuf, filemax);
0888 filepos = 0;
0889 if (!len)
0890 return -1;
0891 #endif
0892 } else {
0893
0894 len = filemax;
0895 memmove (linkbuf, (char *) INODE->i_block, len);
0896 }
0897
0898 #ifdef E2DEBUG
0899 printf ("symlink=%s\n", linkbuf);
0900 #endif
0901
0902 dirname = linkbuf;
0903 if (*dirname == '/') {
0904
0905 current_ino = EXT2_ROOT_INO;
0906 updir_ino = current_ino;
0907 } else {
0908
0909 current_ino = updir_ino;
0910 }
0911
0912
0913 continue;
0914 }
0915
0916
0917 if (!*dirname || isspace (*dirname)) {
0918 if (!S_ISREG (INODE->i_mode)) {
0919 errnum = ERR_BAD_FILETYPE;
0920 return -1;
0921 }
0922
0923 filemax = (INODE->i_size);
0924 return filemax;
0925 }
0926
0927
0928 updir_ino = current_ino;
0929
0930
0931 while (*dirname == '/')
0932 dirname++;
0933
0934
0935 if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode)) {
0936 errnum = ERR_BAD_FILETYPE;
0937 return -1;
0938 }
0939
0940
0941 for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
0942
0943
0944
0945 *rest = 0;
0946 loc = 0;
0947
0948 do {
0949
0950 #ifdef E2DEBUG
0951 printf ("dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);
0952 #endif
0953
0954
0955
0956 if (loc >= INODE->i_size) {
0957 errnum = ERR_FILE_NOT_FOUND;
0958 *rest = ch;
0959 return -1;
0960 }
0961
0962
0963 blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
0964
0965
0966
0967
0968 map = ext2fs_block_map (blk);
0969 #ifdef E2DEBUG
0970 printf ("fs block=%d\n", map);
0971 #endif
0972 mapblock2 = -1;
0973 if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2)) {
0974 errnum = ERR_FSYS_CORRUPT;
0975 *rest = ch;
0976 return -1;
0977 }
0978 off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
0979 dp = (struct ext2_dir_entry *) (DATABLOCK2 + off);
0980
0981 loc += dp->rec_len;
0982
0983
0984
0985 #ifdef E2DEBUG
0986 printf ("directory entry ino=%d\n", dp->inode);
0987 if (dp->inode)
0988 printf ("entry=%s\n", dp->name);
0989 #endif
0990
0991 if (dp->inode) {
0992 int saved_c = dp->name[dp->name_len];
0993
0994 dp->name[dp->name_len] = 0;
0995 str_chk = substring (dirname, dp->name);
0996 dp->name[dp->name_len] = saved_c;
0997 }
0998
0999 }
1000 while (!dp->inode || (str_chk));
1001
1002 current_ino = dp->inode;
1003 *(dirname = rest) = ch;
1004 }
1005
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017