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 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 create_target_filesystem(void) { char *name; struct stat sb; time_t timestamp; struct directory_entry *tmp_dir; struct filesystem_entry *tmp_file; __u32 parent_ino = 1, ino; tmp_dir = dir_list; while (tmp_dir) { parent_ino = 1; timestamp = tmp_dir->sb.st_mtime; name = tmp_dir->name; sb = tmp_dir->sb; if (!tmp_dir->parent) { /* Cope with the root directory */ ino = highest_ino++; mkfs_debug_msg("writing '%s' ino=%lu", name, (unsigned long) ino); /* The root directory need not have a inode */ //output_pipe(ino, &sb); /* The root directory must not have a dirent */ //write_dirent(ino, version++, ino, timestamp, DT_DIR, name); tmp_dir = tmp_dir->next; continue; } parent_ino = tmp_dir->parent->jffs2_ino; tmp_dir->jffs2_ino = ino = highest_ino++; mkfs_debug_msg("writing dir '%s' ino=%lu parent_ino=%lu", name, (unsigned long) ino, (unsigned long) parent_ino); name = basename(tmp_dir->name); write_dirent(parent_ino, version++, ino, timestamp, DT_DIR, name); output_pipe(ino, &sb); tmp_dir = tmp_dir->next; } tmp_file = file_list; while (tmp_file) { parent_ino = 1; sb = tmp_file->sb; name = basename(tmp_file->name); timestamp = tmp_file->sb.st_mtime; ino = tmp_file->jffs2_ino = highest_ino++; if (tmp_file->parent) parent_ino = tmp_file->parent->jffs2_ino; switch (sb.st_mode & S_IFMT) { case S_IFSOCK: write_dirent(parent_ino, version++, ino, timestamp, DT_SOCK, name); output_pipe(ino, &sb); break; case S_IFIFO: write_dirent(parent_ino, version++, ino, timestamp, DT_FIFO, name); output_pipe(ino, &sb); break; case S_IFLNK: { int len; char target[JFFS2_MAX_SYMLINK_LEN + 1]; len = readlink(tmp_file->path, target, JFFS2_MAX_SYMLINK_LEN); if (len < 0) { perror_msg_and_die("readlink"); } if (len > JFFS2_MAX_SYMLINK_LEN) { error_msg("symlink too large. Truncated to %d chars.", JFFS2_MAX_SYMLINK_LEN); len = JFFS2_MAX_SYMLINK_LEN; } mkfs_debug_msg("writing symlink '%s' ino=%lu parent_ino=%lu", name, (unsigned long) ino, (unsigned long) parent_ino); write_dirent(parent_ino, version++, ino, timestamp, DT_LNK, name); output_symlink(target, len, ino, &sb); } break; case S_IFREG: { FILE *file; if (sb.st_size >= JFFS2_MAX_FILE_SIZE) { error_msg_and_die("File \"%s\" too large.", tmp_file->path); } file = xfopen(tmp_file->path, "r"); mkfs_debug_msg("writing file '%s' ino=%lu parent_ino=%lu", name, (unsigned long) ino, (unsigned long) parent_ino); write_dirent(parent_ino, version++, ino, timestamp, DT_REG, name); output_reg(fileno(file), ino, &sb); fclose(file); } break; case S_IFCHR: write_dirent(parent_ino, version++, ino, timestamp, DT_CHR, name); output_dev(ino, &sb); break; case S_IFBLK: write_dirent(parent_ino, version++, ino, timestamp, DT_BLK, name); output_dev(ino, &sb); break; case S_IFDIR: error_msg_and_die("There are not supposed to be directories in the file list!"); default: error_msg("Unknown mode %o for %s", sb.st_mode, tmp_file->path); break; } tmp_file = tmp_file->next; } }
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; }