/* * Metadata Management */ void unpfs_stat(Ixp9Req *r) { int ret = 0; struct stat stbuf; struct unpfs_fid *fid = r->fid->aux; int size; IxpMsg m; struct IxpStat s; char *buf, *name = strdup(fid->path); unpfs_log(LOG_NOTICE, "%s: fid=%u real_path=%s\n", __func__, r->fid->fid, fid->real_path); if (!name || lstat(fid->real_path, &stbuf) < 0) { ret = errno; goto out; } stat_posix_to_9p(&s, basename(name), &stbuf); /* Pack the stat to the binary */ size = ixp_sizeof_stat(&s); buf = ixp_emallocz(size); m = ixp_message(buf, size, MsgPack); ixp_pstat(&m, &s); zfree(&name); r->fid->qid = s.qid; r->ofcall.rstat.nstat = size; r->ofcall.rstat.stat = (uint8_t *)m.data; out: respond(r, ret); }
void ixp_pstat(IxpMsg *msg, Stat *stat) { ushort size; if(msg->mode == MsgPack) size = ixp_sizeof_stat(stat) - 2; ixp_pu16(msg, &size); ixp_pu16(msg, &stat->type); ixp_pu32(msg, &stat->dev); ixp_pqid(msg, &stat->qid); ixp_pu32(msg, &stat->mode); ixp_pu32(msg, &stat->atime); ixp_pu32(msg, &stat->mtime); ixp_pu64(msg, &stat->length); ixp_pstring(msg, &stat->name); ixp_pstring(msg, &stat->uid); ixp_pstring(msg, &stat->gid); ixp_pstring(msg, &stat->muid); }
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); }