unsigned deaccesshead(struct VIOC *vioc,struct HEAD *head,unsigned modmask) { #ifdef DEBUG printf("Deaccessing header %x\n",vioc->cache.keyval); #endif if (modmask) head->fh2$w_checksum = checksum((u_word *) head); return deaccesschunk(vioc,modmask,1); }
unsigned accesshead(struct VCB *vcb,struct fiddef *fid, struct VIOC **vioc,struct HEAD **headbuff, unsigned *modmask,unsigned wrtflg) { register unsigned sts; register struct VCBDEV *vcbdev; register unsigned idxblk = fid->fid$w_num + (fid->fid$b_nmx << 16) - 1; if (fid->fid$b_rvn > vcb->devices) return SS$_NOSUCHFILE; if (fid->fid$b_rvn < 2) { vcbdev = vcb->vcbdev; } else { vcbdev = &vcb->vcbdev[fid->fid$b_rvn - 1]; } if (vcbdev->dev == NULL) return SS$_NOSUCHFILE; if (wrtflg && ((vcb->status & VCB_WRITE) == 0)) return SS$_WRITLCK; #ifdef DEBUG printf("Accessing header (%d,%d,%d)\n",(fid->fid$b_nmx << 16) + fid->fid$w_num,fid->fid$w_seq,fid->fid$b_rvn); #endif idxblk += vcbdev->home.hm2$w_ibmapvbn + vcbdev->home.hm2$w_ibmapsize; if (idxblk >= swapw(vcbdev->idxfcb->head->fh2$w_recattr.fat$l_efblk)) return SS$_NOSUCHFILE; sts = accesschunk(vcbdev->idxfcb,idxblk,vioc,(char **) headbuff, NULL,wrtflg ? 1 : 0,modmask); if (sts & 1) { register struct HEAD *head = *headbuff; if (checksum((u_word *) head) != head->fh2$w_checksum) { #ifdef DEBUG printf("Accesshead checksum %d != %d\n",checksum((u_word *) head),head->fh2$w_checksum); #endif sts = SS$_NOSUCHFILE; } else { if (head->fh2$w_fid.fid$w_num != fid->fid$w_num || head->fh2$w_fid.fid$b_nmx != fid->fid$b_nmx || head->fh2$w_fid.fid$w_seq != fid->fid$w_seq || (head->fh2$w_fid.fid$b_rvn != fid->fid$b_rvn && head->fh2$w_fid.fid$b_rvn != 0)) { #ifdef DEBUG printf("Accesshead fileid doesn't match %d %d %d\n", fid->fid$w_num,fid->fid$w_seq,fid->fid$b_rvn); #endif sts = SS$_NOSUCHFILE; } else { if (head->fh2$b_idoffset < 38 || head->fh2$b_idoffset > head->fh2$b_mpoffset || head->fh2$b_mpoffset > head->fh2$b_acoffset || head->fh2$b_acoffset > head->fh2$b_rsoffset || head->fh2$b_map_inuse > (head->fh2$b_acoffset - head->fh2$b_mpoffset)) { #ifdef DEBUG printf("Accesshead areas incorrect\n"); #endif sts = SS$_NOSUCHFILE; } } } if ((sts & 1) == 0) deaccesschunk(*vioc,0,0); } return sts; }
unsigned update_freecount(struct _vcb *vcbdev,unsigned *retcount) { unsigned sts; unsigned free_clusters = 0; unsigned map_block, map_end; struct _scbdef * scb; sts = exttwo_accesschunk(getmapfcb(vcbdev),1,(char **) &scb,0,1,0); map_end = ((scb->scb$l_volsize/scb->scb$w_cluster) + 4095) / 4096 + 2; for (map_block = 2; map_block < map_end; ) { unsigned blkcount; WORK_UNIT *bitmap,*work_ptr; unsigned work_count; sts = exttwo_accesschunk(getmapfcb(vcbdev),map_block,(char **) &bitmap,&blkcount,0,0); if (!(sts & 1)) return sts; if (blkcount > map_end - map_block) blkcount = map_end - map_block + 1; work_ptr = bitmap; work_count = blkcount * 512 / sizeof(WORK_UNIT); do { WORK_UNIT work_val = *work_ptr++; if (work_val == WORK_MASK) { free_clusters += WORK_BITS; } else { while (work_val != 0) { if (work_val & 1) free_clusters++; work_val = work_val >> 1; } } } while (--work_count > 0); sts = deaccesschunk(0,0,1); if (!(sts & 1)) return sts; map_block += blkcount; } *retcount = free_clusters; return sts; }
unsigned sys_get(struct RAB *rab) { char delim,*buffer,*output; unsigned cpylen,reclen,block,blocks,offset,eofblk; unsigned endflg,rfm,sts; struct VIOC *vioc; struct FCB *fcb = ifi_table[rab->rab$l_fab->fab$w_ifi]->wcf_fcb; rfm = rab->rab$l_fab->fab$b_rfm; if (rfm == FAB$C_STM || rfm == FAB$C_STMCR || rfm == FAB$C_STMLF) { delim = 1; if (rfm == FAB$C_STMLF) { delim = '\n'; } else { if (rfm == FAB$C_STMCR) delim = '\r'; } reclen = rab->rab$w_usz; } else { delim = 0; if (rfm == FAB$C_FIX) { reclen = rab->rab$l_fab->fab$w_mrs; } } offset = rab->rab$w_rfa[2] + rab->rab$w_rsz; block = (rab->rab$w_rfa[1] << 16) + rab->rab$w_rfa[0]; if (block == 0 && offset == 0) { block = 1; } else { if (rab->rab$b_rac != RAB$C_RFA) { if (delim) { offset++; } else { if (rfm == FAB$C_VAR) { offset += 2; } else { if (rfm == FAB$C_VFC) offset += 2 + rab->rab$l_fab->fab$b_fsz; } if (offset & 1) offset++; if (rab->rab$l_fab->fab$b_rat & FAB$M_BLK) offset = (offset + 511) / 512 * 512; } block += offset / 512; } } rab->rab$w_rfa[0] = block & 0xffff; rab->rab$w_rfa[1] = block >> 16; rab->rab$w_rfa[2] = offset = offset % 512; eofblk = swapw(fcb->head->fh2$w_recattr.fat$l_efblk); if (block > eofblk || (block == eofblk && offset >= fcb->head->fh2$w_recattr.fat$w_ffbyte)) return RMS$_EOF; sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0,NULL); if ((sts & 1) == 0) return sts; if (rfm == FAB$C_VAR || rfm == FAB$C_VFC) { unsigned short *lenptr = (unsigned short *) (buffer + offset); reclen = *lenptr; offset += 2; } #ifdef DEBUG printf("Block %d Offset %d Reclen %d Eofblk %d\n",block,offset,reclen,eofblk); #endif if (reclen > rab->rab$w_usz) { sts = deaccesschunk(vioc,0,0); return RMS$_RTB; } endflg = 0; if (block + reclen / 512 >= eofblk) { unsigned remaining = (eofblk - block) * 512 - offset + fcb->head->fh2$w_recattr.fat$w_ffbyte; if (remaining < reclen) { reclen = remaining; endflg = 1; } } cpylen = 0; output = rab->rab$l_ubf; while (cpylen < reclen) { unsigned seglen = blocks * 512 - offset; if (seglen > reclen - cpylen) seglen = reclen - cpylen; if (delim) { char *inptr = buffer + offset; if (delim != 1) { while (seglen-- > 0) { char ch = *inptr++; if (ch == delim) { reclen = cpylen; break; } if (cpylen++ < reclen) { *output++ = ch; } else { sts = RMS$_RTB; reclen = cpylen; break; } } } else { while (seglen-- > 0) { char ch = *inptr++; if (ch != 0 || cpylen > 0) { if (ch == '\f' || ch == '\v' || ch == '\n' || ch == '\r') { reclen = cpylen; } else { if (cpylen++ < reclen) { *output++ = ch; } else { sts = RMS$_RTB; reclen = cpylen; break; } } } } } if (cpylen == reclen && endflg) break; } else { if (rfm == FAB$C_VFC) { unsigned fsz = rab->rab$l_fab->fab$b_fsz; if (fsz > seglen) fsz = seglen; if (cpylen < fsz) { fsz = fsz - cpylen; if (rab->rab$l_rhb) memcpy(rab->rab$l_rhb + cpylen,buffer + offset,fsz); cpylen += fsz; offset += fsz; seglen -= fsz; } } memcpy(output,buffer + offset,seglen); output += seglen; cpylen += seglen; } if (cpylen < reclen) { sts = deaccesschunk(vioc,0,0); block += blocks; if (block > eofblk) return RMS$_EOF; sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0,NULL); if ((sts & 1) == 0) return sts; offset = 0; } } if (rfm == FAB$C_VFC) { rab->rab$w_rsz = cpylen - rab->rab$l_fab->fab$b_fsz;; } else { rab->rab$w_rsz = cpylen; } deaccesschunk(vioc,0,1); return sts; }
unsigned deallocfile(struct FCB *fcb) { register unsigned sts = 1; /* First mark all file clusters as free in BITMAP.SYS */ register unsigned vbn = 1; while (vbn <= fcb->hiblock) { register unsigned sts; unsigned rvn,mapblk,maplen; register struct VCBDEV *vcbdev; sts = getwindow(fcb,vbn,&rvn,&mapblk,&maplen); if ((sts & 1) == 0) break; if (rvn > fcb->vcb->devices) break; if (rvn < 2) { vcbdev = fcb->vcb->vcbdev; } else { vcbdev = &fcb->vcb->vcbdev[rvn - 1]; } if (vcbdev->dev == NULL) { break; } else { unsigned *bitmap,blkcount,modmask; struct VIOC *vioc; register unsigned clustersz = vcbdev->home.hm2$w_cluster; register unsigned clusterno = mapblk / clustersz; sts = accesschunk(vcbdev->mapfcb,clusterno / 4096 + 2, &vioc,(char **) &bitmap,&blkcount,1,&modmask); if (sts & 1) { register unsigned wordno = (clusterno % 4096) / (sizeof(unsigned) * 8); register unsigned bitno = clusterno % (sizeof(unsigned) * 8); do { register unsigned mask = 1 << bitno; vbn += clustersz; maplen -= clustersz; while (maplen > 0 && ++bitno < (sizeof(unsigned) * 8)) { mask |= (mask << 1); vbn += clustersz; maplen -= clustersz; } bitmap[wordno++] |= mask; bitno = 0; } while (maplen > 0 && wordno < blkcount / (sizeof(unsigned) * 8)); sts = deaccesschunk(vioc,modmask,1); } } } /* Now reset file header bit map in INDEXF.SYS and update each of the file headers... */ { unsigned rvn = fcb->rvn; unsigned modmask = fcb->modmask; struct HEAD *head = fcb->head; struct VIOC *headvioc = fcb->headvioc; do { struct fiddef extfid; register struct VCBDEV *vcbdev; if (rvn > fcb->vcb->devices) break; if (rvn < 2) { vcbdev = fcb->vcb->vcbdev; } else { vcbdev = &fcb->vcb->vcbdev[rvn - 1]; } if (vcbdev->dev == NULL) { break; } else { unsigned *bitmap,viocmask; struct VIOC *vioc; register unsigned fileno = (head->fh2$w_fid.fid$b_nmx << 16) + head->fh2$w_fid.fid$w_num - 1; register unsigned idxblk = fileno / 4096 + vcbdev->home.hm2$w_cluster * 4 + 1; sts = accesschunk(vcbdev->idxfcb,idxblk,&vioc, (char **) &bitmap,NULL,1,&viocmask); if (sts & 1) { bitmap[(fileno % 4096) / (sizeof(unsigned) * 8)] &= ~(1 << (fileno % (sizeof(unsigned) * 8))); sts = deaccesschunk(vioc,viocmask,1); } else { break; } } head->fh2$w_fid.fid$w_num = 0; head->fh2$w_fid.fid$b_rvn = 0; head->fh2$w_fid.fid$b_nmx = 0; head->fh2$w_checksum = 0; memcpy(&extfid,&fcb->head->fh2$w_ext_fid,sizeof(struct fiddef)); sts = deaccesshead(headvioc,head,modmask); if ((sts & 1) == 0) break; if (extfid.fid$b_rvn == 0) { extfid.fid$b_rvn = rvn; } else { rvn = extfid.fid$b_rvn; } if (extfid.fid$w_num != 0 || extfid.fid$b_nmx != 0) { sts = accesshead(fcb->vcb,&extfid,&headvioc,&head,&modmask,1); if ((sts & 1) == 0) break; } else { break; } } while (1); if (sts & 1) { fcb->headvioc = NULL; cacheuntouch(&fcb->cache,0,1); cachedelete(&fcb->cache); } } return sts; }