📄 intrep.c
字号:
} return write_len;}#endif#if defined(JFFS_FLASH_SHORTCUT) && JFFS_FLASH_SHORTCUT/* Write a raw inode that takes up a certain amount of space in the flash memory. At the end of the flash device, there is often space that is impossible to use. At these times we want to mark this space as not used. In the cases when the amount of space is greater or equal than a struct jffs_raw_inode, we write a "dummy node" that takes up this space. The space after the raw inode, if it exists, is left as it is. Since this space after the raw inode contains JFFS_EMPTY_BITMASK bytes, we can compute the checksum of it; we don't have to manipulate it any further. If the space left on the device is less than the size of a struct jffs_raw_inode, this space is filled with JFFS_DIRTY_BITMASK bytes. No raw inode is written this time. */static intjffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm){ struct jffs_fmcontrol *fmc = c->fmc; int err; D1(printk("jffs_write_dummy_node(): dirty_fm->offset = 0x%08x, " "dirty_fm->size = %u\n", dirty_fm->offset, dirty_fm->size)); if (dirty_fm->size >= sizeof(struct jffs_raw_inode)) { struct jffs_raw_inode raw_inode; memset(&raw_inode, 0, sizeof(struct jffs_raw_inode)); raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.dsize = dirty_fm->size - sizeof(struct jffs_raw_inode); raw_inode.dchksum = raw_inode.dsize * 0xff; raw_inode.chksum = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode)); if ((err = flash_safe_write(fmc->flash_part, (unsigned char *)dirty_fm->offset, (unsigned char *)&raw_inode, sizeof(struct jffs_raw_inode))) < 0) { return err; } } else { flash_safe_acquire(fmc->flash_part); flash_memset((unsigned char *) dirty_fm->offset, 0, dirty_fm->size); flash_safe_release(fmc->flash_part); } D3(printk("jffs_write_dummy_node(): Leaving...\n")); return 0;}#else/* Write a raw inode that takes up a certain amount of space in the flash memory. */static intjffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm){ struct jffs_raw_inode raw_inode; struct buffer_head *bh; __u32 block = dirty_fm->offset / BLOCK_SIZE; __u32 block_offset = dirty_fm->offset - block * BLOCK_SIZE; kdev_t dev = c->sb->s_dev; D1(printk("jffs_write_dummy_node(): dirty_fm->offset = %u, " "dirty_fm->size = %u\n", dirty_fm->offset, dirty_fm->size)); if (!(bh = jffs_get_write_buffer(dev, block))) { D(printk("jffs_write_dummy_node(): " "Failed to read block.\n")); return -1; } memset(&raw_inode, 0, sizeof(struct jffs_raw_inode)); raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.dsize = dirty_fm->size - sizeof(struct jffs_raw_inode); raw_inode.chksum = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode)) + raw_inode.dsize * 0xff; if (BLOCK_SIZE - block_offset < sizeof(struct jffs_raw_inode)) { __u32 write_size = BLOCK_SIZE - block_offset; memcpy(&bh->b_data[block_offset], &raw_inode, write_size); jffs_put_write_buffer(bh); bh = jffs_get_write_buffer(dev, ++block); memcpy(bh->b_data, (void *)&raw_inode + write_size, sizeof(struct jffs_raw_inode) - write_size); } else { memcpy(&bh->b_data[block_offset], &raw_inode, sizeof(struct jffs_raw_inode)); } jffs_put_write_buffer(bh); D3(printk("jffs_write_dummy_node(): Leaving...\n")); return 0;}#endif#if defined(JFFS_FLASH_SHORTCUT) && JFFS_FLASH_SHORTCUT/* Write a raw inode, possibly its name and possibly some data. */intjffs_write_node(struct jffs_control *c, struct jffs_node *node, struct jffs_raw_inode *raw_inode, const char *name, const unsigned char *data){ struct jffs_fmcontrol *fmc = c->fmc; struct jffs_fm *fm; unsigned char *pos; int err; __u32 total_name_size = raw_inode->nsize + JFFS_GET_PAD_BYTES(raw_inode->nsize); __u32 total_data_size = raw_inode->dsize + JFFS_GET_PAD_BYTES(raw_inode->dsize); __u32 total_size = sizeof(struct jffs_raw_inode) + total_name_size + total_data_size; /* Fire the retrorockets and shoot the fruiton torpedoes, sir! */ ASSERT(if (!node) { printk("jffs_write_node(): node == NULL\n"); return -EINVAL; }); ASSERT(if (raw_inode && raw_inode->nsize && !name) { printk("*** jffs_write_node(): nsize = %u but name == NULL\n", raw_inode->nsize); return -EINVAL; }); D1(printk("jffs_write_node(): filename = \"%s\", ino = %u, " "version = %u, total_size = %u\n", (name ? name : ""), raw_inode->ino, raw_inode->version, total_size)); /* First try to allocate some flash memory. */ if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) { D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) " "failed!\n", fmc, total_size)); return err; } else if (!fm->nodes) { /* The jffs_fm struct that we got is not good enough. Make that space dirty. */ if ((err = jffs_write_dummy_node(c, fm)) < 0) { D(printk("jffs_write_node(): " "jffs_write_dummy_node(): Failed!\n")); kfree(fm); DJM(no_jffs_fm--); return err; } /* Get a new one. */ if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) { D(printk("jffs_write_node(): Second " "jffs_fmalloc(0x%p, %u) failed!\n", fmc, total_size)); return err; } } node->fm = fm; ASSERT(if (fm->nodes == 0) { printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n"); }); pos = (unsigned char *) node->fm->offset; /* Compute the checksum for the data and name chunks. */ raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize); raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize); /* The checksum is calculated without the chksum and accurate fields so set them to zero first. */ raw_inode->accurate = 0; raw_inode->chksum = 0; raw_inode->chksum = jffs_checksum(raw_inode, sizeof(struct jffs_raw_inode)); raw_inode->accurate = 0xff; D3(printk("jffs_write_node(): About to write this raw inode to the " "flash at pos 0x%p:\n", pos)); D3(jffs_print_raw_inode(raw_inode)); /* Step 1: Write the raw jffs inode to the flash. */ if ((err = flash_safe_write(fmc->flash_part, pos, (unsigned char *)raw_inode, sizeof(struct jffs_raw_inode))) < 0) { jffs_fmfree_partly(fmc, fm, total_name_size + total_data_size); D1(printk("jffs_write_node(): Failed to write raw_inode.\n")); return err; } pos += sizeof(struct jffs_raw_inode); /* Step 2: Write the name, if there is any. */ if (raw_inode->nsize) { if ((err = flash_safe_write(fmc->flash_part, pos, (unsigned char *)name, raw_inode->nsize)) < 0) { jffs_fmfree_partly(fmc, fm, total_data_size); D1(printk("jffs_write_node(): Failed to write " "the name.\n")); return err; } pos += total_name_size; } /* Step 3: Append the actual data, if any. */ if (raw_inode->dsize) { if ((err = flash_safe_write(fmc->flash_part, pos, data, raw_inode->dsize)) < 0) { jffs_fmfree_partly(fmc, fm, 0); D1(printk("jffs_write_node(): Failed to write " "the data.\n")); return err; } } D3(printk("jffs_write_node(): Leaving...\n")); return raw_inode->dsize;} /* jffs_write_node() */#else/* Write a raw inode, possibly its name and possibly some data. */intjffs_write_node(struct jffs_control *c, struct jffs_node *node, struct jffs_raw_inode *raw_inode, const char *name, const unsigned char *buf){ struct jffs_write_task wt; struct jffs_fm *fm; int err; __u32 total_size = sizeof(struct jffs_raw_inode) + raw_inode->nsize + JFFS_GET_PAD_BYTES(raw_inode->nsize) + raw_inode->dsize + JFFS_GET_PAD_BYTES(raw_inode->dsize); /* fire the retrorockets and shoot the fruiton torpedoes, sir! */ D1(printk("jffs_write_node(): ino: %u\n", raw_inode->ino)); ASSERT(if (!node) { printk("jffs_write_node(): node == NULL\n"); return -1; }); /* First try to allocate some flash memory. */ if ((err = jffs_fmalloc(c->fmc, total_size, node, &fm)) < 0 ) { D(printk("jffs_write_node(): jffs_fmalloc(0x%08x, %u) " "failed!\n", c->fmc, total_size)); return err; } else if (!fm->nodes) { /* The jffs_fm struct that we got is not good enough. */ if (jffs_write_dummy_node(c, fm) < 0) { D(printk("jffs_write_node(): " "jffs_write_dummy_node(): Failed!\n")); kfree(fm); DJM(no_jffs_fm--); return -1; } /* Get a new one. */ if ((err = jffs_fmalloc(c->fmc, total_size, node)) < 0) { D(printk("jffs_write_node(): Second " "jffs_fmalloc(0x%08x, %u) failed!\n", c->fmc, total_size)); return err; } } node->fm = fm; ASSERT(if (fm->nodes == 0) { printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n"); }); wt.bh = 0; wt.block = node->fm->offset / BLOCK_SIZE; wt.block_offset = node->fm->offset % BLOCK_SIZE; /* Calculate the checksum for this jffs_raw_node and its name and data. The checksum is performed without the chksum and accurate fields so set them to zero first. */ raw_inode->accurate = 0; raw_inode->chksum = 0; raw_inode->chksum = jffs_checksum(raw_inode, sizeof(struct jffs_raw_inode)); raw_inode->accurate = 0xff; if (raw_inode->nsize) { raw_inode->chksum += jffs_checksum(name, raw_inode->nsize); } if (raw_inode->dsize) { raw_inode->chksum += jffs_checksum((void *)buf, raw_inode->dsize); } /* Step 1: Write the raw jffs inode to the flash. */ if (jffs_write_chunk(c, &wt, (unsigned char *)raw_inode, sizeof(struct jffs_raw_inode)) < sizeof(struct jffs_raw_inode)) { return -1; } /* Step 2: Write the name, if there is any. */ if (raw_inode->nsize && name) { if (jffs_write_chunk(c, &wt, name, raw_inode->nsize) < raw_inode->nsize) { return -1; } /* XXX: Hack! (I'm so lazy.) */ if (JFFS_GET_PAD_BYTES(wt.block_offset)) { __u32 ff = 0xffffffff jffs_write_chunk(c, &wt, (unsigned char *)&ff, JFFS_GET_PAD_BYTES(wt.block_offset)); } } /* Step 3: Append the actual data, if any. */ if (raw_inode->dsize && buf) { if (jffs_write_chunk(c, &wt, buf, raw_inode->dsize) < raw_inode->dsize) { return -1; } } if (wt.bh) { D3(printk("jffs_write_node(): wt.bh != NULL, Final write.\n")); jffs_put_write_buffer(wt.bh); } D3(printk("jffs_write_node(): Leaving...\n")); return raw_inode->dsize;}#endif#if defined(JFFS_FLASH_SHORTCUT) && JFFS_FLASH_SHORTCUT/* Read data from the node and write it to the buffer. 'node_offset' is how much we have read from this particular node before and which shouldn't be read again. 'max_size' is how much space there is in the buffer. */static intjffs_get_node_data(struct jffs_file *f, struct jffs_node *node, char *buf, __u32 node_offset, __u32 max_size, kdev_t dev){ struct jffs_fmcontrol *fmc = f->c->fmc; __u32 pos = node->fm->offset + node->fm_offset + node_offset; __u32 avail = node->data_size - node_offset; __u32 r; D2(printk(" jffs_get_node_data(): file: \"%s\", ino: %u, " "version: %u, node_offset: %u\n", f->name, node->ino, node->version, node_offset)); r = jffs_min(avail, max_size); flash_safe_read(fmc->flash_part, (unsigned char *) pos, (unsigned char *)buf, r); D3(printk(" jffs_get_node_data(): Read %u byte%s.\n", r, (r == 1 ? "" : "s"))); return r;}#else/* Read data from the node and write it to the buffer. 'node_offset' is how much we have read from this particular node before and which shouldn't be read again. 'max_size' is how much space there is in the buffer. */static intjffs_get_node_data(struct jffs_file *f, struct jffs_node *node, char *buf, __u32 node_offset, __u32 max_size, kdev_t dev){ struct buffer_head *bh; __u32 first = node->fm->offset + node->fm_offset + node_offset; __u32 block = first / BLOCK_SIZE; __u32 block_offset = first - block * BLOCK_SIZE; __u32 read_len; __u32 total_read = 0; __u32 avail = node->data_size - node_offset; D2(printk("jffs_get_node_data(): file: \"%s\", ino: %lu, " "version: %lu, node_offset: %lu\n", f->name, node->ino, node->version, node_offset)); while ((total_read < max_size) && (avail > 0)) { read_len = jffs_min(avail, BLOCK_SIZE - block_offset); read_len = jffs_min(read_len, max_size - total_read); if (!(bh = bread(dev, block, BLOCK_SIZE))) { D(printk("jffs_get_node_data(): bread() failed. " "(block == %u)\n", block)); return -EIO; } memcpy(&buf[total_read], &bh->b_data[block_offset], read_len); brelse(bh); block++; avail -= read_len; total_read += read_len; block_offset = 0; } return total_read;}#endif/* Read data from the file's nodes. Write the data to the buffer 'buf'. 'read_offset' tells how much data we should skip. */intjffs_read_data(struct jffs_file *f, char *buf, __u32 read_offset, __u32 size){ struct jffs_node *node; __u32 read_data = 0; /* Total amount of read data. */ __u32 node_offset = 0; __u32 pos = 0; /* Number of bytes traversed. */ D1(printk("jffs_read_data(): file = \"%s\", read_offset = %d, " "size = %u\n", (f->name ? f->name : ""), read_offset, size)); if (read_offset >= f->size) { D(printk(" f->size: %d\n", f->size)); return 0; } /* First find the node to read data from. */ node = f->range_head; while (pos <= read_offset) { node_offset = read_offset - pos; if (node_offset >= node->data_size) { pos += node->data_size; node = node->range_next; } else { break; } } /* "Cats are living proof that not everything in nature has to be useful." - Garrison Keilor ('97) */ /* Fill the buffer. */ while (node && (read_data < size)) { int r; if (!node->fm) { /* This node does not refer to real data. */ r = jffs_min(size - read_data, node->data_size - node_offset); memset(&buf[read_data], 0, r); } else if ((r = jffs_get_node_data(f, node, &buf[read_data], node_offset, size - read_data, f->c->sb->s_dev)) < 0) { return r; } read_data += r; node_offset = 0; node = node->range_next; } D3(printk(" jffs_read_data(): Read %u bytes.\n", read_data)); return read_data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -