int init_module(void ) { unsigned char comprtype; uint32_t c, d; int ret; printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", testdata[0],testdata[1],testdata[2],testdata[3], testdata[4],testdata[5],testdata[6],testdata[7], testdata[8],testdata[9],testdata[10],testdata[11], testdata[12],testdata[13],testdata[14],testdata[15]); d = TESTDATA_LEN; c = TESTDATA_LEN; comprtype = jffs2_compress(testdata, comprbuf, &d, &c); printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n", comprtype, c, d); printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d); printk("jffs2_decompress returned %d\n", ret); printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); if (memcmp(decomprbuf, testdata, d)) printk("Compression and decompression corrupted data\n"); else printk("Compression good for %d bytes\n", d); return 1; }
static void output_reg(int fd, __u32 ino, struct stat *statbuf) { unsigned char *buf, *cbuf, *wbuf; struct jffs2_raw_inode ri; unsigned int version, offset; int len; buf = xmalloc(page_size); cbuf = xmalloc(page_size); version = 0; offset = 0; memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_target16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_target16(JFFS2_NODETYPE_INODE); ri.ino = cpu_to_target32(ino); ri.mode = cpu_to_target32(statbuf->st_mode); ri.uid = cpu_to_target32(statbuf->st_uid); ri.gid = cpu_to_target32(statbuf->st_gid); ri.atime = cpu_to_target32(statbuf->st_atime); ri.ctime = cpu_to_target32(statbuf->st_ctime); ri.mtime = cpu_to_target32(statbuf->st_mtime); ri.isize = cpu_to_target32(statbuf->st_size); while ((len = read(fd, buf, page_size))) { unsigned char *tbuf = buf; if (len < 0) { perror_msg_and_die("read"); } while (len) { __u32 dsize, space; pad_block_if_less_than(sizeof(ri) + JFFS2_MIN_DATA_LEN); dsize = len; space = erase_block_size - (out_ofs % erase_block_size) - sizeof(ri); if (space > dsize) space = dsize; ri.compr = jffs2_compress(tbuf, cbuf, &dsize, &space); if (ri.compr) { wbuf = cbuf; } else { wbuf = tbuf; dsize = space; } ri.totlen = cpu_to_target32(sizeof(ri) + space); ri.hdr_crc = cpu_to_target32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); version++; ri.version = cpu_to_target32(version); ri.offset = cpu_to_target32(offset); ri.csize = cpu_to_target32(space); ri.dsize = cpu_to_target32(dsize); ri.node_crc = cpu_to_target32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_target32(crc32(0, wbuf, space)); full_write(out_fd, &ri, sizeof(ri)); full_write(out_fd, wbuf, space); padword(); tbuf += dsize; len -= dsize; offset += dsize; } } if (!ri.version) { /* Was empty file */ version++; ri.version = cpu_to_target32(version); ri.totlen = cpu_to_target32(sizeof(ri)); ri.hdr_crc = cpu_to_target32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); ri.csize = cpu_to_target32(0); ri.dsize = cpu_to_target32(0); ri.node_crc = cpu_to_target32(crc32(0, &ri, sizeof(ri) - 8)); full_write(out_fd, &ri, sizeof(ri)); padword(); } free(buf); free(cbuf); close(fd); }
int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsigned end) { /* Actually commit the write from the page cache page we're looking at. * For now, we write the full page out each time. It sucks, but it's simple */ struct inode *inode = pg->mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); __u32 newsize = max_t(__u32, filp->f_dentry->d_inode->i_size, (pg->index << PAGE_CACHE_SHIFT) + end); __u32 file_ofs = (pg->index << PAGE_CACHE_SHIFT); __u32 writelen = min((__u32)PAGE_CACHE_SIZE, newsize - file_ofs); struct jffs2_raw_inode *ri; int ret = 0; ssize_t writtenlen = 0; D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); if (!start && end == PAGE_CACHE_SIZE) { /* We need to avoid deadlock with page_cache_read() in jffs2_garbage_collect_pass(). So we have to mark the page up to date, to prevent page_cache_read() from trying to re-lock it. */ SetPageUptodate(pg); } ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; while(writelen) { struct jffs2_full_dnode *fn; unsigned char *comprbuf = NULL; unsigned char comprtype = JFFS2_COMPR_NONE; __u32 phys_ofs, alloclen; __u32 datalen, cdatalen; D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, file_ofs)); ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); if (ret) { SetPageError(pg); D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); break; } down(&f->sem); datalen = writelen; cdatalen = min(alloclen - sizeof(*ri), writelen); comprbuf = kmalloc(cdatalen, GFP_KERNEL); if (comprbuf) { // jffs2_bbc_model_set_act_sb(c); /**BBC**/ comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen); } if (comprtype == JFFS2_COMPR_NONE) { /* Either compression failed, or the allocation of comprbuf failed */ if (comprbuf) kfree(comprbuf); comprbuf = page_address(pg) + (file_ofs & (PAGE_CACHE_SIZE -1)); datalen = cdatalen; } /* Now comprbuf points to the data to be written, be it compressed or not. comprtype holds the compression type, and comprtype == JFFS2_COMPR_NONE means that the comprbuf doesn't need to be kfree()d. */ ri->magic = JFFS2_MAGIC_BITMASK; ri->nodetype = JFFS2_NODETYPE_INODE; ri->totlen = sizeof(*ri) + cdatalen; ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); ri->ino = inode->i_ino; ri->version = ++f->highest_version; ri->mode = inode->i_mode; ri->uid = inode->i_uid; ri->gid = inode->i_gid; ri->isize = max((__u32)inode->i_size, file_ofs + datalen); ri->atime = ri->ctime = ri->mtime = CURRENT_TIME; ri->offset = file_ofs; ri->csize = cdatalen; ri->dsize = datalen; ri->compr = comprtype; ri->node_crc = crc32(0, ri, sizeof(*ri)-8); ri->data_crc = crc32(0, comprbuf, cdatalen); fn = jffs2_write_dnode(inode, ri, comprbuf, cdatalen, phys_ofs, NULL); jffs2_complete_reservation(c); if (comprtype != JFFS2_COMPR_NONE) kfree(comprbuf); if (IS_ERR(fn)) { ret = PTR_ERR(fn); up(&f->sem); SetPageError(pg); break; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); if (f->metadata) { jffs2_mark_node_obsolete(c, f->metadata->raw); jffs2_free_full_dnode(f->metadata); f->metadata = NULL; } up(&f->sem); if (ret) { /* Eep */ D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); SetPageError(pg); break; } inode->i_size = ri->isize; inode->i_blocks = (inode->i_size + 511) >> 9; inode->i_ctime = inode->i_mtime = ri->ctime; if (!datalen) { printk(KERN_WARNING "Eep. We didn't actually write any bloody data\n"); ret = -EIO; SetPageError(pg); break; } D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); writtenlen += datalen; file_ofs += datalen; writelen -= datalen; } jffs2_free_raw_inode(ri); if (writtenlen < end) { /* generic_file_write has written more to the page cache than we've actually written to the medium. Mark the page !Uptodate so that it gets reread */ D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n")); SetPageError(pg); ClearPageUptodate(pg); } if (writtenlen <= start) { /* We didn't even get to the start of the affected part */ ret = ret?ret:-ENOSPC; D1(printk(KERN_DEBUG "jffs2_commit_write(): Only %x bytes written to page. start (%x) not reached, returning %d\n", writtenlen, start, ret)); } writtenlen = min(end-start, writtenlen-start); D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d. nrpages is %ld\n",writtenlen?writtenlen:ret, inode->i_mapping->nrpages)); return writtenlen?writtenlen:ret; }
static unsigned int write_regular_file(struct filesystem_entry *e) { int fd, len; uint32_t ver; unsigned int offset; unsigned char *buf, *cbuf, *wbuf; struct jffs2_raw_inode ri; struct stat *statbuf; unsigned int totcomp = 0; statbuf = &(e->sb); if (statbuf->st_size >= JFFS2_MAX_FILE_SIZE) { error_msg("Skipping file \"%s\" too large.", e->path); return -1; } fd = open(e->hostname, O_RDONLY); if (fd == -1) { perror_msg_and_die("%s: open file", e->hostname); } statbuf->st_ino = ++ino; mkfs_debug_msg("writing file '%s' ino=%lu parent_ino=%lu", e->name, (unsigned long) statbuf->st_ino, (unsigned long) e->parent->sb.st_ino); write_dirent(e); buf = xmalloc(page_size); cbuf = NULL; ver = 0; offset = 0; memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri.ino = cpu_to_je32(statbuf->st_ino); ri.mode = cpu_to_jemode(statbuf->st_mode); ri.uid = cpu_to_je16(statbuf->st_uid); ri.gid = cpu_to_je16(statbuf->st_gid); ri.atime = cpu_to_je32(statbuf->st_atime); ri.ctime = cpu_to_je32(statbuf->st_ctime); ri.mtime = cpu_to_je32(statbuf->st_mtime); ri.isize = cpu_to_je32(statbuf->st_size); while ((len = read(fd, buf, page_size))) { unsigned char *tbuf = buf; if (len < 0) { perror_msg_and_die("read"); } while (len) { uint32_t dsize, space; uint16_t compression; pad_block_if_less_than(sizeof(ri) + JFFS2_MIN_DATA_LEN); dsize = len; space = erase_block_size - (out_ofs % erase_block_size) - sizeof(ri); if (space > dsize) space = dsize; compression = jffs2_compress(tbuf, &cbuf, &dsize, &space); ri.compr = compression & 0xff; ri.usercompr = (compression >> 8) & 0xff; if (ri.compr) { wbuf = cbuf; } else { wbuf = tbuf; dsize = space; } ri.totlen = cpu_to_je32(sizeof(ri) + space); ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); ri.version = cpu_to_je32(++ver); ri.offset = cpu_to_je32(offset); ri.csize = cpu_to_je32(space); ri.dsize = cpu_to_je32(dsize); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_je32(crc32(0, wbuf, space)); full_write(out_fd, &ri, sizeof(ri)); totcomp += sizeof(ri); full_write(out_fd, wbuf, space); totcomp += space; padword(); if (tbuf != cbuf) { free(cbuf); cbuf = NULL; } tbuf += dsize; len -= dsize; offset += dsize; } } if (!je32_to_cpu(ri.version)) { /* Was empty file */ pad_block_if_less_than(sizeof(ri)); ri.version = cpu_to_je32(++ver); ri.totlen = cpu_to_je32(sizeof(ri)); ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); ri.csize = cpu_to_je32(0); ri.dsize = cpu_to_je32(0); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); full_write(out_fd, &ri, sizeof(ri)); padword(); } free(buf); close(fd); return totcomp; }