📄 fsys_ext2fs.c
字号:
if (mapblock1 != 3 && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) { errnum = ERR_FSYS_CORRUPT; return -1; } mapblock1 = 3; if (!ext2_rdfsb (((__u32 *) DATABLOCK1) [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)], DATABLOCK2)) { errnum = ERR_FSYS_CORRUPT; return -1; } if (! ext2_rdfsb (((__u32 *) DATABLOCK2) [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], DATABLOCK2)) { errnum = ERR_FSYS_CORRUPT; return -1; } return ((__u32 *) DATABLOCK2)[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];}/* preconditions: all preconds of ext2fs_block_map */unsigned longext2fs_read (char *buf, unsigned long len){ unsigned long logical_block; unsigned long offset; unsigned long ret = 0; unsigned long size = 0; int map;#ifdef E2DEBUG static char hexdigit[] = "0123456789abcdef"; unsigned char *i; for (i = (unsigned char *) INODE; i < ((unsigned char *) INODE + sizeof (struct ext2_inode)); i++) { printf ("%c", hexdigit[*i >> 4]); printf ("%c", hexdigit[*i % 16]); if (! ((i + 1 - (unsigned char *) INODE) % 16)) { printf ("\n"); } else { printf (" "); } }#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; if (map == 0) { memset ((char *) buf, 0, size); } else { disk_read_func = disk_read_hook; devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), offset, size, buf); disk_read_func = NULL; } buf += size; len -= size; /* len always >= 0 */ 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()*/static inlineint ext2_is_fast_symlink (void){ int ea_blocks; ea_blocks = INODE->i_file_acl ? EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE : 0; return INODE->i_blocks == ea_blocks;}/* 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 */#ifdef E2DEBUG unsigned char *i;#endif /* E2DEBUG */ /* 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) */ while (1) {#ifdef E2DEBUG printf ("inode %d\n", current_ino); printf ("dirname=%s\n", dirname);#endif /* E2DEBUG */ /* look up an inode */ group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group); group_desc = group_id >> log2_tmp (EXT2_DESC_PER_BLOCK (SUPERBLOCK)); desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);#ifdef E2DEBUG printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group, EXT2_DESC_PER_BLOCK (SUPERBLOCK)); printf ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);#endif /* E2DEBUG */ if (!ext2_rdfsb ( (WHICH_SUPER + group_desc + SUPERBLOCK->s_first_data_block), (int) GROUP_DESC)) { return 0; } gdp = GROUP_DESC; ino_blk = gdp[desc].bg_inode_table + (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)) >> log2_tmp (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));#ifdef E2DEBUG printf ("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 = (struct ext2_inode *)((char *)INODE + ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) * EXT2_INODE_SIZE (SUPERBLOCK));#ifdef E2DEBUG printf ("ipb=%d, sizeof(inode)=%d\n", EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK)); printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode); printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE); for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode; i++) { printf ("%c", "0123456789abcdef"[*i >> 4]); printf ("%c", "0123456789abcdef"[*i % 16]); if (!((i + 1 - (unsigned char *) INODE) % 16)) { printf ("\n"); } else { printf (" "); } } printf ("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 printf ("first word=%x\n", *((int *) INODE));#endif /* E2DEBUG */ /* If we've got a symbolic link, then chase it. */ if (S_ISLNK (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++; for (len = 0; (ch = dirname[len]) && !isspace (ch); len++) { if (ch == '\\') { len++; if (! (ch = dirname[len])) break; } } /* Get the symlink size. */ filemax = (INODE->i_size); if (filemax + len > PATH_MAX - 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 (! ext2_is_fast_symlink ()) { /* Read the necessary blocks, and reset the file pointer. */ len = grub_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 ("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 (INODE->i_mode)) { errnum = ERR_BAD_FILETYPE; return 0; } filemax = (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 (!(INODE->i_size) || !S_ISDIR (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++); for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++) { if (ch == '\\') { rest++; if (! (ch = *rest)) break; } } /* 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 ("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 >= INODE->i_size) {# ifndef STAGE1_5 if (print_possibilities < 0) {# if 0 putchar ('\n');# endif return 1; }# endif /* STAGE1_5 */ errnum = ERR_FILE_NOT_FOUND; *rest = ch; return 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 ("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 += dp->rec_len; /* NOTE: ext2fs filenames are NOT null-terminated */#ifdef E2DEBUG printf ("directory entry ino=%d\n", dp->inode); if (dp->inode) printf ("entry=%s\n", dp->name);#endif /* E2DEBUG */ if (dp->inode) { //int saved_c = dp->name[dp->name_len]; int j, k; char ch1; char *tmp_name= NAME_BUF; /* EXT2_NAME_LEN is 255, so 512 byte buffer is needed. */ /* copy dp->name to tmp_name, and quote the spaces with a '\\' */ for (j = 0, k = 0; j < dp->name_len; j++) { if (! (ch1 = dp->name[j])) break; if (ch1 == ' ') tmp_name[k++] = '\\'; tmp_name[k++] = ch1; } tmp_name[k] = 0; //dp->name[dp->name_len] = 0; str_chk = substring (dirname, tmp_name, 0);# ifndef STAGE1_5 if (print_possibilities && ch != '/' && (!*dirname || str_chk <= 0)) { if (print_possibilities > 0) print_possibilities = -print_possibilities; print_a_completion (tmp_name); }# endif //dp->name[dp->name_len] = saved_c; } } while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); current_ino = dp->inode; *(dirname = rest) = ch; } /* never get here */}#endif /* FSYS_EXT2_FS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -