size_t LiteFrag::receive(uint8_t* buf, size_t bufSize, uint64_t& endpointId) { if (m_rbuf == nullptr) { LITEFRAG_DBG(F("receive err=no-buffer")); return 0; } while (true) { ReassHdr* hdr = reinterpret_cast<ReassHdr*>(m_rbuf + m_offset); size_t room = m_rbufSize - m_offset - sizeof(hdr->len); uint8_t* fragBuf = &hdr->b0; uint16_t fragLen = static_cast<uint16_t>(inner.receive(fragBuf, room, endpointId)); if (fragLen == 0) { // no incoming packet return 0; } if ((hdr->b0 & LiteFragHdr_b0_HB) == 0) { // no header bit continue; } memcpy(&hdr->len, &fragLen, sizeof(hdr->len)); uint16_t totalLen = sizeof(hdr->len) + fragLen; uint16_t id; memcpy(&id, &hdr->id, sizeof(id)); uint8_t seq = hdr->b0 & LiteFragHdr_b0_SEQ_MASK; if (seq == 0) { if (m_offset != 0) { LITEFRAG_DBG(F("discard-incomplete id=") << m_id << F(" frags=") << m_nextSeq); memmove(m_rbuf, hdr, totalLen); hdr = reinterpret_cast<ReassHdr*>(m_rbuf); m_offset = 0; } } else if (id != m_id || seq != m_nextSeq) { LITEFRAG_DBG(F("drop-ooo want=(") << m_id << "," << m_nextSeq << F(") got=(") << id << "," << seq << ")"); continue; } // accept m_offset += totalLen; m_id = id; m_nextSeq = seq + 1; if ((hdr->b0 & LiteFragHdr_b0_MF) != 0) { // last frag size_t size = reassemble(buf, bufSize); m_offset = 0; return size; } } return 0; }
void rolldown(queue *q, int p, int d[4]) { int i, v, t; dprintf("roll down\n"); for (i = 0; i < 4; i++) { t = d[i]; if (t == 0) d[i] = 9; else --d[i]; v = reassemble(d); if (!visited[v]) enqueue(q, v); press_cnt[v] = press_cnt[p] + 1;; d[i] = t; } }
void rollup(queue *q, int p, int d[4]) { int i, v, t; dprintf("roll up:\n"); for (i = 0; i < 4; i++) { t = d[i]; /* save original */ ++d[i]; d[i] %= 10; v = reassemble(d); if (!visited[v]) enqueue(q, v); press_cnt[v] = press_cnt[p] + 1;; d[i] = t; /* restore original */ } }
void do_auto(const char *const *argv) { const char *partfile; struct partinfo *pi, *refi, *npi, **partlist, *otherthispart; struct partqueue *pq; unsigned int i; int j, ap; long nr; FILE *part; void *buffer; char *p, *q; if (!opt_outputfile) badusage(_("--auto requires the use of the --output option")); if (!(partfile= *argv++) || *argv) badusage(_("--auto requires exactly one part file argument")); refi= nfmalloc(sizeof(struct partqueue)); part= fopen(partfile,"r"); if (!part) ohshite(_("unable to read part file `%.250s'"),partfile); if (!read_info(part,partfile,refi)) { if (!opt_npquiet) printf(_("File `%.250s' is not part of a multipart archive.\n"),partfile); m_output(stdout, _("<standard output>")); exit(1); } fclose(part); scandepot(); partlist= nfmalloc(sizeof(struct partinfo*)*refi->maxpartn); for (i = 0; i < refi->maxpartn; i++) partlist[i] = NULL; for (pq= queue; pq; pq= pq->nextinqueue) { pi= &pq->info; if (!partmatches(pi,refi)) continue; npi= nfmalloc(sizeof(struct partinfo)); mustgetpartinfo(pi->filename,npi); addtopartlist(partlist,npi,refi); } /* If we already have a copy of this version we ignore it and prefer the * new one, but we still want to delete the one in the depot, so we * save its partinfo (with the filename) for later. This also prevents * us from accidentally deleting the source file. */ otherthispart= partlist[refi->thispartn-1]; partlist[refi->thispartn-1]= refi; for (j=refi->maxpartn-1; j>=0 && partlist[j]; j--); if (j>=0) { part= fopen(partfile,"r"); if (!part) ohshite(_("unable to reopen part file `%.250s'"),partfile); buffer= nfmalloc(refi->filesize); nr= fread(buffer,1,refi->filesize,part); if (nr != refi->filesize) rerreof(part,partfile); if (getc(part) != EOF) ohshit(_("part file `%.250s' has trailing garbage"),partfile); if (ferror(part)) rerr(partfile); fclose(part); p = nfmalloc(strlen(opt_depotdir) + 50); q = nfmalloc(strlen(opt_depotdir) + 200); sprintf(p, "%st.%lx", opt_depotdir, (long)getpid()); sprintf(q, "%s%s.%lx.%x.%x", opt_depotdir, refi->md5sum, refi->maxpartlen,refi->thispartn,refi->maxpartn); part= fopen(p,"w"); if (!part) ohshite(_("unable to open new depot file `%.250s'"),p); nr= fwrite(buffer,1,refi->filesize,part); if (nr != refi->filesize) werr(p); if (fflush(part)) ohshite(_("unable to flush file '%s'"), p); if (fsync(fileno(part))) ohshite(_("unable to sync file '%s'"), p); if (fclose(part)) werr(p); if (rename(p,q)) ohshite(_("unable to rename new depot file `%.250s' to `%.250s'"),p,q); printf(_("Part %d of package %s filed (still want "),refi->thispartn,refi->package); /* There are still some parts missing. */ for (i=0, ap=0; i<refi->maxpartn; i++) if (!partlist[i]) printf("%s%d", !ap++ ? "" : i == (unsigned int)j ? _(" and ") : ", ", i + 1); printf(").\n"); dir_sync_path(opt_depotdir); } else { /* We have all the parts. */ reassemble(partlist, opt_outputfile); /* OK, delete all the parts (except the new one, which we never copied). */ partlist[refi->thispartn-1]= otherthispart; for (i=0; i<refi->maxpartn; i++) if (partlist[i]) if (unlink(partlist[i]->filename)) ohshite(_("unable to delete used-up depot file `%.250s'"),partlist[i]->filename); } m_output(stderr, _("<standard error>")); }
int do_auto(const char *const *argv) { const char *partfile; struct partinfo *refi, **partlist, *otherthispart; struct partqueue *pq; unsigned int i; int j; FILE *part; if (!opt_outputfile) badusage(_("--auto requires the use of the --output option")); if (!(partfile= *argv++) || *argv) badusage(_("--auto requires exactly one part file argument")); refi= nfmalloc(sizeof(struct partqueue)); part= fopen(partfile,"r"); if (!part) ohshite(_("unable to read part file `%.250s'"),partfile); if (!read_info(part,partfile,refi)) { if (!opt_npquiet) printf(_("File `%.250s' is not part of a multipart archive.\n"),partfile); m_output(stdout, _("<standard output>")); return 1; } fclose(part); scandepot(); partlist= nfmalloc(sizeof(struct partinfo*)*refi->maxpartn); for (i = 0; i < refi->maxpartn; i++) partlist[i] = NULL; for (pq= queue; pq; pq= pq->nextinqueue) { struct partinfo *npi, *pi = &pq->info; if (!partmatches(pi,refi)) continue; npi= nfmalloc(sizeof(struct partinfo)); mustgetpartinfo(pi->filename,npi); addtopartlist(partlist,npi,refi); } /* If we already have a copy of this version we ignore it and prefer the * new one, but we still want to delete the one in the depot, so we * save its partinfo (with the filename) for later. This also prevents * us from accidentally deleting the source file. */ otherthispart= partlist[refi->thispartn-1]; partlist[refi->thispartn-1]= refi; for (j=refi->maxpartn-1; j>=0 && partlist[j]; j--); if (j>=0) { int fd_src, fd_dst; int ap; char *p, *q; m_asprintf(&p, "%st.%lx", opt_depotdir, (long)getpid()); m_asprintf(&q, "%s%s.%jx.%x.%x", opt_depotdir, refi->md5sum, (intmax_t)refi->maxpartlen, refi->thispartn, refi->maxpartn); fd_src = open(partfile, O_RDONLY); if (fd_src < 0) ohshite(_("unable to reopen part file `%.250s'"), partfile); fd_dst = creat(p, 0644); if (fd_dst < 0) ohshite(_("unable to open new depot file `%.250s'"), p); fd_fd_copy(fd_src, fd_dst, refi->filesize, _("extracting split part")); if (fsync(fd_dst)) ohshite(_("unable to sync file '%s'"), p); if (close(fd_dst)) ohshite(_("unable to close file '%s'"), p); close(fd_src); if (rename(p,q)) ohshite(_("unable to rename new depot file `%.250s' to `%.250s'"),p,q); free(q); free(p); printf(_("Part %d of package %s filed (still want "),refi->thispartn,refi->package); /* There are still some parts missing. */ for (i=0, ap=0; i<refi->maxpartn; i++) if (!partlist[i]) printf("%s%d", !ap++ ? "" : i == (unsigned int)j ? _(" and ") : ", ", i + 1); printf(").\n"); dir_sync_path(opt_depotdir); } else { /* We have all the parts. */ reassemble(partlist, opt_outputfile); /* OK, delete all the parts (except the new one, which we never copied). */ partlist[refi->thispartn-1]= otherthispart; for (i=0; i<refi->maxpartn; i++) if (partlist[i]) if (unlink(partlist[i]->filename)) ohshite(_("unable to delete used-up depot file `%.250s'"),partlist[i]->filename); } m_output(stderr, _("<standard error>")); return 0; }