diff options
Diffstat (limited to 'mkfs.jffs.c')
-rw-r--r-- | mkfs.jffs.c | 1122 |
1 files changed, 561 insertions, 561 deletions
diff --git a/mkfs.jffs.c b/mkfs.jffs.c index 69266ed..1f4595e 100644 --- a/mkfs.jffs.c +++ b/mkfs.jffs.c @@ -33,42 +33,42 @@ static int MAX_CHUNK_SIZE = 32768; /* How many padding bytes should be inserted between two chunks of data on the flash? */ #define JFFS_GET_PAD_BYTES(size) ((JFFS_ALIGN_SIZE \ - - ((uint32_t)(size) % JFFS_ALIGN_SIZE)) \ - % JFFS_ALIGN_SIZE) + - ((uint32_t)(size) % JFFS_ALIGN_SIZE)) \ + % JFFS_ALIGN_SIZE) struct jffs_raw_inode { - uint32_t magic; /* A constant magic number. */ - uint32_t ino; /* Inode number. */ - uint32_t pino; /* Parent's inode number. */ - uint32_t version; /* Version number. */ - uint32_t mode; /* file_type, mode */ - uint16_t uid; - uint16_t gid; - uint32_t atime; - uint32_t mtime; - uint32_t ctime; - uint32_t offset; /* Where to begin to write. */ - uint32_t dsize; /* Size of the file data. */ - uint32_t rsize; /* How much are going to be replaced? */ - uint8_t nsize; /* Name length. */ - uint8_t nlink; /* Number of links. */ - uint8_t spare : 6; /* For future use. */ - uint8_t rename : 1; /* Is this a special rename? */ - uint8_t deleted : 1; /* Has this file been deleted? */ - uint8_t accurate; /* The inode is obsolete if accurate == 0. */ - uint32_t dchksum; /* Checksum for the data. */ - uint16_t nchksum; /* Checksum for the name. */ - uint16_t chksum; /* Checksum for the raw_inode. */ + uint32_t magic; /* A constant magic number. */ + uint32_t ino; /* Inode number. */ + uint32_t pino; /* Parent's inode number. */ + uint32_t version; /* Version number. */ + uint32_t mode; /* file_type, mode */ + uint16_t uid; + uint16_t gid; + uint32_t atime; + uint32_t mtime; + uint32_t ctime; + uint32_t offset; /* Where to begin to write. */ + uint32_t dsize; /* Size of the file data. */ + uint32_t rsize; /* How much are going to be replaced? */ + uint8_t nsize; /* Name length. */ + uint8_t nlink; /* Number of links. */ + uint8_t spare : 6; /* For future use. */ + uint8_t rename : 1; /* Is this a special rename? */ + uint8_t deleted : 1; /* Has this file been deleted? */ + uint8_t accurate; /* The inode is obsolete if accurate == 0. */ + uint32_t dchksum; /* Checksum for the data. */ + uint16_t nchksum; /* Checksum for the name. */ + uint16_t chksum; /* Checksum for the raw_inode. */ }; struct jffs_file { - struct jffs_raw_inode inode; - char *name; - unsigned char *data; + struct jffs_raw_inode inode; + char *name; + unsigned char *data; }; @@ -84,68 +84,68 @@ int endian = ENDIAN_HOST; static uint32_t jffs_checksum(void *data, int size); void jffs_print_trace(const char *path, int depth); int make_root_dir(FILE *fs, int first_ino, const char *root_dir_path, - int depth); + int depth); void write_file(struct jffs_file *f, FILE *fs, struct stat st); void read_data(struct jffs_file *f, const char *path, int offset); int mkfs(FILE *fs, const char *path, int ino, int parent, int depth); -static uint32_t + static uint32_t jffs_checksum(void *data, int size) { - uint32_t sum = 0; - uint8_t *ptr = (uint8_t *)data; + uint32_t sum = 0; + uint8_t *ptr = (uint8_t *)data; - while (size-- > 0) - { - sum += *ptr++; - } + while (size-- > 0) + { + sum += *ptr++; + } - return sum; + return sum; } -void + void jffs_print_trace(const char *path, int depth) { - int path_len = strlen(path); - int out_pos = depth * JFFS_TRACE_INDENT; - int pos = path_len - 1; - char *out = (char *)alloca(depth * JFFS_TRACE_INDENT + path_len + 1); - - if (verbose >= 2) - { - fprintf(stderr, "jffs_print_trace(): path: \"%s\"\n", path); - } - - if (!out) { - fprintf(stderr, "jffs_print_trace(): Allocation failed.\n"); - fprintf(stderr, " path: \"%s\"\n", path); - fprintf(stderr, "depth: %d\n", depth); - exit(1); - } - - memset(out, ' ', depth * JFFS_TRACE_INDENT); - - if (path[pos] == '/') - { - pos--; - } - while (path[pos] && (path[pos] != '/')) - { - pos--; - } - for (pos++; path[pos] && (path[pos] != '/'); pos++) - { - out[out_pos++] = path[pos]; - } - out[out_pos] = '\0'; - fprintf(stderr, "%s\n", out); + int path_len = strlen(path); + int out_pos = depth * JFFS_TRACE_INDENT; + int pos = path_len - 1; + char *out = (char *)alloca(depth * JFFS_TRACE_INDENT + path_len + 1); + + if (verbose >= 2) + { + fprintf(stderr, "jffs_print_trace(): path: \"%s\"\n", path); + } + + if (!out) { + fprintf(stderr, "jffs_print_trace(): Allocation failed.\n"); + fprintf(stderr, " path: \"%s\"\n", path); + fprintf(stderr, "depth: %d\n", depth); + exit(1); + } + + memset(out, ' ', depth * JFFS_TRACE_INDENT); + + if (path[pos] == '/') + { + pos--; + } + while (path[pos] && (path[pos] != '/')) + { + pos--; + } + for (pos++; path[pos] && (path[pos] != '/'); pos++) + { + out[out_pos++] = path[pos]; + } + out[out_pos] = '\0'; + fprintf(stderr, "%s\n", out); } /* Print the contents of a raw inode. */ -void + void jffs_print_raw_inode(struct jffs_raw_inode *raw_inode) { fprintf(stderr, "jffs_raw_inode: inode number: %u\n", raw_inode->ino); @@ -166,13 +166,13 @@ jffs_print_raw_inode(struct jffs_raw_inode *raw_inode) fprintf(stderr, " 0x%02x, /* nsize */\n", raw_inode->nsize); fprintf(stderr, " 0x%02x, /* nlink */\n", raw_inode->nlink); fprintf(stderr, " 0x%02x, /* spare */\n", - raw_inode->spare); + raw_inode->spare); fprintf(stderr, " %u, /* rename */\n", - raw_inode->rename); + raw_inode->rename); fprintf(stderr, " %u, /* deleted */\n", - raw_inode->deleted); + raw_inode->deleted); fprintf(stderr, " 0x%02x, /* accurate */\n", - raw_inode->accurate); + raw_inode->accurate); fprintf(stderr, " 0x%08x, /* dchksum */\n", raw_inode->dchksum); fprintf(stderr, " 0x%04x, /* nchksum */\n", raw_inode->nchksum); fprintf(stderr, " 0x%04x, /* chksum */\n", raw_inode->chksum); @@ -181,536 +181,536 @@ jffs_print_raw_inode(struct jffs_raw_inode *raw_inode) static void write_val32(uint32_t *adr, uint32_t val) { - switch(endian) { - case ENDIAN_HOST: - *adr = val; - break; - case ENDIAN_LITTLE: - *adr = cpu_to_le32(val); - break; - case ENDIAN_BIG: - *adr = cpu_to_be32(val); - break; - } + switch(endian) { + case ENDIAN_HOST: + *adr = val; + break; + case ENDIAN_LITTLE: + *adr = cpu_to_le32(val); + break; + case ENDIAN_BIG: + *adr = cpu_to_be32(val); + break; + } } static void write_val16(uint16_t *adr, uint16_t val) { - switch(endian) { - case ENDIAN_HOST: - *adr = val; - break; - case ENDIAN_LITTLE: - *adr = cpu_to_le16(val); - break; - case ENDIAN_BIG: - *adr = cpu_to_be16(val); - break; - } + switch(endian) { + case ENDIAN_HOST: + *adr = val; + break; + case ENDIAN_LITTLE: + *adr = cpu_to_le16(val); + break; + case ENDIAN_BIG: + *adr = cpu_to_be16(val); + break; + } } static uint32_t read_val32(uint32_t *adr) { - uint32_t val = 0; - - switch(endian) { - case ENDIAN_HOST: - val = *adr; - break; - case ENDIAN_LITTLE: - val = le32_to_cpu(*adr); - break; - case ENDIAN_BIG: - val = be32_to_cpu(*adr); - break; - } - return val; + uint32_t val = 0; + + switch(endian) { + case ENDIAN_HOST: + val = *adr; + break; + case ENDIAN_LITTLE: + val = le32_to_cpu(*adr); + break; + case ENDIAN_BIG: + val = be32_to_cpu(*adr); + break; + } + return val; } /* This function constructs a root inode with no name and no data. The inode is then written to the filesystem image. */ -int + int make_root_dir(FILE *fs, int first_ino, const char *root_dir_path, int depth) { - struct jffs_file f; - struct stat st; - - if (stat(root_dir_path, &st) < 0) - { - perror("stat"); - exit(1); - } - - write_val32(&f.inode.magic, JFFS_MAGIC); - write_val32(&f.inode.ino, first_ino); - write_val32(&f.inode.pino, 0); - write_val32(&f.inode.version, 1); - write_val32(&f.inode.mode, st.st_mode); - write_val16(&f.inode.uid, 0); /* root */ - write_val16(&f.inode.gid, 0); /* root */ - write_val32(&f.inode.atime, st.st_atime); - write_val32(&f.inode.mtime, st.st_mtime); - write_val32(&f.inode.ctime, st.st_ctime); - write_val32(&f.inode.offset, 0); - write_val32(&f.inode.dsize, 0); - write_val32(&f.inode.rsize,0); - f.inode.nsize = 0; - /*f.inode.nlink = st.st_nlink;*/ - f.inode.nlink = 1; - f.inode.spare = 0; - f.inode.rename = 0; - f.inode.deleted = 0; - f.inode.accurate = 0; - write_val32(&f.inode.dchksum, 0); - write_val16(&f.inode.nchksum, 0); - write_val16(&f.inode.chksum, 0); - f.name = 0; - f.data = 0; - write_val16(&f.inode.chksum, jffs_checksum(&f.inode, sizeof(struct jffs_raw_inode))); - f.inode.accurate = 0xff; - write_file(&f, fs, st); - if (verbose >= 1) - { - jffs_print_trace(root_dir_path, depth); - } - if (verbose >= 2) - { - jffs_print_raw_inode(&f.inode); - } - return first_ino; + struct jffs_file f; + struct stat st; + + if (stat(root_dir_path, &st) < 0) + { + perror("stat"); + exit(1); + } + + write_val32(&f.inode.magic, JFFS_MAGIC); + write_val32(&f.inode.ino, first_ino); + write_val32(&f.inode.pino, 0); + write_val32(&f.inode.version, 1); + write_val32(&f.inode.mode, st.st_mode); + write_val16(&f.inode.uid, 0); /* root */ + write_val16(&f.inode.gid, 0); /* root */ + write_val32(&f.inode.atime, st.st_atime); + write_val32(&f.inode.mtime, st.st_mtime); + write_val32(&f.inode.ctime, st.st_ctime); + write_val32(&f.inode.offset, 0); + write_val32(&f.inode.dsize, 0); + write_val32(&f.inode.rsize,0); + f.inode.nsize = 0; + /*f.inode.nlink = st.st_nlink;*/ + f.inode.nlink = 1; + f.inode.spare = 0; + f.inode.rename = 0; + f.inode.deleted = 0; + f.inode.accurate = 0; + write_val32(&f.inode.dchksum, 0); + write_val16(&f.inode.nchksum, 0); + write_val16(&f.inode.chksum, 0); + f.name = 0; + f.data = 0; + write_val16(&f.inode.chksum, jffs_checksum(&f.inode, sizeof(struct jffs_raw_inode))); + f.inode.accurate = 0xff; + write_file(&f, fs, st); + if (verbose >= 1) + { + jffs_print_trace(root_dir_path, depth); + } + if (verbose >= 2) + { + jffs_print_raw_inode(&f.inode); + } + return first_ino; } /* This function writes a chunks of data. A data chunk consists of a raw inode, perhaps a name and perhaps some data. */ -void + void write_file(struct jffs_file *f, FILE *fs, struct stat st) { - int npad = JFFS_GET_PAD_BYTES(f->inode.nsize); - int dpad = JFFS_GET_PAD_BYTES(read_val32(&f->inode.dsize)); - int size = sizeof(struct jffs_raw_inode) + f->inode.nsize + npad - + read_val32(&f->inode.dsize) + dpad; - unsigned char ff_data[] = { 0xff, 0xff, 0xff, 0xff }; - - if (verbose >= 2) - { - fprintf(stderr, "***write_file()\n"); - } - - /* Write the raw inode. */ - fwrite((void *)&f->inode, sizeof(struct jffs_raw_inode), 1, fs); - - /* Write the name. */ - if (f->inode.nsize) - { - fwrite(f->name, 1, f->inode.nsize, fs); - if (npad) - { - fwrite(ff_data, 1, npad, fs); - } - } - - /* Write the data. */ - if (read_val32(&f->inode.dsize)) - { - if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) - { - uint16_t tmp; - - switch(endian) { - case ENDIAN_HOST: - tmp = st.st_rdev; - break; - case ENDIAN_LITTLE: - tmp = cpu_to_le16(st.st_rdev); - break; - case ENDIAN_BIG: - tmp = cpu_to_be16(st.st_rdev); - break; - } - fwrite((char *)&tmp, sizeof(st.st_rdev) / 4, 1, fs); - } - else - { - fwrite(f->data, 1, read_val32(&f->inode.dsize), fs); - } - if (dpad) - { - fwrite(ff_data, 1, dpad, fs); - } - } - - fs_pos += size; - /* If the space left on the block is smaller than the size of an - inode, then skip it. */ + int npad = JFFS_GET_PAD_BYTES(f->inode.nsize); + int dpad = JFFS_GET_PAD_BYTES(read_val32(&f->inode.dsize)); + int size = sizeof(struct jffs_raw_inode) + f->inode.nsize + npad + + read_val32(&f->inode.dsize) + dpad; + unsigned char ff_data[] = { 0xff, 0xff, 0xff, 0xff }; + + if (verbose >= 2) + { + fprintf(stderr, "***write_file()\n"); + } + + /* Write the raw inode. */ + fwrite((void *)&f->inode, sizeof(struct jffs_raw_inode), 1, fs); + + /* Write the name. */ + if (f->inode.nsize) + { + fwrite(f->name, 1, f->inode.nsize, fs); + if (npad) + { + fwrite(ff_data, 1, npad, fs); + } + } + + /* Write the data. */ + if (read_val32(&f->inode.dsize)) + { + if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) + { + uint16_t tmp; + + switch(endian) { + case ENDIAN_HOST: + tmp = st.st_rdev; + break; + case ENDIAN_LITTLE: + tmp = cpu_to_le16(st.st_rdev); + break; + case ENDIAN_BIG: + tmp = cpu_to_be16(st.st_rdev); + break; + } + fwrite((char *)&tmp, sizeof(st.st_rdev) / 4, 1, fs); + } + else + { + fwrite(f->data, 1, read_val32(&f->inode.dsize), fs); + } + if (dpad) + { + fwrite(ff_data, 1, dpad, fs); + } + } + + fs_pos += size; + /* If the space left on the block is smaller than the size of an + inode, then skip it. */ } -void + void read_data(struct jffs_file *f, const char *path, int offset) { - FILE *file; - char *tot_path; - int pos = 0; - int r; - - if (verbose >= 2) - { - fprintf(stderr, "***read_data(): f: 0x%08x, path: \"%s\", offset: %u\r\n", - (unsigned int)f, path, offset); - fprintf(stderr, " file's size: %u\n", read_val32(&f->inode.dsize)); - } - - if (!(f->data = (unsigned char *)malloc(read_val32(&f->inode.dsize)))) - { - fprintf(stderr, "read_data(): malloc() failed! (*data)\n"); - exit(1); - } - - if (!(tot_path = (char *)alloca(strlen(path) + f->inode.nsize + 1))) - { - fprintf(stderr, "read_data(): alloca() failed! (tot_path)\n"); - exit(1); - } - strcpy(tot_path, path); - strncat(tot_path, f->name, f->inode.nsize); - - if (!(file = fopen(tot_path, "r"))) - { - fprintf(stderr, "read_data(): Couldn't open \"%s\".\n", tot_path); - exit(1); - } - - if (fseek(file, offset, SEEK_SET) < 0) - { - fprintf(stderr, "read_data(): fseek failure: path = %s, offset = %u.\n", - path, offset); - exit(1); - } - - while (pos < read_val32(&f->inode.dsize)) - { - if ((r = fread(&f->data[pos], 1, read_val32(&f->inode.dsize) - pos, file)) < 0) - { - fprintf(stderr, "read_data(): fread failure (%s).\n", path); - exit(1); - } - pos += r; - } - - fclose(file); + FILE *file; + char *tot_path; + int pos = 0; + int r; + + if (verbose >= 2) + { + fprintf(stderr, "***read_data(): f: 0x%08x, path: \"%s\", offset: %u\r\n", + (unsigned int)f, path, offset); + fprintf(stderr, " file's size: %u\n", read_val32(&f->inode.dsize)); + } + + if (!(f->data = (unsigned char *)malloc(read_val32(&f->inode.dsize)))) + { + fprintf(stderr, "read_data(): malloc() failed! (*data)\n"); + exit(1); + } + + if (!(tot_path = (char *)alloca(strlen(path) + f->inode.nsize + 1))) + { + fprintf(stderr, "read_data(): alloca() failed! (tot_path)\n"); + exit(1); + } + strcpy(tot_path, path); + strncat(tot_path, f->name, f->inode.nsize); + + if (!(file = fopen(tot_path, "r"))) + { + fprintf(stderr, "read_data(): Couldn't open \"%s\".\n", tot_path); + exit(1); + } + + if (fseek(file, offset, SEEK_SET) < 0) + { + fprintf(stderr, "read_data(): fseek failure: path = %s, offset = %u.\n", + path, offset); + exit(1); + } + + while (pos < read_val32(&f->inode.dsize)) + { + if ((r = fread(&f->data[pos], 1, read_val32(&f->inode.dsize) - pos, file)) < 0) + { + fprintf(stderr, "read_data(): fread failure (%s).\n", path); + exit(1); + } + pos += r; + } + + fclose(file); } /* This is the routine that constructs the filesystem image. */ -int + int mkfs(FILE *fs, const char *path, int ino, int parent, int depth) { - struct dirent *dir_entry; - DIR *dir; - struct stat st; - struct jffs_file f; - int name_len; - int pos = 0; - int new_ino = ino; - char *filename; - int path_len = strlen(path); - - if (verbose >= 2) - { - fprintf(stderr, "***mkfs(): path: \"%s\"\r\n", path); - } - - if (!(dir = opendir(path))) - { - perror("opendir"); - fprintf(stderr, "mkfs(): opendir() failed! (%s)\n", path); - exit(1); - } - - while ((dir_entry = readdir(dir))) - { - if (verbose >= 2) - { - fprintf(stderr, "mkfs(): name: %s\n", dir_entry->d_name); - } - name_len = strlen(dir_entry->d_name); - - if (((name_len == 1) - && (dir_entry->d_name[0] == '.')) - || ((name_len == 2) - && (dir_entry->d_name[0] == '.') - && (dir_entry->d_name[1] == '.'))) - { - continue; - } - - if (!(filename = (char *)alloca(path_len + name_len + 1))) - { - fprintf(stderr, "mkfs(): Allocation failed!\n"); - exit(0); - } - strcpy(filename, path); - strcat(filename, dir_entry->d_name); - - if (verbose >= 2) - { - fprintf(stderr, "mkfs(): filename: %s\n", filename); - } - - if (lstat(filename, &st) < 0) - { - perror("lstat"); - exit(1); - } - - if (verbose >= 2) - { - fprintf(stderr, "mkfs(): filename: \"%s\", ino: %d, parent: %d\n", - filename, new_ino, parent); - } - - write_val32(&f.inode.magic, JFFS_MAGIC); - write_val32(&f.inode.ino, new_ino); - write_val32(&f.inode.pino, parent); - write_val32(&f.inode.version, 1); - write_val32(&f.inode.mode, st.st_mode); - write_val16(&f.inode.uid, st.st_uid); - write_val16(&f.inode.gid, st.st_gid); - write_val32(&f.inode.atime, st.st_atime); - write_val32(&f.inode.mtime, st.st_mtime); - write_val32(&f.inode.ctime, st.st_ctime); - write_val32(&f.inode.dsize, 0); - write_val32(&f.inode.rsize, 0); - f.inode.nsize = name_len; - /*f.inode.nlink = st.st_nlink;*/ - f.inode.nlink = 1; - f.inode.spare = 0; - f.inode.rename = 0; - f.inode.deleted = 0; - f.inode.accurate = 0; - write_val32(&f.inode.dchksum, 0); - write_val16(&f.inode.nchksum, 0); - write_val16(&f.inode.chksum, 0); - if (dir_entry->d_name) - { - f.name = strdup(dir_entry->d_name); - } - else - { - f.name = 0; - } - - repeat: - write_val32(&f.inode.offset, pos); - f.data = 0; - f.inode.accurate = 0; - if (S_ISREG(st.st_mode) && st.st_size) - { - if (st.st_size - pos < MAX_CHUNK_SIZE) - { - write_val32(&f.inode.dsize, st.st_size - pos); - } - else - { - write_val32(&f.inode.dsize, MAX_CHUNK_SIZE); - } - - read_data(&f, path, pos); - pos += read_val32(&f.inode.dsize); - } - else if (S_ISLNK(st.st_mode)) - { - int linklen; - char *linkdata = malloc(1000); - if (!linkdata) - { - fprintf(stderr, "mkfs(): malloc() failed! (linkdata)\n"); - exit(1); - } - if ((linklen = readlink(filename, linkdata, 1000)) < 0) - { - free(linkdata); - fprintf(stderr, "mkfs(): readlink() failed! f.name = \"%s\"\n", - f.name); - exit(1); - } - - write_val32(&f.inode.dsize, linklen); - f.data = (unsigned char *)linkdata; - f.data[linklen] = '\0'; - } - else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) - { - write_val32(&f.inode.dsize, sizeof(st.st_rdev) / 4); - } - - write_val16(&f.inode.chksum, 0); - if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) - { - write_val32(&f.inode.dchksum, jffs_checksum((void *)f.data, read_val32(&f.inode.dsize))); - } - else - { - write_val32(&f.inode.dchksum, jffs_checksum((void *)&st.st_rdev, sizeof(st.st_rdev) / 4)); - } - - write_val16(&f.inode.nchksum, jffs_checksum((void *)f.name, f.inode.nsize)); - write_val16(&f.inode.chksum, jffs_checksum((void *)&f.inode, sizeof(struct jffs_raw_inode))); - f.inode.accurate = 0xff; - - write_file(&f, fs, st); - if (S_ISREG(st.st_mode) && st.st_size) - { - if (pos < st.st_size) - { - write_val32(&f.inode.version, read_val32(&f.inode.version) + 1); - goto repeat; - } - } - - new_ino++; - pos = 0; - if (verbose >= 1) - { - jffs_print_trace(f.name, depth); - } - if (verbose >= 2) - { - jffs_print_raw_inode(&f.inode); - } - - if (S_ISDIR(st.st_mode)) - { - char *new_path; - - if (!(new_path = (char *)alloca(strlen(path) + name_len + 1 + 1))) - { - fprintf(stderr, "mkfs(): alloca() failed! (new_path)\n"); - exit(1); - } - strcpy(new_path, path); - strncat(new_path, f.name, f.inode.nsize); - strcat(new_path, "/"); - - if (verbose >= 2) - { - fprintf(stderr, "mkfs(): new_path: \"%s\"\n", new_path); - } - new_ino = mkfs(fs, new_path, new_ino, new_ino - 1, depth + 1); - } - if (f.name) - { - free(f.name); - } - if (f.data) - { - free(f.data); - } - } - - closedir(dir); - return new_ino; + struct dirent *dir_entry; + DIR *dir; + struct stat st; + struct jffs_file f; + int name_len; + int pos = 0; + int new_ino = ino; + char *filename; + int path_len = strlen(path); + + if (verbose >= 2) + { + fprintf(stderr, "***mkfs(): path: \"%s\"\r\n", path); + } + + if (!(dir = opendir(path))) + { + perror("opendir"); + fprintf(stderr, "mkfs(): opendir() failed! (%s)\n", path); + exit(1); + } + + while ((dir_entry = readdir(dir))) + { + if (verbose >= 2) + { + fprintf(stderr, "mkfs(): name: %s\n", dir_entry->d_name); + } + name_len = strlen(dir_entry->d_name); + + if (((name_len == 1) + && (dir_entry->d_name[0] == '.')) + || ((name_len == 2) + && (dir_entry->d_name[0] == '.') + && (dir_entry->d_name[1] == '.'))) + { + continue; + } + + if (!(filename = (char *)alloca(path_len + name_len + 1))) + { + fprintf(stderr, "mkfs(): Allocation failed!\n"); + exit(0); + } + strcpy(filename, path); + strcat(filename, dir_entry->d_name); + + if (verbose >= 2) + { + fprintf(stderr, "mkfs(): filename: %s\n", filename); + } + + if (lstat(filename, &st) < 0) + { + perror("lstat"); + exit(1); + } + + if (verbose >= 2) + { + fprintf(stderr, "mkfs(): filename: \"%s\", ino: %d, parent: %d\n", + filename, new_ino, parent); + } + + write_val32(&f.inode.magic, JFFS_MAGIC); + write_val32(&f.inode.ino, new_ino); + write_val32(&f.inode.pino, parent); + write_val32(&f.inode.version, 1); + write_val32(&f.inode.mode, st.st_mode); + write_val16(&f.inode.uid, st.st_uid); + write_val16(&f.inode.gid, st.st_gid); + write_val32(&f.inode.atime, st.st_atime); + write_val32(&f.inode.mtime, st.st_mtime); + write_val32(&f.inode.ctime, st.st_ctime); + write_val32(&f.inode.dsize, 0); + write_val32(&f.inode.rsize, 0); + f.inode.nsize = name_len; + /*f.inode.nlink = st.st_nlink;*/ + f.inode.nlink = 1; + f.inode.spare = 0; + f.inode.rename = 0; + f.inode.deleted = 0; + f.inode.accurate = 0; + write_val32(&f.inode.dchksum, 0); + write_val16(&f.inode.nchksum, 0); + write_val16(&f.inode.chksum, 0); + if (dir_entry->d_name) + { + f.name = strdup(dir_entry->d_name); + } + else + { + f.name = 0; + } + +repeat: + write_val32(&f.inode.offset, pos); + f.data = 0; + f.inode.accurate = 0; + if (S_ISREG(st.st_mode) && st.st_size) + { + if (st.st_size - pos < MAX_CHUNK_SIZE) + { + write_val32(&f.inode.dsize, st.st_size - pos); + } + else + { + write_val32(&f.inode.dsize, MAX_CHUNK_SIZE); + } + + read_data(&f, path, pos); + pos += read_val32(&f.inode.dsize); + } + else if (S_ISLNK(st.st_mode)) + { + int linklen; + char *linkdata = malloc(1000); + if (!linkdata) + { + fprintf(stderr, "mkfs(): malloc() failed! (linkdata)\n"); + exit(1); + } + if ((linklen = readlink(filename, linkdata, 1000)) < 0) + { + free(linkdata); + fprintf(stderr, "mkfs(): readlink() failed! f.name = \"%s\"\n", + f.name); + exit(1); + } + + write_val32(&f.inode.dsize, linklen); + f.data = (unsigned char *)linkdata; + f.data[linklen] = '\0'; + } + else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) + { + write_val32(&f.inode.dsize, sizeof(st.st_rdev) / 4); + } + + write_val16(&f.inode.chksum, 0); + if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) + { + write_val32(&f.inode.dchksum, jffs_checksum((void *)f.data, read_val32(&f.inode.dsize))); + } + else + { + write_val32(&f.inode.dchksum, jffs_checksum((void *)&st.st_rdev, sizeof(st.st_rdev) / 4)); + } + + write_val16(&f.inode.nchksum, jffs_checksum((void *)f.name, f.inode.nsize)); + write_val16(&f.inode.chksum, jffs_checksum((void *)&f.inode, sizeof(struct jffs_raw_inode))); + f.inode.accurate = 0xff; + + write_file(&f, fs, st); + if (S_ISREG(st.st_mode) && st.st_size) + { + if (pos < st.st_size) + { + write_val32(&f.inode.version, read_val32(&f.inode.version) + 1); + goto repeat; + } + } + + new_ino++; + pos = 0; + if (verbose >= 1) + { + jffs_print_trace(f.name, depth); + } + if (verbose >= 2) + { + jffs_print_raw_inode(&f.inode); + } + + if (S_ISDIR(st.st_mode)) + { + char *new_path; + + if (!(new_path = (char *)alloca(strlen(path) + name_len + 1 + 1))) + { + fprintf(stderr, "mkfs(): alloca() failed! (new_path)\n"); + exit(1); + } + strcpy(new_path, path); + strncat(new_path, f.name, f.inode.nsize); + strcat(new_path, "/"); + + if (verbose >= 2) + { + fprintf(stderr, "mkfs(): new_path: \"%s\"\n", new_path); + } + new_ino = mkfs(fs, new_path, new_ino, new_ino - 1, depth + 1); + } + if (f.name) + { + free(f.name); + } + if (f.data) + { + free(f.data); + } + } + + closedir(dir); + return new_ino; } -void + void usage(void) { - fprintf(stderr, "Usage: mkfs.jffs -d root_directory [-a little|big] [-e erase_size] [-o output_file] [-v[0-9]]\n"); - fprintf(stderr, " By default, the file system is built using the same endianness as the\n"); - fprintf(stderr, " host. If building for a different target, use the -a option.\n"); + fprintf(stderr, "Usage: mkfs.jffs -d root_directory [-a little|big] [-e erase_size] [-o output_file] [-v[0-9]]\n"); + fprintf(stderr, " By default, the file system is built using the same endianness as the\n"); + fprintf(stderr, " host. If building for a different target, use the -a option.\n"); } -int + int main(int argc, char **argv) { - FILE *fs; - int root_ino; - int len; - int ch; - extern int optind; - extern char *optarg; - - fs = stdout; /* Send constructed file system to stdout by default */ - - while ((ch = getopt(argc, argv, "a:d:e:v::o:h?")) != -1) { - switch((char)ch) { - case 'd': - len = strlen(optarg); - root_directory_name = (char *)malloc(len + 2); - memcpy(root_directory_name, optarg, len); - if (root_directory_name[len - 1] != '/') + FILE *fs; + int root_ino; + int len; + int ch; + extern int optind; + extern char *optarg; + + fs = stdout; /* Send constructed file system to stdout by default */ + + while ((ch = getopt(argc, argv, "a:d:e:v::o:h?")) != -1) { + switch((char)ch) { + case 'd': + len = strlen(optarg); + root_directory_name = (char *)malloc(len + 2); + memcpy(root_directory_name, optarg, len); + if (root_directory_name[len - 1] != '/') + { + root_directory_name[len++] = '/'; + } + root_directory_name[len] = '\0'; + break; + case 'v': + if (!optarg || strlen(optarg) == 0) { + verbose = 1; + } + else if (strlen(optarg) > 1 || !isdigit(optarg[0])) { + fprintf(stderr, "verbose level must be between 0 and 9!\n"); + usage(); + exit(1); + } + else { + verbose = strtol(optarg, NULL, 0); + } + break; + case 'o': + fs = fopen(optarg, "w"); + if (!fs) { + fprintf(stderr, "unable to open file %s for output.\n", optarg); + exit(1); + } + break; + case 'a': + if (strcmp(optarg, "little") == 0) { + endian = ENDIAN_LITTLE; + } + else if (strcmp(optarg, "big") == 0) { + endian = ENDIAN_BIG; + } + else { + usage(); + exit(1); + } + break; + case 'e': + MAX_CHUNK_SIZE = strtol(optarg, NULL, 0) / 2; + break; + case 'h': + case '?': + default: + usage(); + exit(0); + } + } + + if ((argc -= optind)) { + usage(); + exit(1); + } + + if (root_directory_name == NULL) { + fprintf(stderr, "Error: must specify a root directory\n"); + usage(); + exit(1); + } + + if (verbose >= 1) { - root_directory_name[len++] = '/'; + fprintf(stderr, "Constructing JFFS filesystem...\n"); } - root_directory_name[len] = '\0'; - break; - case 'v': - if (!optarg || strlen(optarg) == 0) { - verbose = 1; - } - else if (strlen(optarg) > 1 || !isdigit(optarg[0])) { - fprintf(stderr, "verbose level must be between 0 and 9!\n"); - usage(); - exit(1); - } - else { - verbose = strtol(optarg, NULL, 0); - } - break; - case 'o': - fs = fopen(optarg, "w"); - if (!fs) { - fprintf(stderr, "unable to open file %s for output.\n", optarg); - exit(1); - } - break; - case 'a': - if (strcmp(optarg, "little") == 0) { - endian = ENDIAN_LITTLE; - } - else if (strcmp(optarg, "big") == 0) { - endian = ENDIAN_BIG; - } - else { - usage(); - exit(1); - } - break; - case 'e': - MAX_CHUNK_SIZE = strtol(optarg, NULL, 0) / 2; - break; - case 'h': - case '?': - default: - usage(); - exit(0); - } - } - - if ((argc -= optind)) { - usage(); - exit(1); - } - - if (root_directory_name == NULL) { - fprintf(stderr, "Error: must specify a root directory\n"); - usage(); - exit(1); - } - - if (verbose >= 1) - { - fprintf(stderr, "Constructing JFFS filesystem...\n"); - } - root_ino = make_root_dir(fs, JFFS_MIN_INO, root_directory_name, 0); - mkfs(fs, root_directory_name, root_ino + 1, root_ino, 1); - - fclose(fs); - free(root_directory_name); - exit(0); + root_ino = make_root_dir(fs, JFFS_MIN_INO, root_directory_name, 0); + mkfs(fs, root_directory_name, root_ino + 1, root_ino, 1); + + fclose(fs); + free(root_directory_name); + exit(0); } |