diff rvinterf/etmsync/fsread.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 46ad66a231af
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rvinterf/etmsync/fsread.c	Sat Jun 11 00:13:35 2016 +0000
@@ -0,0 +1,291 @@
+/*
+ * Commands for reading the content of a GSM device's file system
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include "etm.h"
+#include "ffs.h"
+#include "tmffs2.h"
+#include "limits.h"
+#include "ffslimits.h"
+#include "localtypes.h"
+#include "localstruct.h"
+#include "exitcodes.h"
+
+extern char *pathname_for_ffs_child();
+
+void
+ll_print_line(pathname, stat)
+	char *pathname;
+	struct stat_info *stat;
+{
+	char readonly;
+	char rlbuf[256];
+
+	if (stat->flags & OF_READONLY)
+		readonly = 'r';
+	else
+		readonly = ' ';
+	switch (stat->type) {
+	case OT_FILE:
+		printf("f%c %7u %s\n", readonly, stat->size, pathname);
+		return;
+	case OT_DIR:
+		printf("d%c         %s\n", readonly, pathname);
+		return;
+	case OT_LINK:
+		if (do_readlink_sancheck(pathname, rlbuf))
+			strcpy(rlbuf, "<invalid>");
+		printf("l%c         %s -> %s\n", readonly, pathname, rlbuf);
+		return;
+	default:
+		printf("?%c         %s\n", readonly, pathname);
+	}
+}
+
+cmd_ll(argc, argv)
+	char **argv;
+{
+	struct stat_info stat;
+	u_char rdstate[4];
+	char rdbuf[MAX_FN_COMPONENT+1], childpath[MAX_FULL_PATHNAME+1], *childp;
+	int nument, i, rc;
+
+	if (validate_ffs_pathname(argv[1]) < 0)
+		return(ERROR_USAGE);	/* err msg already printed */
+	rc = do_xlstat(argv[1], &stat);
+	if (rc)
+		return(rc);
+	if (stat.type != OT_DIR) {
+		ll_print_line(argv[1], &stat);
+		return(0);
+	}
+	rc = do_opendir(argv[1], rdstate, &nument);
+	if (rc)
+		return(rc);
+	if (!nument) {
+		printf("<empty dir>\n");
+		return(0);
+	}
+	childp = pathname_for_ffs_child(argv[1], childpath);
+	if (!childp) {
+		printf("error: non-empty dir at the limit of pathname depth\n");
+		return(ERROR_TARGET);
+	}
+	for (i = 0; i < nument; i++) {
+		rc = do_readdir(rdstate, rdbuf, MAX_FN_COMPONENT+1);
+		if (rc)
+			return(rc);
+		if (index(rdbuf, '/')) {
+			printf("error: readdir result contains a slash\n");
+			return(ERROR_TARGET);
+		}
+		strcpy(childp, rdbuf);
+		rc = do_xlstat(childpath, &stat);
+		if (rc) {
+			printf("xlstat failed on %s\n", childpath);
+			return(rc);
+		}
+		ll_print_line(childpath, &stat);
+	}
+	return(0);
+}
+
+void
+hexdump_line(offset, buf, len)
+	u_char *buf;
+{
+	int i, c;
+
+	printf("%02X:  ", offset);
+	for (i = 0; i < 16; i++) {
+		if (i < len)
+			printf("%02X ", buf[i]);
+		else
+			fputs("   ", stdout);
+		if (i == 7 || i == 15)
+			putchar(' ');
+	}
+	for (i = 0; i < len; i++) {
+		c = buf[i];
+		if (c < ' ' || c > '~')
+			c = '.';
+		putchar(c);
+	}
+	putchar('\n');
+}
+
+cmd_hd(argc, argv)
+	char **argv;
+{
+	u_char databuf[MAX_READ_DATA];
+	int rc, sz, off, l;
+
+	rc = do_file_read(argv[1], databuf, MAX_READ_DATA, &sz);
+	if (rc)
+		return(rc);
+	printf("%d bytes read\n", sz);
+	for (off = 0; off < sz; off += 16) {
+		l = sz - off;
+		if (l > 16)
+			l = 16;
+		hexdump_line(off, databuf + off, l);
+	}
+	return(0);
+}
+
+cpout_object(ffspath, hostpath)
+	char *ffspath, *hostpath;
+{
+	struct stat_info stat;
+	int rc;
+
+	rc = do_xlstat(ffspath, &stat);
+	if (rc)
+		return(rc);
+	switch (stat.type) {
+	case OT_FILE:
+		return cpout_file(ffspath, hostpath);
+	case OT_DIR:
+		return cpout_dir(ffspath, hostpath);
+	case OT_LINK:
+		printf("skipping FFS symlink %s\n", ffspath);
+		return(0);
+	default:
+		printf("error: stat returned bad objtype for %s\n", ffspath);
+		return(ERROR_TARGET);
+	}
+}
+
+cpout_file(ffspath, hostpath)
+	char *ffspath, *hostpath;
+{
+	int tfd;
+	FILE *of;
+	u_char buf[MAX_READ_DATA];
+	int rc, sz;
+
+	printf("copying %s\n", ffspath);
+	rc = fd_open(ffspath, FFS_O_RDONLY, &tfd);
+	if (rc)
+		return(rc);
+	of = fopen(hostpath, "w");
+	if (!of) {
+		perror(hostpath);
+		fd_close(tfd);
+		return(ERROR_UNIX);
+	}
+	for (;;) {
+		rc = fd_read(tfd, buf, MAX_READ_DATA, &sz);
+		if (rc) {
+			fd_close(tfd);
+			fclose(of);
+			return(rc);
+		}
+		if (!sz)
+			break;
+		fwrite(buf, 1, sz, of);
+	}
+	fclose(of);
+	return fd_close(tfd);
+}
+
+host_mkdir(pathname)
+	char *pathname;
+{
+	int rc;
+	struct stat st;
+
+	rc = stat(pathname, &st);
+	if (rc < 0) {
+		rc = mkdir(pathname, 0777);
+		if (rc < 0) {
+			perror(pathname);
+			return(ERROR_UNIX);
+		}
+		return(0);
+	} else {
+		if (S_ISDIR(st.st_mode))
+			return(0);
+		else {
+			fprintf(stderr,
+			"error: %s already exists and is not a directory\n",
+				pathname);
+			return(ERROR_UNIX);
+		}
+	}
+}
+
+cpout_dir(ffspath_dir, hostpath_dir)
+	char *ffspath_dir, *hostpath_dir;
+{
+	u_char rdstate[4];
+	char rdbuf[MAX_FN_COMPONENT+1], ffspath_child[MAX_FULL_PATHNAME+1];
+	char *childp;
+	char hostpath_child[MAXPATHLEN];
+	int nument, i, rc, childerr;
+
+	printf("dir %s\n", ffspath_dir);
+	rc = host_mkdir(hostpath_dir);
+	if (rc)
+		return(rc);
+	rc = do_opendir(ffspath_dir, rdstate, &nument);
+	if (rc)
+		return(rc);
+	if (!nument)
+		return(0);
+	childp = pathname_for_ffs_child(ffspath_dir, ffspath_child);
+	if (!childp) {
+		printf("error: non-empty dir at the limit of pathname depth\n");
+		return(ERROR_TARGET);
+	}
+	childerr = 0;
+	for (i = 0; i < nument; i++) {
+		rc = do_readdir(rdstate, rdbuf, MAX_FN_COMPONENT+1);
+		if (rc)
+			return(rc);
+		if (index(rdbuf, '/')) {
+			printf("error: readdir result contains a slash\n");
+			return(ERROR_TARGET);
+		}
+		strcpy(childp, rdbuf);
+		if (rdbuf[0] == '.') {
+			printf("skipping %s\n", ffspath_child);
+			continue;
+		}
+		if (strlen(hostpath_dir) + strlen(rdbuf) + 2 >
+		    sizeof hostpath_child) {
+			fprintf(stderr,
+				"error: host side pathname buffer overflow\n");
+			return(ERROR_UNIX);
+		}
+		sprintf(hostpath_child, "%s/%s", hostpath_dir, rdbuf);
+		rc = cpout_object(ffspath_child, hostpath_child);
+		if (rc && rc != ERROR_TARGET)
+			return(rc);
+		if (rc)
+			childerr = rc;
+	}
+	return(childerr);
+}
+
+cmd_cpout(argc, argv)
+	char **argv;
+{
+	if (validate_ffs_pathname(argv[1]) < 0)
+		return(ERROR_USAGE);	/* err msg already printed */
+	return cpout_object(argv[1], argv[2]);
+}
+
+cmd_cpout_file(argc, argv)
+	char **argv;
+{
+	return cpout_file(argv[1], argv[2]);
+}