void ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup) { IxpFileId *file, *tfile; int i; file = ixp_srv_clonefiles(req->fid->aux); for(i=0; i < req->ifcall.twalk.nwname; i++) { if(!strcmp(req->ifcall.twalk.wname[i], "..")) { if(file->next) { tfile = file; file = file->next; ixp_srv_freefile(tfile); } }else{ tfile = lookup(file, req->ifcall.twalk.wname[i]); if(!tfile) break; assert(!tfile->next); if(strcmp(req->ifcall.twalk.wname[i], ".")) { tfile->next = file; file = tfile; } } req->ofcall.rwalk.wqid[i].type = file->tab.qtype; req->ofcall.rwalk.wqid[i].path = QID(file->tab.type, file->id); } /* There should be a way to do this on freefid() */ if(i < req->ifcall.twalk.nwname) { while((tfile = file)) { file=file->next; ixp_srv_freefile(tfile); } ixp_respond(req, Enofile); return; } /* Remove refs for req->fid if no new fid */ if(req->ifcall.hdr.fid == req->ifcall.twalk.newfid) { tfile = req->fid->aux; req->fid->aux = file; while((file = tfile)) { tfile = tfile->next; ixp_srv_freefile(file); } }else req->newfid->aux = file; req->ofcall.rwalk.nwqid = i; ixp_respond(req, nil); }
void ixp_pending_respond(Ixp9Req *req) { IxpFileId *file; IxpPendingLink *p; IxpRequestLink *req_link; IxpQueue *queue; file = req->fid->aux; assert(file->pending); p = file->p; if(p->queue) { queue = p->queue; p->queue = queue->link; req->ofcall.io.data = queue->dat; req->ofcall.io.count = queue->len; if(req->aux) { req_link = req->aux; req_link->next->prev = req_link->prev; req_link->prev->next = req_link->next; free(req_link); } ixp_respond(req, nil); free(queue); }else { req_link = emallocz(sizeof *req_link); req_link->req = req; req_link->next = &p->pending->req; req_link->prev = req_link->next->prev; req_link->next->prev = req_link; req_link->prev->next = req_link; req->aux = req_link; } }
bool ixp_pending_clunk(Ixp9Req *req) { IxpPending *pending; IxpPendingLink *pend_link; IxpRequestLink *req_link; Ixp9Req *r; IxpFileId *file; IxpQueue *queue; bool more; file = req->fid->aux; pend_link = file->p; pending = pend_link->pending; for(req_link=pending->req.next; req_link != &pending->req;) { r = req_link->req; req_link = req_link->next; if(r->fid == pend_link->fid) { pending_flush(r); ixp_respond(r, "interrupted"); } } pend_link->prev->next = pend_link->next; pend_link->next->prev = pend_link->prev; while((queue = pend_link->queue)) { pend_link->queue = queue->link; free(queue->dat); free(queue); } more = (pend_link->pending->fids.next == &pend_link->pending->fids); free(pend_link); ixp_respond(req, nil); return more; }
static void respond(Ixp9Req *r, int err) { const char *msg = NULL; static char buf[ERRNO_MSG_BUF_LENGTH]; if (err) { if (strerror_r(err, buf, sizeof buf) < 0) msg = "Input/output error"; else msg = buf; unpfs_log(LOG_ERR, "respond: type=%u tag=%u fid=%u: %s\n", r->ifcall.hdr.type, r->ifcall.hdr.tag, r->ifcall.hdr.fid, msg); } ixp_respond(r, msg); }
void ixp_srv_readdir(Ixp9Req *req, IxpLookupFn lookup, void (*dostat)(IxpStat*, IxpFileId*)) { IxpMsg msg; IxpFileId *file, *tfile; IxpStat stat; char *buf; ulong size, n; uint64_t offset; file = req->fid->aux; size = req->ifcall.io.count; if(size > req->fid->iounit) size = req->fid->iounit; buf = emallocz(size); msg = ixp_message(buf, size, MsgPack); file = lookup(file, nil); tfile = file; /* Note: The first file is ".", so we skip it. */ offset = 0; for(file=file->next; file; file=file->next) { dostat(&stat, file); n = ixp_sizeof_stat(&stat); if(offset >= req->ifcall.io.offset) { if(size < n) break; ixp_pstat(&msg, &stat); size -= n; } offset += n; } while((file = tfile)) { tfile=tfile->next; ixp_srv_freefile(file); } req->ofcall.io.count = msg.pos - msg.data; req->ofcall.io.data = msg.data; ixp_respond(req, nil); }