/* * ckdrv - check the drive, see if it needs to be logged in. * * Arguments: * d - has this drive been accessed, or had a media change * * * returns: * ERR if getbpb() failed * ENSMEM if log() failed * EINTRN if no room in dirtbl * drive nbr if success. */ long ckdrv(int d) { int curdir; LONG mask; BPB *b; KDEBUG(("ckdrv(%i)\n",d)); mask = 1L << d; if (!(mask & drvsel)) { /* drive has not been selected yet */ b = (BPB *) Getbpb(d); if (!b) return (mask&drvrem) ? EPTHNF : EDRIVE; if ((long)b < 0) return (long)b; if (log_media(b,d)) return ENSMEM; drvsel |= mask; } else if (mask & drvrem) /* handle removable media */ { if (Mediach(d)) { errdrv = d; rwerr = E_CHNG; /* signal media change */ errcode = rwerr; longjmp(errbuf,1); } } /* * ensure that current process has a valid default directory * on this drive */ curdir = run->p_curdir[d]; if (curdir >= NCURDIR) /* validate */ curdir = 0; /* if invalid, say none */ if (!curdir /* no current dir for this drive */ || !dirtbl[curdir].dnd) /* or current dir is invalid */ { curdir = incr_curdir_usage(drvtbl[d]->m_dtl); /* add root DND */ if (curdir < 0) return ENSMEM; run->p_curdir[d] = curdir; /* link to process */ } return d; }
/* * 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); }