diff options
| author | Jeffrey Armstrong <jeffrey.armstrong@approximatrix.com> | 2015-10-09 10:34:49 -0400 |
|---|---|---|
| committer | Jeffrey Armstrong <jeffrey.armstrong@approximatrix.com> | 2015-10-09 10:34:49 -0400 |
| commit | 8b756e368a33a02d7783053b84bc1e5b50419ff0 (patch) | |
| tree | 658a81b96d4522fe3b7e0b33661dc265dbc968e8 /client | |
| download | rback-8b756e368a33a02d7783053b84bc1e5b50419ff0.tar.gz rback-8b756e368a33a02d7783053b84bc1e5b50419ff0.zip | |
Diffstat (limited to 'client')
| -rw-r--r-- | client/f16.c | 73 | ||||
| -rw-r--r-- | client/f16.h | 9 | ||||
| -rw-r--r-- | client/readme.txt | 62 | ||||
| -rw-r--r-- | client/walker.c | 330 |
4 files changed, 474 insertions, 0 deletions
diff --git a/client/f16.c b/client/f16.c new file mode 100644 index 0000000..2fd05f9 --- /dev/null +++ b/client/f16.c @@ -0,0 +1,73 @@ +/* Recursive Walking Backup
+ * Copyright © 2015 Jeffrey Armstrong <jeff@rainbow-100.com>
+ * http://jeff.rainbow-100.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* f16.c - Implementation of a Fletcher 16-bit checksum. The file also
+ * contains a simple test program that can be enabled by defining
+ * TEST_FLETCHER at compile time.
+ */
+
+#include <stdio.h>
+
+/* Computes the Fletcher 16-bit checksum and returns the value in the
+ * b1 and b2 arguments.
+ */
+void fletcher16(unsigned char *data,
+ int n,
+ unsigned char *b1,
+ unsigned char *b2)
+{
+int c1, c2;
+int i;
+int toint;
+
+ c1 = 0; c2 = 0;
+ for(i=0;i<n;i++) {
+ toint = (int)data[i];
+ c1 = (c1 + toint) % 255;
+ c2 = (c2 + c1) % 255;
+ }
+
+ i = (255 - (c1 + c2) % 255);
+ *b1 = (int)i;
+ *b2 = (char)(255 - (c1 + i) % 255);
+}
+
+#ifdef TEST_FLETCHER
+
+#define TEST_STR "The IBM PC/XT is inferior"
+int main(int argc, char *argv[])
+{
+char b1, b2;
+FILE *fp;
+char buf[64];
+int i;
+
+ if(argc > 2) {
+ fletcher16(TEST_STR, strlen(TEST_STR), &b1, &b2);
+ printf("Results for '%s': %d, %d\n", TEST_STR, (int)b1, (int)b2);
+ } else {
+ fp = fopen(argv[1], "rb");
+ fread(buf, sizeof(char), 64, fp);
+ fletcher16(buf, 64, &b1, &b2);
+ printf("Results for 1st 64 bytes: %d, %d\n", (int)b1, (int)b2);
+ fclose(fp);
+ }
+ return (int)b1;
+}
+
+#endif
diff --git a/client/f16.h b/client/f16.h new file mode 100644 index 0000000..44203d0 --- /dev/null +++ b/client/f16.h @@ -0,0 +1,9 @@ +#ifndef _F16_HDR_
+#define _F16_HDR_
+
+void fletcher16(unsigned char *data,
+ int n,
+ unsigned char *b1,
+ unsigned char *b2);
+
+#endif /* _F16_HDR_ */
diff --git a/client/readme.txt b/client/readme.txt new file mode 100644 index 0000000..64690ea --- /dev/null +++ b/client/readme.txt @@ -0,0 +1,62 @@ +Backup Tree Walker +================== + +This software will recursively walk a directory tree and transmit every +file encountered to server software via a serial port. The transmission +protocol is quite basic. When a file is encountered, the name of the +file, in absolute path format, is transmitted to the server followed by +a semicolon. When the server responds with "OK" followed by a semicolon, +this program sends a single byte of how many bytes it will send, 64 by +default. After the block length, it sends the block. Finally, it sends +two bytes representing a Fletcher 16 checksum. This program then waits +until the server responds with "OK," "RETRY," or "ABORT" followed by a +semicolon. On "OK," the server repeats the process with another block. + +Requirements +------------ + +The client software requires FosLib, available at: + + https://bitbucket.org/ArmstrongJ/foslib + +Make sure, when building the library above, to use the same compiler +and memory model. This code works perfectly with the small memory +model. + +Building +-------- + +The code has only recently been tested with Borland Turbo C 2.0. To +compile with Turbo C, use the following: + + tcc -ms -DTURBOC walker.c f16.c fossil.lib + +The command above compiles using a small memory model. The "-DTURBOC" +flag is necessary so that the proper directory search routines are used. + +If compiling with Microsoft C or, possibly, Open Watcom, a similar +command can be used without the "-DTURBOC" flag. + +Executing +--------- + +The backup program, WALKER.EXE, accepts two mandatory arguments, the FOSSIL +driver port and the speed in bits per second. A third, optional argument +specifies the directory in which to start the recursive traversal. By +default, the routine will always start in E: since most people are probably +using this software on a Rainbow 100. If you're using a more obscure system +like an IBM PC, you'll want to specify the third argument. + +To transfer everything on drive E: over COM port 1 (FOSSIL port 0) at 9600bps, +use the following command: + + walker 0 9600 + +To transfer everything in the F:\SRC directory at speed 19200, use the +following command: + + walker 0 19200 F:\SRC + +Note that the speeds are limited by what FOSSIL drivers support. The top +speed is 38400. + diff --git a/client/walker.c b/client/walker.c new file mode 100644 index 0000000..e764332 --- /dev/null +++ b/client/walker.c @@ -0,0 +1,330 @@ +/* Recursive Walking Backup
+ * Copyright © 2015 Jeffrey Armstrong <jeff@rainbow-100.com>
+ * http://jeff.rainbow-100.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* walker.c - This program will walk a directory (by default E:), including
+ * recursively, and transmit every file via FOSSIL to a server
+ * program. To compile with Borland Turbo C (2.0 or 2.01), be
+ * sure to define TURBOC.
+ */
+
+#include <stdio.h>
+#include <dos.h>
+
+#include "fossil.h"
+#include "f16.h"
+
+#ifdef TURBOC
+
+#include <dir.h>
+
+#define FFNAME(x) x.ff_name
+#define FFATTRIB(x) x.ff_attrib
+
+#define SEARCH_FLAGS FA_DIREC
+
+#else
+
+/* MSC defines things a bit differently */
+
+#define findfirst(x, y, z) _dos_findfirst(x, z, y)
+#define findnext(x) _dos_findnext(x)
+
+#define SEARCH_FLAGS _A_SUBDIR | _A_NORMAL
+#define FA_DIREC _A_SUBDIR
+
+#define ffblk find_t
+
+#define FFNAME(x) x.name
+#define FFATTRIB(x) x.attrib
+
+#endif
+
+static char response[16];
+
+/* The transmission block size. This many bytes are transfered
+ * prior to sending the checksum. Do not increase above 255!
+ */
+#define BLOCK_SIZE 64
+
+/* Define this constant to prohibit FOSSIL initialization */
+/* #define NO_FOS_INIT 1 */
+
+/* Sends a null-terminated string */
+void fos_send(const char *text)
+{
+int i, length, r;
+
+ length = strlen(text);
+ for(i=0;i<length;i++) {
+ r = F_Send_Char(TRANSMIT, text[i]);
+ }
+ F_Flush_Out();
+}
+
+/* Reads a semicolon-terminated response from the serial port
+ * and stores the value in the global array "response."
+ */
+void read_response()
+{
+char c;
+int i;
+
+ while(!F_NBPeek());
+
+ memset(response, 0, 16);
+
+ c = 13;
+ i = 0;
+ while(c != ';') {
+ while(!F_NBPeek());
+ c = Get_Raw();
+ response[i] = c;
+ i++;
+ }
+ /* printf("RESPONSE(%s) .. ", response); */
+}
+
+/* Tranmits the passed buffer, measuring "rlen" bytes long, to
+ * the server. The protocol first sends the number of bytes in
+ * the buffer, then the buffer itself, and, finally, a two-byte
+ * Fletcher 16 checksum for the buffer.
+ */
+void transmit(unsigned char *buf, int rlen)
+{
+int i;
+unsigned char b1, b2;
+
+ F_Send_Char(TRANSMIT, (unsigned char)rlen);
+ for(i=0;i<rlen;i++) {
+ F_Send_Char(TRANSMIT, buf[i]);
+ if(i % 8 == 0)
+ F_Flush_Out();
+ }
+ fletcher16(buf, rlen, &b1, &b2);
+ F_Send_Char(TRANSMIT, b1);
+ F_Send_Char(TRANSMIT, b2);
+
+ F_Flush_Out();
+}
+
+/* Transmits the next block in a file pointer. The actual sending
+ * is handled by the "transmit()" function. This routine handles
+ * loading the block from the file and subsequently dealing with the
+ * server response.
+ */
+int send_block(FILE *fp)
+{
+int rlen, i;
+unsigned char buf[BLOCK_SIZE];
+unsigned char b1, b2;
+
+ if(fp == NULL) return -1;
+
+ rlen = fread(buf, sizeof(char), BLOCK_SIZE, fp);
+ if(rlen > 0) {
+ i = 0;
+ do {
+ if(i > 8) {
+ rlen = -1;
+ break;
+ }
+
+ i++;
+ transmit(buf, rlen);
+ read_response();
+ } while(strcmp("OK;", response) != 0);
+ }
+ return rlen;
+}
+
+/* Sends the filename to the server and reads the server response */
+int report_file(const char *fullname)
+{
+ fos_send(fullname);
+ fos_send(";");
+
+ read_response();
+ if(strcmp("OK;", response) == 0)
+ return 1;
+ else
+ return 0;
+
+}
+
+/* Wrapper for sending a file, along with all the bookkeeping, to
+ * the server software. This function will open the file and request
+ * sending all blocks until the entire file is transmitted. It also
+ * produces minimum reports of progress.
+ */
+int send_file(const char *fullname)
+{
+FILE *fp;
+int result;
+char cmd[512];
+
+ printf("File: %s .. ", fullname);
+
+ if(report_file(fullname) == 1)
+ printf("SENDING...");
+ else {
+ printf("ABORT\n");
+ return 0;
+ }
+ fp = fopen(fullname, "rb");
+
+ result = 0;
+ do {
+ /* printf("."); */
+ result = send_block(fp);
+ } while(result > 0);
+
+ /* Send a 0 length flag */
+ F_Send_Char(TRANSMIT, '\0');
+ F_Flush_Out();
+
+ fclose(fp);
+ printf("DONE\n");
+
+ return 1 /* result */;
+}
+
+/* Walks the directory tree starting at the directory specified, and
+ * sends every file. When a directory is encountered, this function
+ * is called recursively.
+ */
+int list_dir(const char *directory)
+{
+int fcount;
+struct ffblk walker;
+char *fname;
+char *fullname;
+char *path;
+
+ fcount = 0;
+
+ fullname = (char *)malloc((strlen(directory)+16)*sizeof(char));
+
+ printf("Entering: %s\n", directory);
+
+ path = (char *)malloc((strlen(directory)+8)*sizeof(char));
+ sprintf(path, "%s\\*.*", directory);
+
+ /* Loop files */
+ if(findfirst(path, &walker, SEARCH_FLAGS) == 0) {
+ do {
+ /* Populate fname */
+ fname = FFNAME(walker);
+ if(fname[0] != '.') {
+ sprintf(fullname, "%s\\%s", directory, fname);
+
+ if(FFATTRIB(walker) & FA_DIREC) {
+
+ fcount += list_dir(fullname);
+
+ } else if(send_file(fullname) != 1) {
+
+ break;
+
+ } else {
+
+ fcount++;
+
+ }
+ }
+ } while(findnext(&walker) == 0);
+ }
+
+ free(fullname);
+ free(path);
+
+ return fcount;
+}
+
+/* Initializes the COM port and FOSSIL driver */
+int start_comm(long fspeed)
+{
+#ifndef NO_FOS_INIT
+
+ printf("Initializing FOSSIL ");
+ if(!F_Init()) {
+ printf("FAIL\n");
+ return 0;
+ } else
+ printf("OK\n");
+
+ printf("Configuring FOSSIL ");
+ if (!F_Set_Baud(fspeed)) {
+ printf("FAIL (speed)\n");
+ return 0;
+ }
+
+ Fl_Ctrl(TXONXOFF|RXONXOFF); /* CTSRTS); */
+ printf("OK\n");
+
+ printf("Raising DTR ");
+ F_Dtr(TRUE);
+ printf("OK\n");
+#endif
+
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+int fcount;
+char *directory;
+long fspeed;
+char c;
+
+ if(argc < 3) {
+ printf("Usage: %s port speed [directory (optional)]\n", argv[0]);
+ return 0;
+ }
+
+ port = atoi(argv[1]);
+ fspeed = atol(argv[2]);
+ printf("Configuring Port %d for %d BPS...\n", port, fspeed);
+
+ dcd_ignore = TRUE;
+
+ if(argc == 3) {
+ directory = "E:";
+ } else {
+ directory = argv[3];
+ }
+
+ if(start_comm(fspeed) != 1) {
+ return 0;
+ }
+
+ printf("Sending test string...\n");
+ fos_send("ONLINE");
+ printf("Press Q to quit or anything else to continue...\n");
+ scanf("%c", &c);
+ if(c == 'q' || c == 'Q') return 0;
+
+ printf("Starting in %s\n\n", directory);
+
+ fcount = list_dir(directory);
+
+ printf("TOTAL: %d\n\n", fcount);
+
+ F_De_Init();
+
+ return fcount;
+}
|
