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);
+}