📄 intrep.c
字号:
flash_safe_release(fmc->flash_part); return -ENOMEM; } DJM(no_jffs_node++); } /* Read the next raw inode. */ memcpy(&raw_inode, pos, sizeof(struct jffs_raw_inode)); /* When we compute the checksum for the inode, we never count the 'accurate' or the 'checksum' fields. */ tmp_accurate = raw_inode.accurate; tmp_chksum = raw_inode.chksum; raw_inode.accurate = 0; raw_inode.chksum = 0; checksum = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode)); raw_inode.accurate = tmp_accurate; raw_inode.chksum = tmp_chksum; D3(printk("*** We have found this raw inode at pos 0x%p " "on the flash:\n", pos)); D3(jffs_print_raw_inode(&raw_inode)); if (checksum != raw_inode.chksum) { D1(printk("jffs_scan_flash(): Bad checksum: " "checksum = %u, " "raw_inode.chksum = %u\n", checksum, raw_inode.chksum)); pos += sizeof(struct jffs_raw_inode); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } /* Check the raw inode read so far. Start with the maximum length of the filename. */ if (raw_inode.nsize > JFFS_MAX_NAME_LEN) { goto bad_inode; } /* The node's data segment should not exceed a certain length. */ if (raw_inode.dsize > fmc->max_chunk_size) { goto bad_inode; } pos += sizeof(struct jffs_raw_inode); /* This shouldn't be necessary because a node that violates the flash boundaries shouldn't be written in the first place. */ if (pos >= end) { goto check_node; } /* Read the name. */ *name = 0; if (raw_inode.nsize) { memcpy(name, pos, raw_inode.nsize); name[raw_inode.nsize] = '\0'; pos += raw_inode.nsize + JFFS_GET_PAD_BYTES(raw_inode.nsize); D3(printk("name == \"%s\"\n", name)); checksum = jffs_checksum(name, raw_inode.nsize); if (checksum != raw_inode.nchksum) { D1(printk("jffs_scan_flash(): Bad checksum: " "checksum = %u, " "raw_inode.nchksum = %u\n", checksum, raw_inode.nchksum)); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } if (pos >= end) { goto check_node; } } /* Read the data in order to be sure it matches the checksum. */ checksum = jffs_checksum(pos, raw_inode.dsize); pos += raw_inode.dsize + JFFS_GET_PAD_BYTES(raw_inode.dsize); if (checksum != raw_inode.dchksum) { D1(printk("jffs_scan_flash(): Bad checksum: " "checksum = %u, " "raw_inode.dchksum = %u\n", checksum, raw_inode.dchksum)); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } check_node: /* Remember the highest inode number in the whole file system. This information will be used when assigning new files new inode numbers. */ if (c->next_ino <= raw_inode.ino) { c->next_ino = raw_inode.ino + 1; } if (raw_inode.accurate) { int err; node->data_offset = raw_inode.offset; node->data_size = raw_inode.dsize; node->removed_size = raw_inode.rsize; /* Compute the offset to the actual data in the on-flash node. */ node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode.nsize + JFFS_GET_PAD_BYTES(raw_inode.nsize); node->fm = jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), node); if (!node->fm) { D(printk("jffs_scan_flash(): !node->fm\n")); kfree(node); DJM(no_jffs_node--); flash_safe_release(fmc->flash_part); return -ENOMEM; } if ((err = jffs_insert_node(c, 0, &raw_inode, name, node)) < 0) { printk("JFFS: Failed to handle raw inode. " "(err = %d)\n", err); break; } D3(jffs_print_node(node)); node = 0; /* Don't free the node! */ } else { jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); D3(printk("jffs_scan_flash(): Just found an obsolete " "raw_inode. Continuing the scan...\n")); /* Reuse this unused struct jffs_node. */ } } if (node) { kfree(node); DJM(no_jffs_node--); } jffs_build_end(fmc); D3(printk("jffs_scan_flash(): Leaving...\n")); flash_safe_release(fmc->flash_part); return 0;} /* jffs_scan_flash() */#else/* Scan the whole flash memory in order to find all nodes in the file systems. */intjffs_scan_flash(struct jffs_control *c){ char name[JFFS_MAX_NAME_LEN + 2]; struct jffs_raw_inode raw_inode; struct jffs_node *node = 0; struct buffer_head *bh; kdev_t dev = c->sb->s_dev; __u32 block = 0; __u32 last_block = c->fmc->flash_size / BLOCK_SIZE - 1; __u32 block_offset = 0; __u32 read_size; __u32 checksum; __u32 offset; /* Offset relative to the start of the flash memory. */ __u8 tmp_accurate; __u32 tmp_chksum; __u32 size; D(printk("jffs_scan_flash()\n")); if (!(bh = bread(dev, block, BLOCK_SIZE))) { D(printk("jffs_scan_flash(): First bread() failed.\n")); return -1; } /* Start the scan. */ while (block <= last_block) { if (block_offset >= BLOCK_SIZE) { brelse(bh); if (block == last_block) { bh = 0; goto end_of_scan; } if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } block_offset = 0; } offset = block * BLOCK_SIZE + block_offset; D(printk("jffs_scan_flash(): offset = %u\n", offset)); switch (*(__u32 *)&bh->b_data[block_offset]) { case JFFS_EMPTY_BITMASK: /* We have found 0xff on this block. We have to scan the rest of the block to be sure it is filled with 0xff. */ D(printk("jffs_scan_flash(): 0xff on block %u, " "block_offset %u.\n", block, block_offset)); block_offset += 4; while (block <= last_block) { for (; block_offset < BLOCK_SIZE; block_offset += 4) { if (JFFS_EMPTY_BITMASK != *(__u32 *)&bh->b_data[block_offset]) { goto ff_scan_end; } } brelse(bh); block_offset = 0; if (block >= last_block) { bh = 0; D(printk("jffs_scan_flash(): " "0xff size: %d\n", (last_block + 1) * BLOCK_SIZE - offset)); goto end_of_scan; } if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } } ff_scan_end: D(printk("jffs_scan_flash(): 0xff size: %d\n", block * BLOCK_SIZE + block_offset - offset)); continue; case JFFS_DIRTY_BITMASK: /* We have found 0x00 on this block. We have to scan as far as possible to find out how much is dirty. */ D(printk("jffs_scan_flash(): 0x00 on block %u, " "block_offset %u.\n", block, block_offset)); block_offset += 4; while (block < last_block) { for (; block_offset < BLOCK_SIZE; block_offset += 4) { if (*(__u32 *)&bh->b_data[block_offset] != JFFS_DIRTY_BITMASK) { goto zero_scan_end; } } brelse(bh); if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } block_offset = 0; } zero_scan_end: D(printk("jffs_scan_flash(): 0x00 size: %d\n", block * BLOCK_SIZE + block_offset - offset)); jffs_fmalloced(c->fmc, offset, block * BLOCK_SIZE + block_offset - offset, 0); continue; case JFFS_MAGIC_BITMASK: /* We have probably found a new raw inode. */ break; default: /* We're f*cked. This is not solved yet. We have to scan for the magic pattern. */ D(printk("jffs_scan_flash(): Block #%u at " "block_offset %u is dirty!\n", block, block_offset)); D(printk(" offset: %u\n", offset)); D(printk(" data: %u\n", *(__u32 *)&bh->b_data[block_offset])); jffs_fmalloced(c->fmc, offset, BLOCK_SIZE - block_offset, 0); block_offset = BLOCK_SIZE; continue; } /* We have found the beginning of an inode. Create a node for it. */ if (!node) { if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { brelse(bh); return -ENOMEM; } DJM(no_jffs_node++); } /* Read the next raw inode. */ read_size = jffs_min(BLOCK_SIZE - block_offset, sizeof(struct jffs_raw_inode)); memcpy(&raw_inode, &bh->b_data[block_offset], read_size); D(printk("jffs_scan_flash(): block_offset: %u, " "read_size: %u\n", block_offset, read_size)); block_offset += read_size; if (read_size < sizeof(struct jffs_raw_inode)) { brelse(bh); if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } block_offset = sizeof(struct jffs_raw_inode) - read_size; memcpy((void *)&raw_inode + read_size, bh->b_data, block_offset); } /* When we compute the checksum for the inode, we never count the 'accurate' or the 'checksum' fields. */ tmp_accurate = raw_inode.accurate; tmp_chksum = raw_inode.chksum; raw_inode.accurate = 0; raw_inode.chksum = 0; checksum = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode)); raw_inode.accurate = tmp_accurate; raw_inode.chksum = tmp_chksum; D(printk("*** We have found this raw inode at pos 0x%08x " "on the flash:\n", offset)); jffs_print_raw_inode(&raw_inode); if (block_offset == BLOCK_SIZE) { brelse(bh); if (block == last_block) { bh = 0; goto check_node; } if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } block_offset = 0; } /* Read the name. */ *name = 0; if (raw_inode.nsize) { read_size = jffs_min(BLOCK_SIZE - block_offset, raw_inode.nsize); memcpy(name, &bh->b_data[block_offset], read_size); block_offset += read_size; if (read_size < raw_inode.nsize) { /* We haven't read the whole name. */ brelse(bh); if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } block_offset = raw_inode.nsize - read_size; memcpy(&name[read_size], bh->b_data, block_offset); } block_offset += JFFS_GET_PAD_BYTES(block_offset); name[raw_inode.nsize] = '\0'; checksum += jffs_checksum(name, raw_inode.nsize); } if (block_offset == BLOCK_SIZE) { brelse(bh); if (block == last_block) { bh = 0; goto check_node; } if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } block_offset = 0; } /* Read the data in order to be sure it matches the checksum. */ if (raw_inode.dsize) { __u32 chunk_size = jffs_min(BLOCK_SIZE - block_offset, raw_inode.dsize); __u32 data_read = chunk_size; checksum += jffs_checksum(&bh->b_data[block_offset], data_read); block_offset += chunk_size; while (data_read < raw_inode.dsize) { brelse(bh); if (!(bh = bread(dev, ++block, BLOCK_SIZE))) { return -1; } chunk_size = jffs_min(BLOCK_SIZE, raw_inode.dsize - data_read); data_read += chunk_size; checksum += jffs_checksum(bh->b_data, chunk_size); block_offset = chunk_size; } } size = sizeof(struct jffs_raw_inode) + raw_inode.nsize + raw_inode.dsize; block_offset += JFFS_GET_PAD_BYTES(block_offset); /* Make sure the checksums are equal. */ if (checksum != raw_inode.chksum) { /* Something was wrong with the node. The node has to be discarded. */ D(printk("jffs_scan_flash(): checksum == %u, " "raw_inode.chksum == %u\n", checksum, raw_inode.chksum)); jffs_fmalloced(c->fmc, offset, size, 0); /* Reuse this unused struct jffs_node. */ continue; } /* Remember the highest inode number in the whole file system. This information will be used when assigning new files new inode numbers. */ if (c->next_ino <= raw_inode.ino) { c->next_ino = raw_inode.ino + 1; } check_node: if (raw_inode.accurate) { node->data_offset = raw_inode.offset; node->data_size = raw_inode.dsize; node->removed_size = raw_inode.rsize; node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode.nsize + JFFS_GET_PAD_BYTES(raw_inode.nsize); node->fm = jffs_fmalloced(c->fmc, offset, size, node); if (!node->fm) { D(printk("jffs_scan_flash(): !node->fm\n")); kfree(node); DJM(no_jffs_node--); brelse(bh); return -ENOMEM; } jffs_insert_node(c, 0, &raw_inode, name, node); jffs_print_node(node); node = 0; /* Don't free the node! */ } else { jffs_fmalloced(c->fmc, offset, size, 0); D(printk("jffs_scan_flash(): Just found an obsolete " "raw_inode. Continuing the scan...\n")); /* Reuse this unused struct jffs_node. */ } } end_of_scan: brelse(bh); if (node) { kfree(node); DJM(no_jffs_node--); } jffs_build_end(c->fmc); D(printk("jffs_scan_flash(): Leaving...\n")); return 0;} /* jffs_scan_flash() */#endif/* Insert any kind of node into the file system. Take care of data insertions and deletions. Also remove redundant information. The memory allocated for the `name' is regarded as "given away" in the caller's perspective. */intjffs_insert_node(struct jffs_control *c, struct jffs_file *f, const struct jffs_raw_inode *raw_inode, const char *name, struct jffs_node *node){ int update_name = 0; int insert_into_tree = 0; D2(printk("jffs_insert_node(): ino = %u, version = %u, name = \"%s\"\n", raw_inode->ino, raw_inode->version, ((name && *name) ? name : ""))); /* If there doesn't exist an associated jffs_file, then create, initialize and insert one into the file system. */ if (!f && !(f = jffs_find_file(c, raw_inode->ino))) { if (!(f = jffs_create_file(c, raw_inode))) { return -ENOMEM; } jffs_insert_file_into_hash(f); insert_into_tree = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -