static void write_dirent(struct filesystem_entry *e) { char *name = e->name; struct jffs2_raw_dirent rd; struct stat *statbuf = &(e->sb); static uint32_t version = 0; memset(&rd, 0, sizeof(rd)); rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd.totlen = cpu_to_je32(sizeof(rd) + strlen(name)); rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node) - 4)); rd.pino = cpu_to_je32((e->parent) ? e->parent->sb.st_ino : 1); rd.version = cpu_to_je32(version++); rd.ino = cpu_to_je32(statbuf->st_ino); rd.mctime = cpu_to_je32(statbuf->st_mtime); rd.nsize = strlen(name); rd.type = IFTODT(statbuf->st_mode); //rd.unused[0] = 0; //rd.unused[1] = 0; rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd) - 8)); rd.name_crc = cpu_to_je32(crc32(0, name, strlen(name))); pad_block_if_less_than(sizeof(rd) + rd.nsize); full_write(out_fd, &rd, sizeof(rd)); full_write(out_fd, name, rd.nsize); padword(); }
void write_dirent(fsinfo_t *fsopts, fsnode *node) { struct chfs_flash_dirent_node fdirent; char *name; name = emalloc(strlen(node->name)); memcpy(name, node->name, strlen(node->name)); memset(&fdirent, 0, sizeof(fdirent)); fdirent.magic = htole16(CHFS_FS_MAGIC_BITMASK); fdirent.type = htole16(CHFS_NODETYPE_DIRENT); fdirent.length = htole32(CHFS_PAD(sizeof(fdirent) + strlen(name))); fdirent.hdr_crc = htole32(crc32(0, (uint8_t *)&fdirent, CHFS_NODE_HDR_SIZE - 4)); fdirent.vno = htole64(node->inode->ino); if (node->parent != NULL) { fdirent.pvno = htole64(node->parent->inode->ino); } else { fdirent.pvno = htole64(node->inode->ino); } fdirent.version = htole64(version++); fdirent.mctime = 0; fdirent.nsize = htole32(strlen(name)); fdirent.dtype = htole32(IFTOCHT(node->type & S_IFMT)); fdirent.name_crc = htole32(crc32(0, (uint8_t *)name, fdirent.nsize)); fdirent.node_crc = htole32(crc32(0, (uint8_t *)&fdirent, sizeof(fdirent) - 4)); pad_block_if_less_than(fsopts, sizeof(fdirent) + fdirent.nsize); buf_write(fsopts, &fdirent, sizeof(fdirent)); buf_write(fsopts, name, fdirent.nsize); padword(fsopts); }
static void output_symlink(const char *target, int len, __u32 ino, struct stat *statbuf) { struct jffs2_raw_inode ri; memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_target16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_target16(JFFS2_NODETYPE_INODE); ri.totlen = cpu_to_target32(sizeof(ri) + len); ri.hdr_crc = cpu_to_target32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); 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); ri.version = cpu_to_target32(1); ri.csize = cpu_to_target32(len); ri.dsize = cpu_to_target32(len); ri.node_crc = cpu_to_target32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_target32(crc32(0, target, len)); pad_block_if_less_than(sizeof(ri) + len); full_write(out_fd, &ri, sizeof(ri)); full_write(out_fd, target, len); padword(); }
void write_xref_to_buff(union jffs2_node_union *node) { pad_block_if_less_than(je32_to_cpu(node->r.totlen), JFFS2_SUMMARY_XREF_SIZE); add_sum_xref_mem(node); /* Add xref summary mem to summary list */ full_write(data_buffer + data_ofs, &(node->r), je32_to_cpu(node->r.totlen)); padword(); }
static void write_dirent(__u32 pino, __u32 ver, __u32 ino, __u32 mctime, __u32 type, unsigned char *name) { struct jffs2_raw_dirent rd; memset(&rd, 0, sizeof(rd)); rd.magic = cpu_to_target16(JFFS2_MAGIC_BITMASK); rd.nodetype = cpu_to_target16(JFFS2_NODETYPE_DIRENT); rd.totlen = cpu_to_target32(sizeof(rd) + strlen(name)); rd.hdr_crc = cpu_to_target32(crc32(0, &rd, sizeof(struct jffs2_unknown_node) - 4)); rd.pino = cpu_to_target32(pino); rd.version = cpu_to_target32(ver); rd.ino = cpu_to_target32(ino); rd.mctime = cpu_to_target32(mctime); rd.nsize = strlen(name); rd.type = type; //rd.unused[0] = 0; //rd.unused[1] = 0; rd.node_crc = cpu_to_target32(crc32(0, &rd, sizeof(rd) - 8)); rd.name_crc = cpu_to_target32(crc32(0, name, strlen(name))); pad_block_if_less_than(sizeof(rd) + rd.nsize); full_write(out_fd, &rd, sizeof(rd)); full_write(out_fd, name, rd.nsize); padword(); }
void write_dirent_to_buff(union jffs2_node_union *node) { pad_block_if_less_than(je32_to_cpu (node->d.totlen),JFFS2_SUMMARY_DIRENT_SIZE(node->d.nsize)); add_sum_dirent_mem(node); full_write(data_buffer + data_ofs, &(node->d), je32_to_cpu (node->d.totlen)); padword(); }
void write_inode_to_buff(union jffs2_node_union *node) { pad_block_if_less_than(je32_to_cpu (node->i.totlen),JFFS2_SUMMARY_INODE_SIZE); add_sum_inode_mem(node); /* Add inode summary mem to summary list */ full_write(data_buffer + data_ofs, &(node->i), je32_to_cpu (node->i.totlen)); /* Write out the inode to inode_buffer */ padword(); }
void write_vnode(fsinfo_t *fsopts, fsnode *node) { struct chfs_flash_vnode fvnode; memset(&fvnode, 0, sizeof(fvnode)); fvnode.magic = htole16(CHFS_FS_MAGIC_BITMASK); fvnode.type = htole16(CHFS_NODETYPE_VNODE); fvnode.length = htole32(CHFS_PAD(sizeof(fvnode))); fvnode.hdr_crc = htole32(crc32(0, (uint8_t *)&fvnode, CHFS_NODE_HDR_SIZE - 4)); fvnode.vno = htole64(node->inode->ino); fvnode.version = htole64(version++); fvnode.mode = htole32(node->inode->st.st_mode); fvnode.dn_size = htole32(node->inode->st.st_size); fvnode.atime = htole32(node->inode->st.st_atime); fvnode.ctime = htole32(node->inode->st.st_ctime); fvnode.mtime = htole32(node->inode->st.st_mtime); fvnode.gid = htole32(node->inode->st.st_uid); fvnode.uid = htole32(node->inode->st.st_gid); fvnode.node_crc = htole32(crc32(0, (uint8_t *)&fvnode, sizeof(fvnode) - 4)); pad_block_if_less_than(fsopts, sizeof(fvnode)); buf_write(fsopts, &fvnode, sizeof(fvnode)); padword(fsopts); }
void write_data(fsinfo_t *fsopts, fsnode *node, unsigned char *buf, size_t len, uint32_t ofs) { struct chfs_flash_data_node fdata; memset(&fdata, 0, sizeof(fdata)); if (len == 0) { return; } pad_block_if_less_than(fsopts, sizeof(fdata) + len); fdata.magic = htole16(CHFS_FS_MAGIC_BITMASK); fdata.type = htole16(CHFS_NODETYPE_DATA); fdata.length = htole32(CHFS_PAD(sizeof(fdata) + len)); fdata.hdr_crc = htole32(crc32(0, (uint8_t *)&fdata, CHFS_NODE_HDR_SIZE - 4)); fdata.vno = htole64(node->inode->ino); fdata.data_length = htole32(len); fdata.offset = htole32(ofs); fdata.data_crc = htole32(crc32(0, (uint8_t *)buf, len)); fdata.node_crc = htole32(crc32(0, (uint8_t *)&fdata, sizeof(fdata) - 4)); buf_write(fsopts, &fdata, sizeof(fdata)); buf_write(fsopts, buf, len); padword(fsopts); }
static void write_symlink(struct filesystem_entry *e) { int len; struct stat *statbuf; struct jffs2_raw_inode ri; statbuf = &(e->sb); statbuf->st_ino = ++ino; mkfs_debug_msg("writing symlink '%s' ino=%lu parent_ino=%lu", e->name, (unsigned long) statbuf->st_ino, (unsigned long) e->parent->sb.st_ino); write_dirent(e); len = strlen(e->link); if (len > JFFS2_MAX_SYMLINK_LEN) { error_msg("symlink too large. Truncated to %d chars.", JFFS2_MAX_SYMLINK_LEN); len = JFFS2_MAX_SYMLINK_LEN; } memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri.totlen = cpu_to_je32(sizeof(ri) + len); ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); 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); ri.version = cpu_to_je32(1); ri.csize = cpu_to_je32(len); ri.dsize = cpu_to_je32(len); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_je32(crc32(0, e->link, len)); pad_block_if_less_than(sizeof(ri) + len); full_write(out_fd, &ri, sizeof(ri)); full_write(out_fd, e->link, len); padword(); }
static xattr_entry_t *create_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len) { xattr_entry_t *xe; struct jffs2_raw_xattr rx; int name_len; /* create xattr entry */ name_len = strlen(xname); xe = xcalloc(1, sizeof(xattr_entry_t) + name_len + 1 + value_len); xe->next = NULL; xe->xid = ++highest_xid; xe->xprefix = xprefix; xe->xname = ((char *)xe) + sizeof(xattr_entry_t); xe->xvalue = xe->xname + name_len + 1; xe->name_len = name_len; xe->value_len = value_len; strcpy(xe->xname, xname); memcpy(xe->xvalue, xvalue, value_len); /* write xattr node */ memset(&rx, 0, sizeof(rx)); rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); rx.totlen = cpu_to_je32(PAD(sizeof(rx) + xe->name_len + 1 + xe->value_len)); rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); rx.xid = cpu_to_je32(xe->xid); rx.version = cpu_to_je32(1); /* initial version */ rx.xprefix = xprefix; rx.name_len = xe->name_len; rx.value_len = cpu_to_je16(xe->value_len); rx.data_crc = cpu_to_je32(crc32(0, xe->xname, xe->name_len + 1 + xe->value_len)); rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(rx) - 4)); pad_block_if_less_than(sizeof(rx) + xe->name_len + 1 + xe->value_len); full_write(out_fd, &rx, sizeof(rx)); full_write(out_fd, xe->xname, xe->name_len + 1 + xe->value_len); padword(); return xe; }
static void write_special_file(struct filesystem_entry *e) { jint16_t kdev; struct stat *statbuf; struct jffs2_raw_inode ri; statbuf = &(e->sb); statbuf->st_ino = ++ino; write_dirent(e); kdev = cpu_to_je16((major(statbuf->st_rdev) << 8) + minor(statbuf->st_rdev)); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri.totlen = cpu_to_je32(sizeof(ri) + sizeof(kdev)); ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); 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); ri.version = cpu_to_je32(1); ri.csize = cpu_to_je32(sizeof(kdev)); ri.dsize = cpu_to_je32(sizeof(kdev)); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_je32(crc32(0, &kdev, sizeof(kdev))); pad_block_if_less_than(sizeof(ri) + sizeof(kdev)); full_write(out_fd, &ri, sizeof(ri)); full_write(out_fd, &kdev, sizeof(kdev)); padword(); }
static void write_pipe(struct filesystem_entry *e) { struct stat *statbuf; struct jffs2_raw_inode ri; statbuf = &(e->sb); statbuf->st_ino = ++ino; if (S_ISDIR(statbuf->st_mode)) { mkfs_debug_msg("writing dir '%s' ino=%lu parent_ino=%lu", e->name, (unsigned long) statbuf->st_ino, (unsigned long) (e->parent) ? e->parent->sb. st_ino : 1); } write_dirent(e); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri.totlen = cpu_to_je32(sizeof(ri)); ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); 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(0); ri.version = cpu_to_je32(1); ri.csize = cpu_to_je32(0); ri.dsize = cpu_to_je32(0); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_je32(0); pad_block_if_less_than(sizeof(ri)); full_write(out_fd, &ri, sizeof(ri)); padword(); }
static void output_dev(__u32 ino, struct stat *statbuf) { struct jffs2_raw_inode ri; /* FIXME: I am using illicit insider knowledge of kernel * major/minor representation... */ unsigned short kdev; kdev = cpu_to_target16((major(statbuf->st_rdev) << 8) + minor(statbuf->st_rdev)); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_target16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_target16(JFFS2_NODETYPE_INODE); ri.totlen = cpu_to_target32(sizeof(ri) + sizeof(kdev)); ri.hdr_crc = cpu_to_target32(crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4)); 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); ri.version = cpu_to_target32(1); ri.csize = cpu_to_target32(sizeof(kdev)); ri.dsize = cpu_to_target32(sizeof(kdev)); ri.node_crc = cpu_to_target32(crc32(0, &ri, sizeof(ri) - 8)); ri.data_crc = cpu_to_target32(crc32(0, &kdev, sizeof(kdev))); pad_block_if_less_than(sizeof(ri) + sizeof(kdev)); full_write(out_fd, &ri, sizeof(ri)); full_write(out_fd, &kdev, sizeof(kdev)); padword(); }
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); }
static void write_xattr_entry(struct filesystem_entry *e) { struct jffs2_raw_xref ref; struct xattr_entry *xe; char xlist[XATTR_BUFFER_SIZE], xvalue[XATTR_BUFFER_SIZE]; char *xname, *prefix_str; int i, xprefix, prefix_len; int list_sz, offset, name_len, value_len; if (!enable_xattr) return; list_sz = llistxattr(e->hostname, xlist, XATTR_BUFFER_SIZE); if (list_sz < 0) { if (verbose) printf("llistxattr('%s') = %d : %s\n", e->hostname, errno, strerror(errno)); return; } for (offset = 0; offset < list_sz; offset += name_len) { xname = xlist + offset; name_len = strlen(xname) + 1; for (i = 0; (xprefix = xprefix_tbl[i].xprefix); i++) { prefix_str = xprefix_tbl[i].string; prefix_len = xprefix_tbl[i].length; if (prefix_str[prefix_len - 1] == '.') { if (!strncmp(xname, prefix_str, prefix_len - 1)) break; } else { if (!strcmp(xname, prefix_str)) break; } } if (!xprefix) { if (verbose) printf("%s: xattr '%s' is not supported.\n", e->hostname, xname); continue; } if ((enable_xattr & (1 << xprefix)) == 0) continue; value_len = lgetxattr(e->hostname, xname, xvalue, XATTR_BUFFER_SIZE); if (value_len < 0) { if (verbose) printf("lgetxattr('%s', '%s') = %d : %s\n", e->hostname, xname, errno, strerror(errno)); continue; } xe = find_xattr_entry(xprefix, xname + prefix_len, xvalue, value_len); if (!xe) { if (verbose) printf("%s : xattr '%s' was ignored.\n", e->hostname, xname); continue; } memset(&ref, 0, sizeof(ref)); ref.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ref.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); ref.totlen = cpu_to_je32(sizeof(ref)); ref.hdr_crc = cpu_to_je32(crc32(0, &ref, sizeof(struct jffs2_unknown_node) - 4)); ref.ino = cpu_to_je32(e->sb.st_ino); ref.xid = cpu_to_je32(xe->xid); ref.xseqno = cpu_to_je32(highest_xseqno += 2); ref.node_crc = cpu_to_je32(crc32(0, &ref, sizeof(ref) - 4)); pad_block_if_less_than(sizeof(ref)); full_write(out_fd, &ref, sizeof(ref)); padword(); } }
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; }