15 #define PAD(x) (((x)+3)&~3)
17 #if BYTE_ORDER == BIG_ENDIAN
18 # define CLEANMARKER "\x19\x85\x20\x03\x00\x00\x00\x0c\xf0\x60\xdc\x98"
20 # define CLEANMARKER "\x85\x19\x03\x20\x0c\x00\x00\x00\xb1\xb0\x1e\xe4"
23 static int last_ino = 0;
24 static int last_version = 0;
25 static char *buf = NULL;
28 static int mtdofs = 0;
29 static int target_ino = 0;
31 static void prep_eraseblock(void);
33 static void pad(int size)
35 if ((ofs % size == 0) && (ofs < erasesize))
38 if (ofs < erasesize) {
39 memset(buf + ofs, 0xff, (size - (ofs % size)));
40 ofs += (size - (ofs % size));
42 ofs = ofs % erasesize;
44 mtd_erase_block(outfd, mtdofs);
45 write(outfd, buf, erasesize);
50 static inline int rbytes(void)
52 return erasesize - (ofs % erasesize);
55 static inline void add_data(char *ptr, int len)
57 if (ofs + len > erasesize) {
61 memcpy(buf + ofs, ptr, len);
65 static void prep_eraseblock(void)
70 add_data(CLEANMARKER, sizeof(CLEANMARKER) - 1);
73 static int add_dirent(const char *name, const char type, int parent)
75 struct jffs2_raw_dirent *de;
77 if (ofs - erasesize < sizeof(struct jffs2_raw_dirent) + strlen(name))
82 memset(buf + ofs, 0, sizeof(struct jffs2_raw_dirent));
83 de = (struct jffs2_raw_dirent *) (buf + ofs);
85 de->magic = JFFS2_MAGIC_BITMASK;
86 de->nodetype = JFFS2_NODETYPE_DIRENT;
88 de->name_crc = crc32(0, name, strlen(name));
91 de->totlen = sizeof(*de) + strlen(name);
92 de->hdr_crc = crc32(0, (void *) de, sizeof(struct jffs2_unknown_node) - 4);
93 de->version = last_version++;
95 de->nsize = strlen(name);
96 de->node_crc = crc32(0, (void *) de, sizeof(*de) - 8);
97 memcpy(de->name, name, strlen(name));
99 ofs += sizeof(struct jffs2_raw_dirent) + de->nsize;
105 static int add_dir(const char *name, int parent)
107 struct jffs2_raw_inode ri;
110 inode = add_dirent(name, IFTODT(S_IFDIR), parent);
112 if (rbytes() < sizeof(ri))
116 memset(&ri, 0, sizeof(ri));
117 ri.magic = JFFS2_MAGIC_BITMASK;
118 ri.nodetype = JFFS2_NODETYPE_INODE;
119 ri.totlen = sizeof(ri);
120 ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4);
123 ri.mode = S_IFDIR | 0755;
125 ri.atime = ri.ctime = ri.mtime = 0;
126 ri.isize = ri.csize = ri.dsize = 0;
128 ri.node_crc = crc32(0, &ri, sizeof(ri) - 8);
131 add_data((char *) &ri, sizeof(ri));
136 static void add_file(const char *name, int parent)
138 int inode, f_offset = 0, fd;
139 struct jffs2_raw_inode ri;
145 if (stat(name, &st)) {
146 fprintf(stderr, "File %s does not exist\n", name);
150 fname = strrchr(name, '/');
156 inode = add_dirent(fname, IFTODT(S_IFREG), parent);
157 memset(&ri, 0, sizeof(ri));
158 ri.magic = JFFS2_MAGIC_BITMASK;
159 ri.nodetype = JFFS2_NODETYPE_INODE;
162 ri.mode = st.st_mode;
164 ri.atime = st.st_atime;
165 ri.ctime = st.st_ctime;
166 ri.mtime = st.st_mtime;
167 ri.isize = st.st_size;
173 fprintf(stderr, "File %s does not exist\n", name);
181 len = rbytes() - sizeof(ri);
189 if (len > sizeof(wbuf))
192 len = read(fd, wbuf, len);
196 ri.totlen = sizeof(ri) + len;
197 ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4);
198 ri.version = ++last_version;
199 ri.offset = f_offset;
200 ri.csize = ri.dsize = len;
201 ri.node_crc = crc32(0, &ri, sizeof(ri) - 8);
202 ri.data_crc = crc32(0, wbuf, len);
204 add_data((char *) &ri, sizeof(ri));
213 int mtd_replace_jffs2(int fd, int ofs, const char *filename)
218 buf = malloc(erasesize);
222 add_file(filename, target_ino);
225 /* add eof marker, pad to eraseblock size and write the data */
226 add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1);
231 void mtd_parse_jffs2data(const char *buf, const char *dir)
233 struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf;
234 unsigned int ofs = 0;
236 while (ofs < erasesize) {
237 node = (struct jffs2_unknown_node *) (buf + ofs);
238 if (node->magic != 0x1985)
241 ofs += PAD(node->totlen);
242 if (node->nodetype == JFFS2_NODETYPE_DIRENT) {
243 struct jffs2_raw_dirent *de = (struct jffs2_raw_dirent *) node;
245 /* is this the right directory name and is it a subdirectory of / */
246 if (*dir && (de->pino == 1) && !strncmp(de->name, dir, de->nsize))
247 target_ino = de->ino;
249 /* store the last inode and version numbers for adding extra files */
250 if (last_ino < de->ino)
252 if (last_version < de->version)
253 last_version = de->version;
258 int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir)
260 int err = -1, fdeof = 0;
263 outfd = mtd_check_open(mtd);
268 fprintf(stderr, "Appending %s to jffs2 partition %s\n", filename, mtd);
270 buf = malloc(erasesize);
272 fprintf(stderr, "Out of memory!\n");
279 /* parse the structure of the jffs2 first
280 * locate the directory that the file is going to be placed in */
282 struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf;
284 if (read(outfd, buf, erasesize) != erasesize) {
290 if (node->magic == 0x8519) {
291 fprintf(stderr, "Error: wrong endianness filesystem\n");
295 /* assume no magic == end of filesystem
296 * the filesystem will probably end with be32(0xdeadc0de) */
297 if (node->magic != 0x1985)
300 mtd_parse_jffs2data(buf, dir);
304 fprintf(stderr, "Error: No room for additional data\n");
308 /* jump back one eraseblock */
310 lseek(outfd, mtdofs, SEEK_SET);
318 target_ino = add_dir(dir, 1);
320 add_file(filename, target_ino);
323 /* add eof marker, pad to eraseblock size and write the data */
324 add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1);