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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
Arquivo: file.c Projeto: cilynx/dd-wrt
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;
}
Exemplo n.º 4
0
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;
}