FreeCalypso > hg > freecalypso-tools
view ffstools/tiffs-mkfs/output.c @ 1004:d15d337ac0a9
loadtools/scripts: remove long-deprecated -h gta02 config
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 09 Dec 2023 18:35:30 +0000 |
parents | 178ed445021d |
children |
line wrap: on
line source
#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; chunk_buffer = malloc(chunk_size_max); if (!chunk_buffer) { perror("malloc of file chunk buffer"); exit(1); } } 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 (datalen) 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 (datalen) { if (data) bcopy(data, dp, datalen); dp += datalen; *dp++ = 0; } /* fill the inode */ inp->size = htole16(size); inp->type = type; inp->location = htole32(location >> 4); 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; 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); } cc = read(fd, chunk_buffer, chunk_size_max); if (cc < 0) { read_err: perror("error reading file content"); exit(1); } if (cc == 0) { /* zero length file */ close(fd); return create_object(to->name, OBJTYPE_FILE, (u_char *) 0, 0); } head = create_object(to->name, OBJTYPE_FILE, chunk_buffer, cc); inp = inode_array + head; for (;;) { cc = read(fd, chunk_buffer, chunk_size_max); if (cc < 0) goto read_err; if (cc == 0) break; seg = create_object((char *) 0, OBJTYPE_SEGMENT, chunk_buffer, cc); inp->child = htole16(seg); inp = inode_array + seg; } close(fd); 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 create_journal() { int ino; ino = create_object(".journal", OBJTYPE_FILE_RO, (u_char *) 0, journal_size); *root.u.d.ffs_link_ptr = htole16(ino); root.u.d.ffs_link_ptr = &inode_array[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); }