diff --git a/ChangeLog b/ChangeLog index 2a52cbcf..7ebec00a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -38,12 +38,11 @@ v0.37.7 09-Sep-2003 mbcico: Fixed MB state error from the previous version. - Added more code to debug the broken transfer problem. - Add attempt to send a resync command, please test. Rewrote another part of the binkp driver, initializing the options. If doesn't do Multiple Batch mode anymore against binkp/1.1 mailers. + File resync during receive finally works. mbtask: Added support for debug logfile. Dropped the debug switch for diff --git a/mbcico/binkp.c b/mbcico/binkp.c index b9cd2fc5..56c6d3bf 100644 --- a/mbcico/binkp.c +++ b/mbcico/binkp.c @@ -94,6 +94,7 @@ static int ansbinkp(void); static int binkp_batch(file_list *); +extern char *tempinbound; extern char *ttystat[]; extern int Loaded; extern pid_t mypid; @@ -133,6 +134,7 @@ struct binkprec { int role; /* 1=orig, 0=answer */ int RxState; /* Receiver state */ int TxState; /* Transmitter state */ + int DidSendGET; /* Did we send a GET command */ long rsize; /* Receiver filesize */ long roffs; /* Receiver offset */ char *rname; /* Receiver filename */ @@ -168,6 +170,7 @@ void binkp_init(void) bp.CRCflag = WeCan; bp.Major = 1; bp.Minor = 0; + bp.DidSendGET = FALSE; } @@ -442,15 +445,26 @@ void binkp_send_control(int id,...) +/* + * This function is called two times if a partial file exists from openfile. + * 1. A partial file is detected, send a GET to the remote, set DidSendGET flag. + * 2. DidSendGET is set, return 0 and let openfile open the file in append mode. + */ int resync(off_t off) { - Syslog('b', "Binkp: resync(%d)", off); - if (bp.CRCflag == Active) { - binkp_send_control(MM_GET, "%s %ld %ld %ld %lx", bp.rname, &bp.rsize, &bp.rtime, &bp.roffs, &bp.rcrc); - } else { - binkp_send_control(MM_GET, "%s %ld %ld %ld", bp.rname, &bp.rsize, &bp.rtime, &bp.roffs); + Syslog('b', "Binkp: resync(%d) DidSendGET=%s", off, bp.DidSendGET ?"TRUE":"FALSE"); + if (!bp.DidSendGET) { + if (bp.CRCflag == Active) { + binkp_send_control(MM_GET, "%s %ld %ld %ld %lx", bp.rname, bp.rsize, bp.rtime, off, bp.rcrc); + } else { + binkp_send_control(MM_GET, "%s %ld %ld %ld", bp.rname, bp.rsize, bp.rtime, off); + } + bp.DidSendGET = TRUE; + Syslog('+', "Binkp: already %lu bytes received, requested restart with offset", (unsigned long)off); + return -1; /* Signal openfile not to open the file */ } - return 0; + bp.DidSendGET = FALSE; + return 0; /* Signal openfile to open the file in append mode */ } @@ -858,11 +872,9 @@ SM_STATE(WaitOk) SM_STATE(Opts) /* - * Room to negotiate more protocol options. - * When we are binkp/1.1 and remote is 1.0 we should - * negotiate MB mode here. + * Try to initiate the MB option if the remote is binkp/1.0 */ - if (bp.MBflag == WeCan) { + if ((bp.MBflag == WeCan) && (bp.Major == 1) && (bp.Minor == 0)) { bp.MBflag = WeWant; Syslog('b', "MBflag WeCan => WeWant"); binkp_send_control(MM_NUL, "OPT MB"); @@ -1190,6 +1202,7 @@ int binkp_batch(file_list *to_send) struct timeval rxtvstart, rxtvend; struct timeval txtvstart, txtvend; struct timezone tz; + struct statfs sfs; rxtvstart.tv_sec = rxtvstart.tv_usec = 0; rxtvend.tv_sec = rxtvend.tv_usec = 0; @@ -1550,7 +1563,13 @@ int binkp_batch(file_list *to_send) transferred = TRUE; } } else { - Syslog('+', "Binkp: unexpected DATA frame %d", rxbuf[0]); + if (!bp.DidSendGET) { + /* + * Do not log after a GET command, there will be data packets + * in the pipeline that must be ignored. + */ + Syslog('+', "Binkp: unexpected DATA frame %d", rxbuf[0]); + } } } } @@ -1576,8 +1595,26 @@ int binkp_batch(file_list *to_send) bp.rname, date(bp.rtime), bp.rsize, bp.roffs); (void)binkp2unix(bp.rname); rxfp = openfile(binkp2unix(bp.rname), bp.rtime, bp.rsize, &rxbytes, resync); + + if (bp.DidSendGET) { + /* + * The file was partly received, via the openfile the resync function + * has send a GET command to start this file with a offset. This means + * we will get a new FILE command to open this file with a offset. + */ + bp.RxState = RxWaitFile; + break; + } + gettimeofday(&rxtvstart, &tz); - rxpos = 0; + rxpos = bp.roffs; + + /* + * FIXME: if we have a rxpos, we are appending a partial received file. + * We now need to know the CRC of the already received part! + * Note, file is open in a+ mode, so we can read the already received + * part and calculate the crc. For now, don't use CRC32 mode. + */ rxcrc = 0xffffffff; rxerror = FALSE; @@ -1590,6 +1627,17 @@ int binkp_batch(file_list *to_send) break; } + if (statfs(tempinbound, &sfs) == 0) { + Syslog('b', "blocksize %lu free blocks %lu", sfs.f_bsize, sfs.f_bfree); + Syslog('b', "need %lu blocks", (unsigned long)(bp.rsize / (sfs.f_bsize + 1))); + if ((bp.rsize / (sfs.f_bsize + 1)) >= sfs.f_bfree) { + Syslog('!', "Only %lu blocks free (need %lu) in %s", sfs.f_bfree, + (unsigned long)(bp.rsize / (sfs.f_bsize + 1)), tempinbound); + closefile(); + rxfp = NULL; /* Force SKIP command */ + } + } + if (bp.rsize == rxbytes) { /* * We already got this file, send GOT so it will diff --git a/mbcico/openfile.c b/mbcico/openfile.c index e156240c..4da536c5 100644 --- a/mbcico/openfile.c +++ b/mbcico/openfile.c @@ -61,12 +61,12 @@ extern char *tempinbound; FILE *openfile(char *fname, time_t remtime, off_t remsize, off_t *resofs, int(*resync)(off_t)) { char *opentype, *p, x, ctt[32], tmpfname[16]; - int rc, ncount; + int rc, rsc, ncount; struct stat st; strcpy(ctt,date(remtime)); - Syslog('s', "openfile(\"%s\",%s,%lu,...)", MBSE_SS(fname), MBSE_SS(ctt),(unsigned long)remsize); + Syslog('s', "openfile(\"%s\",%s,%lu,...)", MBSE_SS(fname), MBSE_SS(ctt), (unsigned long)remsize); if ((fname == NULL) || (fname[0] == '\0')) { sprintf(tmpfname,"%08lx.pkt",(unsigned long)sequencer()); @@ -97,8 +97,7 @@ FILE *openfile(char *fname, time_t remtime, off_t remsize, off_t *resofs, int(*r } infpath = xstrcat(infpath, fname); if (stat(infpath, &st) == 0) { - /* FIXME: temp normal logging now! */ - Syslog('-', "remtine=%ld, st_time=%ld, remsize=%ld, st_size=%ld", remtime, st.st_mtime, remsize, st.st_size); + Syslog('s', "remtine=%ld, st_time=%ld, remsize=%ld, st_size=%ld", remtime, st.st_mtime, remsize, st.st_size); if ((remtime == st.st_mtime) && (remsize == st.st_size)) { Syslog('+', "File %s is already here", fname); @@ -158,13 +157,20 @@ FILE *openfile(char *fname, time_t remtime, off_t remsize, off_t *resofs, int(*r *resofs = 0L; opentype = (char *)"w"; if ((rc == 0) && (remsize != 0)) { - Syslog('+', "Resyncing at offset %lu of \"%s\"", (unsigned long)st.st_size, infpath); - if (resync(st.st_size) == 0) { - opentype = (char *)"a"; - *resofs = st.st_size; - Syslog('s', "resync == 0"); - } else { - Syslog('s', "resync != 0"); + rsc = resync(st.st_size); + Syslog('s', "resync(%d) rsc=%d", (int)st.st_size, rsc); + switch (rsc) { + case 0: /* Success */ + opentype = (char *)"a+"; + *resofs = st.st_size; + Syslog('+', "Resyncing at offset %lu of \"%s\"", (unsigned long)st.st_size, infpath); + break; + case -1: /* Binkp did send a GET, return here and do not open file */ + free(infpath); + infpath = NULL; + return NULL; + default: /* Error from xmrecv, do nothing */ + break; } } Syslog('s', "try fopen(\"%s\",\"%s\")", infpath, opentype);