FreeCalypso > hg > freecalypso-tools
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]); +}