static Spfcall* ufs_read(Spfid *fid, u64 offset, u32 count, Spreq *req) { int n; Fid *f; Spfcall *ret; f = fid->aux; ret = sp_alloc_rread(count); if (f->dir) n = ufs_read_dir(fid, ret->data, offset, count, fid->conn->dotu); else { n = pread(f->fd, ret->data, count, offset); if (n < 0) create_rerror(errno); } if (sp_haserror()) { free(ret); ret = NULL; } else sp_set_rread_count(ret, n); return ret; }
static Spfcall* npfs_read(Spfid *fid, u64 offset, u32 count, Spreq *req) { int n; Fid *f; Spfcall *ret; f = fid->aux; ret = sp_alloc_rread(count); npfs_change_user(fid->user); if (f->dir) n = npfs_read_dir(f, ret->data, offset, count, fid->conn->dotu); else { if(mmapreads) { struct stat s; n = count; if(!f->aux) { fstat(f->fd, &s); f->aux=mmap(0, s.st_size, PROT_READ, MAP_SHARED, f->fd, 0); if(f->aux < 0) { create_rerror(errno); goto error; } } if(offset+count > s.st_size) n = s.st_size-offset; if(n>0) memcpy(ret->data, f->aux+offset, n); else n = 0; } else { n = pread(f->fd, ret->data, count, offset); if (n < 0) create_rerror(errno); } } error: if (sp_haserror()) { free(ret); ret = NULL; } else sp_set_rread_count(ret, n); return ret; }
Spfcall * sp_read(Spreq *req, Spfcall *tc) { int n; Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (tc->count+IOHDRSZ > conn->msize) { sp_werror(Etoolarge, EIO); goto done; } if (fid->type&Qtauth) { if (conn->srv->auth) { rc = sp_alloc_rread(tc->count); if (!rc) goto done; n = conn->srv->auth->read(fid, tc->offset, tc->count, rc->data); if (n >= 0) sp_set_rread_count(rc, n); else { free(rc); rc = NULL; } } else sp_werror(Ebadusefid, EIO); goto done; } if (fid->omode==(u16)~0 || (fid->omode&3)==Owrite) { sp_werror(Ebadusefid, EIO); goto done; } if (fid->type&Qtdir && tc->offset != fid->diroffset) { sp_werror(Ebadoffset, EIO); goto done; } rc = (*conn->srv->read)(fid, tc->offset, tc->count, req); /* if (rc && rc->id==Rread && fid->type&Qtdir) { fid->diroffset = tc->offset + rc->count; } */ done: return rc; }