view rvinterf/etmsync/fswrite.c @ 333:74d5e95ee84a

uptools/libcoding: alphabetic address handling implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 03 Feb 2018 23:53:20 +0000
parents 8136fb5eb292
children a0754c98fc2b
line wrap: on
line source

/*
 * FFS write operation commands
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "etm.h"
#include "ffs.h"
#include "ffserr.h"
#include "tmffs2.h"
#include "limits.h"
#include "localtypes.h"
#include "localstruct.h"
#include "exitcodes.h"

extern u_char rvi_msg[];
extern int rvi_msg_len;

cmd_mkdir(argc, argv)
	char **argv;
{
	return do_mkdir_existok(argv[1]);
}

cmd_delete(argc, argv)
	char **argv;
{
	u_char cmdpkt[MAX_PKT_TO_TARGET], *dp;
	int rc, slen;

	slen = strlen(argv[1]);
	if (slen >= TMFFS_STRING_SIZE) {
		printf("error: pathname arg exceeds string length limit\n");
		return(ERROR_USAGE);
	}
	dp = cmdpkt + 1;
	*dp++ = ETM_FFS2;
	*dp++ = TMFFS_REMOVE;
	*dp++ = slen + 1;
	strcpy(dp, argv[1]);
	dp += slen + 1;
	rc = etm_pkt_exch(cmdpkt, dp - cmdpkt - 1);
	if (rc)
		return(rc);
	if (rvi_msg_len != 5) {
		printf("error: TMFFS_REMOVE response has wrong length\n");
		return(ERROR_TARGET);
	}
	if (rvi_msg[3]) {
		report_ffs_err("ffs_remove", rvi_msg[3]);
		return(ERROR_TARGET);
	}
	return(0);
}

hexdigit(c)
{
	if (isdigit(c))
		return(c - '0');
	else if (isupper(c))
		return(c - 'A' + 10);
	else
		return(c - 'a' + 10);
}

fwrite_hex_string(pathname, strarg)
	char *pathname, *strarg;
{
	u_char buf[256];
	int maxlen, len;
	char *cp;

	maxlen = max_short_file_write(pathname);
	for (cp = strarg, len = 0; ; cp += 2) {
		while (isspace(*cp))
			cp++;
		if (!*cp)
			break;
		if (!isxdigit(cp[0]) || !isxdigit(cp[1])) {
			fprintf(stderr, "error: invalid hex string argument\n");
			return(ERROR_USAGE);
		}
		if (len >= maxlen) {
			fprintf(stderr,
			"error: hex string exceeds write packet limit\n");
			return(ERROR_USAGE);
		}
		buf[len++] = hexdigit(cp[0]) << 4 | hexdigit(cp[1]);
	}
	return do_short_fwrite(pathname, buf, len);
}

fwrite_from_file(pathname, srcfile)
	char *pathname, *srcfile;
{
	u_char buf[240];
	FILE *srcf;
	int rc, cc, first, tfd;

	srcf = fopen(srcfile, "r");
	if (!srcf) {
		perror(srcfile);
		return(ERROR_UNIX);
	}
	for (first = 1; cc = fread(buf, 1, sizeof buf, srcf); first = 0) {
		if (first) {
			if (cc < sizeof buf &&
			    cc <= max_short_file_write(pathname)) {
				fclose(srcf);
				return do_short_fwrite(pathname, buf, cc);
			}
			rc = fd_open(pathname,
				     FFS_O_WRONLY | FFS_O_CREATE | FFS_O_TRUNC,
				     &tfd);
			if (rc) {
				fclose(srcf);
				return(rc);
			}
		}
		rc = fd_write(tfd, buf, cc);
		if (rc) {
			fclose(srcf);
			fd_close(tfd);
			return(rc);
		}
	}
	fclose(srcf);
	if (first) {
		/* 0 length file: do an open-for-write to create it */
		rc = fd_open(pathname,
				FFS_O_WRONLY | FFS_O_CREATE | FFS_O_TRUNC,
				&tfd);
		if (rc)
			return(rc);
	}
	return fd_close(tfd);
}

cmd_fwrite(argc, argv)
	char **argv;
{
	if (strlen(argv[1]) >= TMFFS_STRING_SIZE) {
		fprintf(stderr,
			"error: pathname arg exceeds string length limit\n");
		return(ERROR_USAGE);
	}
	if (!strcmp(argv[2], "ascii"))
		return do_short_fwrite(argv[1], argv[3], strlen(argv[3]));
	else if (!strcmp(argv[2], "hex"))
		return fwrite_hex_string(argv[1], argv[3]);
	else if (!strcmp(argv[2], "file"))
		return fwrite_from_file(argv[1], argv[3]);
	else {
		fprintf(stderr,
"error: middle argument to fwrite cmd must be \"ascii\", \"hex\" or \"file\"\n"
			);
		return(ERROR_USAGE);
	}
}

write_buf_to_file(pathname, data, datalen)
	char *pathname;
	u_char *data;
{
	int tfd, rc, chunk, remain;

	if (datalen <= max_short_file_write(pathname))
		return do_short_fwrite(pathname, data, datalen);
	/* do it the long way */
	rc = fd_open(pathname, FFS_O_WRONLY | FFS_O_CREATE | FFS_O_TRUNC, &tfd);
	if (rc)
		return(rc);
	for (remain = datalen; remain; remain -= chunk) {
		chunk = remain;
		if (chunk > 240)
			chunk = 240;
		rc = fd_write(tfd, data, chunk);
		if (rc) {
			fd_close(tfd);
			return(rc);
		}
		data += chunk;
	}
	return fd_close(tfd);
}