void flush(BCB *b) { int n,d; DMD *dm; /* if buffer not in use or not dirty, no work to do */ if ((b->b_bufdrv == -1) || (!b->b_dirty)) { b->b_bufdrv = -1; return; } dm = b->b_dm; /* media descr for buffer */ n = b->b_buftyp; d = b->b_bufdrv; b->b_bufdrv = -1; /* invalidate in case of error */ longjmp_rwabs(1, (long)b->b_bufr, 1, b->b_bufrec+dm->m_recoff[n], d); /* flush to both fats */ if (n == BT_FAT) { longjmp_rwabs(1, (long)b->b_bufr, 1, b->b_bufrec+dm->m_recoff[BT_FAT]-dm->m_fsiz, d); } b->b_bufdrv = d; /* re-validate */ b->b_dirty = 0; }
/* * getbcb - called by getrec() to get the BCB for the desired record * * buftype is BT_FAT, BT_ROOT, or BT_DATA */ BCB *getbcb(DMD *dmd,WORD buftype,RECNO recnum) { BCB *b; BCB *p, *mtbuf, **q, **phdr; int err; mtbuf = 0; phdr = &bufl[buftype==BT_FAT ? BI_FAT : BI_DATA]; /* * See if the desired record for the desired drive is in memory. * If it is, we will use it. Otherwise we will use * the last invalid (available) buffer, or * the last (least recently) used buffer. */ for (b = *(q = phdr); b; b = *(q = &b->b_link)) { if ((b->b_bufdrv == dmd->m_drvnum) && (b->b_buftyp == buftype) && (b->b_bufrec == recnum)) break; /* * keep track of the last invalid buffer */ if (b->b_bufdrv == -1) /* if buffer not valid */ mtbuf = b; /* then it's 'empty' */ } if (!b) { /* * not in memory. If there was an 'empty' buffer, use it. */ if (mtbuf) b = mtbuf; /* * find predecessor of mtbuf, or last guy in list, which * is the least recently used. */ doio: for (p = *(q = phdr); p->b_link; p = *(q = &p->b_link)) if (b == p) break; b = p; /* * flush the current contents of the buffer, and read in the * new record. */ flush(b); longjmp_rwabs(0, (long)b->b_bufr, 1, recnum+dmd->m_recoff[buftype], dmd->m_drvnum); /* * make the new buffer current */ b->b_bufrec = recnum; b->b_dirty = 0; b->b_buftyp = buftype; b->b_bufdrv = dmd->m_drvnum; b->b_dm = dmd; } else { /* use a buffer, but first validate media */ err = Mediach(b->b_bufdrv); if (err != 0) { if (err == 1) { goto doio; /* media may be changed */ } else if (err == 2) { /* media definitely changed */ errdrv = b->b_bufdrv; rwerr = E_CHNG; /* media change */ errcode = rwerr; longjmp(errbuf,1); } } } /* * now put the current buffer at the head of the list */ *q = b->b_link; b->b_link = *phdr; *phdr = b; return b; }
char *getrec(RECNO recn, OFD *of, int wrtflg) { DMD *dm = of->o_dmd; register BCB *b; BCB *p,*mtbuf,**q,**phdr; int n,err; #if DBGFSBUF kprintf("getrec 0x%lx, %p, 0x%x\n", (long)recn, dm, wrtflg); #endif /* put bcb management here */ if (of->o_dmd->m_fatofd == of) /* is this the OFD for the 'FAT file'? */ n = BT_FAT; /* yes, must be FAT access */ else if (!of->o_dnode) /* no - do we have a dir node? */ n = BT_ROOT; /* no, must be root */ else n = BT_DATA; /* yes, must be normal dir/file */ #if DBGFSBUF kprintf("n=%i , dm->m_recoff[n] = 0x%lx\n", n, dm->m_recoff[n]); #endif mtbuf = 0; phdr = &bufl[n==BT_FAT ? BI_FAT : BI_DATA]; /* * See, if the desired record for the desired drive is in memory. * If it is, we will use it. Otherwise we will use * the last invalid (available) buffer, or * the last (least recently) used buffer. */ for (b = *(q = phdr); b; b = *(q = &b->b_link)) { if ((b->b_bufdrv == dm->m_drvnum) && (b->b_buftyp == n) && (b->b_bufrec == recn)) break; /* * keep track of the last invalid buffer */ if (b->b_bufdrv == -1) /* if buffer not valid */ mtbuf = b; /* then it's 'empty' */ } if (!b) { /* * not in memory. If there was an 'empty' buffer, use it. */ if (mtbuf) b = mtbuf; /* * find predecessor of mtbuf, or last guy in list, which * is the least recently used. */ doio: for (p = *(q = phdr); p->b_link; p = *(q = &p->b_link)) if (b == p) break; b = p; /* * flush the current contents of the buffer, and read in the * new record. */ flush(b); longjmp_rwabs(0, (long)b->b_bufr, 1, recn+dm->m_recoff[n], dm->m_drvnum); /* * make the new buffer current */ b->b_bufrec = recn; b->b_dirty = 0; b->b_buftyp = n; b->b_bufdrv = dm->m_drvnum; b->b_dm = dm; } else { /* use a buffer, but first validate media */ err = Mediach(b->b_bufdrv); if (err != 0) { if (err == 1) { goto doio; /* media may be changed */ } else if (err == 2) { /* media definitely changed */ errdrv = b->b_bufdrv; rwerr = E_CHNG; /* media change */ errcode = rwerr; longjmp(errbuf,1); } } } /* * now put the current buffer at the head of the list */ *q = b->b_link; b->b_link = *phdr; *phdr = b; /* * if we are writing to the buffer, dirty it. */ if (wrtflg) { b->b_dirty = 1; } return(b->b_bufr); }