diff --git a/Makefile b/Makefile index a61c404..81a1397 100644 --- a/Makefile +++ b/Makefile @@ -8,16 +8,19 @@ COptions-68K = {COptions} {Sym-68K} ### Source Files ### SrcFiles = ∂ + mac_from_unix.c ∂ mac_to_unix.c ∂ sync.c ### Object Files ### ObjFiles-PPC = ∂ + mac_from_unix.c.x ∂ mac_to_unix.c.x ∂ sync.c.x ObjFiles-68K = ∂ + mac_from_unix.c.o ∂ mac_to_unix.c.o ∂ sync.c.o @@ -73,13 +76,18 @@ SyncFiles ƒƒ {ObjFiles-68K} {LibFiles-68K} Dependencies ƒ $OutOfDate MakeDepend ∂ -append Makefile ∂ - -ignore "{CIncludes}" ∂ + -skip "{CIncludes}" ∂ -objext .x ∂ -objext .o ∂ {SrcFiles} #*** Dependencies: Cut here *** -# These dependencies were produced at 10:09:51 PM on Sat, Mar 6, 2021 by MakeDepend +# These dependencies were produced at 10:53:16 AM on Thu, Mar 11, 2021 by MakeDepend + +:mac_from_unix.c.x :mac_from_unix.c.o ƒ ∂ + :mac_from_unix.c ∂ + :defs.h ∂ + :mac_from_unix_data.h :mac_to_unix.c.x :mac_to_unix.c.o ƒ ∂ :mac_to_unix.c ∂ @@ -88,3 +96,4 @@ Dependencies ƒ $OutOfDate :sync.c.x :sync.c.o ƒ ∂ :sync.c ∂ :defs.h + diff --git a/defs.h b/defs.h index 306950c..9e6348c 100644 --- a/defs.h +++ b/defs.h @@ -1,2 +1,11 @@ -void mac_to_unix(unsigned char **outptr, unsigned char *outend, - const unsigned char **inptr, const unsigned char *inend); +void print_err(const char *msg, ...); +void print_errcode(int err, const char *msg, ...); + +int mac_to_unix(unsigned char **outptr, unsigned char *outend, + const unsigned char **inptr, const unsigned char *inend); + +int mac_from_unix(unsigned char **outptr, unsigned char *outend, + const unsigned char **inptr, const unsigned char *inend); + +int mac_from_unix_init(void); +void mac_from_unix_term(void); diff --git a/mac_from_unix.c b/mac_from_unix.c new file mode 100644 index 0000000..3378ca4 --- /dev/null +++ b/mac_from_unix.c @@ -0,0 +1,112 @@ +#include "defs.h" +#include "mac_from_unix_data.h" + +#include + +#include + +static unsigned short *gFromUnixData; + +static void print_uerr(const unsigned char *start, const unsigned char *end) { + const unsigned char *ptr; + int lineno = 1, colno = 0; + for (ptr = start; ptr != end; ptr++) { + colno++; + if (*ptr == '\r') { + lineno++; + colno = 0; + } + } + fprintf(stderr, "## Error: line %d, column %d: invalid character\n", lineno, + colno); +} + +int mac_from_unix(unsigned char **outptr, unsigned char *outend, + const unsigned char **inptr, const unsigned char *inend) { + unsigned char *op = *outptr; + const unsigned char *ip = *inptr, *curpos; + const unsigned short *table; + unsigned entry, value, state, c, last, curvalue; + + table = gFromUnixData; + if (table == NULL) { + print_err("table not loaded"); + return 1; + } + last = 0; + while (ip < inend && op < outend) { + c = *ip; + if (c < 128) { + if (c == '\n') { + c = '\r'; + } + if (op == outend) { + break; + } + *op = c; + last = c; + ip++; + op++; + } else { + // Find the longest matching Unicode character. + state = table[last] & 0xff00; + if (state != 0) { + // Continue from previous character. + op--; + curpos = ip; + curvalue = last; + } else { + // Continue from current character. + curpos = NULL; + curvalue = 0; + } + do { + entry = table[*ip++]; + state = entry & 0xff00; + value = entry & 0xff; + if (value != 0) { + curpos = ip; + curvalue = value; + } + } while (state != 0 && ip < inend); + if (curvalue == 0) { + print_uerr(*outptr, op); + *outptr = op; + *inptr = ip; + return 1; + } + ip = curpos; + *op++ = curvalue; + } + } + *outptr = op; + *inptr = ip; + return 0; +} + +int mac_from_unix_init(void) { + Ptr ptr, src, dest; + OSErr err; + + if (gFromUnixData != NULL) { + return 0; + } + ptr = NewPtr(FROM_UNIX_DATALEN); + err = MemError(); + if (err != 0) { + print_errcode(err, "out of memory"); + return 1; + } + src = (void *)kFromUnixData; + dest = ptr; + UnpackBits(&src, &dest, FROM_UNIX_DATALEN); + gFromUnixData = (void *)ptr; + return 0; +} + +void mac_from_unix_term(void) { + if (gFromUnixData != NULL) { + DisposePtr((void *)gFromUnixData); + gFromUnixData = NULL; + } +} diff --git a/mac_from_unix_data.h b/mac_from_unix_data.h new file mode 100644 index 0000000..1b57d6e --- /dev/null +++ b/mac_from_unix_data.h @@ -0,0 +1,52 @@ +/* This file is automatically generated. */ +// clang-format off +#define FROM_UNIX_DATALEN 27648 +static const unsigned char kFromUnixData[1256] = { +254,0,16,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,254,0,127,11,0,12,0,10,0,14,0,15,0, +16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,0, +32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0, +48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,1,61,0,62,0,63,0, +64,3,65,0,66,5,67,0,68,7,69,0,70,0,71,0,72,9,73,0,74,0,104,75,0,76,0,77,11,78, +13,79,0,80,0,81,0,82,0,83,0,84,15,85,0,86,0,87,0,88,17,89,0,90,0,91,0,92,0,93,0, +94,0,95,0,96,19,97,0,98,21,99,0,100,23,101,0,102,0,103,0,104,25,105,0,106,0,107, +0,108,0,109,27,110,29,111,0,112,0,113,0,114,0,115,0,116,31,117,0,118,0,119,0, +120,33,121,0,122,0,123,0,124,0,125,0,126,0,127,129,0,253,0,8,35,0,36,0,37,0,38, +0,39,248,0,0,40,252,0,2,41,0,42,220,0,0,43,232,0,0,51,129,0,129,0,129,0,200,0,0, +2,129,0,129,0,129,0,169,0,0,173,129,0,129,0,129,0,129,0,219,0,0,4,129,0,129,0, +153,0,6,203,0,231,0,229,0,204,248,0,0,128,254,0,0,129,129,0,129,0,129,0,129,0, +129,0,255,0,0,6,129,0,129,0,129,0,203,0,0,130,129,0,129,0,129,0,129,0,185,0,0,8, +129,0,129,0,153,0,4,233,0,131,0,230,246,0,0,232,129,0,129,0,129,0,129,0,129,0, +251,0,0,10,129,0,129,0,153,0,4,237,0,234,0,235,246,0,0,236,129,0,129,0,129,0, +129,0,129,0,251,0,0,12,129,0,129,0,147,0,0,132,129,0,129,0,129,0,129,0,129,0, +241,0,0,14,129,0,129,0,153,0,6,241,0,238,0,239,0,205,248,0,0,133,129,0,129,0, +129,0,129,0,129,0,251,0,0,16,129,0,129,0,153,0,4,244,0,242,0,243,246,0,0,134, +129,0,129,0,129,0,129,0,129,0,251,0,0,18,129,0,129,0,137,0,0,217,129,0,129,0, +129,0,129,0,129,0,251,0,0,20,129,0,129,0,153,0,6,136,0,135,0,137,0,139,248,0,0, +138,254,0,0,140,129,0,129,0,129,0,129,0,129,0,255,0,0,22,129,0,129,0,129,0,203, +0,0,141,129,0,129,0,129,0,129,0,185,0,0,24,129,0,129,0,153,0,4,143,0,142,0,144, +246,0,0,145,129,0,129,0,129,0,129,0,129,0,251,0,0,26,129,0,129,0,153,0,4,147,0, +146,0,148,246,0,0,149,129,0,129,0,129,0,129,0,129,0,251,0,0,28,129,0,129,0,147, +0,0,150,129,0,129,0,129,0,129,0,129,0,241,0,0,30,129,0,129,0,153,0,6,152,0,151, +0,153,0,155,248,0,0,154,129,0,129,0,129,0,129,0,129,0,251,0,0,32,129,0,129,0, +153,0,4,157,0,156,0,158,246,0,0,159,129,0,129,0,129,0,129,0,129,0,251,0,0,34, +129,0,129,0,137,0,0,216,129,0,129,0,129,0,129,0,210,0,6,202,0,193,0,162,0,163, +254,0,0,180,254,0,10,164,0,172,0,169,0,187,0,199,0,194,254,0,6,168,0,248,0,161, +0,177,252,0,8,171,0,181,0,166,0,225,0,252,254,0,2,188,0,200,250,0,0,192,129,0, +129,0,129,0,31,0,203,0,231,0,229,0,204,0,128,0,129,0,174,0,130,0,233,0,131,0, +230,0,232,0,237,0,234,0,235,0,236,254,0,10,132,0,241,0,238,0,239,0,205,0,133, +254,0,8,175,0,244,0,242,0,243,0,134,252,0,32,167,0,136,0,135,0,137,0,139,0,138, +0,140,0,190,0,141,0,143,0,142,0,144,0,145,0,147,0,146,0,148,0,149,254,0,22,150, +0,152,0,151,0,153,0,155,0,154,0,214,0,191,0,157,0,156,0,158,0,159,252,0,0,216, +129,0,129,0,129,0,158,0,0,245,129,0,129,0,129,0,192,0,2,206,0,207,184,0,0,217, +129,0,129,0,129,0,206,0,0,196,129,0,129,0,129,0,154,0,2,246,0,255,224,0,10,249, +0,250,0,251,0,254,0,247,0,253,129,0,129,0,129,0,129,0,234,0,0,189,129,0,129,0, +129,0,212,0,0,185,129,0,129,0,129,0,131,0,4,44,0,45,0,46,254,0,0,47,250,0,2,48, +0,49,230,0,0,50,129,0,129,0,129,0,137,0,2,208,0,209,250,0,4,212,0,213,0,226,254, +0,4,210,0,211,0,227,254,0,4,160,0,224,0,165,250,0,0,201,238,0,0,228,240,0,2,220, +0,221,129,0,129,0,129,0,238,0,0,218,129,0,129,0,129,0,129,0,178,0,0,219,129,0, +129,0,129,0,150,0,0,170,129,0,129,0,129,0,194,0,0,182,250,0,0,198,240,0,0,184, +254,0,0,183,240,0,0,195,250,0,0,176,232,0,0,186,129,0,129,0,129,0,200,0,0,197, +210,0,0,173,250,0,2,178,0,179,129,0,129,0,129,0,184,0,0,215,129,0,129,0,129,0, +129,0,209,0,0,52,240,0,0,53,129,0,129,0,129,0,129,0,219,0,0,240,129,0,129,0,129, +0,254,0,2,222,0,223,129,0,135,0, +}; diff --git a/mac_to_unix.c b/mac_to_unix.c index d024cd4..ab576b4 100644 --- a/mac_to_unix.c +++ b/mac_to_unix.c @@ -28,8 +28,8 @@ static const unsigned short kToUnixTable[256] = { 184, 733, 731, 711, }; -void mac_to_unix(unsigned char **outptr, unsigned char *outend, - const unsigned char **inptr, const unsigned char *inend) { +int mac_to_unix(unsigned char **outptr, unsigned char *outend, + const unsigned char **inptr, const unsigned char *inend) { unsigned char *op = *outptr; const unsigned char *ip = *inptr; unsigned cp; @@ -62,4 +62,5 @@ void mac_to_unix(unsigned char **outptr, unsigned char *outend, } *outptr = op; *inptr = ip; + return 0; } diff --git a/sync.c b/sync.c index 2ee457b..00493c9 100644 --- a/sync.c +++ b/sync.c @@ -22,11 +22,11 @@ enum { kMaxFileSize = 64 * 1024, }; -typedef void (*convert_func)(unsigned char **outptr, unsigned char *outend, - const unsigned char **inptr, - const unsigned char *inend); +typedef int (*convert_func)(unsigned char **outptr, unsigned char *outend, + const unsigned char **inptr, + const unsigned char *inend); -static void print_err(const char *msg, ...) { +void print_err(const char *msg, ...) { va_list ap; fputs("## Error: ", stderr); va_start(ap, msg); @@ -43,26 +43,29 @@ struct error_message { OSErr err; const char *msg; }; +#define E(e, m) \ + { e, m "\0" #e } const struct error_message kErrorMessages[] = { - {dirFulErr, "directory full"}, // -33 - {dskFulErr, "disk full"}, // -34 - {ioErr, "I/O error"}, // -36 - {bdNamErr, "bad name"}, // -37 - {fnfErr, "file not found"}, // -43 - {wPrErr, "disk is write-protected"}, // -44 - {fLckdErr, "file is locked"}, // -45 - {vLckdErr, "volume is locked"}, // -46 - {dupFNErr, "destination already exists"}, // -48 - {opWrErr, "file already open for writing"}, // -49 - {paramErr, "parameter error"}, // -50 - {permErr, "cannot write to locked file"}, // -54 - {dirNFErr, "directory not found"}, // -120 - {wrgVolTypErr, "not an HFS volume"}, // -123 - {diffVolErr, "files on different volumes"}, // -1303 - {afpAccessDenied, "user does not have access privileges (AFP)"}, // -5000 - {afpObjectTypeErr, - "file/directory specified where directory/file expected"}, // -5025 - {afpSameObjectErr, "objects are the same"}, // -5038 + E(dirFulErr, "directory full"), // -33 + E(dskFulErr, "disk full"), // -34 + E(ioErr, "I/O error"), // -36 + E(bdNamErr, "bad name"), // -37 + E(fnfErr, "file not found"), // -43 + E(wPrErr, "disk is write-protected"), // -44 + E(fLckdErr, "file is locked"), // -45 + E(vLckdErr, "volume is locked"), // -46 + E(fBsyErr, "file is busy"), // -47 + E(dupFNErr, "destination already exists"), // -48 + E(opWrErr, "file already open for writing"), // -49 + E(paramErr, "parameter error"), // -50 + E(permErr, "cannot write to locked file"), // -54 + E(dirNFErr, "directory not found"), // -120 + E(wrgVolTypErr, "not an HFS volume"), // -123 + E(diffVolErr, "files on different volumes"), // -1303 + E(afpAccessDenied, "user does not have access privileges (AFP)"), // -5000 + E(afpObjectTypeErr, + "file/directory specified where directory/file expected"), // -5025 + E(afpSameObjectErr, "objects are the same"), // -5038 }; static const char *mac_strerror(OSErr err) { @@ -75,7 +78,7 @@ static const char *mac_strerror(OSErr err) { return NULL; } -static void print_errcode(OSErr err, const char *msg, ...) { +void print_errcode(int err, const char *msg, ...) { va_list ap; const char *emsg; @@ -91,6 +94,22 @@ static void print_errcode(OSErr err, const char *msg, ...) { } } +static void log_call(int err, const char *function) { + const char *emsg; + + if (err == 0) { + fprintf(stderr, "## %s: noErr\n", function); + return; + } + emsg = mac_strerror(err); + if (emsg != NULL) { + emsg += strlen(emsg) + 1; + fprintf(stderr, "## %s: %s (%d)\n", function, emsg, err); + } else { + fprintf(stderr, "## %s: %d\n", function, err); + } +} + // Convert a C to Pascal string. static int c2pstr(Str255 ostr, const char *istr) { size_t n = strlen(istr); @@ -452,10 +471,13 @@ static int write_file(FSSpec *dest, short tempVol, long tempDir, Ptr data, // First, try to exchange files if destination exists. if (destExists) { err = FSpExchangeFiles(&temp, dest); + if (gLogLevel >= kLogVerbose) { + log_call(err, "FSpExchangeFiles"); + } if (err == 0) { err = FSpDelete(&temp); if (err != 0) { - print_errcode(err, "could not rename temporary file"); + print_errcode(err, "could not remove temporary file"); return 1; } return 0; @@ -484,6 +506,9 @@ static int write_file(FSSpec *dest, short tempVol, long tempDir, Ptr data, pb.copyParam.ioNewDirID = dest->parID; pb.copyParam.ioDirID = temp.parID; err = PBHMoveRenameSync(&pb); + if (gLogLevel >= kLogVerbose) { + log_call(err, "PBHMoveRename"); + } if (err == 0) { return 0; } @@ -492,9 +517,6 @@ static int write_file(FSSpec *dest, short tempVol, long tempDir, Ptr data, print_errcode(err, "could not rename temporary file"); goto error; } - if (gLogLevel >= kLogVerbose) { - fputs("## PBHMoveRename not supported\n", stderr); - } // Finally, try move and then rename. if (dest->parID != temp.parID) { @@ -507,6 +529,9 @@ static int write_file(FSSpec *dest, short tempVol, long tempDir, Ptr data, cm.ioNewDirID = dest->parID; cm.ioDirID = temp.parID; err = PBCatMoveSync(&cm); + if (gLogLevel >= kLogVerbose) { + log_call(err, "PBCatMove"); + } if (err != 0) { print_errcode(err, "could not move temporary file"); goto error; @@ -518,6 +543,9 @@ static int write_file(FSSpec *dest, short tempVol, long tempDir, Ptr data, fputs("## FSpRename\n", stderr); } err = FSpRename(&temp, dest->name); + if (gLogLevel >= kLogVerbose) { + log_call(err, "FSpRename"); + } if (err != 0) { print_errcode(err, "could not rename temporary file"); goto error; @@ -714,6 +742,12 @@ static int command_main(char *destpath, int mode) { } // Synchronize the files. + if (mode == kModePull) { + r = mac_from_unix_init(); + if (r != 0) { + return 1; + } + } tempVol = 0; tempDir = 0; for (i = 0; i < n; i++) { @@ -796,6 +830,7 @@ int main(int argc, char **argv) { if (gFiles != NULL) { DisposeHandle(gFiles); } + mac_from_unix_term(); if (gLogLevel >= kLogVerbose) { fputs("## Done\n", stderr); }