diff simtool/bfsearch.c @ 10:ddd767f6e15b

fc-simtool ported over
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 14 Mar 2021 07:11:25 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simtool/bfsearch.c	Sun Mar 14 07:11:25 2021 +0000
@@ -0,0 +1,230 @@
+/*
+ * This module implements a brute force search of file ID space at a given
+ * file system directory level.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "simresp.h"
+#include "file_id.h"
+
+static
+parse_skip_ids(argv, array, total)
+	char **argv;
+	unsigned *array, total;
+{
+	unsigned n;
+
+	for (n = 0; n < total; n++) {
+		if (!isxdigit(argv[n][0]) || !isxdigit(argv[n][1]) ||
+		    !isxdigit(argv[n][2]) || !isxdigit(argv[n][3]) ||
+		    argv[n][4]) {
+			fprintf(stderr, "error: argument is not 4-digit hex\n");
+			return(-1);
+		}
+		array[n] = strtoul(argv[n], 0, 16);
+	}
+	return(0);
+}
+
+static void
+report_ef_struct(outf)
+	FILE *outf;
+{
+	unsigned total_size, record_len;
+
+	fputs("EF, ", outf);
+	total_size = (sim_resp_data[2] << 8) | sim_resp_data[3];
+	switch (sim_resp_data[13]) {
+	case 0x00:
+		fprintf(outf, "transparent, length %u\n", total_size);
+		return;
+	case 0x01:
+		fputs("linear fixed, ", outf);
+		break;
+	case 0x03:
+		fputs("cyclic, ", outf);
+		break;
+	default:
+		fprintf(outf, "struct 0x%02X\n", sim_resp_data[13]);
+		return;
+	}
+	if (sim_resp_data_len < 15) {
+		fprintf(outf, "response struct cut off\n");
+		return;
+	}
+	record_len = sim_resp_data[14];
+	fprintf(outf, "record length %u", record_len);
+	if (record_len && total_size % record_len == 0)
+		fprintf(outf, ", %u records", total_size / record_len);
+	putc('\n', outf);
+}
+
+cmd_bfsearch(argc, argv, outf)
+	char **argv;
+	FILE *outf;
+{
+	unsigned skip_ids[8], num_skip_ids;
+	unsigned bfs, n;
+	int rc;
+
+	num_skip_ids = argc - 1;
+	rc = parse_skip_ids(argv + 1, skip_ids, num_skip_ids);
+	if (rc < 0)
+		return(rc);
+	rc = elem_select_op(skip_ids[0]);
+	if (rc < 0)
+		return(rc);
+	if (!rc) {
+		fprintf(stderr, "error: starting file ID 0x%04X not found\n",
+			skip_ids[0]);
+		return(-1);
+	}
+	for (bfs = 0; bfs <= 0xFFFF; bfs++) {
+		for (n = 0; n < num_skip_ids; n++) {
+			if (bfs == skip_ids[n])
+				break;
+		}
+		if (n < num_skip_ids)
+			continue;
+		rc = elem_select_op(bfs);
+		if (rc < 0)
+			return(rc);
+		if (!rc)
+			continue;
+		rc = get_response_op();
+		if (rc < 0)
+			return(rc);
+		fprintf(outf, "%04X: ", bfs);
+		if (sim_resp_data_len < 14)
+			fprintf(outf, "too-short response struct\n");
+		else {
+			switch (sim_resp_data[6]) {
+			case 0x01:
+				fprintf(outf, "MF\n");
+				break;
+			case 0x02:
+				fprintf(outf, "DF\n");
+				break;
+			case 0x04:
+				report_ef_struct(outf);
+				break;
+			default:
+				fprintf(outf, "unknown file type %02X\n",
+					sim_resp_data[6]);
+			}
+		}
+		rc = elem_select_op(skip_ids[0]);
+		if (rc < 0)
+			return(rc);
+		if (!rc) {
+			fprintf(stderr,
+			"reselecting starting file ID 0x%04X not-found error\n",
+				skip_ids[0]);
+			return(-1);
+		}
+	}
+	return(0);
+}
+
+static
+bfsearch_dir(path, pathlen, siblings, nsiblings, outf)
+	unsigned *path, pathlen, *siblings, nsiblings;
+	FILE *outf;
+{
+	unsigned bfs, n;
+	unsigned df_children[255], ndfc;
+	unsigned childpath[8];
+	int rc;
+
+	for (n = 0; n < pathlen; n++) {
+		rc = elem_select_op(path[n]);
+		if (rc < 0)
+			return(rc);
+		if (!rc) {
+			fprintf(stderr,
+				"error selecting 0x%04X: file not found\n",
+				path[n]);
+			return(-1);
+		}
+	}
+	ndfc = 0;
+	for (bfs = 0; bfs <= 0xFFFF; bfs++) {
+		for (n = 0; n < pathlen; n++) {
+			if (bfs == path[n])
+				break;
+		}
+		if (n < pathlen)
+			continue;
+		for (n = 0; n < nsiblings; n++) {
+			if (bfs == siblings[n])
+				break;
+		}
+		if (n < nsiblings)
+			continue;
+		rc = elem_select_op(bfs);
+		if (rc < 0)
+			return(rc);
+		if (!rc)
+			continue;
+		rc = get_response_op();
+		if (rc < 0)
+			return(rc);
+		for (n = 0; n < pathlen; n++)
+			fprintf(outf, "%04X/", path[n]);
+		fprintf(outf, "%04X: ", bfs);
+		if (sim_resp_data_len < 14)
+			fprintf(outf, "too-short response struct\n");
+		else {
+			switch (sim_resp_data[6]) {
+			case 0x01:
+				fprintf(outf, "MF\n");
+				break;
+			case 0x02:
+				fprintf(outf, "DF\n");
+				if (ndfc < 255)
+					df_children[ndfc++] = bfs;
+				break;
+			case 0x04:
+				report_ef_struct(outf);
+				break;
+			default:
+				fprintf(outf, "unknown file type %02X\n",
+					sim_resp_data[6]);
+			}
+		}
+		rc = elem_select_op(path[pathlen-1]);
+		if (rc < 0)
+			return(rc);
+		if (!rc) {
+			fprintf(stderr,
+			"reselecting starting file ID 0x%04X not-found error\n",
+				path[pathlen-1]);
+			return(-1);
+		}
+	}
+	if (pathlen >= 8)
+		return(0);
+	for (n = 0; n < pathlen; n++)
+		childpath[n] = path[n];
+	for (n = 0; n < ndfc; n++) {
+		childpath[pathlen] = df_children[n];
+		rc = bfsearch_dir(childpath, pathlen + 1, df_children, ndfc,
+				  outf);
+		if (rc < 0)
+			return(rc);
+	}
+	return(0);
+}
+
+cmd_bfsearch_full(argc, argv, outf)
+	char **argv;
+	FILE *outf;
+{
+	unsigned initpath;
+
+	initpath = FILEID_MF;
+	return bfsearch_dir(&initpath, 1, &initpath, 1, outf);
+}