ER zmodem_recv_file(ID portid, void *buf, SIZE size, SIZE *filesz) { sio_portid = portid; static char fname[MAX_PATH+1]; int file_bytes; //, ftime, total_files, total_bytes; BOOL success=FALSE; int i; wait_file_sender(); i=zmodem_recv_init(&zm); if (zm.cancelled) return(1); if(i<0) return(-1); switch(i) { case ZFILE: SAFECOPY(fname,zm.current_file_name); file_bytes = zm.current_file_size; // ftime = zm.current_file_time; // total_files = zm.files_remaining; // total_bytes = zm.bytes_remaining; if (filesz != NULL) *filesz = file_bytes; syslog(LOG_DEBUG, "%s(): Incoming filename: %s, size: %d", __FUNCTION__, fname, file_bytes); break; case ZFIN: case ZCOMPL: return(!success); default: return(-1); } cookie_io_functions_t memfile_func = { .read = memfile_read, .write = memfile_write, .seek = memfile_seek, .close = memfile_close }; FILE *fp; /* Set up the cookie before calling fopencookie() */ struct memfile_cookie mycookie; mycookie.buf = buf; mycookie.allocated = size; mycookie.offset = 0; mycookie.endpos = 0; fp = fopencookie(&mycookie,"w+", memfile_func); int errors = zmodem_recv_file_data(&zm,fp,0); if (errors > zm.max_errors) { assert(false); return E_TMOUT; } else if (errors > 0) { syslog(LOG_WARNING, "%s(): Final errors %d", __FUNCTION__, errors); } i = zmodem_recv_init(&zm); if (i != ZFIN && i != ZCOMPL) { syslog(LOG_ERROR, "%s(): Last header has an unexpected type %d", __FUNCTION__, i); return E_TMOUT; } syslog(LOG_DEBUG, "%s(): Endpos %d", __FUNCTION__, mycookie.endpos); return E_OK; }
static int receive_files(char** fname_list, int fnames) { char str[MAX_PATH+1]; char fname[MAX_PATH+1]; int i; int fnum=0; uint errors; uint total_files=0; uint cps; uint wr; BOOL success=FALSE; long fmode; long serial_num=-1; ulong file_bytes=0,file_bytes_left=0; ulong total_bytes=0; FILE* fp; time_t t,startfile,ftime; if(fnames>1) lprintf(LOG_INFO,"Receiving %u files",fnames); outbuf.highwater_mark=0; /* don't delay ACK/NAK transmits */ /* Purge input buffer */ while(is_connected(NULL) && (i=recv_byte(NULL,0))!=NOINP) lprintf(LOG_WARNING,"Throwing out received: %s",chr((uchar)i)); while(is_connected(NULL)) { if(mode&XMODEM) { SAFECOPY(str,fname_list[0]); /* we'll have at least one fname */ file_bytes=file_bytes_left=0x7fffffff; } else { if(mode&YMODEM) { lprintf(LOG_INFO,"Fetching Ymodem header block"); for(errors=0;errors<=xm.max_errors && !xm.cancelled;errors++) { if(errors>(xm.max_errors/2) && mode&CRC && !(mode&GMODE)) mode&=~CRC; xmodem_put_nak(&xm, /* expected_block: */ 0); if(xmodem_get_block(&xm, block, /* expected_block: */ 0) == 0) { send_byte(NULL,ACK,10); break; } } if(errors>=xm.max_errors || xm.cancelled) { lprintf(LOG_ERR,"Error fetching Ymodem header block"); xmodem_cancel(&xm); return(1); } if(!block[0]) { lprintf(LOG_INFO,"Received Ymodem termination block"); return(0); } file_bytes=ftime=total_files=total_bytes=0; i=sscanf(block+strlen(block)+1,"%ld %lo %lo %lo %d %ld" ,&file_bytes /* file size (decimal) */ ,&ftime /* file time (octal unix format) */ ,&fmode /* file mode (not used) */ ,&serial_num /* program serial number */ ,&total_files /* remaining files to be sent */ ,&total_bytes /* remaining bytes to be sent */ ); lprintf(LOG_DEBUG,"Ymodem header (%u fields): %s", i, block+strlen(block)+1); SAFECOPY(fname,block); } else { /* Zmodem */ lprintf(LOG_INFO,"Waiting for Zmodem sender..."); i=zmodem_recv_init(&zm); if(zm.cancelled) return(1); if(i<0) return(-1); switch(i) { case ZFILE: SAFECOPY(fname,zm.current_file_name); file_bytes = zm.current_file_size; ftime = zm.current_file_time; total_files = zm.files_remaining; total_bytes = zm.bytes_remaining; break; case ZFIN: case ZCOMPL: return(!success); default: return(-1); } } if(!file_bytes) file_bytes=0x7fffffff; file_bytes_left=file_bytes; if(!total_files) total_files=fnames-fnum; if(!total_files) total_files=1; if(total_bytes<file_bytes) total_bytes=file_bytes; lprintf(LOG_DEBUG,"Incoming filename: %.64s ",fname); if(mode&RECVDIR) sprintf(str,"%s%s",fname_list[0],getfname(fname)); else { SAFECOPY(str,getfname(fname)); for(i=0;i<fnames;i++) { if(!fname_list[i][0]) /* name blank or already used */ continue; if(!stricmp(getfname(fname_list[i]),str)) { SAFECOPY(str,fname_list[i]); fname_list[i][0]=0; break; } } if(i==fnames) { /* Not found in list */ if(fnames) fprintf(statfp," - Not in receive list!"); if(!fnames || fnum>=fnames || !fname_list[fnum][0]) SAFECOPY(str,getfname(fname)); /* worst case */ else { SAFECOPY(str,fname_list[fnum]); fname_list[fnum][0]=0; } } } fprintf(statfp,"File size: %lu bytes\n", file_bytes); if(total_files>1) fprintf(statfp,"Remaining: %lu bytes in %u files\n", total_bytes, total_files); } lprintf(LOG_DEBUG,"Receiving: %.64s ",str); fnum++; if(!(mode&RECVDIR) && fnames && fnum>fnames) { lprintf(LOG_WARNING,"Attempt to send more files than specified"); xmodem_cancel(&xm); break; } if(fexistcase(str) && !(mode&OVERWRITE)) { lprintf(LOG_WARNING,"%s already exists",str); if(mode&ZMODEM) { zmodem_send_zskip(&zm); continue; } xmodem_cancel(&xm); return(1); } if((fp=fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY))==NULL && (fp=fopen(str,"wb"))==NULL) { lprintf(LOG_ERR,"Error %d creating %s",errno,str); if(mode&ZMODEM) { zmodem_send_zskip(&zm); continue; } xmodem_cancel(&xm); return(1); } if(mode&XMODEM) lprintf(LOG_INFO,"Receiving %s via Xmodem %s" ,str ,mode&CRC ? "CRC-16":"Checksum"); else lprintf(LOG_INFO,"Receiving %s (%lu KB) via %s %s" ,str ,file_bytes/1024 ,mode&YMODEM ? mode&GMODE ? "Ymodem-G" : "Ymodem" :"Zmodem" ,mode&ZMODEM ? "" : (mode&CRC ? "CRC-16" : "Checksum")); startfile=time(NULL); success=FALSE; if(mode&ZMODEM) { errors=zmodem_recv_file_data(&zm,fp,0); /* * wait for the eof header */ for(;errors<=zm.max_errors && !success && !zm.cancelled; errors++) { if(zmodem_recv_header_and_check(&zm)) success=TRUE; } } else { errors=0; block_num=1; xmodem_put_nak(&xm, block_num); while(is_connected(NULL)) { xmodem_progress(NULL,block_num,ftell(fp),file_bytes,startfile); i=xmodem_get_block(&xm, block, block_num); if(i!=0) { if(i==EOT) { /* end of transfer */ success=TRUE; xmodem_put_ack(&xm); break; } if(i==CAN) { /* Cancel */ xm.cancelled=TRUE; break; } if(mode&GMODE) return(-1); if(++errors>=xm.max_errors) { lprintf(LOG_ERR,"Too many errors (%u)",errors); xmodem_cancel(&xm); break; } if(block_num==1 && errors>(xm.max_errors/2) && mode&CRC && !(mode&GMODE)) mode&=~CRC; xmodem_put_nak(&xm, block_num); continue; } if(!(mode&GMODE)) send_byte(NULL,ACK,10); if(file_bytes_left<=0L) { /* No more bytes to send */ lprintf(LOG_WARNING,"Attempt to send more byte specified in header"); break; } wr=xm.block_size; if(wr>file_bytes_left) wr=file_bytes_left; if(fwrite(block,1,wr,fp)!=wr) { lprintf(LOG_ERR,"Error writing %u bytes to file at offset %lu" ,wr,ftell(fp)); xmodem_cancel(&xm); return(1); } file_bytes_left-=wr; block_num++; } } /* Use correct file size */ fflush(fp); if(file_bytes < (ulong)filelength(fileno(fp))) { lprintf(LOG_INFO,"Truncating file to %lu bytes", file_bytes); chsize(fileno(fp),file_bytes); } else file_bytes = filelength(fileno(fp)); fclose(fp); t=time(NULL)-startfile; if(!t) t=1; if(success) lprintf(LOG_INFO,"Successful - Time: %lu:%02lu CPS: %lu" ,t/60,t%60,file_bytes/t); else lprintf(LOG_ERR,"File Transfer %s", aborted ? "Aborted":"Failure"); if(!(mode&XMODEM) && ftime) setfdate(str,ftime); if(logfp) { lprintf(LOG_DEBUG,"Updating DSZLOG: %s", dszlog); fprintf(logfp,"%c %6lu %5u bps %4lu cps %3u errors %5u %4u " "%s %d\n" ,success ? (mode&ZMODEM ? 'Z' : 'R') : 'E' ,file_bytes ,115200 /* baud */ ,file_bytes/t ,errors ,flows ,mode&ZMODEM ? zm.block_size : xm.block_size ,dszlog_filename(str) ,serial_num); fflush(logfp); } if(aborted) { lprintf(LOG_DEBUG,"Locally aborted, sending cancel to remote"); if(mode&ZMODEM) zmodem_abort_receive(&zm); xm.cancelled=FALSE; xmodem_cancel(&xm); break; } if(mode&XMODEM) /* maximum of one file */ break; if((cps=file_bytes/t)==0) cps=1; total_files--; total_bytes-=file_bytes; if(total_files>1 && total_bytes) lprintf(LOG_INFO,"Remaining - Time: %lu:%02lu Files: %u KBytes: %lu" ,(total_bytes/cps)/60 ,(total_bytes/cps)%60 ,total_files ,total_bytes/1024 ); } return(!success); /* 0=success */ }
void zmodem_recv_task(intptr_t unused) { int file_bytes; //, ftime, total_files, total_bytes; int i; wait_file_sender(); i=zmodem_recv_init(&zm); #if 1 if (zm.cancelled) { recv_ercd = E_TMOUT; goto error_exit; } if (i != ZFILE) { recv_ercd = E_OBJ; goto error_exit; } assert(i == ZFILE); SAFECOPY(recv_file_name,zm.current_file_name); file_bytes = zm.current_file_size; if (p_recv_filesz != NULL) *p_recv_filesz = file_bytes; syslog(LOG_DEBUG, "%s(): Incoming filename: %s, size: %d", __FUNCTION__, recv_file_name, file_bytes); bitmap_draw_string("Name: ", global_brick_info.lcd_screen, 0, offset_y, global_brick_info.font_w10h16, ROP_COPY); bitmap_draw_string(zm.current_file_name, global_brick_info.lcd_screen, strlen("Name: ") * 10, offset_y, global_brick_info.font_w10h16, ROP_COPY); offset_y += global_brick_info.font_w10h16->height; #else BOOL success=FALSE; if (zm.cancelled) return(1); if(i<0) return(-1); switch(i) { case ZFILE: SAFECOPY(recv_file_name,zm.current_file_name); file_bytes = zm.current_file_size; // ftime = zm.current_file_time; // total_files = zm.files_remaining; // total_bytes = zm.bytes_remaining; if (p_recv_filesz != NULL) *p_recv_filesz = file_bytes; syslog(LOG_DEBUG, "%s(): Incoming filename: %s, size: %d", __FUNCTION__, recv_file_name, file_bytes); break; case ZFIN: case ZCOMPL: return(!success); default: return(-1); } #endif int errors = zmodem_recv_file_data(&zm, recv_file,0); if (errors > zm.max_errors || is_cancelled(&zm)) { assert(errors <= zm.max_errors); recv_ercd = E_TMOUT; goto error_exit; } else if (errors > 0) { syslog(LOG_WARNING, "%s(): Final errors %d", __FUNCTION__, errors); } i = zmodem_recv_init(&zm); if (i != ZFIN && i != ZCOMPL) { syslog(LOG_ERROR, "%s(): Last header has an unexpected type %d", __FUNCTION__, i); recv_ercd = E_TMOUT; goto error_exit; } // syslog(LOG_DEBUG, "%s(): Endpos %d", __FUNCTION__, mycookie.endpos); recv_ercd = E_OK; error_exit: recv_task_compl = true; return; }