/* called when RecvPacket timed out */ void transfer_timeout(int signum) { if (otries++>=NUM_TRIES) { fprintf(stderr,"No reply from terminal ! Assuming dead, hence aborting\n"); transfer_abort(RET_EPROTO); } SEND(obuf,osize); alarm(1); }
static void showPacket(int size) { int i; fprintf(stderr,"unexpected %c packet, size %d, content :\n", ibuf[0], size); for (i=0;i<size;i++) { fprintf(stderr,"%2x ", ibuf[i]); if (!((i+1)%10)) fprintf(stderr,"\n"); } if (otries++<NUM_TRIES) return; fprintf(stderr,"couldn't recover, so aborting...\n"); transfer_abort(RET_EPROTO); }
void handleint(int signum) { fprintf(stderr,"aborting on signal %d\n",signum); transfer_abort(RET_INT); }
/* get file f on VisioBraille */ void fileget(char *f) { int n=strlen(f),lnpath,lnext; char *c,*d; int res; int fd; struct stat st; char *path,*ext; if (n==0) return; /* find path, if any */ for (c=f+n-1; c>=f && *c!='/'; c--); if (c>=f) { path=f; lnpath=c-f; *c++='\0'; f=c; } else { path=NULL; lnpath=-1; } /* remove extension */ for (c=f; *c && *c!='.'; c++); if (*c) { ext=c; lnext=n-(ext-f); } else { ext=NULL; lnext=-1; } n=c-f; if (path) printf("getting %s in %s\n",f,path); else printf("getting %s\n",f); transfer_init(fileget); /* sending filename (can contain * and ?) */ obuf[0]=VB_UNLOAD; memcpy(&obuf[1],f,n); osize=n+1; otries=0; while(1) { SEND(obuf,osize); numpacket='1'; RECV(); if (ibuf[0]==VB_FILES_OVER[0]) break; /* end of file list */ if (res<3) { showPacket(res); continue; } if (ibuf[0]!=VB_FILEHERE) { showPacket(res); continue; } if (ibuf[1]!=numpacket) { showPacket(res); continue; } /* ok, VisioBraille proposed a file, let's try to get it */ if (res-3>VB_MAXFNLEN) { fprintf(stderr,"name too long, giving up that file\n"); obuf[0]=VB_NEXT; obuf[1]=ibuf[1]; osize=2; otries=0; continue; } /* copy its name */ { char fullpath[(lnpath+1)+(res-3)+(ext?lnext+1:strlen(visiobases_ext))+1]; if (path) { strcpy(fullpath,path); strcat(fullpath,"/"); } for(c=ibuf+3,d=fullpath+lnpath+1;c-ibuf<res;*d++=tolower(*c++)) fullpath[lnpath+1+res-3]='\0'; strcat(fullpath,ext?ext:visiobases_ext); if (backup && stat(fullpath,&st)>=0) if (renameBackups(fullpath)==-1) perror("couldn't rename backups, overwriting"); if ((fd=open(fullpath,O_WRONLY|O_CREAT|O_TRUNC,0644))<0) { /* openout failed, give up that file */ perror(fullpath); fprintf(stderr,"open failed, giving up that file\n"); obuf[0]=VB_NEXT; obuf[1]=ibuf[1]; osize=2; otries=0; continue; } /* start transfer : */ obuf[0]=VB_ACK_DATA; obuf[1]=numpacket; osize=2; otries=0; numpacket=(numpacket+1)&'7'; sizetransferred=0; /* ready to transfer ! */ while (1) { SEND(obuf,osize); printf("\r%s: %dKo...",fullpath,sizetransferred>>10); fflush(stdout); RECV(); if (ibuf[0]==VB_DATA_OVER) break; if (res<2) { showPacket(res); continue; } if (ibuf[0]!=VB_HERES_DATA) { showPacket(res); continue; } if (ibuf[1]!=numpacket) { showPacket(res); continue; } if (write(fd,ibuf+2,res-2)<res-2) { fprintf(stderr,"writing data on disk for file %s\n" "So giving up\n",fullpath); transfer_abort(RET_EUNIX); } obuf[0]=VB_ACK_DATA; obuf[1]=numpacket; osize=2; otries=0; sizetransferred+=res-2; numpacket=(numpacket+1)&'7'; } /* transfer finished */ close(fd); printf("ok\n"); obuf[0]=VB_OK; osize=1; otries=0; } } transferring=0; }
int transfer(const char *from, const char *to) { #define CLOSE(fd) { if (close(fd)) PERROR("error closing fd"); } int fdread, fdwrite; ssize_t readbytes; char buf[TRANSFER_SIZE]; int w_flags; pthread_mutex_lock(&m_transfer); if (from && to) { lock_set(t_state.job->path, LOCK_TRANSFER); VERBOSE("beginning transfer: '%s' -> '%s'", from, to); t_state.read_path = strdup(from); t_state.write_path = strdup(to); w_flags = O_WRONLY | O_CREAT | O_TRUNC; } else if (!t_state.active) { pthread_mutex_unlock(&m_transfer); return TRANSFER_FINISH; } else { VERBOSE("resuming transfer: '%s' -> '%s' at %ld", t_state.read_path, t_state.write_path, t_state.offset); w_flags = O_WRONLY | O_APPEND; } if (!t_state.read_path || !t_state.write_path) { ERROR("t_state.read_path or t_state.write_path is NULL"); lock_remove(t_state.job->path, LOCK_TRANSFER); goto failure; } /* open files */ if ((fdread = open(t_state.read_path, O_RDONLY)) == -1 || lseek(fdread, t_state.offset, SEEK_SET) == -1) { PERROR(t_state.read_path); goto failure; } if ((fdwrite = open(t_state.write_path, w_flags, 0666)) == -1 || lseek(fdwrite, t_state.offset, SEEK_SET) == -1) { PERROR(t_state.write_path); goto failure; } while (ONLINE && !worker_blocked()) { readbytes = read(fdread, buf, sizeof buf); if (readbytes && (readbytes < 0 || write(fdwrite, buf, readbytes) < readbytes || fsync(fdwrite))) { if (readbytes < 0) ERROR("failed to read from file"); else ERROR("failed or incomplete write"); goto failure; } /* copy completed, set mode and ownership */ if (readbytes < sizeof buf) { CLOSE(fdread); CLOSE(fdwrite); copy_attrs(t_state.read_path, t_state.write_path); VERBOSE("transfer finished: '%s' -> '%s'", t_state.read_path, t_state.write_path); lock_remove(t_state.job->path, LOCK_TRANSFER); pthread_mutex_unlock(&m_transfer); transfer_reset_state(); return TRANSFER_FINISH; } } t_state.offset = lseek(fdread, 0, SEEK_CUR); CLOSE(fdread); CLOSE(fdwrite); pthread_mutex_unlock(&m_transfer); return TRANSFER_OK; failure: pthread_mutex_unlock(&m_transfer); transfer_abort(); return TRANSFER_FAIL; #undef CLOSE }