#include "makuosan.h" static mfile *msend_mfdel(mfile *m) { mfile *r; if(!m) return(NULL); r = m->next; if(m->fd != -1) close(m->fd); if(m->mark) free(m->mark); mfdel(m); return(r); } static int msend_encrypt(mdata *data) { int szdata; MD5_CTX ctx; szdata = data->head.szdata; if(moption.cryptena && data->head.szdata){ MD5_Init(&ctx); MD5_Update(&ctx, data->data, data->head.szdata); MD5_Final(data->head.hash, &ctx); for(szdata=0;szdata<data->head.szdata;szdata+=8){ BF_encrypt((BF_LONG *)(data->data + szdata), &EncKey); } data->head.flags |= MAKUO_FLAG_CRYPT; } return(szdata); } /* * ãã±ãããéåºãã */ static int msend_packet(int s, mdata *data, struct sockaddr_in *addr) { int r; int szdata; mdata senddata; memcpy(&senddata, data, sizeof(senddata)); szdata = msend_encrypt(&senddata); /* ãããããããã¯ã¼ã¯ãã¤ããªã¼ãã¸å¤æ */ senddata.head.szdata = htons(senddata.head.szdata); senddata.head.flags = htons(senddata.head.flags); senddata.head.reqid = htonl(senddata.head.reqid); senddata.head.seqno = htonl(senddata.head.seqno); while(1){ r = sendto(s, &senddata, sizeof(mhead) + szdata, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in)); if(r == sizeof(mhead) + szdata){ break; }else{ if(r != -1){ lprintf(0,"msend_packet: size error sock=%d op=%d rid=%d state=%d size=%d send=%d seqno=%d\n", s, data->head.opcode, data->head.reqid, data->head.nstate, sizeof(mhead) + szdata, r, data->head.seqno); return(0); }else{ if(errno == EINTR){ continue; }else{ lprintf(0,"msend_packet: send error errno=%d sock=%d op=%d rid=%d state=%d size=%d seqno=%d\n", errno, s, data->head.opcode, data->head.reqid, data->head.nstate, sizeof(mhead) + szdata, data->head.seqno); return(-1); } } } } return(1); } static void msend_shot(int s, mfile *m) { msend_packet(s, &(m->mdata), &(m->addr)); msend_mfdel(m); } static void msend_ack(int s, mfile *m) { if(m->markcount){ m->mdata.head.szdata = m->marksize * sizeof(uint32_t); memcpy(m->mdata.data, m->mark, m->marksize * sizeof(uint32_t)); } msend_packet(s, &(m->mdata), &(m->addr)); msend_mfdel(m); m = NULL; } static void msend_file_break(int s, mfile *m) { lprintf(9, "msend_file: BREAK %s\n", m->fn); msend_packet(s, &(m->mdata), &(m->addr)); msend_mfdel(m); } static void msend_mark(int s, mfile *m) { int i; int r; if(!m->markcount){ /* close */ m->initstate = 1; m->mdata.head.seqno = 0; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; lprintf(4, "msend_file_mark: file send complate! %s\n",m->fn); }else{ lprintf(4, "msend_file_mark: block send retry %d\n",m->markcount); for(i=0;i<m->markcount;i++){ m->mdata.head.seqno = m->mark[i]; lseek(m->fd, (m->mdata.head.seqno - 1) * MAKUO_BUFFER_SIZE, SEEK_SET); r = read(m->fd, m->mdata.data, MAKUO_BUFFER_SIZE); if(r>0){ m->mdata.head.szdata = r; msend_packet(s, &(m->mdata), &(m->addr)); }else{ if(!r){ lprintf(0, "msend_mark: read eof? seqno=%d\n", m->mdata.head.seqno); }else{ lprintf(0, "msend_mark: read err! seqno=%d errno=%d\n", m->mdata.head.seqno, errno); } } } /* eof */ m->markcount = 0; m->initstate = 1; m->mdata.head.seqno = 0; m->mdata.head.nstate = MAKUO_SENDSTATE_MARK; } } static void msend_data(int s, mfile *m) { int readsize; lseek(m->fd, (m->mdata.head.seqno - 1) * MAKUO_BUFFER_SIZE, SEEK_SET); readsize = read(m->fd, m->mdata.data, MAKUO_BUFFER_SIZE); if(readsize > 0){ m->mdata.head.szdata = readsize; if(msend_packet(s, &(m->mdata), &(m->addr)) == 1){ m->mdata.head.seqno++; } }else{ if(readsize == -1){ /* err */ lprintf(0, "msend_data: read error! seqno=%d errno=%d\n", m->mdata.head.seqno, errno); }else{ /* eof */ lprintf(4, "msend_data: block send count=%d\n", m->mdata.head.seqno); m->mdata.head.seqno = 0; m->mdata.head.nstate = MAKUO_SENDSTATE_MARK; m->initstate = 1; m->lickflag = 1; } } } static void msend_file_stat_init(int s, mfile *m) { if(!m->comm){ lprintf(9, "msend_file: STATINIT %s (CANCEL)\n", m->fn); msend_mfdel(m); m = NULL; }else{ lprintf(9, "msend_file: STATINIT %s\n", m->fn); m->sendwait = 1; m->initstate = 0; ack_clear(m, -1); msend_packet(s, &(m->mdata), &(m->addr)); } } static void msend_file_stat(int s, mfile *m) { mhost *h; if(m->initstate){ msend_file_stat_init(s, m); return; } if(m->sendwait){ msend_packet(s, &(m->mdata), &(m->addr)); return; } lprintf(9,"msend_file: STAT %s\n", m->fn); if(m->dryrun){ if(ack_check(m, MAKUO_RECVSTATE_UPDATE) != 1){ cprintf(5, m->comm, "(%s)\r\n", m->fn); }else{ cprintf(0, m->comm, "[%s]\r\n", m->fn); if(!m->sendto){ for(h=members;h;h=h->next){ if(h->state == MAKUO_RECVSTATE_UPDATE) cprintf(1, m->comm, "%s: update\r\n", h->hostname); if(h->state == MAKUO_RECVSTATE_SKIP) cprintf(2, m->comm, "%s: skip\r\n", h->hostname); if(h->state == MAKUO_RECVSTATE_READONLY) cprintf(2, m->comm, "%s: skip(read only)\r\n", h->hostname); } } } m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; }else{ if(ack_check(m, MAKUO_RECVSTATE_UPDATE) != 1){ cprintf(5, m->comm, "(%s)\r\n", m->fn); m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; }else{ lprintf(1, "msend_file_stat: update %s\n", m->fn); cprintf(1, m->comm, "[%s]\r\n", m->fn); if(!m->sendto){ for(h=members;h;h=h->next){ if(h->state == MAKUO_RECVSTATE_UPDATE) cprintf(2, m->comm, "%s: update\r\n", h->hostname); if(h->state == MAKUO_RECVSTATE_SKIP) cprintf(3, m->comm, "%s: skip\r\n", h->hostname); if(h->state == MAKUO_RECVSTATE_READONLY) cprintf(3, m->comm, "%s: skip(read only)\r\n", h->hostname); } } m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_OPEN; } } } static void msend_file_open_init(int s, mfile *m) { lprintf(9,"msend_file: OPENINIT %s\n", m->fn); m->sendwait = 1; m->initstate = 0; ack_clear(m, MAKUO_RECVSTATE_UPDATE); m->mdata.head.nstate = MAKUO_SENDSTATE_OPEN; /*----- symlink -----*/ if(S_ISLNK(m->fs.st_mode)){ msend_packet(s, &(m->mdata), &(m->addr)); }else{ /*----- dir -----*/ if(S_ISDIR(m->fs.st_mode)){ msend_packet(s, &(m->mdata), &(m->addr)); } /*----- file -----*/ if(S_ISREG(m->fs.st_mode)){ m->fd = open(m->fn, O_RDONLY, 0); if(m->fd != -1){ msend_packet(s, &(m->mdata), &(m->addr)); lprintf(4, "msend_file: open fd=%d %s\n", m->fd, m->fn); }else{ m->sendwait = 0; m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; cprintf(0, m->comm, "msend_file: open error errno=%d %s\n", errno, m->fn); lprintf(0, "msend_file: open error errno=%d %s\n", errno, m->fn); } } } } static void msend_file_open(int s, mfile *m) { if(m->initstate){ msend_file_open_init(s, m); return; } if(m->sendwait){ msend_packet(s, &(m->mdata), &(m->addr)); return; } lprintf(9,"msend_file: OPEN %s\n", m->fn); if(ack_check(m, MAKUO_RECVSTATE_OPEN) != 1){ m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; }else{ if(S_ISLNK(m->fs.st_mode)){ m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; }else{ if(S_ISDIR(m->fs.st_mode)){ m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; } if(S_ISREG(m->fs.st_mode)){ m->mdata.head.seqno = 1; } } } } static void msend_file_close_init(int s, mfile *m) { lprintf(9,"msend_file: CLOSEINIT %s\n", m->fn); m->sendwait = 1; m->initstate = 0; ack_clear(m, MAKUO_RECVSTATE_OPEN); ack_clear(m, MAKUO_RECVSTATE_UPDATE); m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; msend_packet(s, &(m->mdata), &(m->addr)); } static void msend_file_close(int s, mfile *m) { if(m->initstate){ msend_file_close_init(s, m); return; } if(m->sendwait){ msend_packet(s, &(m->mdata), &(m->addr)); return; } lprintf(9,"msend_file: CLOSE %s\n",m->fn); msend_mfdel(m); m = NULL; } static void msend_file_mark_init(int s, mfile *m) { m->sendwait = 1; m->initstate = 0; ack_clear(m, MAKUO_RECVSTATE_OPEN); m->mdata.head.nstate = MAKUO_SENDSTATE_MARK; msend_packet(s, &(m->mdata), &(m->addr)); } static void msend_file_mark(int s, mfile *m) { if(m->initstate){ msend_file_mark_init(s, m); return; } if(m->sendwait){ msend_packet(s, &(m->mdata), &(m->addr)); return; } m->mdata.head.seqno = 1; } /*---------------------------------------------------------------------------- * * send * */ static void msend_file(int s, mfile *m) { mstat fs; if(m->mdata.head.seqno){ if(!m->comm){ m->mdata.head.seqno = 0; m->mdata.head.nstate = MAKUO_SENDSTATE_BREAK; }else{ if(m->lickflag){ msend_mark(s, m); /* send rery */ }else{ msend_data(s, m); /* send data */ } } }else{ if(!m->comm){ msend_mfdel(m); return; } m->mdata.p = m->mdata.data; m->mdata.head.szdata = sizeof(fs); m->mdata.head.szdata += strlen(m->fn) + 1; m->mdata.head.szdata += strlen(m->ln) + 1; if(m->mdata.head.szdata > MAKUO_BUFFER_SIZE){ lprintf(0, "msend_file: buffer size over size=%d file=%s\n", m->mdata.head.szdata, m->fn); cprintf(0, m->comm, "error: buffer size over size=%d file=%s\n", m->mdata.head.szdata, m->fn); return; } fs.mode = htonl(m->fs.st_mode); fs.uid = htons(m->fs.st_uid); fs.gid = htons(m->fs.st_gid); fs.sizel = htonl((uint32_t)(m->fs.st_size & 0xFFFFFFFF)); fs.sizeh = htonl((uint32_t)(m->fs.st_size >> 32)); fs.mtime = htonl(m->fs.st_mtime); fs.ctime = htonl(m->fs.st_ctime); fs.fnlen = htons(strlen(m->fn)); fs.lnlen = htons(strlen(m->ln)); memcpy(m->mdata.p, &fs, sizeof(fs)); m->mdata.p += sizeof(fs); strcpy(m->mdata.p, m->fn); m->mdata.p += strlen(m->fn); strcpy(m->mdata.p, m->ln); m->mdata.p += strlen(m->ln); switch(m->mdata.head.nstate){ case MAKUO_SENDSTATE_BREAK: msend_file_break(s, m); break; case MAKUO_SENDSTATE_STAT: msend_file_stat(s, m); break; case MAKUO_SENDSTATE_OPEN: msend_file_open(s, m); break; case MAKUO_SENDSTATE_CLOSE: msend_file_close(s, m); break; case MAKUO_SENDSTATE_MARK: msend_file_mark(s, m); break; } } } /*---------------------------------------------------------------------------- * * md5 * */ static void msend_md5_open_init(int s, mfile *m) { lprintf(9,"msend_md5: OPENINIT %s\n", m->fn); m->sendwait = 1; m->initstate = 0; ack_clear(m, -1); m->mdata.head.nstate = MAKUO_SENDSTATE_OPEN; msend_packet(s, &(m->mdata), &(m->addr)); } static void msend_md5_open(int s, mfile *m) { if(m->initstate){ msend_md5_open_init(s, m); return; } if(m->sendwait){ msend_packet(s, &(m->mdata), &(m->addr)); return; } lprintf(9,"msend_md5: OPEN %s\n", m->fn); m->initstate = 1; m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; } static void msend_md5_close_init(int s, mfile *m) { lprintf(9,"msend_md5: CLOSEINIT %s\n", m->fn); m->sendwait = 1; m->initstate = 0; ack_clear(m, MAKUO_RECVSTATE_MD5OK); ack_clear(m, MAKUO_RECVSTATE_MD5NG); m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE; msend_packet(s, &(m->mdata), &(m->addr)); } static void msend_md5_close(int s, mfile *m) { if(m->initstate){ msend_md5_close_init(s, m); return; } if(m->sendwait){ msend_packet(s, &(m->mdata), &(m->addr)); return; } lprintf(9,"msend_md5: CLOSE %s\n",m->fn); msend_mfdel(m); m = NULL; } static void msend_md5(int s, mfile *m) { switch(m->mdata.head.nstate){ case MAKUO_SENDSTATE_OPEN: msend_md5_open(s, m); break; case MAKUO_SENDSTATE_CLOSE: msend_md5_close(s, m); break; } } static void msend_retry(mfile *m) { if(!m->sendwait){ m->retrycnt = MAKUO_SEND_RETRYCNT; }else{ mhost *t; lprintf(2, "msend_retry: send retry count=%02d rid=%06d state=%d %s\n", m->retrycnt, m->mdata.head.reqid, m->mdata.head.nstate, m->fn); for(t=members;t;t=t->next){ switch(moption.loglevel){ case 3: if(t->state == MAKUO_RECVSTATE_NONE){ lprintf(0, "msend_retry: state=%d %s(%s)\n", t->state, inet_ntoa(t->ad), t->hostname); } break; default: lprintf(4, "msend_retry: state=%d %s(%s)\n", t->state, inet_ntoa(t->ad), t->hostname); break; } } m->retrycnt--; } } /* * mfile ãªãã¸ã§ã¯ããéä¿¡ããé¢æ° * å®éã®éä¿¡å¦çã¯å¥ã®é¢æ°ã§ãã * ãªãã³ã¼ããè¦ã¦ã©ã®é¢æ°ã使ãã決ãã */ void msend(int s, mfile *m) { if(!m){ return; } msend_retry(m); mtimeget(&m->lastsend); if(m->mdata.head.flags & MAKUO_FLAG_ACK){ /* ack */ switch(m->mdata.head.opcode){ case MAKUO_OP_PING: msend_shot(s, m); break; case MAKUO_OP_FILE: case MAKUO_OP_MD5: msend_ack(s, m); break; } }else{ /* req */ switch(m->mdata.head.opcode){ case MAKUO_OP_PING: case MAKUO_OP_EXIT: msend_shot(s, m); break; case MAKUO_OP_FILE: msend_file(s, m); break; case MAKUO_OP_MD5: msend_md5(s, m); break; } } }