unsigned accessfile(struct VCB * vcb,struct fiddef * fid,struct FCB **fcbadd, unsigned wrtflg) { register struct FCB *fcb; unsigned create = sizeof(struct FCB); register unsigned fileno = (fid->fid$b_nmx << 16) + fid->fid$w_num; #ifdef DEBUG printf("Accessing file (%d,%d,%d)\n",(fid->fid$b_nmx << 16) + fid->fid$w_num,fid->fid$w_seq,fid->fid$b_rvn); #endif if (fileno < 1) return SS$_BADPARAM; if (wrtflg && ((vcb->status & VCB_WRITE) == 0)) return SS$_WRITLCK; if (fid->fid$b_rvn > 1) fileno |= ((fid->fid$b_rvn - 1) << 24); fcb = cachesearch((void *) &vcb->fcb,fileno,0,NULL,NULL,&create); if (fcb == NULL) return SS$_INSFMEM; /* If not found make one... */ if (create == 0) { fcb->cache.status |= 0x100; /* For debugging! */ fcb->rvn = fid->fid$b_rvn; if (fcb->rvn == 0 && vcb->devices > 1) fcb->rvn = 1; fcb->vcb = vcb; fcb->wcb = NULL; fcb->headvioc = NULL; fcb->vioc = NULL; fcb->cache.objmanager = fcbmanager; } if (wrtflg) { if (fcb->headvioc != NULL && (fcb->cache.status & CACHE_WRITE) == 0) { deaccesshead(fcb->headvioc,NULL,0); fcb->headvioc = NULL; } fcb->cache.status |= CACHE_WRITE; } if (fcb->headvioc == NULL) { register unsigned sts; if (vcb->idxboot != NULL) { *fcbadd = fcb; fcb->hiblock = 32767; /* guess at indexf.sys file size */ fcb->highwater = 0; fcb->head = vcb->idxboot; /* Load bootup header */ } sts = accesshead(vcb,fid,&fcb->headvioc,&fcb->head,&fcb->modmask,wrtflg); if (sts & 1) { fcb->hiblock = swapw(fcb->head->fh2$w_recattr.fat$l_hiblk); if (fcb->head->fh2$b_idoffset > 39) { fcb->highwater = fcb->head->fh2$l_highwater; } else { fcb->highwater = 0; } } else { fcb->cache.objmanager = NULL; cacheuntouch(&fcb->cache,0,0); cachefree(&fcb->cache); return sts; } } *fcbadd = fcb; return SS$_NORMAL; }
/* ast parser, the way we pass context around is very very hacky... */ searchNode *search_astparse(searchCtx *ctx, char *loc) { searchASTCache *cache = ctx->arg; searchASTExpr *expr = cachesearch(cache, (exprunion *)&loc); searchNode *node; char **v; int i; if(!expr) { parseError = "WARNING: AST parsing failed"; return NULL; } switch(expr->type) { case AST_NODE_LITERAL: if (!(node=(searchNode *)malloc(sizeof(searchNode)))) { parseError = "malloc: could not allocate memory for this search."; return NULL; } node->localdata = getsstring(expr->u.literal,512); node->returntype = RETURNTYPE_CONST | RETURNTYPE_STRING; node->exe = literal_exe; node->free = literal_free; return node; case AST_NODE_CHILD: v = (char **)malloc(expr->u.child.argc * sizeof(char *)); if(!v) { parseError = "malloc: could not allocate memory for this search."; return NULL; } for(i=0;i<expr->u.child.argc;i++) { searchASTExpr *child = &expr->u.child.argv[i]; cachepush(cache, child); switch(child->type) { case AST_NODE_LITERAL: v[i] = child->u.literal; break; case AST_NODE_CHILD: v[i] = (char *)child; break; default: parseError = "static_parse: bad child node type"; free(v); return NULL; } } node = expr->u.child.fn(ctx, expr->u.child.argc, v); free(v); return node; default: parseError = "static_parse: bad node type"; return NULL; } }
unsigned dircache(struct VCB *vcb,char *dirnam,int dirlen,struct fiddef *dirid) { register struct DIRCACHE *dir; if (dirlen < 1) { dirid->fid$w_num = 4; dirid->fid$w_seq = 4; dirid->fid$b_rvn = 0; dirid->fid$b_nmx = 0; return 1; } else { unsigned create = 0; dir = cachesearch((void *) &vcb->dircache,0,dirlen,dirnam,dircmp,&create); if (dir != NULL) { memcpy(dirid,&dir->dirid,sizeof(struct fiddef)); return 1; } return 0; } }
unsigned accesschunk(struct FCB *fcb,unsigned vbn,struct VIOC **retvioc, char **retbuff,unsigned *retblocks,unsigned wrtblks, unsigned *retmodmask) { /* First find cache entry... */ register struct VIOC *vioc; unsigned create = sizeof(struct VIOC); register unsigned base = (vbn - 1) / VIOC_CHUNKSIZE * VIOC_CHUNKSIZE + 1; #ifdef DEBUG printf("Access chunk %8x %d (%x)\n",base,vbn,fcb->cache.keyval); #endif if (wrtblks && ((fcb->cache.status & CACHE_WRITE) == 0)) return SS$_WRITLCK; if (vbn < 1 || vbn > fcb->hiblock) return SS$_ENDOFFILE; vioc = cachesearch((void *) &fcb->vioc,base,0,NULL,NULL,&create); if (vioc == NULL) return SS$_INSFMEM; /* If not found make one... */ if (create == 0) { register unsigned length; register char *address; register unsigned mapbase = base; vioc->cache.status |= 0x400; /* For debugging! */ vioc->fcb = fcb; vioc->wrtmask = 0; vioc->modmask = 0; length = fcb->hiblock - mapbase + 1; if (length > VIOC_CHUNKSIZE) length = VIOC_CHUNKSIZE; address = (char *) vioc->data; do { if (fcb->highwater > 0 && mapbase >= fcb->highwater) { memset(address,0,length * 512); length = 0; } else { register unsigned sts; unsigned rvn,mapblk,maplen; register struct VCBDEV *vcbdev; sts = getwindow(fcb,mapbase,&rvn,&mapblk,&maplen); if (sts & 1) { if (maplen > length) maplen = length; if (fcb->highwater > 0 && mapbase + maplen > fcb->highwater) { maplen = fcb->head->fh2$l_highwater - mapbase; } if (rvn > fcb->vcb->devices) { sts = SS$_NOSUCHFILE; } else { if (rvn < 2) { vcbdev = fcb->vcb->vcbdev; } else { vcbdev = &fcb->vcb->vcbdev[rvn - 1]; } if (vcbdev->dev == NULL) return SS$_NOSUCHFILE; sts = phyio_read(vcbdev->dev->handle,mapblk,maplen * 512,address); } } if ((sts & 1) == 0) { cacheuntouch(&vioc->cache,0,0); cachefree(&vioc->cache); return sts; } length -= maplen; mapbase += maplen; address += maplen * 512; } } while (length > 0); } if (wrtblks) { vioc->cache.status |= CACHE_WRITE; vioc->cache.objmanager = viocmanager; } /* Return result to caller... */ *retvioc = vioc; *retbuff = vioc->data[vbn - base]; if (wrtblks || retblocks != NULL || retmodmask != NULL) { register unsigned modmask = 0; register unsigned blocks = base + VIOC_CHUNKSIZE - vbn; if (blocks > fcb->hiblock - vbn) blocks = fcb->hiblock - vbn + 1; if (wrtblks) if (blocks > wrtblks) blocks = wrtblks; if (retblocks != NULL) *retblocks = blocks; if (wrtblks) { modmask = 1 << (vbn - base); if (blocks > 1) { while (--blocks > 0) modmask |= modmask << 1; } vioc->wrtmask |= modmask; } if (retmodmask != NULL) *retmodmask = modmask; } return SS$_NORMAL; }
unsigned getwindow(struct FCB * fcb,unsigned vbn,unsigned *phyrvn,unsigned *phyblk,unsigned *phylen) { register struct WCB *wcb; struct WCB *prev_wcb = NULL; unsigned create = sizeof(struct WCB); #ifdef DEBUG printf("Accessing window for vbn %d, file (%x)\n",vbn,fcb->cache.keyval); #endif wcb = cachesearch((void *) &fcb->wcb,0,vbn,&prev_wcb,wincmp,&create); if (wcb == NULL) return SS$_INSFMEM; /* If not found make one... */ if (create == 0) { register unsigned wd_base,wd_exts; unsigned prev_hiblk,rvn; struct VIOC *vioc; struct HEAD *head; wcb->cache.status |= 0x200; /* For debugging! */ vioc = NULL; wd_base = 1; rvn = fcb->rvn; head = fcb->head; prev_hiblk = 0; if (prev_wcb != NULL) { register unsigned sts; register struct fiddef *fid = &prev_wcb->hd_fid; register struct fiddef *filefid = &fcb->head->fh2$w_fid; if (fid->fid$w_num != filefid->fid$w_num || fid->fid$b_nmx != filefid->fid$b_nmx || ((fid->fid$b_rvn > 1 || fcb->rvn > 1) && fid->fid$b_rvn != fcb->rvn)) { wd_base = prev_wcb->hd_base; rvn = prev_wcb->hd_fid.fid$b_rvn; sts = accesshead(fcb->vcb,fid,&vioc,&head,NULL,0); if ((sts & 1) == 0) { cacheuntouch(&wcb->cache,0,0); cachefree(&wcb->cache); return sts; } } prev_hiblk = prev_wcb->hiblk; } wcb->hd_base = wd_base; wd_exts = 0; #ifdef DEBUG printf("Making window %d %d\n",wd_base,prev_hiblk); #endif do { register unsigned short *mp = (unsigned short *) head + head->fh2$b_mpoffset; register unsigned short *me = mp + head->fh2$b_map_inuse; while (mp < me) { register unsigned phylen,phyblk; switch ((*mp) >> 14) { case 0: phylen = 0; mp++; break; case 1: phylen = ((*mp) & 0377) + 1; phyblk = (((*mp) & 037400) << 8) + mp[1]; mp += 2; break; case 2: phylen = ((*mp) & 037777) + 1; phyblk = (mp[2] << 16) + mp[1]; mp += 3; break; case 3: phylen = (((*mp) & 037777) << 16) + mp[1] + 1; phyblk = (mp[3] << 16) + mp[2]; mp += 4; } if (phylen > 0 && wd_base > prev_hiblk) { register struct EXT *ext; if (wd_exts == 0) wcb->loblk = wd_base; ext = &wcb->ext[wd_exts++]; ext->phylen = phylen; ext->phyblk = phyblk; wd_base += phylen; if (wd_exts >= EXTMAX) { if (wd_base > vbn) { break; } else { wd_exts = 0; } } } else { wd_base += phylen; } } if (wd_base > vbn) { break; } else { register unsigned sts; struct fiddef extfid; memcpy(&extfid,&head->fh2$w_ext_fid,sizeof(struct fiddef)); if (extfid.fid$b_rvn != 0 && extfid.fid$b_rvn != rvn) { wd_exts = 0;/* Can't let window extend across devices */ rvn = extfid.fid$b_rvn; } else { extfid.fid$b_rvn = rvn; } if (vioc != NULL) deaccesshead(vioc,NULL,0); sts = accesshead(fcb->vcb,&extfid,&vioc,&head,NULL,0); if ((sts & 1) == 0) { cacheuntouch(&wcb->cache,0,0); cachefree(&wcb->cache); return sts; } wcb->hd_base = wd_base; } } while (wd_base <= vbn); memcpy(&wcb->hd_fid,&head->fh2$w_fid,sizeof(struct fiddef)); wcb->hd_fid.fid$b_rvn = rvn; wcb->hiblk = wd_base - 1; wcb->extcount = wd_exts; if (vioc != NULL) deaccesshead(vioc,NULL,0); } { register struct EXT *ext = wcb->ext; register unsigned extcnt = wcb->extcount; register unsigned togo = vbn - wcb->loblk; while (togo >= ext->phylen) { togo -= (ext++)->phylen; if (extcnt-- < 1) return SS$_BUGCHECK; } *phyrvn = wcb->hd_fid.fid$b_rvn; *phyblk = ext->phyblk + togo; *phylen = ext->phylen - togo; #ifdef DEBUG printf("Mapping vbn %d to %d (%d -> %d)[%d] file (%x)\n", vbn,*phyblk,wcb->loblk,wcb->hiblk,wcb->hd_base,fcb->cache.keyval); #endif cacheuntouch(&wcb->cache,1,0); } return SS$_NORMAL; }