📄 fsys_ext2fs.c
字号:
logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); if (mapblock1 != 3 && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_TIND_BLOCK]), DATABLOCK1)) { errnum = ERR_FSYS_CORRUPT; return -1; } mapblock1 = 3; if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK1) [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)]), DATABLOCK2)) { errnum = ERR_FSYS_CORRUPT; return -1; } if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK2) [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]), DATABLOCK2)) { errnum = ERR_FSYS_CORRUPT; return -1; } return __le32_to_cpu(((__u32 *) DATABLOCK2) [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);}/* preconditions: all preconds of ext2fs_block_map */intext2fs_read (char *buf, int len){ int logical_block; int offset; int map; int ret = 0; int size = 0;#ifdef E2DEBUG printf("ext2fs_read(0x%x, %d)\n", buf, len); dump_inode(INODE); dump_inode_data((unsigned char *)INODE, sizeof (struct ext2_inode));#endif /* E2DEBUG */ while (len > 0) { /* find the (logical) block component of our location */ logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); map = ext2fs_block_map (logical_block);#ifdef E2DEBUG printf ("map=%d\n", map);#endif /* E2DEBUG */ if (map < 0) break; size = EXT2_BLOCK_SIZE (SUPERBLOCK); size -= offset; if (size > len) size = len; disk_read_func = disk_read_hook; devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), offset, size, buf); disk_read_func = 0; buf += size; len -= size; filepos += size; ret += size; } if (errnum) ret = 0; return ret;}/* Based on: def_blk_fops points to blkdev_open, which calls (I think): sys_open() do_open() open_namei() dir_namei() which accesses current->fs->root fs->root was set during original mount: (something)... which calls (I think): ext2_read_super() iget() __iget() read_inode() ext2_read_inode() uses desc_per_block_bits, which is set in ext2_read_super() also uses group descriptors loaded during ext2_read_super() lookup() ext2_lookup() ext2_find_entry() ext2_getblk()*//* preconditions: ext2fs_mount already executed, therefore supblk in buffer * known as SUPERBLOCK * returns: 0 if error, nonzero iff we were able to find the file successfully * postconditions: on a nonzero return, buffer known as INODE contains the * inode of the file we were trying to look up * side effects: messes up GROUP_DESC buffer area */intext2fs_dir (char *dirname){ int current_ino = EXT2_ROOT_INO; /* start at the root */ int updir_ino = current_ino; /* the parent of the current directory */ int group_id; /* which group the inode is in */ int group_desc; /* fs pointer to that group */ int desc; /* index within that group */ int ino_blk; /* fs pointer of the inode's information */ int str_chk = 0; /* used to hold the results of a string compare */ struct ext2_group_desc *gdp; struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */ char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ int link_count = 0; char *rest; char ch; /* temp char holder */ int off; /* offset within block of directory entry (off mod blocksize) */ int loc; /* location within a directory */ int blk; /* which data blk within dir entry (off div blocksize) */ long map; /* fs pointer of a particular block from dir entry */ struct ext2_dir_entry *dp; /* pointer to directory entry */ /* loop invariants: current_ino = inode to lookup dirname = pointer to filename component we are cur looking up within the directory known pointed to by current_ino (if any) */#ifdef E2DEBUG printf("****** ext2fs_dir(%s)\n", dirname); dump_super(SUPERBLOCK);#endif /* E2DEBUG */ while (1) {#ifdef E2DEBUG printf ("ext2fs_dir: inode %d\n", current_ino); printf ("ext2fs_dir: dirname=%s\n", dirname);#endif /* E2DEBUG */ /* look up an inode */ group_id = (current_ino - 1) / __le32_to_cpu(SUPERBLOCK->s_inodes_per_group); group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK)); desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);#ifdef E2DEBUG printf ("ext2fs_dir: ipg=%d, dpb=%d\n", __le32_to_cpu(SUPERBLOCK->s_inodes_per_group), EXT2_DESC_PER_BLOCK (SUPERBLOCK)); printf ("ext2fs_dir: group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);#endif /* E2DEBUG */ if (!ext2_rdfsb ( (WHICH_SUPER + group_desc + __le32_to_cpu(SUPERBLOCK->s_first_data_block)), (char*) GROUP_DESC)) { return 0; }#ifdef E2DEBUG dump_group_desc(GROUP_DESC);#endif /* E2DEBUG */ gdp = GROUP_DESC; ino_blk = __le32_to_cpu(gdp[desc].bg_inode_table) + (((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)) >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));#ifdef E2DEBUG printf ("ext2fs_dir: itab_blk=%d, i_in_grp=%d, log2=%d\n", __le32_to_cpu(gdp[desc].bg_inode_table), ((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)), log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode))); printf ("ext2fs_dir: inode table fsblock=%d\n", ino_blk);#endif /* E2DEBUG */ if (!ext2_rdfsb (ino_blk, (int) INODE)) { return 0; } /* reset indirect blocks! */ mapblock2 = mapblock1 = -1; raw_inode = INODE + ((current_ino - 1) & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));#ifdef E2DEBUG printf ("ext2fs_dir: ipb=%d, sizeof(inode)=%d\n", (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)), sizeof (struct ext2_inode)); printf ("ext2fs_dir: inode=%x, raw_inode=%x\n", INODE, raw_inode); printf ("ext2fs_dir: offset into inode table block=%d\n", (int) raw_inode - (int) INODE); dump_inode(raw_inode); dump_inode_data((unsigned char *)INODE, EXT2_BLOCK_SIZE(SUPERBLOCK)); printf ("ext2fs_dir: first word=%x\n", *((int *) raw_inode));#endif /* E2DEBUG */ /* copy inode to fixed location */ memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));#ifdef E2DEBUG dump_inode(INODE); printf ("ext2fs_dir: first word=%x\n", *((int *) INODE));#endif /* E2DEBUG */ /* If we've got a symbolic link, then chase it. */ if (S_ISLNK (__le16_to_cpu(INODE->i_mode))) { int len; if (++link_count > MAX_LINK_COUNT) { errnum = ERR_SYMLINK_LOOP; return 0; } /* Find out how long our remaining name is. */ len = 0; while (dirname[len] && !isspace (dirname[len])) len++; /* Get the symlink size. */ filemax = __le32_to_cpu(INODE->i_size); if (filemax + len > sizeof (linkbuf) - 2) { errnum = ERR_FILELENGTH; return 0; } if (len) { /* Copy the remaining name to the end of the symlink data. Note that DIRNAME and LINKBUF may overlap! */ memmove (linkbuf + filemax, dirname, len); } linkbuf[filemax + len] = '\0'; /* Read the symlink data. */ if (__le32_to_cpu(INODE->i_blocks)) { /* Read the necessary blocks, and reset the file pointer. */ len = file_read (linkbuf, filemax); filepos = 0; if (!len) return 0; } else { /* Copy the data directly from the inode. */ len = filemax; memmove (linkbuf, (char *) INODE->i_block, len); }#ifdef E2DEBUG printf ("ext2fs_dir: symlink=%s\n", linkbuf);#endif dirname = linkbuf; if (*dirname == '/') { /* It's an absolute link, so look it up in root. */ current_ino = EXT2_ROOT_INO; updir_ino = current_ino; } else { /* Relative, so look it up in our parent directory. */ current_ino = updir_ino; } /* Try again using the new name. */ continue; } /* if end of filename, INODE points to the file's inode */ if (!*dirname || isspace (*dirname)) { if (!S_ISREG (__le16_to_cpu(INODE->i_mode))) { errnum = ERR_BAD_FILETYPE; return 0; } filemax = __le32_to_cpu(INODE->i_size); return 1; } /* else we have to traverse a directory */ updir_ino = current_ino; /* skip over slashes */ while (*dirname == '/') dirname++; /* if this isn't a directory of sufficient size to hold our file, abort */ if (!(__le32_to_cpu(INODE->i_size)) || !S_ISDIR (__le16_to_cpu(INODE->i_mode))) { errnum = ERR_BAD_FILETYPE; return 0; } /* skip to next slash or end of filename (space) */ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); /* look through this directory and find the next filename component */ /* invariant: rest points to slash after the next filename component */ *rest = 0; loc = 0; do {#ifdef E2DEBUG printf ("ext2fs_dir: dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);#endif /* E2DEBUG */ /* if our location/byte offset into the directory exceeds the size, give up */ if (loc >= __le32_to_cpu(INODE->i_size)) { if (print_possibilities < 0) {# if 0 putchar ('\n');# endif } else { errnum = ERR_FILE_NOT_FOUND; *rest = ch; } return (print_possibilities < 0); } /* else, find the (logical) block component of our location */ blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); /* we know which logical block of the directory entry we are looking for, now we have to translate that to the physical (fs) block on the disk */ map = ext2fs_block_map (blk);#ifdef E2DEBUG printf ("ext2fs_dir: fs block=%d\n", map);#endif /* E2DEBUG */ mapblock2 = -1; if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2)) { errnum = ERR_FSYS_CORRUPT; *rest = ch; return 0; } off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); dp = (struct ext2_dir_entry *) (DATABLOCK2 + off); /* advance loc prematurely to next on-disk directory entry */ loc += __le16_to_cpu(dp->rec_len); /* NOTE: ext2fs filenames are NOT null-terminated */#ifdef E2DEBUG printf ("ext2fs_dir: directory entry ino=%d\n", __le32_to_cpu(dp->inode)); if (__le32_to_cpu(dp->inode)) printf ("entry=%s\n", dp->name);#endif /* E2DEBUG */ if (__le32_to_cpu(dp->inode)) { int saved_c = dp->name[dp->name_len]; dp->name[dp->name_len] = 0; str_chk = substring (dirname, dp->name);# ifndef STAGE1_5 if (print_possibilities && ch != '/' && (!*dirname || str_chk <= 0)) { if (print_possibilities > 0) print_possibilities = -print_possibilities; print_a_completion (dp->name); }# endif dp->name[dp->name_len] = saved_c; } } while (!__le32_to_cpu(dp->inode) || (str_chk || (print_possibilities && ch != '/'))); current_ino = __le32_to_cpu(dp->inode); *(dirname = rest) = ch; } /* never get here */}#endif /* FSYS_EXT2_FS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -