14 #define PAD(x) (((x)+3)&~3)
16 #define CLEANMARKER "\x85\x19\x03\x20\x0c\x00\x00\x00\xb1\xb0\x1e\xe4"
18 static int last_ino = 0;
19 static int last_version = 0;
20 static char *buf = NULL;
23 static int mtdofs = 0;
24 static int target_ino = 0;
26 static void prep_eraseblock(void);
28 static void pad(int size)
30 if ((ofs % size == 0) && (ofs < erasesize))
33 if (ofs < erasesize) {
34 memset(buf + ofs, 0xff, (size - (ofs % size)));
35 ofs += (size - (ofs % size));
37 ofs = ofs % erasesize;
39 mtd_erase_block(outfd, mtdofs);
40 write(outfd, buf, erasesize);
45 static inline int rbytes(void)
47 return erasesize - (ofs % erasesize);
50 static inline void add_data(char *ptr, int len)
52 if (ofs + len > erasesize) {
56 memcpy(buf + ofs, ptr, len);
60 static void prep_eraseblock(void)
65 add_data(CLEANMARKER, sizeof(CLEANMARKER) - 1);
68 static int add_dirent(const char *name, const char type, int parent)
70 struct jffs2_raw_dirent *de;
72 if (ofs - erasesize < sizeof(struct jffs2_raw_dirent) + strlen(name))
77 memset(buf + ofs, 0, sizeof(struct jffs2_raw_dirent));
78 de = (struct jffs2_raw_dirent *) (buf + ofs);
80 de->magic = JFFS2_MAGIC_BITMASK;
81 de->nodetype = JFFS2_NODETYPE_DIRENT;
83 de->name_crc = crc32(0, name, strlen(name));
86 de->totlen = sizeof(*de) + strlen(name);
87 de->hdr_crc = crc32(0, (void *) de, sizeof(struct jffs2_unknown_node) - 4);
88 de->version = last_version++;
90 de->nsize = strlen(name);
91 de->node_crc = crc32(0, (void *) de, sizeof(*de) - 8);
92 memcpy(de->name, name, strlen(name));
94 ofs += sizeof(struct jffs2_raw_dirent) + de->nsize;
100 static int add_dir(const char *name, int parent)
102 struct jffs2_raw_inode ri;
105 inode = add_dirent(name, IFTODT(S_IFDIR), parent);
107 if (rbytes() < sizeof(ri))
111 memset(&ri, 0, sizeof(ri));
112 ri.magic = JFFS2_MAGIC_BITMASK;
113 ri.nodetype = JFFS2_NODETYPE_INODE;
114 ri.totlen = sizeof(ri);
115 ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4);
118 ri.mode = S_IFDIR | 0755;
120 ri.atime = ri.ctime = ri.mtime = 0;
121 ri.isize = ri.csize = ri.dsize = 0;
123 ri.node_crc = crc32(0, &ri, sizeof(ri) - 8);
126 add_data((char *) &ri, sizeof(ri));
131 static void add_file(const char *name, int parent)
133 int inode, f_offset = 0, fd;
134 struct jffs2_raw_inode ri;
140 if (stat(name, &st)) {
141 fprintf(stderr, "File %s does not exist\n", name);
145 fname = strrchr(name, '/');
151 inode = add_dirent(fname, IFTODT(S_IFREG), parent);
152 memset(&ri, 0, sizeof(ri));
153 ri.magic = JFFS2_MAGIC_BITMASK;
154 ri.nodetype = JFFS2_NODETYPE_INODE;
157 ri.mode = st.st_mode;
159 ri.atime = st.st_atime;
160 ri.ctime = st.st_ctime;
161 ri.mtime = st.st_mtime;
162 ri.isize = st.st_size;
168 fprintf(stderr, "File %s does not exist\n", name);
176 len = rbytes() - sizeof(ri);
184 if (len > sizeof(wbuf))
187 len = read(fd, wbuf, len);
191 ri.totlen = sizeof(ri) + len;
192 ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4);
193 ri.version = ++last_version;
194 ri.offset = f_offset;
195 ri.csize = ri.dsize = len;
196 ri.node_crc = crc32(0, &ri, sizeof(ri) - 8);
197 ri.data_crc = crc32(0, wbuf, len);
199 add_data((char *) &ri, sizeof(ri));
208 int mtd_replace_jffs2(int fd, int ofs, const char *filename)
213 buf = malloc(erasesize);
217 add_file(filename, target_ino);
220 /* add eof marker, pad to eraseblock size and write the data */
221 add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1);
226 void mtd_parse_jffs2data(const char *buf, const char *dir)
228 struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf;
229 unsigned int ofs = 0;
231 while (ofs < erasesize) {
232 node = (struct jffs2_unknown_node *) (buf + ofs);
233 if (node->magic != 0x1985)
236 ofs += PAD(node->totlen);
237 if (node->nodetype == JFFS2_NODETYPE_DIRENT) {
238 struct jffs2_raw_dirent *de = (struct jffs2_raw_dirent *) node;
240 /* is this the right directory name and is it a subdirectory of / */
241 if (*dir && (de->pino == 1) && !strncmp(de->name, dir, de->nsize))
242 target_ino = de->ino;
244 /* store the last inode and version numbers for adding extra files */
245 if (last_ino < de->ino)
247 if (last_version < de->version)
248 last_version = de->version;
253 int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir)
255 int err = -1, fdeof = 0;
258 outfd = mtd_check_open(mtd);
263 fprintf(stderr, "Appending %s to jffs2 partition %s\n", filename, mtd);
265 buf = malloc(erasesize);
267 fprintf(stderr, "Out of memory!\n");
274 /* parse the structure of the jffs2 first
275 * locate the directory that the file is going to be placed in */
277 struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf;
279 if (read(outfd, buf, erasesize) != erasesize) {
285 if (node->magic == 0x8519) {
286 fprintf(stderr, "Error: wrong endianness filesystem\n");
290 /* assume no magic == end of filesystem
291 * the filesystem will probably end with be32(0xdeadc0de) */
292 if (node->magic != 0x1985)
295 mtd_parse_jffs2data(buf, dir);
299 fprintf(stderr, "Error: No room for additional data\n");
303 /* jump back one eraseblock */
305 lseek(outfd, mtdofs, SEEK_SET);
313 target_ino = add_dir(dir, 1);
315 add_file(filename, target_ino);
318 /* add eof marker, pad to eraseblock size and write the data */
319 add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1);