FreeCalypso > hg > freecalypso-tools
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-mkfs/output.c Wed May 20 06:55:58 2020 +0000 @@ -0,0 +1,227 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <stdio.h> +#include <stdint.h> +#include <endian.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include "struct.h" +#include "globals.h" + +u_char tiffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02}; + +void +prepare_output_buffers() +{ + inode_block = malloc(ffs_sector_size); + if (!inode_block) { + perror("malloc of inode block buffer"); + exit(1); + } + memset(inode_block, 0xFF, ffs_sector_size); + bcopy(tiffs_header, inode_block, 6); + inode_block[8] = 0xAB; + inode_array = (struct tiffs_inode *) inode_block; + inode_fill_level = 1; + + data_block = malloc(ffs_sector_size); + if (!data_block) { + perror("malloc of data block buffer"); + exit(1); + } + memset(data_block, 0xFF, ffs_sector_size); + bcopy(tiffs_header, data_block, 6); + data_block[8] = 0xBD; + data_fill_level = 0x10; + objects_in_block = 0; +} + +void +open_output_file() +{ + output_fd = open(output_filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (output_fd < 0) { + perror(output_filename); + exit(1); + } + lseek(output_fd, (off_t) ffs_sector_size, SEEK_SET); +} + +void +write_out_block(buf) + u_char *buf; +{ + if (write(output_fd, buf, ffs_sector_size) != ffs_sector_size) { + perror("write of sector bits to output file"); + exit(1); + } +} + +void +flush_data_block() +{ + write_out_block(data_block); + blocks_written++; + memset(data_block + 0x10, 0xFF, ffs_sector_size - 0x10); + data_fill_level = 0x10; + objects_in_block = 0; +} + +create_object(name, type, data, datalen) + char *name; + u_char *data; + unsigned datalen; +{ + int ino; + struct tiffs_inode *inp; + unsigned size, location; + u_char *dp; + + if (inode_fill_level >= (ffs_sector_size >> 4)) { + fprintf(stderr, "error: inode block is full\n"); + exit(1); + } + ino = inode_fill_level++; + inp = inode_array + ino; + if (name) + size = strlen(name) + 1; + else + size = 0; + if (data) + size += datalen + 1; + size = (size + 15) & ~15; + if (ffs_sector_size - data_fill_level < size || + objects_in_block >= block_files_max) + flush_data_block(); + if (blocks_written >= ffs_nsectors - 2) { + fprintf(stderr, "error: wrote max number of data blocks\n"); + exit(1); + } + location = (blocks_written + 1) * ffs_sector_size + data_fill_level; + /* write the data */ + dp = data_block + data_fill_level; + if (name) { + strcpy(dp, name); + dp += strlen(name) + 1; + } + if (data) { + bcopy(data, dp, datalen); + dp += datalen; + *dp++ = 0; + } + /* fill the inode */ + inp->size = htole16(size); + inp->type = type; + inp->location = htole32(location); + inp->sequence = htole16(ino - 1); + inp->updates = 0; + /* accounting */ + data_fill_level += size; + objects_in_block++; + return ino; +} + +void +create_root_dir() +{ + int rootino; + + rootino = create_object(format_name, OBJTYPE_DIR, (u_char *) 0, 0); + root.u.d.ffs_link_ptr = &inode_array[rootino].child; +} + +create_file_object(to) + struct tree_object *to; +{ + int fd, cc; + u_char *data; + int head, seg; + struct tiffs_inode *inp; + + fd = open(to->u.f.host_pathname, O_RDONLY); + if (fd < 0) { + perror(to->u.f.host_pathname); + exit(1); + } + data = malloc(chunk_size_max); + if (!data) { + perror("malloc of file chunk buffer"); + exit(1); + } + cc = read(fd, data, chunk_size_max); + if (cc < 0) { +read_err: perror("error reading file content"); + exit(1); + } + if (cc == 0) { + /* zero length file */ + close(fd); + free(data); + return create_object(to->name, OBJTYPE_FILE, (u_char *) 0, 0); + } + head = create_object(to->name, OBJTYPE_FILE, data, cc); + inp = inode_array + head; + for (;;) { + cc = read(fd, data, chunk_size_max); + if (cc < 0) + goto read_err; + if (cc == 0) + break; + seg = create_object((char *) 0, OBJTYPE_SEGMENT, data, cc); + inp->child = htole16(seg); + inp = inode_array + seg; + } + close(fd); + free(data); + return head; +} + +create_subdir(to) + struct tree_object *to; +{ + int ino; + + ino = create_object(to->name, OBJTYPE_DIR, (u_char *) 0, 0); + to->u.d.ffs_link_ptr = &inode_array[ino].child; + return ino; +} + +void +process_dir_level(dto) + struct tree_object *dto; +{ + unsigned n; + struct tree_object *cto; + int child_ino; + + for (n = 0; n < dto->u.d.nchildren; n++) { + cto = dto->u.d.children[n]; + if (cto->is_dir) { + child_ino = create_subdir(cto); + process_dir_level(cto); + } else + child_ino = create_file_object(cto); + *dto->u.d.ffs_link_ptr = htole16(child_ino); + dto->u.d.ffs_link_ptr = &inode_array[child_ino].sibling; + } +} + +void +finish_output() +{ + if (objects_in_block) + flush_data_block(); + while (blocks_written < ffs_nsectors - 2) { + write_out_block(data_block); + blocks_written++; + } + /* free block at the end */ + data_block[8] = 0xBF; + write_out_block(data_block); + /* write out the inode block */ + lseek(output_fd, (off_t) 0, SEEK_SET); + write_out_block(inode_block); +}