comparison ffstools/tiffs-mkfs/output.c @ 705:12ae93940467

tiffs-mkfs program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 20 May 2020 06:55:58 +0000
parents
children 805885936f62
comparison
equal deleted inserted replaced
704:dacd9fdc392a 705:12ae93940467
1 #include <sys/types.h>
2 #include <sys/param.h>
3 #include <sys/file.h>
4 #include <stdio.h>
5 #include <stdint.h>
6 #include <endian.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <strings.h>
10 #include <unistd.h>
11 #include "struct.h"
12 #include "globals.h"
13
14 u_char tiffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02};
15
16 void
17 prepare_output_buffers()
18 {
19 inode_block = malloc(ffs_sector_size);
20 if (!inode_block) {
21 perror("malloc of inode block buffer");
22 exit(1);
23 }
24 memset(inode_block, 0xFF, ffs_sector_size);
25 bcopy(tiffs_header, inode_block, 6);
26 inode_block[8] = 0xAB;
27 inode_array = (struct tiffs_inode *) inode_block;
28 inode_fill_level = 1;
29
30 data_block = malloc(ffs_sector_size);
31 if (!data_block) {
32 perror("malloc of data block buffer");
33 exit(1);
34 }
35 memset(data_block, 0xFF, ffs_sector_size);
36 bcopy(tiffs_header, data_block, 6);
37 data_block[8] = 0xBD;
38 data_fill_level = 0x10;
39 objects_in_block = 0;
40 }
41
42 void
43 open_output_file()
44 {
45 output_fd = open(output_filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
46 if (output_fd < 0) {
47 perror(output_filename);
48 exit(1);
49 }
50 lseek(output_fd, (off_t) ffs_sector_size, SEEK_SET);
51 }
52
53 void
54 write_out_block(buf)
55 u_char *buf;
56 {
57 if (write(output_fd, buf, ffs_sector_size) != ffs_sector_size) {
58 perror("write of sector bits to output file");
59 exit(1);
60 }
61 }
62
63 void
64 flush_data_block()
65 {
66 write_out_block(data_block);
67 blocks_written++;
68 memset(data_block + 0x10, 0xFF, ffs_sector_size - 0x10);
69 data_fill_level = 0x10;
70 objects_in_block = 0;
71 }
72
73 create_object(name, type, data, datalen)
74 char *name;
75 u_char *data;
76 unsigned datalen;
77 {
78 int ino;
79 struct tiffs_inode *inp;
80 unsigned size, location;
81 u_char *dp;
82
83 if (inode_fill_level >= (ffs_sector_size >> 4)) {
84 fprintf(stderr, "error: inode block is full\n");
85 exit(1);
86 }
87 ino = inode_fill_level++;
88 inp = inode_array + ino;
89 if (name)
90 size = strlen(name) + 1;
91 else
92 size = 0;
93 if (data)
94 size += datalen + 1;
95 size = (size + 15) & ~15;
96 if (ffs_sector_size - data_fill_level < size ||
97 objects_in_block >= block_files_max)
98 flush_data_block();
99 if (blocks_written >= ffs_nsectors - 2) {
100 fprintf(stderr, "error: wrote max number of data blocks\n");
101 exit(1);
102 }
103 location = (blocks_written + 1) * ffs_sector_size + data_fill_level;
104 /* write the data */
105 dp = data_block + data_fill_level;
106 if (name) {
107 strcpy(dp, name);
108 dp += strlen(name) + 1;
109 }
110 if (data) {
111 bcopy(data, dp, datalen);
112 dp += datalen;
113 *dp++ = 0;
114 }
115 /* fill the inode */
116 inp->size = htole16(size);
117 inp->type = type;
118 inp->location = htole32(location);
119 inp->sequence = htole16(ino - 1);
120 inp->updates = 0;
121 /* accounting */
122 data_fill_level += size;
123 objects_in_block++;
124 return ino;
125 }
126
127 void
128 create_root_dir()
129 {
130 int rootino;
131
132 rootino = create_object(format_name, OBJTYPE_DIR, (u_char *) 0, 0);
133 root.u.d.ffs_link_ptr = &inode_array[rootino].child;
134 }
135
136 create_file_object(to)
137 struct tree_object *to;
138 {
139 int fd, cc;
140 u_char *data;
141 int head, seg;
142 struct tiffs_inode *inp;
143
144 fd = open(to->u.f.host_pathname, O_RDONLY);
145 if (fd < 0) {
146 perror(to->u.f.host_pathname);
147 exit(1);
148 }
149 data = malloc(chunk_size_max);
150 if (!data) {
151 perror("malloc of file chunk buffer");
152 exit(1);
153 }
154 cc = read(fd, data, chunk_size_max);
155 if (cc < 0) {
156 read_err: perror("error reading file content");
157 exit(1);
158 }
159 if (cc == 0) {
160 /* zero length file */
161 close(fd);
162 free(data);
163 return create_object(to->name, OBJTYPE_FILE, (u_char *) 0, 0);
164 }
165 head = create_object(to->name, OBJTYPE_FILE, data, cc);
166 inp = inode_array + head;
167 for (;;) {
168 cc = read(fd, data, chunk_size_max);
169 if (cc < 0)
170 goto read_err;
171 if (cc == 0)
172 break;
173 seg = create_object((char *) 0, OBJTYPE_SEGMENT, data, cc);
174 inp->child = htole16(seg);
175 inp = inode_array + seg;
176 }
177 close(fd);
178 free(data);
179 return head;
180 }
181
182 create_subdir(to)
183 struct tree_object *to;
184 {
185 int ino;
186
187 ino = create_object(to->name, OBJTYPE_DIR, (u_char *) 0, 0);
188 to->u.d.ffs_link_ptr = &inode_array[ino].child;
189 return ino;
190 }
191
192 void
193 process_dir_level(dto)
194 struct tree_object *dto;
195 {
196 unsigned n;
197 struct tree_object *cto;
198 int child_ino;
199
200 for (n = 0; n < dto->u.d.nchildren; n++) {
201 cto = dto->u.d.children[n];
202 if (cto->is_dir) {
203 child_ino = create_subdir(cto);
204 process_dir_level(cto);
205 } else
206 child_ino = create_file_object(cto);
207 *dto->u.d.ffs_link_ptr = htole16(child_ino);
208 dto->u.d.ffs_link_ptr = &inode_array[child_ino].sibling;
209 }
210 }
211
212 void
213 finish_output()
214 {
215 if (objects_in_block)
216 flush_data_block();
217 while (blocks_written < ffs_nsectors - 2) {
218 write_out_block(data_block);
219 blocks_written++;
220 }
221 /* free block at the end */
222 data_block[8] = 0xBF;
223 write_out_block(data_block);
224 /* write out the inode block */
225 lseek(output_fd, (off_t) 0, SEEK_SET);
226 write_out_block(inode_block);
227 }