upas/fs: handle errors from fetch for cachebody()/cacheheaders()

for imap, when a fetch fails, error out of read and stat. also don't
add failed to download messages into the lru.
This commit is contained in:
cinap_lenrek 2018-12-12 19:33:08 +01:00
parent 9b194f23b2
commit eb5676d4be
2 changed files with 63 additions and 33 deletions

View file

@ -7,6 +7,9 @@ addlru(Mcache *c, Message *m)
{ {
Message *l, **ll; Message *l, **ll;
if((m->cstate & (Cheader|Cbody)) == 0)
return;
c->nlru++; c->nlru++;
ll = &c->lru; ll = &c->lru;
while((l = *ll) != nil){ while((l = *ll) != nil){
@ -360,7 +363,7 @@ cacheidx(Mailbox *mb, Message *m)
{ {
if(m->cstate & Cidx) if(m->cstate & Cidx)
return 0; return 0;
if(cachebody(mb, m) == -1) if(cachebody(mb, m) < 0)
return -1; return -1;
m->cstate |= Cidxstale|Cidx; m->cstate |= Cidxstale|Cidx;
return 0; return 0;

View file

@ -394,13 +394,15 @@ fileinfo(Mailbox *mb, Message *m, int t, char **pp)
int len, i; int len, i;
static char buf[64 + 512]; static char buf[64 + 512];
cacheidx(mb, m); if(cacheidx(mb, m) < 0)
return -1;
sanembmsg(mb, m); sanembmsg(mb, m);
p = nil; p = nil;
len = -1; len = -1;
switch(t){ switch(t){
case Qbody: case Qbody:
cachebody(mb, m); if(cachebody(mb, m) < 0)
return -1;
p = m->body; p = m->body;
len = m->bend - p; len = m->bend - p;
break; break;
@ -453,7 +455,8 @@ fileinfo(Mailbox *mb, Message *m, int t, char **pp)
p = buf; p = buf;
break; break;
case Qraw: case Qraw:
cachebody(mb, m); if(cachebody(mb, m) < 0)
return -1;
p = m->start; p = m->start;
if(p != nil) if(p != nil)
if(strncmp(p, "From ", 5) == 0) if(strncmp(p, "From ", 5) == 0)
@ -462,27 +465,32 @@ fileinfo(Mailbox *mb, Message *m, int t, char **pp)
len = m->rbend - p; len = m->rbend - p;
break; break;
case Qrawunix: case Qrawunix:
cachebody(mb, m); if(cachebody(mb, m) < 0)
return -1;
p = m->start; p = m->start;
len = m->end - p; len = m->end - p;
break; break;
case Qrawbody: case Qrawbody:
cachebody(mb, m); if(cachebody(mb, m) < 0)
return -1;
p = m->rbody; p = m->rbody;
len = m->rbend - p; len = m->rbend - p;
break; break;
case Qrawheader: case Qrawheader:
cacheheaders(mb, m); if(cacheheaders(mb, m) < 0)
return -1;
p = m->header; p = m->header;
len = m->hend - p; len = m->hend - p;
break; break;
case Qmimeheader: case Qmimeheader:
cacheheaders(mb, m); if(cacheheaders(mb, m) < 0)
return -1;
p = m->mheader; p = m->mheader;
len = m->mhend - p; len = m->mhend - p;
break; break;
case Qreferences: case Qreferences:
cacheheaders(mb, m); if(cacheheaders(mb, m) < 0)
return -1;
e = buf + sizeof buf; e = buf + sizeof buf;
s = buf; s = buf;
for(i = 0; i < nelem(m->references); i++){ for(i = 0; i < nelem(m->references); i++){
@ -529,7 +537,8 @@ fileinfo(Mailbox *mb, Message *m, int t, char **pp)
len = snprint(buf, sizeof buf, "%D", m->fileid); len = snprint(buf, sizeof buf, "%D", m->fileid);
break; break;
case Qunixheader: case Qunixheader:
cacheheaders(mb, m); if(cacheheaders(mb, m) < 0)
return -1;
p = m->unixheader; p = m->unixheader;
break; break;
case Qdigest: case Qdigest:
@ -586,7 +595,8 @@ readinfo(Mailbox *mb, Message *m, char *buf, long off, int count)
m->infolen = s - buf + off0; m->infolen = s - buf + off0;
break; break;
} }
n = fileinfo(mb, m, infofields[i], &p); if((n = fileinfo(mb, m, infofields[i], &p)) < 0)
return -1;
if(off > n){ if(off > n){
off -= n + 1; off -= n + 1;
continue; continue;
@ -606,10 +616,11 @@ readinfo(Mailbox *mb, Message *m, char *buf, long off, int count)
return s - buf; return s - buf;
} }
static void static int
mkstat(Dir *d, Mailbox *mb, Message *m, int t) mkstat(Dir *d, Mailbox *mb, Message *m, int t)
{ {
char *p, *e; char *p, *e;
int n;
d->uid = user; d->uid = user;
d->gid = user; d->gid = user;
@ -659,8 +670,9 @@ mkstat(Dir *d, Mailbox *mb, Message *m, int t)
d->qid.path = PATH(0, Qctl); d->qid.path = PATH(0, Qctl);
break; break;
case Qheader: case Qheader:
if(cacheheaders(mb, m) < 0)
return -1;
d->name = dirtab[t]; d->name = dirtab[t];
cacheheaders(mb, m);
d->length = readheader(m, hbuf, 0, sizeof hbuf); d->length = readheader(m, hbuf, 0, sizeof hbuf);
putcache(mb, m); putcache(mb, m);
break; break;
@ -672,18 +684,22 @@ mkstat(Dir *d, Mailbox *mb, Message *m, int t)
d->qid.path = PATH(mb->id, Qmboxctl); d->qid.path = PATH(mb->id, Qmboxctl);
break; break;
case Qinfo: case Qinfo:
if((n = readinfo(mb, m, hbuf, 0, sizeof hbuf)) < 0)
return -1;
d->name = dirtab[t]; d->name = dirtab[t];
d->length = readinfo(mb, m, hbuf, 0, sizeof hbuf); d->length = n;
d->qid.path = PATH(m->id, t); d->qid.path = PATH(m->id, t);
break; break;
case Qraw: case Qraw:
cacheheaders(mb, m); if(cacheheaders(mb, m) < 0)
p = m->start; return -1;
if(strncmp(m->start, "From ", 5) == 0)
if(e = strchr(p, '\n'))
p = e + 1;
d->name = dirtab[t]; d->name = dirtab[t];
d->length = m->size - (p - m->start); d->length = m->size;
p = m->start;
if(p != nil)
if(strncmp(p, "From ", 5) == 0)
if(e = strchr(p, '\n'))
d->length -= ++e - p;
putcache(mb, m); putcache(mb, m);
break; break;
case Qrawbody: case Qrawbody:
@ -694,7 +710,8 @@ mkstat(Dir *d, Mailbox *mb, Message *m, int t)
d->name = dirtab[t]; d->name = dirtab[t];
d->length = m->size; d->length = m->size;
if(mb->addfrom && Topmsg(mb, m)){ if(mb->addfrom && Topmsg(mb, m)){
cacheheaders(mb, m); if(cacheheaders(mb, m) < 0)
return -1;
d->length += strlen(m->unixheader); d->length += strlen(m->unixheader);
putcache(mb, m); putcache(mb, m);
} }
@ -702,11 +719,14 @@ mkstat(Dir *d, Mailbox *mb, Message *m, int t)
case Qflags: case Qflags:
d->mode = 0666; d->mode = 0666;
default: default:
if((n = fileinfo(mb, m, t, &p)) < 0)
return -1;
d->name = dirtab[t]; d->name = dirtab[t];
d->length = fileinfo(mb, m, t, &p); d->length = n;
d->qid.path = PATH(m->id, t); d->qid.path = PATH(m->id, t);
break; break;
} }
return 0;
} }
char* char*
@ -927,7 +947,7 @@ ropen(Fid *f)
/* make sure we've decoded */ /* make sure we've decoded */
if(file == Qbody){ if(file == Qbody){
if(cachebody(f->mb, f->m) == -1) if(cachebody(f->mb, f->m) < 0)
return Eio; return Eio;
decode(f->m); decode(f->m);
convert(f->m); convert(f->m);
@ -1023,8 +1043,8 @@ readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen)
/* act like deleted files aren't there */ /* act like deleted files aren't there */
if(msg->deleted) if(msg->deleted)
continue; continue;
if(mkstat(&d, f->mb, msg, Qdir) < 0)
mkstat(&d, f->mb, msg, Qdir); continue;
m = convD2M(&d, &buf[n], blen - n); m = convD2M(&d, &buf[n], blen - n);
if(off <= pos){ if(off <= pos){
if(m <= BIT16SZ || m > cnt) if(m <= BIT16SZ || m > cnt)
@ -1053,7 +1073,8 @@ readmsgdir(Fid *f, uchar *buf, long off, int cnt, int blen)
n = 0; n = 0;
pos = 0; pos = 0;
for(i = 0; i < Qmax; i++){ for(i = 0; i < Qmax; i++){
mkstat(&d, f->mb, f->m, i); if(mkstat(&d, f->mb, f->m, i) < 0)
continue;
m = convD2M(&d, &buf[n], blen - n); m = convD2M(&d, &buf[n], blen - n);
if(off <= pos){ if(off <= pos){
if(m <= BIT16SZ || m > cnt) if(m <= BIT16SZ || m > cnt)
@ -1064,7 +1085,8 @@ readmsgdir(Fid *f, uchar *buf, long off, int cnt, int blen)
pos += m; pos += m;
} }
for(msg = f->m->part; msg != nil; msg = msg->next){ for(msg = f->m->part; msg != nil; msg = msg->next){
mkstat(&d, f->mb, msg, Qdir); if(mkstat(&d, f->mb, msg, Qdir) < 0)
continue;
m = convD2M(&d, &buf[n], blen - n); m = convD2M(&d, &buf[n], blen - n);
if(off <= pos){ if(off <= pos){
if(m <= BIT16SZ || m > cnt) if(m <= BIT16SZ || m > cnt)
@ -1114,24 +1136,27 @@ rread(Fid *f)
switch(t){ switch(t){
case Qctl: case Qctl:
rhdr.count = 0;
break; break;
case Qmboxctl: case Qmboxctl:
i = mboxctlread(f->mb, &p); i = mboxctlread(f->mb, &p);
goto output; goto output;
case Qheader: case Qheader:
cacheheaders(f->mb, f->m); if(cacheheaders(f->mb, f->m) < 0)
return Eio;
rhdr.count = readheader(f->m, (char*)mbuf, off, cnt); rhdr.count = readheader(f->m, (char*)mbuf, off, cnt);
putcache(f->mb, f->m); putcache(f->mb, f->m);
break; break;
case Qinfo: case Qinfo:
if(cnt > sizeof mbuf) if(cnt > sizeof mbuf)
cnt = sizeof mbuf; cnt = sizeof mbuf;
rhdr.count = readinfo(f->mb, f->m, (char*)mbuf, off, cnt); if((i = readinfo(f->mb, f->m, (char*)mbuf, off, cnt)) < 0)
return Eio;
rhdr.count = i;
break; break;
case Qrawunix: case Qrawunix:
if(f->mb->addfrom && Topmsg(f->mb, f->m)){ if(f->mb->addfrom && Topmsg(f->mb, f->m)){
cacheheaders(f->mb, f->m); if(cacheheaders(f->mb, f->m) < 0)
return Eio;
p = f->m->unixheader; p = f->m->unixheader;
if(off < strlen(p)){ if(off < strlen(p)){
rhdr.count = strlen(p + off); rhdr.count = strlen(p + off);
@ -1139,11 +1164,12 @@ rread(Fid *f)
break; break;
} }
off -= strlen(p); off -= strlen(p);
putcache(f->mb, f->m);
} }
default: default:
i = fileinfo(f->mb, f->m, t, &p); i = fileinfo(f->mb, f->m, t, &p);
output: output:
if(i < 0)
return Eio;
if(off < i){ if(off < i){
if(off + cnt > i) if(off + cnt > i)
cnt = i - off; cnt = i - off;
@ -1320,7 +1346,8 @@ rstat(Fid *f)
if(FILE(f->qid.path) == Qmbox) if(FILE(f->qid.path) == Qmbox)
syncmbox(f->mb, 1); syncmbox(f->mb, 1);
mkstat(&d, f->mb, f->m, FILE(f->qid.path)); if(mkstat(&d, f->mb, f->m, FILE(f->qid.path)) < 0)
return Eio;
rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ); rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
rhdr.stat = mbuf; rhdr.stat = mbuf;
return 0; return 0;