mirror of
https://github.com/ksherlock/mpw-tools.git
synced 2024-11-18 19:07:36 +00:00
237 lines
3.1 KiB
C
237 lines
3.1 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include <errno.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "OverlayIIgs-flags.h"
|
||
|
|
||
|
int tox(char c)
|
||
|
{
|
||
|
c |= 0x20;
|
||
|
if (c >='0' && c <= '9') return c - '0';
|
||
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
off_t hex(const char *in)
|
||
|
{
|
||
|
off_t rv = 0;
|
||
|
|
||
|
int i;
|
||
|
for (i = 0; ; ++i)
|
||
|
{
|
||
|
off_t tmp;
|
||
|
char c;
|
||
|
|
||
|
c = *in++;
|
||
|
if (!c) break;
|
||
|
|
||
|
if (!isxdigit(c)) return -1;
|
||
|
|
||
|
|
||
|
tmp = rv;
|
||
|
rv <<= 4;
|
||
|
rv |= tox(c);
|
||
|
|
||
|
// numver too large.
|
||
|
if (rv < tmp)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i == 0) return -1;
|
||
|
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
off_t dec(const char *in)
|
||
|
{
|
||
|
off_t rv = 0;
|
||
|
|
||
|
int i;
|
||
|
for (i = 0; ; ++i)
|
||
|
{
|
||
|
off_t tmp;
|
||
|
char c;
|
||
|
|
||
|
c = *in++;
|
||
|
if (!c) break;
|
||
|
|
||
|
if (!isdigit(c)) return -1;
|
||
|
|
||
|
|
||
|
tmp = rv;
|
||
|
rv = rv * 10;
|
||
|
rv += c - '0';
|
||
|
|
||
|
// numver too large.
|
||
|
if (rv < tmp)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i == 0) return -1;
|
||
|
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
off_t getnum(const char *cp)
|
||
|
{
|
||
|
if (!cp) return -1;
|
||
|
|
||
|
if (cp[0] == '$')
|
||
|
{
|
||
|
return hex(cp + 1);
|
||
|
}
|
||
|
|
||
|
if (cp[0] == '0' && cp[1] == 'x')
|
||
|
{
|
||
|
return hex(cp + 2);
|
||
|
}
|
||
|
return dec(cp);
|
||
|
}
|
||
|
|
||
|
|
||
|
int seek_to(int fd, off_t address)
|
||
|
{
|
||
|
// posix lseek(2) will seek past the eof and zero-fill
|
||
|
// when a write occurs.
|
||
|
|
||
|
// mpw lseek will fail (ENXIO) in such situations.
|
||
|
// SetEOF will not zero-fill.
|
||
|
|
||
|
// to compensate, manually zero-fill to the address
|
||
|
// if address > eof.
|
||
|
|
||
|
off_t eof;
|
||
|
|
||
|
eof = lseek(fd, 0, SEEK_END);
|
||
|
if (eof < 0)
|
||
|
return -1;
|
||
|
|
||
|
while (eof < address)
|
||
|
{
|
||
|
static char buffer[512] = { 0 };
|
||
|
|
||
|
off_t size = address - eof;
|
||
|
if (size > 512) size = 512;
|
||
|
|
||
|
size = write(fd, buffer, size);
|
||
|
if (size < 0) return -1;
|
||
|
eof += size;
|
||
|
}
|
||
|
|
||
|
eof = lseek(fd, address, SEEK_SET);
|
||
|
if (eof < 0)
|
||
|
return -1;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
char *src;
|
||
|
char *dest;
|
||
|
|
||
|
int srcFD, destFD;
|
||
|
off_t address;
|
||
|
int rv;
|
||
|
|
||
|
|
||
|
argc = FlagsParse(argc, argv);
|
||
|
|
||
|
if (argc != 3)
|
||
|
{
|
||
|
FlagsHelp();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (!flags._a)
|
||
|
{
|
||
|
FlagsHelp();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
address = getnum(flags._a);
|
||
|
if (address == -1)
|
||
|
{
|
||
|
|
||
|
fprintf(stderr, "Invalid address: %s\n", flags._a);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
src = argv[1];
|
||
|
dest = argv[2];
|
||
|
|
||
|
srcFD = open(src, O_RDONLY | O_BINARY);
|
||
|
if (srcFD < 0)
|
||
|
{
|
||
|
fprintf(stderr, "Unable to open input file %s: %s",
|
||
|
src, strerror(errno));
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
destFD = open(dest, O_WRONLY | O_CREAT | O_BINARY);
|
||
|
if (destFD < 0)
|
||
|
{
|
||
|
fprintf(stderr, "Unable to open input file %s: %s",
|
||
|
dest, strerror(errno));
|
||
|
close(srcFD);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//if (lseek(destFD, address, SEEK_SET) < 0)
|
||
|
if (seek_to(destFD, address) < 0)
|
||
|
{
|
||
|
fprintf(stderr, "Error seeking %s: %s",
|
||
|
dest, strerror(errno));
|
||
|
close(srcFD);
|
||
|
close(destFD);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// copy it
|
||
|
rv = 0;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
|
||
|
unsigned char buffer[4096];
|
||
|
ssize_t rsize;
|
||
|
ssize_t wsize;
|
||
|
|
||
|
rsize = read(srcFD, buffer, 4096);
|
||
|
|
||
|
if (rsize == 0) break;
|
||
|
|
||
|
if (rsize < 0)
|
||
|
{
|
||
|
fprintf(stderr, "Error reading %s: %s\n",
|
||
|
src, strerror(errno));
|
||
|
rv = 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
wsize = write(destFD, buffer, rsize);
|
||
|
if (wsize < 0 || wsize != rsize)
|
||
|
{
|
||
|
fprintf(stderr, "Error writing %s: %s\n",
|
||
|
dest, strerror(errno));
|
||
|
rv = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close(srcFD);
|
||
|
close(destFD);
|
||
|
|
||
|
|
||
|
return rv;
|
||
|
}
|