
DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 1
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (1)



    1        	/*
    2        		DFU V2.4
    3        	
    4        		DFU_IFSCAN.C
    5        		
    6        		This file contains all routines needed
    7        		for scanning and parsing the Index File
    8        	
    9        		Called by SEARCH, REPORT , VERIFY ,UNDELETE, INDEX,
   10        		and DIRECTORY/VERSION , /EMPTY or /ALIAS, DEFRAG/DISK
   11        	
   12        	*/
   13        	
   14        	#ifndef VAXC
   15        	#pragma message disable(ALIGNEXT)
   16        	#pragma message disable(GLOBALEXT)
   17        	#endif
   18        	
   19        	#include "file_hdr"
  457        	#include "home2def"
  609        	#include ssdef
 2100        	#include stdio
 2776        	#include descrip
 3752        	#include fibdef
 4230        	#include clidef
 4676        	#include climsgdef
 5022        	#include lib$routines
 6791        	#include libdef
 7166        	#include sor$routines
 7319        	#include atrdef
 7515        	#include dcdef
 8148        	#include devdef
 8373        	#include mntdef
 8645        	#include dvidef
 8923        	#include iodef
 9898        	#include strdef
10029        	#include trmdef
10203        	#include smgdef
11042        	
11043        	typedef unsigned long Boolean;
11044        	
11045        	typedef struct _flist { 
11046        	  char name[86]; 
11047        	  short flen; 
11048        	};
11049        	typedef struct _quad { 
11050        	  int date[2]; 
11051        	};
11052        	typedef struct f_id {
11053        	  unsigned short fid_num, fid_seq; 
11054        	  unsigned char fid_rvn, fid_nmx;
11055        	} 
11056        	;
11057        	typedef struct _it3 { 
11058        	  short buflen, itemcode;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 2
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (1)

11059        	  unsigned int *bufadr; 
11060        	  unsigned int *retlen; 
11061        	};
11062        	
11063        	/* Structure for work list */
11064        	typedef struct work { 
11065        	  unsigned short fid_num, fid_seq;
11066        	  unsigned char fid_rvn, fid_nmx;
11067        	  unsigned short did_num, did_seq;
11068        	  unsigned char did_rvn, did_nmx; 
11069        	  char name[86]; 
11070        	  char function;
11071        	  short rvn; 
11072        	  struct work *next; 
11073        	};
11074        	
11075        	static struct _cln {
11076        	unsigned int channels : 
11077        	  1;
11078        	unsigned int events : 
11079        	  1; 
11080        	unsigned int fopen : 
11081        	  1;
11082        	unsigned int sort : 
11083        	  1;
11084        	unsigned int expreg : 
11085        	  1;
11086        	} 
11087        	clean_flags;
11088        	
11089        	extern struct work *first, *list;
11090        	
11091        	/* Structure for dynamic array */
11092        	struct _da { 
11093        	  short fid[3]; 
11094        	  unsigned int bakfid, a_size, f_link; 
11095        	  char rvn, bitje; 
11096        	} 
11097        	*dyn_array;
11098        	
11099        	extern unsigned int ctrlc, SOR$GK_RECORD, SOR$M_STABLE, keyb_id, tchan, 
11100        	rows, colls, disp1_id, paste_id, lbnstart, lbncount;
11101        	extern Boolean trigger, smg$enable, trace_on;
11102        	extern int ctrlt_ast();
11103        	extern char outbuf[255];
11104        	globalvalue DFU_NOPRIV, DFU_EXPREG, DFU_ASSIGN, DFU_INDEXERR, 
11105        	DFU_EXHFAIL, DFU_IOERR;
11106        	
11107        	const int iocnt=2;
11108        	
11109        	char block[512]; 	/* One page/block */
11110        	
11111        	extern _align(PAGE) struct _hdr {	
11112        	  /* Large enough to hold 1001 headers */
11113        	  char block[512];
11114        	} 
11115        	header[1001];

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 3
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (1)

11116        	
11117        	static struct _ibmap {
11118        	  char block[512];
11119        	} 
11120        	bitmap[257]; /* Space for index file bitmap */
11121        	
11122        	static struct HM2_Struct home[33];	/* 32 home blocks */
11123        	
11124        	static struct _vol {	/* Structure for relative volume table */
11125        	  char devnam[64], fulldevnam[64];
11126        	  unsigned int devnam_len, fulldevnam_len, 
11127        	  i_open,vbn_file_1,if_size, maxblocks;
11128        	  unsigned short channel, bchan;
11129        	  Boolean wlk, slow;
11130        	  int addr[2], bmap_addr[2]; /* For EXPREG calls */
11131        	} 
11132        	rvt[33];
11133        	
11134        	static unsigned int volcount, maxvol, volnum, orig_rvn, curvol, strategy;
11135        	static unsigned int lendev, status, iosize, vbn, headers, highbit;
11136        	static unsigned short lock_chan;
11137        	static char device[64];
11138        	
11139        	static struct { 
11140        	  unsigned short iosb_1;
11141        	  unsigned int length;
11142        	  short spec; 
11143        	} 
11144        	iostat[3];
11145        	
11146        	/* context block for I/O processing */
11147        	static struct { 
11148        	  unsigned int i, starti, endi, thread;
11149        	  struct header_area_struct *hdr;
11150        	  struct ident_area_struct *id;
11151        	  Boolean end; 
11152        	} 
11153        	ctx; 
11154        	
11155        	static int efn[2]; /* Event flags */
11156        	
11157        	static unsigned short map_ptr[4];
11158        	static Boolean progress_ind;
11159        	
11160        	static struct _dr { 
11161        	  short lendir;
11162        	  char dirnam[198]; 
11163        	} 
11164        	dirrec;
11165        	
11166        	static struct { 
11167        	  unsigned short atr_size, atr_type;
11168        	  int *atr_address; 
11169        	} 
11170        	acb[2]= {
11171        	  {
11172        	    200, ATR$C_FILE_SPEC, (int *) &dirrec   }

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 4
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (1)

11173        	  ,
11174        	  { 
11175        	    0,0,0  } 
11176        	}; /* Attribute control block */
11177        	
11178        	static struct { 
11179        	  int forward_link, handler_addr, arg_count, condition; 
11180        	} 
11181        	desblk;
11182        	
11183        	static FILE *fp;
11184        	
11185        	void cleanup(), copy_fid(), disass_map_ptr(), add_item(), 
11186        	read_indexf_bitmap(), fid_to_name();
11187        	
11188        	int open_device(), get_next_header();
11189        	
11190        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 5
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (2)

             	
11191        	int display_stat(struct dsc$descriptor *out_str, int user_arg)
11192        	/* user action routine to catch LIB$SHOW_TIMER output */
11193        	{ 
11194        	  if (smg$enable)
11195        	  { 
11196        	    sprintf(outbuf,"%.*s\n",out_str->dsc$w_length, out_str->dsc$a_pointer);
11197        	    put_status(2);
11198        	  }
11199        	  else
11200        	    printf("\n%.*s\n",out_str->dsc$w_length, out_str->dsc$a_pointer);
11201        	  return(1);    
11202        	}
11203        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 6
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (3)

             	
11204        	void do_abort(void)
11205        	/* Show user that the CTRL/C is in progress */
11206        	{ 
11207        	  sprintf(outbuf,"\n%%DFU-W-ABORTED , command interrupted by CTRL/C");
11208        	  put_disp();
11209        	  sprintf(outbuf," ");
11210        	  put_status(2);
11211        	}
11212        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 7
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

             	
11213        	int search_command (int mask)
11214        	
11215        	/*
11216        		Search through INDEXF.SYS for files with certain
11217        		attributes specified on the command line
11218        	
11219        	*/
11220        	
11221        	{
11222        	  static char dummy_item[80], name[86], dir[200], 
11223        	  fname[80], ident[30], date_s[23], format_str[80], fmode[2];
11224        	  struct header_area_struct *hdr;
11225        	  struct ident_area_struct *id;
11226        	  short keybuf[5] = {
11227        	    1, DSC$K_DTYPE_T, 0, 0, 255   };
11228        	  int reclen = 255;
11229        	  struct _flist file[50], exclfile[50];
11230        	  int fcnt, efcnt, flgs;
11231        	  struct _quad cre_bef, cre_sin, mod_bef, mod_sin, 
11232        	  exp_bef, exp_sin, bak_bef, bak_sin, diff;
11233        	  register int i;
11234        	  Boolean matmult, dispfull, matsumm, matplaced, matnovolset,
11235        	  matnosearch, mathome, matstat, matalloc, dummy, matlbn,
11236        	  mat_r_minsize, mat_r_maxsize, mat_a_minsize, mat_a_maxsize,
11237        	  matoutput , matname, matexcl, found, matnonebackup, matnoneexpired, 
11238        	  matbefcreated, matsincreated, matbefmodified, matsinmodified,
11239        	  matbefbackup, matsinbackup, matbefexpired, matsinexpired,matsort,
11240        	  matbakfid, matfid, matchars, mator, matmark, matuic, matfragment,
11241        	  matversion, matformat, matover, matappend;
11242        	  int size_min, size_max, parse_type, free_hdr, ivbn, k, j, x,
11243        	  bitblk, bitje, bitval, find, rvn , flags, size,
11244        	  retr_min, retr_max, vers_min, vers_max, hdrs, rtvptr, lbn, spacing;
11245        	  int parse_item(), read_indexf_multi(), dfu_check();
11246        	  unsigned short fid[3] ;
11247        	  unsigned int r_size, a_size , tot_r_size, tot_a_size, fcount, val_headers,
11248        	  fidnum, infid, bakfid, chars, setchar, uic, tothdr, totfrag, 
11249        	  offset, map_words, over_alloc;
11250        	  void get_map_pointers();
11251        	  /* FAO parameters */
11252        	  int faolen; 
11253        	  unsigned short outlen; 
11254        	  $DESCRIPTOR(out_descr , outbuf);
11255        	  $DESCRIPTOR(device_descr , device);
11256        	  $DESCRIPTOR(dummy_descr , dummy_item);
11257        	  $DESCRIPTOR(dir_descr , dir);
11258        	  $DESCRIPTOR(file_descr , fname);
11259        	  $DESCRIPTOR(name_descr , name);
11260        	  $DESCRIPTOR(id_descr , ident);
11261        	  $DESCRIPTOR(date_descr , date_s);
11262        	  $DESCRIPTOR(ctrstr0, "!%I (!%U)");
11263        	  $DESCRIPTOR(ctrstr4, "!#AS!9UL/!UL");
11264        	  $DESCRIPTOR(ctrstr7, "!#AS!9UL/!9<!UL!>!4UL/!UL");
11265        	  $DESCRIPTOR(ctrstr8, format_str);
11266        	
11267        	  /* Code starts here */
11268        	  /* Parse the various qualifiers */

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 8
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11269        	
11270        	  progress_ind = TRUE;
11271        	  /* Get device name */
11272        	  status = parse_item("device", &device_descr, 0, &dummy , 0);
11273        	  if (status == 1) 
11274        	  { 
11275        	    if (strindex(&device,":",64) == -1) 
11276        	    {
11277        	      device[device_descr.dsc$w_length]=':'; 
11278        	      device_descr.dsc$w_length += 1;
11279        	    }
11280        	  }
11281        	  clean_flags.fopen = 0;
11282        	  flgs = SMG$M_WRAP_CHAR;
11283        	  /* Check file name(s) */
11284        	  dummy_descr.dsc$a_pointer = (char *) &fcnt;
11285        	  status = parse_item("file", &dummy_descr, &file[0].name, &matname , 3);
11286        	  /* Check exclude file name(s) */
11287        	  dummy_descr.dsc$a_pointer = (char *) &efcnt;
11288        	  status = parse_item("exclude", &dummy_descr, &exclfile[0].name, 
11289        	  &matexcl ,3);
11290        	  dummy_descr.dsc$a_pointer = (char *) &dummy_item;
11291        	  /* Search on allocated filesize */
11292        	  status = parse_item("allocated", &dummy_descr, 0, &matalloc, 2);
11293        	  if (matalloc == TRUE) 
11294        	  { /* Check minimum size entered */
11295        	    status = parse_item("size_min", &dummy_descr, &size_min, &mat_a_minsize , 1);
11296        	    if ((status & 1) != 1) return(status); 
11297        	    /* Check maximum size entered */
11298        	    status = parse_item("size_max", &dummy_descr, &size_max, &mat_a_maxsize , 1);
11299        	    if ((status & 1) != 1) return(status); 
11300        	    mat_r_minsize = FALSE; 
11301        	    mat_r_maxsize = FALSE;
11302        	    if (mat_a_minsize == TRUE && mat_a_maxsize == TRUE )
11303        	      if (size_min > size_max) 
11304        	      { 
11305        	        sprintf(outbuf,"%%DFU-E-SIZEERR, Minimum size > maximum size\n");
11306        	        put_disp();
11307        	        cleanup();
11308        	        return(1);
11309        	      }
11310        	  }
11311        	  else
11312        	  { /* Check minimum size entered */
11313        	    status = parse_item("size_min", &dummy_descr, &size_min, &mat_r_minsize , 1);
11314        	    if ((status & 1) != 1) return(status); 
11315        	    /* Check maximum size entered */
11316        	    status = parse_item("size_max", &dummy_descr, &size_max, &mat_r_maxsize , 1);
11317        	    if ((status & 1) != 1) return(status); 
11318        	    mat_a_minsize = FALSE; 
11319        	    mat_a_maxsize = FALSE;
11320        	    if (mat_r_minsize == TRUE && mat_r_maxsize == TRUE )
11321        	      if (size_min > size_max) 
11322        	      { 
11323        	        sprintf(outbuf,"%%DFU-E-SIZEERR, Minimum size > maximum size\n");
11324        	        put_disp(); 
11325        	        cleanup();

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 9
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11326        	        return(1);
11327        	      }
11328        	  }
11329        	  /* Check format string */
11330        	  status = parse_item("format", &ctrstr8, 0, &matformat , 0);
11331        	  /* Check backlink file id */
11332        	  status = parse_item("bakfid", &dummy_descr, &bakfid, &matbakfid , 1);
11333        	  if ((status & 1) != 1) return(status); 
11334        	  /* Check specific LBN */
11335        	  status = parse_item("lbn", &dummy_descr, &lbn, &matlbn , 1);
11336        	  if ((status & 1) != 1) return(status); 
11337        	  /* Check file id */
11338        	  status = parse_item("fid", &dummy_descr, &infid, &matfid , 1);
11339        	  if ((status & 1) != 1) return(status); 
11340        	  /* Check overallocated files */
11341        	  status = parse_item("over", &dummy_descr, &over_alloc, &matover , 1);
11342        	  if ((status & 1) != 1) return(status); 
11343        	  /* Files with multi headers */
11344        	  status = parse_item("multiple", &dummy_descr, 0, &matmult, 2);
11345        	  /* Full output display */
11346        	  status = parse_item("full", &dummy_descr, 0, &dispfull, 2);
11347        	  /* Summary output*/
11348        	  status = parse_item("summary", &dummy_descr, 0, &matsumm, 2);
11349        	  /* Files with placement pointers */
11350        	  status = parse_item("placed", &dummy_descr, 0, &matplaced, 2);
11351        	  /* Disallow volume set processing*/
11352        	  status = parse_item("novolset", &dummy_descr, 0, &matnovolset, 2);
11353        	  /* Home block only */
11354        	  status = parse_item("nosearch", &dummy_descr, 0, &matnosearch, 2);
11355        	  /* Display home block info */
11356        	  status = parse_item("home", &dummy_descr, 0, &mathome, 2);
11357        	  /* Display statistics */
11358        	  status = parse_item("statistics", &dummy_descr, 0, &matstat, 2);
11359        	  /* Sort output */
11360        	  status = parse_item("sort", &dummy_descr, 0, &matsort, 2);
11361        	  /* Fragmentation */
11362        	  status = parse_item("fragment", &dummy_descr, 0, &matfragment, 2);
11363        	  if (matfragment == TRUE) 
11364        	  { 
11365        	    retr_min = 0; 
11366        	    retr_max = 0;
11367        	    status = parse_item("retr_min", &dummy_descr, &retr_min, &matfragment , 1);
11368        	    if ((status & 1) != 1) return(status); 
11369        	    status = parse_item("retr_max", &dummy_descr, &retr_max, &matfragment , 1);
11370        	    if ((status & 1) != 1) return(status); 
11371        	    matfragment = TRUE;
11372        	  }
11373        	  /* Version check */
11374        	  status = parse_item("version_number", &dummy_descr, 0, &matversion, 2);
11375        	  if (matversion == TRUE)
11376        	  { 
11377        	    vers_min = 0; 
11378        	    vers_max = 0;
11379        	    status = parse_item("vers_min", &dummy_descr, &vers_min, &matversion , 1);
11380        	    if ((status & 1) != 1) return(status);
11381        	    status = parse_item("vers_max", &dummy_descr, &vers_max, &matversion , 1);
11382        	    if ((status & 1) != 1) return(status);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 10
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11383        	    matversion = TRUE;
11384        	  }
11385        	  /* Date and time options */
11386        	  status = parse_item("bak_none", &dummy_descr, 0, &matnonebackup, 2);
11387        	  status = parse_item("exp_none", &dummy_descr, 0, &matnoneexpired, 2);
11388        	  status = parse_item("cre_before", &dummy_descr, &cre_bef, &matbefcreated, 4);
11389        	  status = parse_item("cre_since", &dummy_descr, &cre_sin, &matsincreated, 4);
11390        	  status = parse_item("mod_before", &dummy_descr, &mod_bef, &matbefmodified,4);
11391        	  status = parse_item("mod_since", &dummy_descr, &mod_sin, &matsinmodified,4);
11392        	  status = parse_item("bak_before", &dummy_descr, &bak_bef, &matbefbackup, 4);
11393        	  status = parse_item("bak_since", &dummy_descr, &bak_sin, &matsinbackup, 4);
11394        	  status = parse_item("exp_before", &dummy_descr, &exp_bef, &matbefexpired,4);
11395        	  status = parse_item("exp_since", &dummy_descr, &exp_sin, &matsinexpired,4);
11396        	  /* File characteristics options */
11397        	  chars=0;
11398        	  dummy_descr.dsc$a_pointer = (char *) &chars;
11399        	  status = parse_item("or", &dummy_descr, 0, &mator, 2);
11400        	  setchar = FH2$M_NOBACKUP;
11401        	  status = parse_item("nobackup", &dummy_descr, &setchar, &matchars, 5);
11402        	  setchar = FH2$M_CONTIGB;
11403        	  status = parse_item("besttry", &dummy_descr, &setchar, &matchars, 5);
11404        	  setchar = FH2$M_LOCKED;
11405        	  status = parse_item("locked", &dummy_descr, &setchar, &matchars, 5);
11406        	  setchar = FH2$M_CONTIG;
11407        	  status = parse_item("contiguous", &dummy_descr, &setchar, &matchars, 5);
11408        	  setchar = FH2$M_BADACL;
11409        	  status = parse_item("badacl", &dummy_descr, &setchar, &matchars, 5);
11410        	  setchar = FH2$M_SPOOL;
11411        	  status = parse_item("spool", &dummy_descr, &setchar, &matchars, 5);
11412        	  setchar = FH2$M_DIRECTORY;
11413        	  status = parse_item("directory", &dummy_descr, &setchar, &matchars, 5);
11414        	  setchar = FH2$M_BADBLOCK;
11415        	  status = parse_item("badblock", &dummy_descr, &setchar, &matchars, 5);
11416        	  setchar = FH2$M_MARKDEL;
11417        	  status = parse_item("marked", &dummy_descr, &setchar, &matmark, 5);
11418        	  if (matmark == TRUE) matchars = TRUE;
11419        	  setchar = FH2$M_NOCHARGE;
11420        	  status = parse_item("nocharge", &dummy_descr, &setchar, &matchars, 5);
11421        	  setchar = FH2$M_ERASE;
11422        	  status = parse_item("erase", &dummy_descr, &setchar, &matchars, 5);
11423        	  setchar = FH2$M_SCRATCH;
11424        	  status = parse_item("scratch", &dummy_descr, &setchar, &matchars, 5);
11425        	  setchar = FH2$M_NOMOVE;
11426        	  status = parse_item("nomove", &dummy_descr, &setchar, &matchars, 5);
11427        	  setchar = FH2$M_NOSHELVABLE;
11428        	  status = parse_item("noshelvable", &dummy_descr, &setchar, &matchars, 5);
11429        	  setchar = FH2$M_SHELVED;
11430        	  status = parse_item("isshelved", &dummy_descr, &setchar, &matchars, 5);
11431        	  if (chars !=0) matchars = TRUE;
11432        	  dummy_descr.dsc$a_pointer = (char *) &dummy_item;
11433        	
11434        	  /* Ident or UIC */
11435        	  status = parse_item("ident", &dummy_descr, &uic, &matuic, 6);
11436        	  if (matuic == FALSE) 
11437        	    status = parse_item("uic", &dummy_descr, &uic, &matuic, 6);
11438        	  if ((status &1 ) != 1)
11439        	  { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 11
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11440        	    sprintf(outbuf,"%%DFU-E-INVID, Wrong uic or identifier,");
11441        	    put_disp(); 
11442        	    singlemsg(0,status);
11443        	    return(1); 
11444        	  }
11445        	  id_descr.dsc$w_length = 30;
11446        	
11447        	  /* Get output file */
11448        	  strcpy(fmode,"w");
11449        	  status = parse_item("outfile", &file_descr, 0, &matoutput , 0);
11450        	  if (!matoutput)
11451        	    status = parse_item("append", &file_descr, 0, &matappend , 0);
11452        	  if (matappend)
11453        	  { 
11454        	    matoutput = TRUE; 
11455        	    strcpy(fmode,"a");
11456        	  }  
11457        	  if (matoutput == FALSE) 
11458        	  {
11459        	    strcpy(fname,"SYS$OUTPUT:"); 
11460        	    file_descr.dsc$w_length = 11;
11461        	  }
11462        	  else
11463        	    fname[file_descr.dsc$w_length] = '\0'; 
11464        	  fp = fopen(fname,fmode,"mrs=255","rfm=var","ctx=rec","rat=cr","rop=WBH");	
11465        	  clean_flags.fopen = 1;
11466        	  if (matsort == FALSE)
11467        	    clean_flags.sort = 0;
11468        	  else
11469        	  { 
11470        	    status = sor$begin_sort(&keybuf,&reclen,0,0,0,0,SOR$GK_RECORD,0,0);
11471        	    if ((status &1 ) != 1)
11472        	    { 
11473        	      singlemsg(0,status); 
11474        	      return(status); 
11475        	    }
11476        	    clean_flags.sort = 1;
11477        	  }
11478        	  /* All qualifiers parsed */
11479        	
11480        	  if (matstat == TRUE) status = lib$init_timer();
11481        	  clean_flags.channels = 0;
11482        	  clean_flags.events = 0;
11483        	  clean_flags.expreg = 0;
11484        	  tot_r_size = 0; 
11485        	  tot_a_size = 0;
11486        	  tothdr = 0; 
11487        	  totfrag = 0;
11488        	  fcount = 0;
11489        	  val_headers = 0; 
11490        	  spacing = colls;
11491        	
11492        	  /* Open the volume (set) , read in the home block */
11493        	
11494        	  status = open_device(&device_descr,0);
11495        	  if ((status & 1) != 1) 
11496        	  { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 12
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11497        	    cleanup();
11498        	    return(status); 
11499        	  }
11500        	
11501        	  curvol = 1; 
11502        	  size = 1;
11503        	  ctx.end = FALSE;
11504        	  if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_OFF);
11505        	  while ((curvol <= maxvol) && (!ctx.end))
11506        	  { 
11507        	    ctx.i = -1; /* Clear context */
11508        	    if (rvt[curvol].i_open ==1) 
11509        	    { 
11510        	      if (maxvol == 1)
11511        	      {	
11512        	        sprintf(outbuf,"%%DFU-I-SEARCH, Start search on %.*s (%s)\n",
11513        	        device_descr.dsc$w_length, device,
11514        	        &rvt[curvol].fulldevnam[1]); 
11515        	      }
11516        	      else
11517        	      {	
11518        	        if (matnovolset == TRUE) curvol = orig_rvn; /*No volume set */
11519        	        sprintf(outbuf,"%%DFU-I-SEARCH, Start search on %.*s (%s) , RVN = %d\n",
11520        	        rvt[curvol].devnam_len, rvt[curvol].devnam, 
11521        	        &rvt[curvol].fulldevnam[1],curvol); 
11522        	      }
11523        	      put_disp();
11524        	      headers=0;
11525        	      val_headers = 0;
11526        	      /* Read in index file bitmap, and return free hdrs + highest bit set */
11527        	      read_indexf_bitmap(&free_hdr);
11528        	
11529        	      /* Display home block info if needed */
11530        	      if (mathome == TRUE) 
11531        	      { 
11532        	        sprintf(outbuf,"\nVolume name       :  %.12s",home[curvol].volname);
11533        	        put_disp();
11534        	        sprintf(outbuf,"Volume owner      :  %.12s",home[curvol].ownername);
11535        	        put_disp();
11536        	        sprintf(outbuf,"Structure name    :  %.12s",home[curvol].strucname);
11537        	        put_disp();
11538        	        sprintf(outbuf,"Cluster size      :  %d",home[curvol].cluster);
11539        	        put_disp();
11540        	        sprintf(outbuf,"Maximum # files   :  %d",home[curvol].maxfiles);
11541        	        put_disp();
11542        	        sprintf(outbuf,"Header count      :  %d",rvt[curvol].if_size);
11543        	        put_disp();
11544        	        sprintf(outbuf,"First header VBN  :  %d",rvt[curvol].vbn_file_1);
11545        	        put_disp();
11546        	        sprintf(outbuf,"Available headers :  %d\n",free_hdr);
11547        	        put_disp();
11548        	      }
11549        	
11550        	      if (matnosearch == TRUE ) ctx.end = TRUE;
11551        	      status = get_next_header();
11552        	      if ((status & 1) != 1) return(status);
11553        	      while (! ctx.end) /* Loop until end of INDEXF or CTRL C entered */

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 13
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11554        	      { 
11555        	        hdr = ctx.hdr;
11556        	        id = ctx.id;
11557        	        if (matfid == TRUE) /* Special case if FID requested */
11558        	        { 
11559        	          ctx.end = TRUE;
11560        	          if (infid > rvt[curvol].if_size)
11561        	          { 
11562        	            sprintf(outbuf,"%%DFU-E-FIDTOOBIG, File id specified > max file id\n");
11563        	            put_disp(); 
11564        	            goto nexti;
11565        	          }
11566        	          vbn = rvt[curvol].vbn_file_1 + infid - 1;
11567        	          status = SYS$QIOW(0,rvt[curvol].channel,IO$_READVBLK,
11568        	          &iostat[(ctx.thread)-1],0,0,&header[ctx.i],512,vbn,0,0,0);
11569        	        }
11570        	        /* Check corresponding bitmap bit (must be set) */
11571        	        bitblk = (headers + 4095) / 4096 - 1;
11572        	        bitje = (headers - 1 - bitblk*4096) / 32;
11573        	        bitval = (headers - 1) % 32;
11574        	        status = lib$ffs(&bitval,&size,&bitmap[bitblk+1].block[bitje*4],
11575        	        &find);
11576        	        if (status == LIB$_NOTFOU) goto nexti;
11577        	        rvn = curvol;
11578        	        if (matlbn == FALSE ) if (hdr->seg_num !=0) goto nexti; /* Skip extension header */
11579        	        rtvptr = 0; 
11580        	        status = verify_header(hdr);
11581        	        if (status != SS$_NORMAL) goto nexti; /* Not a valid header */
11582        	
11583        	        /* Check marked for delete files, skip unless explicitly requested */
11584        	        if (matmark == FALSE) 
11585        	          if ((hdr->filechar & FH2$M_MARKDEL) == FH2$M_MARKDEL) goto nexti;
11586        	
11587        	        /*  We have a valid file header.
11588        	            Now check the various attributes for a match 
11589        	        */ 
11590        	        val_headers++;
11591        	        /* Check for specific LBN */
11592        	        if (matlbn == TRUE) 
11593        	        { 
11594        	          found = FALSE;
11595        	          offset = hdr->mpoffset; /* Start of map area */
11596        	          map_words = hdr->map_inuse;
11597        	          for (j = offset; j<(offset+map_words);)
11598        	          { 
11599        	            disass_map_ptr(hdr,&j);
11600        	            if ((lbn >= lbnstart) && (lbn < (lbnstart + lbncount))) 
11601        	            { 
11602        	              found = TRUE; 
11603        	              j = offset + map_words + 1;
11604        	            }
11605        	          }
11606        	          if (!found) goto nexti;
11607        	          if (hdr->seg_num > 0 ) /* read backlink for primary header */
11608        	          { 
11609        	            rvn = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn;
11610        	            if (rvn == 0) rvn = curvol;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 14
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11611        	            fidnum = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx << 16;
11612        	            fidnum += hdr->bk_fid_overlay.backlink[0];
11613        	            ivbn = rvt[rvn].vbn_file_1 + fidnum - 1; 
11614        	            status = SYS$QIOW(0,rvt[rvn].channel,IO$_READVBLK,
11615        	            &iostat[iocnt],0,0,&header[ctx.i],512,ivbn,0,0,0);
11616        	            if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
11617        	            if ((status & 1) != 1) 
11618        	            { 
11619        	              sprintf(outbuf,"%%DFU-E-READERR, Error reading backlink header,\n");
11620        	              put_disp(); 
11621        	              singlemsg(0,status);
11622        	              goto nexti;
11623        	            }
11624        	            status = verify_header(hdr);
11625        	            if (status != SS$_NORMAL) goto nexti; /* Not a valid header */
11626        	          }
11627        	        }
11628        	
11629        	        /* Get size fields (NOTE : they are stored in reverse order ! */
11630        	        a_size = hdr->hiblk_overlay.hiblk_fields.hiblkh << 16;
11631        	        a_size += hdr->hiblk_overlay.hiblk_fields.hiblkl;
11632        	        r_size = hdr->efblk_overlay.efblk_fields.efblkh << 16;
11633        	        r_size += hdr->efblk_overlay.efblk_fields.efblkl;
11634        	        if (r_size > 0) 
11635        	          if (hdr->ffbyte == 0) r_size--; /* Correct size on block boundary*/
11636        	
11637        	        /* Check for over allocated files */
11638        	        if (matover)
11639        	        { 
11640        	          if ((a_size - r_size) < over_alloc) goto nexti;
11641        	        }
11642        	
11643        	        /* Check for 'placed' files */
11644        	        if (matplaced)
11645        	        { 
11646        	          j = hdr->mpoffset; /* Start of map area */
11647        	          if (hdr->map_inuse == 0) goto nexti; /* Skip empty files */
11648        	          disass_map_ptr(hdr,&j);
11649        	          if (lbncount != 0) goto nexti;
11650        	        }
11651        	
11652        	        /* Check file characteristics */
11653        	        if (matchars == TRUE )
11654        	        { 
11655        	          setchar = (hdr->filechar & chars);
11656        	          if (mator == FALSE) 
11657        	            if (setchar != chars) goto nexti;
11658        	            else
11659        	              if (setchar == 0) goto nexti; 
11660        	        }
11661        	
11662        	        /* Check files with backlink id */
11663        	        if (matbakfid == TRUE)
11664        	        { 
11665        	          fidnum = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx << 16;
11666        	          fidnum += hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num;
11667        	          if (fidnum != bakfid) goto nexti;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 15
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11668        	        }
11669        	
11670        	        /* Check multiheader files */
11671        	        if (matmult == TRUE) 
11672        	          if (hdr->ext_fid_overlay.ext_fid[0] == 0) goto nexti;
11673        	
11674        	        /* Check the UIC */
11675        	        if (matuic == TRUE)
11676        	          if (uic != hdr->fileowner_overlay.fileowner) goto nexti;
11677        	
11678        	        /* Check fragmentation */
11679        	        hdrs = 1; 
11680        	        rtvptr = 0;
11681        	        if (matfragment ==  TRUE) 
11682        	        { 
11683        	          get_map_pointers(hdr, &rtvptr);
11684        	          if (hdr->ext_fid_overlay.ext_fid[0] != 0) 
11685        	            status = follow_extents(hdr, &rtvptr, &hdrs);
11686        	          if (rtvptr < retr_min) goto nexti;
11687        	          if (retr_max !=0) if (rtvptr > retr_max) goto nexti;
11688        	        } 
11689        	
11690        	        /* Check the file name */
11691        	        if (matname || matexcl || matversion)
11692        	        { 
11693        	          memcpy(&name[0],id->filename,20);
11694        	          if (name[19] != ' ') memcpy(&name[20],id->filenamext,66);
11695        	          name_descr.dsc$w_length = strindex(name," ",86);
11696        	        }
11697        	        if (matname == TRUE)
11698        	        { 
11699        	          j=0; 
11700        	          found = FALSE; 
11701        	          while (!found)
11702        	          { 
11703        	            dummy_descr.dsc$a_pointer = (char *) &file[j].name;
11704        	            dummy_descr.dsc$w_length = file[j].flen;
11705        	            status = str$match_wild(&name_descr,&dummy_descr);
11706        	            if (status == STR$_MATCH) found = TRUE;
11707        	            j++;            
11708        	            if (j+1 > fcnt ) found = TRUE;
11709        	          }
11710        	          if (status != STR$_MATCH) goto nexti;
11711        	        }
11712        	        if (matexcl == TRUE)
11713        	        { 
11714        	          j=0; 
11715        	          found = FALSE; 
11716        	          while (!found)
11717        	          { 
11718        	            dummy_descr.dsc$a_pointer = (char *) &exclfile[j].name;
11719        	            dummy_descr.dsc$w_length = exclfile[j].flen;
11720        	            status = str$match_wild(&name_descr,&dummy_descr);
11721        	            if (status == STR$_MATCH) found = TRUE;
11722        	            j++;            
11723        	            if (j+1 > efcnt ) found = TRUE;
11724        	          }

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 16
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11725        	          if (status == STR$_MATCH) goto nexti;
11726        	        }
11727        	
11728        	        /* Version check */
11729        	        if (matversion == TRUE)
11730        	        { 
11731        	          name[name_descr.dsc$w_length]=0;
11732        	          j = atol ( &name[strindex(name,";",86)+1] );
11733        	          if ( j < vers_min) goto nexti;
11734        	          if ( vers_max != 0) if ( j > vers_max ) goto nexti;
11735        	        }
11736        	
11737        	        /* Check date/time options */
11738        	        if (matbefcreated == TRUE) 
11739        	        { 
11740        	          status = lib$subx(&cre_bef, &id->credate[0], &diff);
11741        	          if (diff.date[1] <= 0) goto nexti;
11742        	        }
11743        	        if (matsincreated == TRUE) 
11744        	        { 
11745        	          status = lib$subx(&cre_sin, &id->credate[0], &diff);
11746        	          if (diff.date[1] > 0 ) goto nexti;
11747        	        }
11748        	        if (matbefmodified == TRUE) 
11749        	        { 
11750        	          status = lib$subx(&mod_bef, &id->revdate[0], &diff);
11751        	          if (diff.date[1] <= 0) goto nexti;
11752        	        }
11753        	        if (matsinmodified == TRUE) 
11754        	        { 
11755        	          status = lib$subx(&mod_sin, &id->revdate[0], &diff);
11756        	          if (diff.date[1] > 0 ) goto nexti;
11757        	        }
11758        	        if (matbefbackup == TRUE) 
11759        	          /* Skip files without backup date */
11760        	        { 
11761        	          if (id->bakdate[0] == 0 && id->bakdate[1] == 0) goto nexti;
11762        	          status = lib$subx(&bak_bef, &id->bakdate[0], &diff);
11763        	          if (diff.date[1] <= 0) goto nexti;
11764        	        }
11765        	        if (matsinbackup == TRUE) 
11766        	        { 
11767        	          status = lib$subx(&bak_sin, &id->bakdate[0], &diff);
11768        	          if (diff.date[1] > 0 ) goto nexti;
11769        	        }
11770        	        if (matbefexpired == TRUE) 
11771        	          /* Skip files without expiration date */
11772        	        { 
11773        	          if (id->expdate[0] == 0 && id->expdate[1] == 0) goto nexti;
11774        	          status = lib$subx(&exp_bef, &id->expdate[0], &diff);
11775        	          if (diff.date[1] <= 0) goto nexti;
11776        	        }
11777        	        if (matsinexpired == TRUE) 
11778        	        { 
11779        	          status = lib$subx(&exp_sin, &id->expdate[0], &diff);
11780        	          if (diff.date[1] > 0 ) goto nexti;
11781        	        }

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 17
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11782        	        if (matnonebackup == TRUE )
11783        	          if (id->bakdate[0] > 0 || id->bakdate[1] > 0) goto nexti;
11784        	        if (matnoneexpired == TRUE )
11785        	          if (id->expdate[0] > 0 || id->expdate[1] > 0) goto nexti;
11786        	
11787        	        /* Check file sizes */
11788        	        if (mat_r_minsize) if (r_size < size_min) goto nexti;
11789        	        if (mat_r_maxsize) if (r_size > size_max) goto nexti;
11790        	        if (mat_a_minsize) if (a_size < size_min) goto nexti;
11791        	        if (mat_a_maxsize) if (a_size > size_max) goto nexti;
11792        	
11793        	        /* Post the results to user */
11794        	
11795        	        tot_r_size += r_size;
11796        	        tot_a_size += a_size;
11797        	        tothdr += hdrs;
11798        	        totfrag += rtvptr;
11799        	        fcount++;
11800        	        if (matsumm == TRUE) goto nexti;
11801        	        fid_to_name(&dir); /* Get the file name */
11802        	        dir_descr.dsc$w_length = strlen(dir);
11803        	        if (dispfull == FALSE )
11804        	        { 
11805        	          if (matfragment == FALSE)
11806        	          { 
11807        	            if (spacing > 80) faolen = 86 + spacing*((dir_descr.dsc$w_length + 46 - 1)/spacing);
11808        	            else faolen = 56 + spacing*((dir_descr.dsc$w_length + 24 - 1)/spacing);
11809        	            status = SYS$FAO(&ctrstr4, &outlen, &out_descr,
11810        	            faolen, &dir_descr, r_size, a_size);
11811        	          }
11812        	          else
11813        	          { 
11814        	            if (spacing > 80) faolen = 76 + spacing*((dir_descr.dsc$w_length + 56 - 1)/spacing);
11815        	            else faolen = 46 + spacing*((dir_descr.dsc$w_length + 34 - 1)/spacing);
11816        	            status = SYS$FAO(&ctrstr7, &outlen, &out_descr,
11817        	            faolen, &dir_descr, r_size, a_size, hdrs, rtvptr);
11818        	          }
11819        	          if (matsort == FALSE)  
11820        	          { 
11821        	            outbuf[outlen] = '\0';
11822        	            put_disp();
11823        	            outbuf[outlen] = ' ';
11824        	            if (matformat) 
11825        	            { 
11826        	              out_descr.dsc$w_length = 255; 
11827        	              status = SYS$FAO(&ctrstr8, &outlen, &out_descr, &dir_descr);
11828        	            }
11829        	            if (matoutput) fprintf(fp,"%.*s\n",outlen,outbuf); 
11830        	            out_descr.dsc$w_length = 255;
11831        	          }
11832        	          else
11833        	          { 
11834        	            out_descr.dsc$w_length = outlen; 
11835        	            sor$release_rec(&out_descr,0);
11836        	            out_descr.dsc$w_length = 255; 
11837        	          }
11838        	        }  

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 18
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11839        	        else
11840        	        { 
11841        	          x = strindex(&dirrec.dirnam,"]",198); 
11842        	          x++;
11843        	          sprintf(outbuf,"Filename: %s",&dirrec.dirnam[x]);
11844        	          put_disp(); 
11845        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
11846        	          fidnum = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx << 16;
11847        	          fidnum += hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num;
11848        	          sprintf(outbuf,"Directory: %.*s , Backlink ID (%d,%d,%d)",
11849        	          x,&dirrec.dirnam[0],fidnum,
11850        	          hdr->bk_fid_overlay.bk_fid_fields.bk_fid_seq,
11851        	          hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn);
11852        	          put_disp(); 
11853        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
11854        	          status = SYS$FAO(&ctrstr0, &id_descr.dsc$w_length , &id_descr, 
11855        	          hdr->fileowner_overlay.fileowner, hdr->fileowner_overlay.fileowner);
11856        	          fidnum = hdr->fid_overlay.fid_fields.fid_nmx << 16;
11857        	          fidnum += hdr->fid_overlay.fid[0];
11858        	          ivbn = rvt[curvol].vbn_file_1 + fidnum - 1;
11859        	          sprintf(outbuf,"VBN : %d , File ID (%d,%d,%d) , UIC : %.*s",
11860        	          ivbn, fidnum, hdr->fid_overlay.fid[1], 
11861        	          hdr->fid_overlay.fid_fields.fid_rvn,id_descr.dsc$w_length,ident);
11862        	          put_disp(); 
11863        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
11864        	          id_descr.dsc$w_length = 30;
11865        	          sprintf(outbuf,"Size : %d/%d,     Revision count : %d",
11866        	          r_size, a_size, id->revision);
11867        	          put_disp(); 
11868        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
11869        	          status = SYS$ASCTIM(&date_descr.dsc$w_length ,&date_descr,
11870        	          &id->credate,0);
11871        	          sprintf(outbuf, "Created : %.*s",date_descr.dsc$w_length, date_s);
11872        	          put_disp(); 
11873        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
11874        	          status = SYS$ASCTIM(&date_descr.dsc$w_length ,&date_descr,
11875        	          &id->revdate,0);
11876        	          sprintf(outbuf, "Revised : %.*s",date_descr.dsc$w_length, date_s);
11877        	          put_disp(); 
11878        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
11879        	          if (id->expdate[0] == 0 && id->expdate[1] == 0)
11880        	          { 
11881        	            strcpy(date_s,"<None specified>");
11882        	            sprintf(outbuf, "Expired : %s", date_s);
11883        	            put_disp(); 
11884        	            if (matoutput) fprintf(fp,"%s\n",outbuf);
11885        	          }
11886        	          else
11887        	          { 
11888        	            status = SYS$ASCTIM(&date_descr.dsc$w_length ,&date_descr,
11889        	            &id->expdate,0);
11890        	            sprintf(outbuf, "Expired : %.*s",date_descr.dsc$w_length, date_s);
11891        	            put_disp(); 
11892        	            if (matoutput) fprintf(fp,"%s\n",outbuf);
11893        	          }
11894        	          if (id->bakdate[0] == 0 && id->bakdate[1] == 0)
11895        	          { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 19
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11896        	            strcpy(date_s,"<No backup recorded>");
11897        	            sprintf(outbuf, "Backup  : %s\n", date_s);
11898        	            put_disp(); 
11899        	            if (matoutput) fprintf(fp,"%s\n",outbuf);
11900        	          }
11901        	          else
11902        	          { 
11903        	            status = SYS$ASCTIM(&date_descr.dsc$w_length ,&date_descr,
11904        	            &id->bakdate,0);
11905        	            sprintf(outbuf, "Backup  : %.*s\n",date_descr.dsc$w_length, date_s);
11906        	            put_disp(); 
11907        	            if (matoutput) fprintf(fp,"%s\n",outbuf);
11908        	          }
11909        	        }	    
11910        	
11911        	        /* Next header */
11912        	nexti: 
11913        	        status = get_next_header();
11914        	        if ((status & 1) != 1) return(status);
11915        	      }
11916        	    }
11917        	    if (ctrlc !=1) 
11918        	    { 
11919        	      sprintf(outbuf,"     Progress : 100%%     Status : READY");
11920        	      put_status(1);
11921        	      sprintf(outbuf,"\n%%DFU-I-EOF, End of file INDEXF.SYS, Primary headers : %d\n"
11922        	        ,val_headers);
11923        	      put_disp();
11924        	    }
11925        	    curvol++; 
11926        	    ctx.end = FALSE; /* Next volume unless ...*/
11927        	    if (matnovolset == TRUE) ctx.end = TRUE;
11928        	    if (clean_flags.events == 1) 
11929        	    { 
11930        	      for (i=1; i <= iocnt ; i++) status = lib$free_ef(&efn[i-1]);
11931        	      clean_flags.events = 0;
11932        	    }
11933        	  }
11934        	
11935        	  if (ctrlc == 1) 
11936        	  { 
11937        	    ctrlc = 0; 
11938        	    do_abort();
11939        	  }
11940        	  if (matsort == TRUE)
11941        	  { 
11942        	    sprintf(outbuf,"%%DFU-I-SORT, Sorting ... \n");
11943        	    put_disp();
11944        	    status = sor$sort_merge();
11945        	    if ((status & 1 ) != 1)
11946        	    { 
11947        	      sprintf(outbuf,"%%DFU-E-SORTERR, Error sorting output,\n");
11948        	      put_disp(); 
11949        	      singlemsg(0,status);
11950        	    }
11951        	    status = sor$return_rec(&out_descr, &outlen);
11952        	    while (status != SS$_ENDOFFILE)

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 20
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (4)

11953        	    { 
11954        	      outbuf[outlen] = '\0';
11955        	      put_disp();
11956        	      if (matoutput) fprintf(fp,"%.*s\n",outlen,outbuf); 
11957        	      status = sor$return_rec(&out_descr, &outlen);
11958        	    }
11959        	    sprintf(outbuf," \n"); 
11960        	    put_disp();
11961        	  }
11962        	  if (matfragment == FALSE) 
11963        	  { 
11964        	    sprintf(outbuf,"%%DFU-S-FND , Files found : %d, Size : %d/%d\n",
11965        	    fcount,tot_r_size,tot_a_size); 
11966        	    put_disp();
11967        	  }
11968        	  else
11969        	  { 
11970        	    sprintf(outbuf,"%%DFU-S-FND , Files found : %d, Size : %d/%d, Hdr/Frag : %d/%d\n",
11971        	    fcount,tot_r_size,tot_a_size, tothdr, totfrag);
11972        	    put_disp();
11973        	  }
11974        	  /* Now cleanup the stuff */
11975        	  cleanup();
11976        	  if (matstat == TRUE) status = lib$show_timer(0,0,display_stat,0);
11977        	  return(1);
11978        	}            
11979        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 21
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

             	
11980        	int report_command(int mask)
11981        	/*
11982        	    Create disk fragmentation report
11983        	    by scanning INDEXF.SYS, BITMAP.SYS and QUOTA.SYS
11984        	*/
11985        	
11986        	{
11987        	  static char dummy_item[80], fname[80], bfile[255], fmode[2];
11988        	  Boolean dummy, matoutput, matappend, matgraph, matusage, matstat, 
11989        	  matnobitmap, matnovol, matnoindex;
11990        	  struct header_area_struct *hdr;
11991        	  register int i;
11992        	  unsigned short badfid[3];
11993        	  float a, b, avefrag, scale;
11994        	  int ivbn, bitblk, bitje, bitval, find, rvn, x, 
11995        	  fcount, mcount, acount , ccount, dcount, ucount, badrtv, if_frag,
11996        	  bad_r_size, bad_a_size, mark_r_size, mark_a_size, mmp_hdr, mmp_blks,
11997        	  r_size, a_size, hdrs, rtvptr, free_hdr, totfrag, tothdr,
11998        	  tot_r_size, tot_a_size, map_in_use ,map_prc , k, size; 
11999        	  int freeext, largest, freeblocks , large_lbn;
12000        	  unsigned int uic, page_cnt, table[70];
12001        	  char line[70];
12002        	  struct { 
12003        	    int own_uic, flag, rsize, asize, hdr; 
12004        	  } 
12005        	  usage_table[750];
12006        	  void get_map_pointers(),
12007        	  add_usage(), report_usage();
12008        	  /* FAO parameters */
12009        	  unsigned short outlen; 
12010        	  $DESCRIPTOR(out_descr , outbuf);
12011        	  $DESCRIPTOR(badfile , bfile);
12012        	  $DESCRIPTOR(device_descr , device);
12013        	  $DESCRIPTOR(file_descr , fname);
12014        	  $DESCRIPTOR(dummy_descr , dummy_item);
12015        	
12016        	  /* Code starts here */
12017        	  /* Parse the various qualifiers */
12018        	
12019        	  progress_ind = TRUE;
12020        	  /* Get device name */
12021        	  status = parse_item("device", &device_descr, 0, &dummy , 0);
12022        	  if (status == 1) 
12023        	  { 
12024        	    if (strindex(&device,":",64) == -1) 
12025        	    {
12026        	      device[device_descr.dsc$w_length]=':'; 
12027        	      device_descr.dsc$w_length += 1;
12028        	    }
12029        	  }
12030        	  status = parse_item("graph", &dummy_descr, 0, &matgraph, 2);
12031        	  status = parse_item("nofile", &dummy_descr, 0, &matnoindex, 2);
12032        	  status = parse_item("novolume", &dummy_descr, 0, &matnovol, 2);
12033        	  status = parse_item("nobitmap", &dummy_descr, 0, &matnobitmap, 2);
12034        	  status = parse_item("statistics", &dummy_descr, 0, &matstat, 2);
12035        	  status = parse_item("usage", &dummy_descr, &uic, &matusage, 6);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 22
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12036        	  if (matusage == TRUE) for (i=0; i < 750; i++) usage_table[i].flag = 0;
12037        	  /* Get output file */
12038        	  clean_flags.fopen = 0;
12039        	  strcpy(fmode,"w");
12040        	  status = parse_item("outfile", &file_descr, 0, &matoutput , 0);
12041        	  if (!matoutput)
12042        	    status = parse_item("append", &file_descr, 0, &matappend , 0);
12043        	  if (matappend)
12044        	  { 
12045        	    matoutput = TRUE; 
12046        	    strcpy(fmode,"a");
12047        	  }  
12048        	  if (matoutput == FALSE) 
12049        	  {
12050        	    strcpy(fname,"SYS$OUTPUT:"); 
12051        	    file_descr.dsc$w_length = 11;
12052        	  }
12053        	  else
12054        	  {
12055        	    fname[file_descr.dsc$w_length] = '\0'; 
12056        	  }
12057        	  fp = fopen(fname,fmode,"mrs=255","rfm=var","ctx=rec","rat=cr","rop=WBH");	
12058        	  clean_flags.fopen = 1;
12059        	
12060        	  /* All qualifiers parsed */
12061        	  if (matstat == TRUE) status = lib$init_timer();
12062        	  clean_flags.sort = 0;
12063        	  clean_flags.channels = 0;
12064        	  clean_flags.events = 0;
12065        	  clean_flags.expreg = 0;
12066        	
12067        	  /* Open the volume (set) , read in the home block */
12068        	
12069        	  status = open_device(&device_descr,0);
12070        	  if ((status & 1) != 1) return(status); 
12071        	
12072        	  curvol = 1; 
12073        	  size = 1;
12074        	  ctx.end = FALSE;
12075        	  if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_OFF);
12076        	  while ((curvol <= maxvol) && (!ctx.end))
12077        	  { 
12078        	    ctx.i = -1; /* Clear context */
12079        	    if (rvt[curvol].i_open ==1) 
12080        	    { 
12081        	      if (maxvol == 1)
12082        	      {	
12083        	        sprintf(outbuf,"%%DFU-I-REPORT, Reporting on %.*s (%s)\n",
12084        	        device_descr.dsc$w_length, device, &rvt[curvol].fulldevnam[1]); 
12085        	      }
12086        	      else
12087        	      {	
12088        	        sprintf(outbuf,"%%DFU-I-REPORT, Reporting on %.*s (%s) , RVN = %d\n",
12089        	        rvt[curvol].devnam_len, rvt[curvol].devnam, 
12090        	        &rvt[curvol].fulldevnam[1], curvol); 
12091        	      }
12092        	      put_disp();

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 23
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12093        	      headers=0;
12094        	      /* Read in index file bitmap, and return free hdrs + highest bit set */
12095        	      read_indexf_bitmap(&free_hdr);
12096        	      fcount = 0; 
12097        	      mcount = 0; 
12098        	      acount = 0; 
12099        	      ccount = 0; 
12100        	      dcount = 0; 
12101        	      ucount = 0;
12102        	      bad_r_size = 0; 
12103        	      bad_a_size = 0; 
12104        	      mark_r_size = 0; 
12105        	      mark_a_size = 0;
12106        	      badrtv = 0; 
12107        	      mmp_hdr = 0; 
12108        	      mmp_blks = 0; 
12109        	      headers = 0; 
12110        	      tot_r_size = 0; 
12111        	      tot_a_size = 0; 
12112        	      tothdr = 0; 
12113        	      totfrag = 0;
12114        	
12115        	      /* Report home block info */
12116        	      if (!matnovol)
12117        	      { 
12118        	        sprintf(outbuf,"      ***** Volume info for %.*s (from HOME block) *****",
12119        	        rvt[curvol].devnam_len, rvt[curvol].devnam);
12120        	        put_disp(); 
12121        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12122        	        sprintf(outbuf," Volume name                      :  %.12s",
12123        	        home[curvol].volname);
12124        	        put_disp(); 
12125        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12126        	        sprintf(outbuf," Volume owner                     :  %.12s",
12127        	        home[curvol].ownername);
12128        	        put_disp(); 
12129        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12130        	        sprintf(outbuf," Structure name                   :  %.12s",
12131        	        home[curvol].strucname);
12132        	        put_disp(); 
12133        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12134        	        sprintf(outbuf," Cluster size                     :  %d",
12135        	        home[curvol].cluster);
12136        	        put_disp(); 
12137        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12138        	        sprintf(outbuf," Maximum # files                  :  %d",
12139        	        home[curvol].maxfiles);
12140        	        put_disp(); 
12141        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12142        	        sprintf(outbuf," Header count                     :  %d",
12143        	        rvt[curvol].if_size);
12144        	        put_disp(); 
12145        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12146        	        sprintf(outbuf," First header VBN                 :  %d",
12147        	        rvt[curvol].vbn_file_1);                   
12148        	        put_disp(); 
12149        	        if (matoutput) fprintf(fp,"%s\n",outbuf);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 24
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12150        	        sprintf(outbuf," Free headers                     :  %d\n",free_hdr);
12151        	        put_disp(); 
12152        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12153        	      }
12154        	
12155        	      status = get_next_header();
12156        	      if ((status & 1) != 1) return(status);
12157        	      while (! ctx.end) /* Loop until end of INDEXF or CTRL C entered */
12158        	      { 
12159        	        hdr = ctx.hdr;
12160        	        /* Check corresponding bitmap bit (must be set) */
12161        	        bitblk = (headers + 4095) / 4096 - 1;
12162        	        bitje = (headers - 1 - bitblk*4096) / 32;
12163        	        bitval = (headers - 1) % 32;
12164        	        status = lib$ffs(&bitval,&size,&bitmap[bitblk+1].block[bitje*4],
12165        	        &find);
12166        	        if (status == LIB$_NOTFOU) goto next_rep;
12167        	        rvn = curvol;
12168        	        if (hdr->seg_num !=0) goto next_rep; /* Skip extension header */
12169        	        status = verify_header(hdr);
12170        	        if (status != SS$_NORMAL) goto next_rep; /* Not a valid header */
12171        	        /* We have a valid header, proceed...*/
12172        	        fcount +=1;
12173        	        if (headers == 1) 
12174        	        { 
12175        	          map_in_use = hdr->map_inuse;
12176        	          map_prc = (100*map_in_use) / (hdr->acoffset - hdr->mpoffset);
12177        	        }
12178        	
12179        	        /* Get size fields (NOTE : they are stored in reverse order ! */
12180        	        a_size = hdr->hiblk_overlay.hiblk_fields.hiblkh << 16;
12181        	        a_size += hdr->hiblk_overlay.hiblk_fields.hiblkl;
12182        	        r_size = hdr->efblk_overlay.efblk_fields.efblkh << 16;
12183        	        r_size += hdr->efblk_overlay.efblk_fields.efblkl;
12184        	        if (r_size > 0) 
12185        	          if (hdr->ffbyte == 0) r_size--; /* Correct size on block boundary*/
12186        	        if (a_size > 0) acount++;
12187        	        tot_r_size += r_size;
12188        	        tot_a_size += a_size;
12189        	
12190        	        /* Increment counters */
12191        	        if ((hdr->filechar & FH2$M_MARKDEL) == FH2$M_MARKDEL) 
12192        	        { 
12193        	          mcount++;
12194        	          mark_r_size += r_size;
12195        	          mark_a_size += a_size;
12196        	        }
12197        	        if ((hdr->filechar & FH2$M_DIRECTORY) == FH2$M_DIRECTORY) dcount++;
12198        	
12199        	        /* Get fragmentation info */  
12200        	        hdrs = 1; 
12201        	        rtvptr = 0;
12202        	        get_map_pointers(hdr, &rtvptr);
12203        	        if (hdr->ext_fid_overlay.ext_fid[0] !=0)
12204        	        { 
12205        	          ucount++; 
12206        	          status = follow_extents(hdr, &rtvptr, &hdrs);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 25
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12207        	        }
12208        	        if (headers == 1) if_frag = rtvptr; /* Indexf.Sys fragments */
12209        	        if (rtvptr == 1) ccount++;
12210        	        else
12211        	        { 
12212        	          if (headers == 1) /* Special case for INDEXF.SYS */
12213        	            if (rtvptr == 4) ccount++;
12214        	            else
12215        	            { 
12216        	              mmp_hdr = mmp_hdr + rtvptr - 3;
12217        	              mmp_blks = mmp_blks + a_size - rvt[curvol].vbn_file_1;
12218        	            }
12219        	          else
12220        	            if (rtvptr > 3) 
12221        	            { 
12222        	              mmp_hdr = mmp_hdr + rtvptr - 3;
12223        	              mmp_blks += a_size;
12224        	            }
12225        	        }
12226        	        tothdr += hdrs;
12227        	        if (headers == 1) totfrag++;   
12228        	        else if (a_size != 0) totfrag += rtvptr;
12229        	        if (rtvptr > badrtv) 
12230        	        { 
12231        	          badfid[0] = hdr->fid_overlay.fid[0];
12232        	          badfid[1] = hdr->fid_overlay.fid[1];
12233        	          badfid[2] = curvol + (hdr->fid_overlay.fid_fields.fid_nmx << 16);
12234        	          badrtv = rtvptr;
12235        	          bad_r_size = r_size;
12236        	          bad_a_size = a_size;
12237        	        }
12238        	        /* Update usage table */
12239        	        if ((matusage == TRUE) && (headers > 3))
12240        	          add_usage(&usage_table, hdr->fileowner_overlay.fileowner, 
12241        	          r_size, a_size, hdrs);
12242        	        /* Next header */
12243        	next_rep: 
12244        	        status = get_next_header();
12245        	        if ((status & 1) != 1) return(status);
12246        	      }
12247        	    }
12248        	    if (ctrlc !=1) 
12249        	    { 
12250        	      sprintf(outbuf,"     Progress : 100%%     Status : READY");
12251        	      put_status(1);
12252        	    }
12253        	    if ((ctrlc !=1) && (!matnoindex))
12254        	    { 
12255        	      sprintf(outbuf,"      ***** File Statistics (from INDEXF.SYS) *****");
12256        	      put_disp(); 
12257        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12258        	      sprintf(outbuf,
12259        	      " INDEXF.SYS fragments/ map_in_use :  %d /%d words ( %d%% used)"
12260        	        ,if_frag, map_in_use, map_prc);
12261        	      put_disp(); 
12262        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12263        	      sprintf(outbuf," Total files                      :  %d", fcount);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 26
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12264        	      put_disp(); 
12265        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12266        	      scale = (fcount > 50) ? 1.0 : fcount/50;
12267        	      fcount -= acount;
12268        	      sprintf(outbuf," Empty files                      :  %d", fcount);
12269        	      put_disp(); 
12270        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12271        	      sprintf(outbuf," Files with allocation            :  %d", acount);
12272        	      put_disp(); 
12273        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12274        	      sprintf(outbuf," Files with extension headers     :  %d", ucount);
12275        	      put_disp(); 
12276        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12277        	      if (mcount == 0)
12278        	        sprintf(outbuf," Files marked for delete          :  %d", mcount);
12279        	      else
12280        	        sprintf(outbuf," Files marked for delete          :  %d, size %d/%d blocks", 
12281        	        mcount, mark_r_size, mark_a_size);
12282        	      put_disp(); 
12283        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12284        	      sprintf(outbuf," Directory files                  :  %d", dcount);
12285        	      put_disp(); 
12286        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12287        	      sprintf(outbuf," Contiguous files                 :  %d", ccount);
12288        	      put_disp(); 
12289        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12290        	      sprintf(outbuf," Total used/ allocated size       :  %d /%d", 
12291        	      tot_r_size, tot_a_size);
12292        	      put_disp(); 
12293        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12294        	      sprintf(outbuf," Total fragments                  :  %d", totfrag);
12295        	      a = totfrag; 
12296        	      b = acount;
12297        	      avefrag = a/b;
12298        	      sprintf(outbuf," Average fragments per file       :  %.3f", avefrag);
12299        	      put_disp(); 
12300        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12301        	      a = mmp_hdr; 
12302        	      b = mmp_blks / home[curvol].cluster;
12303        	      avefrag = (avefrag*avefrag) - 1;
12304        	      if (b > 0) avefrag += (a/b*10);
12305        	      strcpy(dummy_item," (poor) ");      
12306        	      if (avefrag < 3.0) strcpy(dummy_item," (fair) ");      
12307        	      if (avefrag < 2.0) strcpy(dummy_item," (good) ");      
12308        	      if (avefrag < 1.0) strcpy(dummy_item," (excellent) ");
12309        	      sprintf(outbuf," File fragmentation index         :  %.3f %s",
12310        	      avefrag,dummy_item);
12311        	      put_disp(); 
12312        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12313        	      tot_a_size = tot_a_size / totfrag;
12314        	      sprintf(outbuf," Average size per fragment        :  %d", tot_a_size);
12315        	      put_disp(); 
12316        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12317        	      sprintf(outbuf," Most fragmented file             : ");
12318        	      put_disp(); 
12319        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12320        	      status = lib$fid_to_name(&device_descr, &badfid[0],&badfile,

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 27
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12321        	      &outlen, 0, 0);
12322        	      x = strindex(bfile,"[",255);
12323        	      outlen -=x;
12324        	      sprintf(outbuf,"    %s%.*s ( %d/%d blocks; %d fragments)\n", 
12325        	      &rvt[curvol].fulldevnam[1],
12326        	      outlen, &bfile[x], bad_r_size, bad_a_size, badrtv);
12327        	      put_disp(); 
12328        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
12329        	    }
12330        	    if (ctrlc !=1)
12331        	      /* Now continue with bitmap processing */
12332        	    { 
12333        	      sprintf(outbuf,"     Progress :   0%%     Status : Processing BITMAP.SYS");
12334        	      put_status(1);
12335        	      strcpy(device, rvt[curvol].devnam);
12336        	      device_descr.dsc$w_length = rvt[curvol].devnam_len;
12337        	      rvt[curvol].bchan = 0;
12338        	      status = SYS$ASSIGN(&device_descr, &rvt[curvol].bchan, 0, 0);
12339        	      if ((status & 1) != 1) 
12340        	      { 
12341        	        singlemsg(DFU_ASSIGN,status); 
12342        	        cleanup(); 
12343        	        return(status);
12344        	      }      
12345        	      page_cnt = (rvt[curvol].maxblocks / home[curvol].cluster) ;
12346        	      for (i=1; i<= 70; i++) table[i-1]=100;
12347        	      status = scan_bitmap(rvt[curvol].bchan, page_cnt, rvt[curvol].wlk, &freeext,
12348        	      &largest, &freeblocks, &large_lbn, &table);
12349        	      if (status == 1)
12350        	      { 
12351        	        sprintf(outbuf,"     Progress : 100%%     Status : READY");
12352        	        put_status(1);
12353        	        if (!matnobitmap)
12354        	        {
12355        	          largest = largest * home[curvol].cluster; /* Adjust for cluster size */
12356        	          freeblocks = freeblocks * home[curvol].cluster;
12357        	          large_lbn = large_lbn * home[curvol].cluster;
12358        	          sprintf(outbuf,"      ***** Free space statistics (from BITMAP.SYS) *****");
12359        	          put_disp(); 
12360        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12361        	          sprintf(outbuf," Total blocks on disk             :  %d",
12362        	          rvt[curvol].maxblocks);
12363        	          put_disp(); 
12364        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12365        	          sprintf(outbuf," Total free blocks                :  %d",freeblocks);
12366        	          put_disp(); 
12367        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12368        	          tot_a_size = (100*freeblocks) / rvt[curvol].maxblocks;
12369        	          sprintf(outbuf," Percentage free (rounded)        :  %d",tot_a_size);
12370        	          put_disp(); 
12371        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12372        	          sprintf(outbuf," Total free extents               :  %d",freeext);
12373        	          put_disp(); 
12374        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12375        	          sprintf(outbuf,
12376        	          " Largest free extent              :  %d  blocks at LBN: %d",
12377        	          largest, large_lbn);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 28
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12378        	          put_disp(); 
12379        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12380        	          tot_a_size = (freeext == 0) ? 0 : freeblocks / freeext;
12381        	          sprintf(outbuf," Average extent size (rounded)    :  %d",tot_a_size);
12382        	          put_disp(); 
12383        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12384        	          a = freeext - 1;
12385        	          b = (freeblocks/home[curvol].cluster - 1);
12386        	          avefrag = (a > 0) ? a/b*100 : 0;
12387        	          strcpy(dummy_item," (poor) ");      
12388        	          if (avefrag < 3.0) strcpy(dummy_item," (fair) ");      
12389        	          if (avefrag < 2.0) strcpy(dummy_item," (good) ");      
12390        	          if (avefrag < 1.0) strcpy(dummy_item," (excellent) ");
12391        	          sprintf(outbuf," Free space fragmentation index   :  %.3f %s",
12392        	          avefrag,dummy_item);
12393        	          put_disp(); 
12394        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12395        	        }
12396        	        if (matgraph == TRUE)
12397        	        {
12398        	          /* Now print the graph table */
12399        	          tot_a_size = 105;
12400        	          sprintf(outbuf,
12401        	          "\n %%free----------------------------------------------------------------------");
12402        	          put_disp(); 
12403        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12404        	          for (k=1; k <=20; k++) 
12405        	          { 
12406        	            tot_a_size -= 5;
12407        	            for (i=1; i<=70; i++)
12408        	              if (table[i-1] >= tot_a_size) 
12409        	                line[i-1] = '*';
12410        	              else
12411        	                line[i-1] = ' ';
12412        	            sprintf(outbuf," %3d |%.*s|",tot_a_size,70,line);
12413        	            put_disp(); 
12414        	            if (matoutput) fprintf(fp,"%s\n",outbuf);
12415        	          }
12416        	          sprintf(outbuf,
12417        	          "      ----------------------------------------------------------------------");
12418        	          put_disp(); 
12419        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12420        	          sprintf(outbuf, 
12421        	          " LBN: 0                                                               %d",
12422        	          rvt[curvol].maxblocks);
12423        	          put_disp(); 
12424        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
12425        	          tot_a_size = rvt[curvol].maxblocks/1400;
12426        	          sprintf(outbuf," Free space distribution; each * = %d free blocks",
12427        	          tot_a_size);
12428        	          put_disp(); 
12429        	          if (matoutput) fprintf(fp,"%s",outbuf);
12430        	        }
12431        	      }
12432        	      else 
12433        	      { 
12434        	        cleanup();

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 29
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (5)

12435        	        return(status);
12436        	      }
12437        	      curvol++; 
12438        	      if (ctrlc !=1) ctx.end = FALSE; /* Next volume */
12439        	      if (curvol <= maxvol) 
12440        	      { 
12441        	        sprintf(outbuf," "); 
12442        	        put_disp();
12443        	      }
12444        	      if (clean_flags.events == 1) 
12445        	      { 
12446        	        for (i=1; i <= iocnt ; i++) status = lib$free_ef(&efn[i-1]);
12447        	        clean_flags.events = 0;
12448        	      }
12449        	    } 
12450        	  }
12451        	  curvol = 1;
12452        	  /* Now continue with usage table processing */
12453        	  if ((matusage == TRUE) && (ctrlc != 1))
12454        	  { 
12455        	    sprintf(outbuf,"     Progress :   0%%     Status : Processing QUOTA.SYS");
12456        	    put_status(1);
12457        	    report_usage(&usage_table, rvt[curvol].bchan, fp,matoutput,uic); 
12458        	    sprintf(outbuf,"     Progress : 100%%     Status : READY");
12459        	    put_status(1);
12460        	  }
12461        	  if (ctrlc == 1) do_abort();
12462        	  cleanup();  
12463        	  sprintf(outbuf,"\n%%DFU-I-READY, REPORT command ready");
12464        	  put_disp();
12465        	  if (matstat == TRUE) status = lib$show_timer(0,0,display_stat,0);
12466        	  return(1);
12467        	}
12468        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 30
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

             	
12469        	int undel_command(int mask)
12470        	/*
12471        		Undelete a file on a disk
12472        		After write locking the disk
12473        		the INDEXF.SYS and BITMAP files are updated
12474        		unless the blocks or file headers have been reused.
12475        		Undeleted files are entered in the original directory
12476        		May also be used to produce a listing of recoverable files
12477        	
12478        		V2.4: Added support to undelete files marked-for-delete
12479        	*/
12480        	
12481        	{
12482        	  static char dummy_item[80], fname[86], name[86],ans[4],ident[30], *tmp;
12483        	  struct header_area_struct *hdr, *oldhdr;
12484        	  struct ident_area_struct *id;
12485        	  struct _hd { 
12486        	    unsigned short block[256] ; 
12487        	  } 
12488        	  *head;
12489        	  struct { 
12490        	    int pagecnt; 
12491        	  } 
12492        	  bmap[33];
12493        	  static struct fibdef fib;	/* File information block */
12494        	  struct { 
12495        	    int fiblen; 
12496        	    struct fibdef *fibadr; 
12497        	  } 
12498        	  fibdescr;
12499        	  struct f_id lost_fid;
12500        	  Boolean dummy, matstat, matname, matlist, matuic, matnoconfirm, 
12501        	  matoutput, matunmark, found, lostfile;
12502        	  register int i;
12503        	  unsigned short qchan;
12504        	  int ivbn, bitblk, bitje, bitval, find, rvn, x, j,
12505        	  uic, s_uic, a_size, hdrs, rtvptr, free_hdr, k, size,
12506        	  bytes, fidnum, modifiers, fcount, syslost; 
12507        	  void dfu_handler(), add_quota();
12508        	  $DESCRIPTOR(device_descr , device);
12509        	  $DESCRIPTOR(file_descr , fname);
12510        	  $DESCRIPTOR(dummy_descr , dummy_item);
12511        	  $DESCRIPTOR(id_descr , ident);
12512        	  $DESCRIPTOR(name_descr , name);
12513        	  $DESCRIPTOR(answer , ans);
12514        	  $DESCRIPTOR(prompt,"Recover this file ? (Y/N) [N] : ");
12515        	
12516        	  /* Code starts here */
12517        	  /* Check the privileges */
12518        	  if (mask > -1) 
12519        	  { 
12520        	    singlemsg(0,DFU_NOPRIV);
12521        	    return(SS$_NOPRIV);
12522        	  }
12523        	  /* Fill in FIB */
12524        	  fibdescr.fiblen = sizeof(fib);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 31
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12525        	  fibdescr.fibadr = &fib;
12526        	  syslost = 0;
12527        	  progress_ind = TRUE;
12528        	
12529        	  /* Parse the various qualifiers */
12530        	  /* Get device name */
12531        	  status = parse_item("device", &device_descr, 0, &dummy , 0);
12532        	  if (status == 1) 
12533        	  { 
12534        	    if (strindex(&device,":",64) == -1) 
12535        	    {
12536        	      device[device_descr.dsc$w_length]=':'; 
12537        	      device_descr.dsc$w_length += 1;
12538        	    }
12539        	  }
12540        	  status = parse_item("statistics", &dummy_descr, 0, &matstat, 2);
12541        	  status = parse_item("noconfirm", &dummy_descr, 0, &matnoconfirm, 2);
12542        	  status = parse_item("unmark", &dummy_descr, 0 , &matunmark, 2);
12543        	  /* Get output file */
12544        	  clean_flags.fopen = 0;
12545        	  matoutput = FALSE;
12546        	  status = parse_item("list", &file_descr, 0, &matlist , 0);
12547        	  if (matlist)
12548        	  { 
12549        	    fname[file_descr.dsc$w_length] = '\0'; 
12550        	    status = strncmp(fname,"SYS$OUTPUT",10);
12551        	    if (status != 0) matoutput = TRUE;
12552        	  }
12553        	  if (matoutput)
12554        	  { 
12555        	    fp = fopen(fname,"w","mrs=255","rfm=var","ctx=rec","rat=cr","rop=WBH");	
12556        	    clean_flags.fopen = 1;
12557        	  }
12558        	
12559        	  /* Ident or UIC */
12560        	  status = parse_item("ident", &dummy_descr, &uic, &matuic, 6);
12561        	  if (matuic == FALSE) 
12562        	    status = parse_item("uic", &dummy_descr, &uic, &matuic, 6);
12563        	  if ((status &1 ) != 1)
12564        	  { 
12565        	    sprintf(outbuf,"%%DFU-E-INVID, Wrong uic or identifier,");
12566        	    put_disp(); 
12567        	    singlemsg(0,status); 
12568        	    return(status); 
12569        	  }
12570        	  id_descr.dsc$w_length = 30;
12571        	
12572        	  /* Check file name */
12573        	  dummy_descr.dsc$a_pointer = (char *) &x;
12574        	  status = parse_item("file", &dummy_descr, &fname, &matname , 3);
12575        	  if (matname == FALSE) strcpy(fname,"*.*;*"); 
12576        	  if (strindex(&fname,"\0",80) == -1) 
12577        	  { 
12578        	    x = strindex(&fname," ",80); 
12579        	    fname[x] = '\0';
12580        	  }
12581        	  dummy_descr.dsc$a_pointer = (char *) &fname;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 32
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12582        	  dummy_descr.dsc$w_length = strindex(&fname,"\0",86);
12583        	
12584        	  /* All qualifiers parsed */
12585        	  first = NULL; 
12586        	  list = NULL;
12587        	  clean_flags.channels = 0;
12588        	  clean_flags.events = 0;
12589        	  clean_flags.expreg = 0;
12590        	  modifiers = SMG$M_NOKEEP | SMG$M_NORECALL;
12591        	  if (matstat == TRUE) status = lib$init_timer();
12592        	
12593        	  /* Open the volume (set) , read in the home block */
12594        	
12595        	  if (matlist) status = open_device(&device_descr,0);
12596        	  else status = open_device(&device_descr,1);
12597        	  if ((status & 1) != 1) return(status);
12598        	  if (rvt[1].wlk == TRUE) /* Write locked device */
12599        	  { 
12600        	    sprintf(outbuf,"%%DFU-E-WRITELK, Cannot undelete on write-locked device");
12601        	    put_disp(); 
12602        	    cleanup(); 
12603        	    return(1);
12604        	  }
12605        	  if (home[1].volchar_overlay.volchar_bits.erase == 1) /*Erase on delete */
12606        	  { 
12607        	    sprintf(outbuf,
12608        	    "%%DFU-E-ERASED, Cannot undelete ; erase-on-delete set on device");
12609        	    put_disp(); 
12610        	    cleanup(); 
12611        	    return(1);
12612        	  }
12613        	
12614        	  /* Setup exit handler to ensure that we unlock the volume */
12615        	  if (!matlist)
12616        	  { 
12617        	    desblk.handler_addr = (int) &dfu_handler;
12618        	    desblk.condition = (int) &status;
12619        	    desblk.arg_count = 1;
12620        	    status = SYS$DCLEXH(&desblk);
12621        	    if ((status & 1) !=1) 
12622        	    { 
12623        	      singlemsg(DFU_EXHFAIL,status); 
12624        	      cleanup(); 
12625        	      return(status);
12626        	    }
12627        	  }
12628        	
12629        	  fcount = 0;
12630        	  curvol = 1; 
12631        	  size = 1;
12632        	  ctx.end = FALSE;
12633        	
12634        	  /* Read in the BITMAP.SYS we need it anyway... */
12635        	  sprintf(outbuf,"%%DFU-I-READBMAP, Reading BITMAP.SYS...");
12636        	  put_disp();
12637        	  for (x=1; x <=maxvol; x++) 
12638        	    /* Assign a channel for BITMAP, create dynamic space, and read in the BITMAP*/

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 33
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12639        	  { 
12640        	    strcpy(device, rvt[x].devnam);
12641        	    device_descr.dsc$w_length = rvt[x].devnam_len;
12642        	    status = SYS$ASSIGN(&device_descr, &rvt[x].bchan, 0, 0);
12643        	    if ((status & 1) != 1) 
12644        	    { 
12645        	      singlemsg(DFU_ASSIGN,status); 
12646        	      cleanup(); 
12647        	      return(status);
12648        	    }
12649        	    clean_flags.expreg = 1;
12650        	    rvt[x].bmap_addr[0] = 0; 
12651        	    bmap[x].pagecnt = rvt[x].maxblocks/home[x].cluster;
12652        	    bmap[x].pagecnt = (bmap[x].pagecnt + 4095) / 4096;
12653        	    status = SYS$EXPREG(bmap[x].pagecnt, &rvt[x].bmap_addr[0],
12654        	    0 , 0);
12655        	    if ((status & 1) != 1) 
12656        	    { 
12657        	      singlemsg(DFU_EXPREG,status); 
12658        	      cleanup(); 
12659        	      return(status);
12660        	    }
12661        	    status = read_bitmap(rvt[x].bchan, bmap[x].pagecnt, 
12662        	    rvt[x].wlk, &rvt[x].bmap_addr[0]);
12663        	    if ((status & 1) != 1) 
12664        	    { 
12665        	      sprintf(outbuf,"%%DFU-E-NOTUNDEL, File undeletes not possible,");
12666        	      put_disp(); 
12667        	      cleanup(); 
12668        	      return(status); 
12669        	    }
12670        	  }
12671        	
12672        	  /* Loop for all volumes in the set */
12673        	  if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_OFF);
12674        	  while ((curvol <= maxvol) && (!ctx.end))
12675        	  { 
12676        	    ctx.i = -1;
12677        	    if (rvt[curvol].i_open ==1) 
12678        	    { 
12679        	      if (maxvol == 1)
12680        	      {	
12681        	        sprintf(outbuf,"%%DFU-I-UNDEL, Start search on %.*s (%s)",
12682        	        device_descr.dsc$w_length, device, &rvt[curvol].fulldevnam[1]); 
12683        	        put_disp();
12684        	      }
12685        	      else
12686        	      {	
12687        	        sprintf(outbuf,"%%DFU-I-UNDEL, Start search on %.*s (%s) , RVN = %d",
12688        	        rvt[curvol].devnam_len, rvt[curvol].devnam, 
12689        	        &rvt[curvol].fulldevnam[1], curvol); 
12690        	        put_disp();
12691        	      }
12692        	      headers=0; 
12693        	      qchan = 0;
12694        	
12695        	      /* Read in index file bitmap, and return free hdrs + highest bit set */

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 34
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12696        	      read_indexf_bitmap(&free_hdr);
12697        	
12698        	      status = get_next_header();
12699        	      if ((status & 1) != 1) return(status);
12700        	      while (! ctx.end) /* Loop until end of INDEXF or CTRL C entered */
12701        	      { 
12702        	        hdr = ctx.hdr;
12703        	        id = ctx.id;
12704        	        rvn = curvol;
12705        	        if (hdr->seg_num !=0) goto next_und; /* Skip extension header */
12706        	
12707        	        /* Check for a valid deleted file header */
12708        	        if ((hdr->filechar & FH2$M_MARKDEL) != FH2$M_MARKDEL) 
12709        	          goto next_und;
12710        	        /* Skip next test if we only unamrk files */
12711        	        if (!matunmark)
12712        	        { 
12713        	          if ((header[ctx.i].block[510] != 0) || (header[ctx.i].block[511] != 0))
12714        	            goto next_und; /* Checksum must be zero */
12715        	          if (hdr->fid_overlay.fid_fields.fid_num != 0) goto next_und;
12716        	          if ((hdr->filechar & FH2$M_ERASE) == FH2$M_ERASE) /*Skip erased file*/
12717        	            goto next_und;
12718        	        }
12719        	        else
12720        	        { 
12721        	          status = verify_header(hdr);
12722        	          if (status != SS$_NORMAL) goto next_und;
12723        	        }
12724        	
12725        	        if (matuic == TRUE)
12726        	          if (uic != hdr->fileowner_overlay.fileowner) goto next_und;
12727        	        /* get the file name and check if we requested this name */
12728        	        memcpy(&name[0],id->filename,20);
12729        	        if (name[19] != ' ') memcpy(&name[20],id->filenamext,66);
12730        	        if (strlen(name) == 0) goto next_und; /* Unused file header */
12731        	        name_descr.dsc$w_length = strindex(name," ",86);
12732        	        name[name_descr.dsc$w_length] = '\0';
12733        	        status = str$match_wild(&name_descr,&dummy_descr);
12734        	        if (status != STR$_MATCH) goto next_und;
12735        	        if (!matunmark)
12736        	        { 
12737        	          found = TRUE; 
12738        	          oldhdr = hdr;
12739        	          /* Check the BITMAP for multiple allocated blocks, if we
12740        	              find some we just skip this file */
12741        	          /* Reset fid_num and fid_nmx field */
12742        	          hdr->fid_overlay.fid_fields.fid_num = (headers % 65536);
12743        	          hdr->fid_overlay.fid_fields.fid_nmx = headers / 65536;
12744        	          while (found)
12745        	          { 
12746        	            status = rebuild_bitmap(hdr, rvt[rvn].bmap_addr[0],
12747        	            home[rvn].cluster, curvol, TRUE);
12748        	            if ((status & 1) != 1) found = FALSE;
12749        	            if (hdr->ext_fid_overlay.ext_fid[0] ==0) found = FALSE;
12750        	            /* Read in extension header */
12751        	            if (found)
12752        	            { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 35
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12753        	              x = 0; 
12754        	              rvn = hdr->ext_fid_overlay.ext_fid_fields.ext_fid_rvn;
12755        	              if (rvn == 0) rvn = curvol;
12756        	              fidnum = hdr->ext_fid_overlay.ext_fid_fields.ext_fid_nmx << 16;
12757        	              fidnum += hdr->ext_fid_overlay.ext_fid[0];
12758        	              ivbn = rvt[rvn].vbn_file_1 + fidnum - 1; 
12759        	              hdr = (struct header_area_struct *) &header[x];   
12760        	              status = SYS$QIOW(0,rvt[rvn].channel,IO$_READVBLK,
12761        	              &iostat[iocnt],0,0,&header[0],512,ivbn,0,0,0);
12762        	              if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
12763        	              if ((status & 1) != 1) found = FALSE;
12764        	              /* Check if this header is valid */
12765        	              if (found)
12766        	              { 
12767        	                if ((hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num != 
12768        	                  oldhdr->fid_overlay.fid_fields.fid_num) ||
12769        	                  (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_seq != 
12770        	                  oldhdr->fid_overlay.fid_fields.fid_seq) ||
12771        	                  (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx != 
12772        	                  oldhdr->fid_overlay.fid_fields.fid_nmx))
12773        	                { 
12774        	                  found = FALSE; 
12775        	                  status = 0;
12776        	                }
12777        	              }
12778        	            }
12779        	          }
12780        	          if ((status & 1) != 1) goto next_und;
12781        	          hdr = oldhdr;
12782        	          rvn = curvol;
12783        	        }
12784        	
12785        		lostfile = FALSE;
12786        	        /* get the full directory name */
12787        	        if (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num == 0 )
12788        	        { strcpy(dirrec.dirnam,"[]");
12789        	          lostfile = TRUE;
12790        	        }
12791        	        else
12792        	        { 
12793        	          copy_fid(&fib.fib$w_fid[0], 
12794        	          &hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num, TRUE);
12795        	          fib.fib$w_did[0] = 0;
12796        	          fib.fib$w_did[1] = 0;
12797        	          fib.fib$w_did[2] = 0;
12798        	          fib.fib$w_nmctl = 0;
12799        	          fib.fib$l_acctl = 0;
12800        	          status = SYS$QIOW(0,rvt[rvn].channel,IO$_ACCESS,
12801        	          &iostat[iocnt],0,0,&fibdescr,0,0,0,&acb,0);
12802        	          status = iostat[iocnt].iosb_1;
12803        	          if ((status & 1) != 1) 
12804        	          { strcpy(dirrec.dirnam,"[]");
12805        	            lostfile = TRUE;
12806        	          }
12807        	          else
12808        	            /* Now rearrange the directory name found */
12809        	          { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 36
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12810        	            x = strindex(&dirrec.dirnam,"[",198); 
12811        	            strncpy(dirrec.dirnam,&dirrec.dirnam[x],(198-x));
12812        	            tmp = (char *) strstr(dirrec.dirnam,".DIR;"); 
12813        	            if (tmp != NULL) 
12814        	            { 
12815        	              *tmp = ']';
12816        	              tmp = (char *) strstr(dirrec.dirnam,"]"); 
12817        	              *tmp = '.';
12818        	            }
12819        	            else strcpy(dirrec.dirnam,"[]");
12820        	            if (strstr(dirrec.dirnam,"[000000") != 0)
12821        	            { 
12822        	              dirrec.dirnam[7] = '[';
12823        	              strcpy(dirrec.dirnam,&dirrec.dirnam[7]);
12824        	            }
12825        	          }
12826        	          x = strindex(&dirrec.dirnam,"]",198); 
12827        	          dirrec.dirnam[x+1] = '\0';
12828        	        }  
12829        	        fcount++;         
12830        	        sprintf(outbuf,"Recoverable file %s%s found ", dirrec.dirnam, name);
12831        	        put_disp(); 
12832        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
12833        	        x = 4; 
12834        	        ans[0] = 'n';
12835        	        if (!matlist)
12836        	          if(!matnoconfirm)
12837        	          { 
12838        	            if (smg$enable)
12839        	            { 
12840        	              SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_ON);
12841        	              status = SMG$READ_COMPOSED_LINE(&keyb_id, 0, &answer,
12842        	              &prompt, &k, &disp1_id, &modifiers, 0,0,0,0,0);
12843        	              SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_OFF);
12844        	            }
12845        	            else
12846        	              status = SMG$READ_COMPOSED_LINE(&keyb_id, 0, &answer,
12847        	              &prompt, &k, 0, &modifiers, 0,0,0,0,0);
12848        	          }
12849        	          else
12850        	            strcpy(ans,"Y");
12851        	        if ((ans[0] == 'y') || (ans[0] == 'Y')) 
12852        	        {  
12853        	          /* Actual recovery starts here as follows (loop for all extension headers) :
12854        	          	- If unmark requested just clear the MARKDEL bit else :
12855        	                    - Reenter retrieval pointers in BITMAP
12856        	                      - If oke then 
12857        	          	      - Rewrite all BITMAP.SYS
12858        	          	      - Rewrite all Headers
12859        	          	      - Rewrite index file bitmap bit. At this point recovery is oke
12860        	          	      - Update QUOTA.SYS
12861        	          	      - Setup entry for enter file routine
12862        	          	- After all undeletes are done ...
12863        	          	    - Unlock volume
12864        	          	    - Reenter files in directory
12865        	          
12866        	          Save size and uic for possible quota processing */

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 37
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12867        	
12868        	          if (matunmark) goto rewrite_hdr;
12869        	          a_size = hdr->hiblk_overlay.hiblk_fields.hiblkh << 16;
12870        	          a_size += hdr->hiblk_overlay.hiblk_fields.hiblkl;
12871        	          s_uic = hdr->fileowner_overlay.fileowner;
12872        	          found = TRUE; 
12873        	          hdrs = 0; 
12874        	          x = i;
12875        	          oldhdr = hdr;
12876        	          /* Loop for all headers... */
12877        	          while (found)
12878        	          { 
12879        	            hdrs +=1; 
12880        	            /* Now rebuild the mapping pointers into the bitmap.
12881        	               If any multiple allocated blocks are discovered we break
12882        	               off the whole undelete process */
12883        	            status = rebuild_bitmap(hdr, rvt[rvn].bmap_addr[0],
12884        	            home[rvn].cluster, curvol, FALSE);
12885        	            if ((status & 1) != 1) 
12886        	            { 
12887        	              sprintf(outbuf,"%%DFU-E-NOTUNDEL, File cannot be undeleted");
12888        	              put_disp();
12889        	              ctx.end = TRUE; 
12890        	              curvol = maxvol; 
12891        	              goto next_und;
12892        	            }
12893        	            if (hdr->ext_fid_overlay.ext_fid[0] == 0) found = FALSE;
12894        	            else
12895        	              /* Read in extension header */
12896        	            { 
12897        	              x = 0; 
12898        	              rvn = hdr->ext_fid_overlay.ext_fid_fields.ext_fid_rvn;
12899        	              if (rvn == 0) rvn = curvol;
12900        	              fidnum = hdr->ext_fid_overlay.ext_fid_fields.ext_fid_nmx << 16;
12901        	              fidnum += hdr->ext_fid_overlay.ext_fid[0];
12902        	              ivbn = rvt[rvn].vbn_file_1 + fidnum - 1; 
12903        	              hdr = (struct header_area_struct *) &header[x];   
12904        	              status = SYS$QIOW(0,rvt[rvn].channel,IO$_READVBLK,
12905        	              &iostat[iocnt],0,0,&header[0],512,ivbn,0,0,0);
12906        	              if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
12907        	              if ((status & 1) != 1) 
12908        	              { 
12909        	                sprintf(outbuf,
12910        	                "%%DFU-E-READERR, Error reading extension header,");
12911        	                put_disp(); 
12912        	                singlemsg(0,status); 
12913        	                sprintf(outbuf,"%%DFU-E-NOTUNDEL, File cannot be undeleted");
12914        	                put_disp();
12915        	                ctx.end = TRUE; 
12916        	                curvol = maxvol; 
12917        	                goto next_und;
12918        	              }                       
12919        	              /* Check if this header is valid */
12920        	              if ((hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num != 
12921        	                oldhdr->fid_overlay.fid_fields.fid_num) ||
12922        	                (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_seq != 
12923        	                oldhdr->fid_overlay.fid_fields.fid_seq) ||

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 38
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12924        	                (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx != 
12925        	                oldhdr->fid_overlay.fid_fields.fid_nmx))
12926        	              { 
12927        	                sprintf(outbuf,
12928        	                "%%DFU-E-BADEXTHDR, Extension header linkage broken");
12929        	                put_disp();
12930        	                sprintf(outbuf,"%%DFU-E-NOTUNDEL, File cannot be undeleted");
12931        	                put_disp();
12932        	                ctx.end = TRUE; 
12933        	                curvol = maxvol; 
12934        	                goto next_und;
12935        	              }
12936        	            } 
12937        	          } /* end while */
12938        	          /* So we have rebuild the bitmap(s), now rewrite them */
12939        	          for (j = 1; j <= maxvol; j++) 
12940        	          { 
12941        	            if (rvt[j].bchan != 0)
12942        	            { 
12943        	              bytes = 512 * bmap[j].pagecnt;
12944        	              status = SYS$QIOW(0,rvt[j].bchan, IO$_WRITEVBLK, &iostat[iocnt],
12945        	              0,0, rvt[j].bmap_addr[0], bytes, 2,0,0,0);
12946        	              if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
12947        	              if ((status & 1) != 1) 
12948        	              { 
12949        	                sprintf(outbuf,"%%DFU-E-BITMAPERR, Error writing BITMAP.SYS,");
12950        	                put_disp(); 
12951        	                singlemsg(0,status); 
12952        	                sprintf(outbuf,
12953        	                "- Use ANALYZE/DISK/REPAIR to repair the volume");
12954        	                put_disp();
12955        	                ctx.end = TRUE; 
12956        	                curvol = maxvol; 
12957        	                goto next_und;
12958        	              }                       
12959        	            }
12960        	          }
12961        	          /* Now rewrite all the file headers */
12962        	rewrite_hdr:
12963        	          /* Setup the RVN, FileChar and Checksum fields */
12964        	          x = ctx.i; 
12965        	          rvn = curvol; 
12966        	          found = TRUE; 
12967        	          bytes = 512;
12968        	          hdr = (struct header_area_struct *) &header[x];
12969        	          fidnum = hdr->fid_overlay.fid_fields.fid_nmx << 16;
12970        	          fidnum += hdr->fid_overlay.fid[0];
12971        	          while(found)
12972        	          { 
12973        	            hdr->fid_overlay.fid_fields.fid_rvn = 0;
12974        	            hdr->filechar = hdr->filechar & ~(FH2$M_MARKDEL);
12975        	            /* Check if we are dealing with a directory file */ 
12976        	            if ( ((hdr->rattrib & FAT$M_NOSPAN) == FAT$M_NOSPAN) || 
12977        	              (strstr(name , ".DIR;1") != 0) )
12978        	            { 
12979        	              hdr->filechar = hdr->filechar | FH2$M_DIRECTORY;
12980        	              hdr->filechar = hdr->filechar | FH2$M_CONTIG;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 39
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

12981        	            }
12982        	            head = (struct _hd *) hdr; 
12983        	            head->block[255] = 0;
12984        	            for (j=0; j<=254; j++) head->block[255] += head->block[j];
12985        	            vbn = rvt[rvn].vbn_file_1 + fidnum - 1;
12986        	            status = SYS$QIOW(0, rvt[rvn].channel, IO$_WRITEVBLK,
12987        	            &iostat[iocnt], 0, 0, &header[x], bytes, vbn, 0, 0, 0);
12988        	            if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
12989        	            if ((status & 1) != 1) 
12990        	            { 
12991        	              sprintf(outbuf,"%%DFU-E-INDEXFERR, Error writing INDEXF.SYS,");
12992        	              put_disp(); 
12993        	              singlemsg(0,status); 
12994        	              sprintf(outbuf,"- Use ANALYZE/DISK/REPAIR to repair the volume");
12995        	              put_disp();
12996        	              ctx.end = TRUE; 
12997        	              curvol = maxvol; 
12998        	              goto next_und;
12999        	            }                       
13000        	            if ((hdr->ext_fid_overlay.ext_fid[0] == 0) 
13001        	              || (matunmark) ) found = FALSE;
13002        	            else
13003        	              /* Read in extension header */
13004        	            { 
13005        	              x = 0; 
13006        	              rvn = hdr->ext_fid_overlay.ext_fid_fields.ext_fid_rvn;
13007        	              if (rvn == 0) rvn = curvol;
13008        	              fidnum = hdr->ext_fid_overlay.ext_fid_fields.ext_fid_nmx << 16;
13009        	              fidnum += hdr->ext_fid_overlay.ext_fid[0];
13010        	              ivbn = rvt[rvn].vbn_file_1 + fidnum - 1; 
13011        	              hdr = (struct header_area_struct *) &header[x];   
13012        	              status = SYS$QIOW(0,rvt[rvn].channel,IO$_READVBLK,
13013        	              &iostat[iocnt],0,0,&header[0],512,ivbn,0,0,0);
13014        	              hdr->fid_overlay.fid_fields.fid_num = fidnum % 65536;
13015        	              hdr->fid_overlay.fid_fields.fid_nmx = fidnum / 65536;
13016        	            }
13017        	          } /* End while */
13018        	          hdr = (struct header_area_struct *) &header[ctx.i];
13019        	          sprintf(outbuf,"%%DFU-S-RECOVER, File succesfully recovered");
13020        	          put_disp(); 
13021        	          /* Rewrite the indexf bitmap bit */
13022        	          bitblk = (headers + 4095) / 4096 - 1;
13023        	          bitje = (headers - 1 - bitblk*4096) / 32;
13024        	          bitval = (headers - 1) % 32;
13025        	          j = 1;
13026        	          lib$insv(&j, &bitval, &j, &bitmap[bitblk+1].block[bitje*4]);
13027        	          bytes = 512; 
13028        	          vbn = home[curvol].ibmapvbn + bitblk;
13029        	          status = SYS$QIOW(0, rvt[curvol].channel, IO$_WRITEVBLK,	    
13030        	          &iostat[iocnt],0,0,&bitmap[bitblk+1],bytes,vbn,0,0,0);
13031        	          /* Add quota if needed */
13032        	          if (!matunmark)
13033        	          { 
13034        	            strcpy(device, rvt[1].devnam);
13035        	            device_descr.dsc$w_length = rvt[1].devnam_len;
13036        	            if (qchan == 0) 
13037        	            { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 40
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

13038        	              status = SYS$ASSIGN(&device_descr, &qchan, 0, 0);
13039        	              if ((status & 1) != 1) 
13040        	                singlemsg(DFU_ASSIGN,status); 
13041        	            }
13042        	            if (qchan != 0) add_quota(qchan, s_uic, hdrs, a_size);
13043        	          }
13044        	          sprintf(outbuf," "); 
13045        	          put_disp();
13046        	/* Set up work entry for entering file in directory */
13047        	          rvn = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn;
13048        	          if (rvn ==0) rvn = curvol;
13049        	          if (first == NULL )
13050        	          { 
13051        	            list = (struct work *) malloc(sizeof(struct work));
13052        	            first = list; /* pointer to first element */
13053        	          }
13054        	           else
13055        	          { 
13056        	            list->next = (struct work *) malloc(sizeof(struct work));
13057        	            list = list->next;
13058        	          }
13059        	/* File in Directory and File id */
13060        	          list->rvn = rvn;
13061        	          copy_fid(&list->did_num, 
13062        	            &hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num, FALSE);
13063        	/* Special case for MFD */
13064        	          if (headers == 4) 
13065        	            list->did_rvn = 0;
13066        	           else
13067        	            list->did_rvn = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn;
13068        	          copy_fid(&list->fid_num, &hdr->fid_overlay.fid_fields.fid_num,
13069        	            FALSE);
13070        	          list->fid_rvn = curvol; 
13071        	          if (lostfile) list->function = 2;
13072        	           else list->function = 1;
13073        	          list->next = NULL;
13074        	          strcpy(list->name,name);
13075        	        }
13076        	        /* Next header */
13077        	next_und: 
13078        	        status = get_next_header();
13079        	        if ((status & 1) != 1) return(status);
13080        	      }
13081        	    }
13082        	    if (ctrlc == 1)
13083        	    { 
13084        	      ctx.end = TRUE;
13085        	      do_abort();
13086        	    }
13087        	    else
13088        	    { 
13089        	      curvol++; 
13090        	      sprintf(outbuf,"     Progress : 100%%     Status : READY");
13091        	      put_status(1);
13092        	      ctx.end = FALSE; /* Next volume */
13093        	      if (clean_flags.events == 1) 
13094        	      { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 41
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

13095        	        for (i=1; i <= iocnt ; i++) status = lib$free_ef(&efn[i-1]);
13096        	        clean_flags.events = 0;
13097        	      }
13098        	      if (curvol <= maxvol) 
13099        	      { 
13100        	        sprintf(outbuf," "); 
13101        	        put_disp();
13102        	      }
13103        	    }
13104        	  }
13105        	
13106        	  /* Now unlock the volume */
13107        	  if (!matlist)
13108        	  { 
13109        	    dfu_handler();
13110        	    SYS$CANEXH(&desblk);
13111        	  }
13112        	  if (qchan !=0) SYS$DASSGN(qchan);
13113        	
13114        	  /* Now enter files in directories */
13115        	  fib.fib$w_nmctl = 0;
13116        	  if (first != NULL) 
13117        	  { 
13118        	    sprintf(outbuf,"%%DFU-I-ENTER, Entering file(s) in directory...");
13119        	    put_disp();
13120        	  }
13121        	  for (i=1; i <=maxvol ; i++)
13122        	    status = SYS$QIOW(0,rvt[i].channel,IO$_DEACCESS,&iostat[iocnt],
13123        	    0,0,0,0,0,0,0,0); 
13124        	  while (first != NULL)
13125        	  { 
13126        	    list = first; 
13127        	    rvn = list->rvn; if (rvn ==0) rvn = 1;
13128        	    copy_fid(&fib.fib$w_did[0], &list->did_num, FALSE);
13129        	    copy_fid(&fib.fib$w_fid[0], &list->fid_num, FALSE);
13130        	    strcpy(name,list->name); 
13131        	    name_descr.dsc$w_length = strlen(name);
13132        	    if (list->function == 1) 
13133        	      status = enter_file(rvt[rvn].channel, &fib, &name_descr);
13134        	     else status = 2; /* If lost backlink enter the file in SYSLOST anyway */
13135        	    first = list->next;
13136        	    free(list); /*Return dynamic space to pool */
13137        	    if ((status & 1) != 1) 
13138        	    { 
13139        	      if (syslost == 0) 
13140        	        syslost = make_syslost(&lost_fid);
13141        	      if (syslost == 1) /* Try entering the file in [SYSLOST] */
13142        	      { 
13143        	        copy_fid(&fib.fib$w_did[0], &lost_fid.fid_num, FALSE);
13144        	        status = enter_file(rvt[rvn].channel, &fib, &name_descr);
13145        	      }
13146        	      if (syslost == 2) 
13147        	      { 
13148        	        sprintf(outbuf,"%%DFU-E-NOTENTER, File %s not entered in directory,",name);
13149        	        put_disp(); 
13150        	        singlemsg(0,status); 
13151        	        sprintf(outbuf,

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 42
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (6)

13152        	        "- Use ANALYZE/DISK/REPAIR to move the file to [SYSLOST]");
13153        	        put_disp();
13154        	      }
13155        	    }
13156        	  }
13157        	
13158        	  curvol = 1;
13159        	  cleanup();  
13160        	  if (matlist) 
13161        	  { 
13162        	    sprintf(outbuf,"\n%%DFU-S-FND , %d recoverable files found",fcount);
13163        	    put_disp();
13164        	  }
13165        	  sprintf(outbuf,"\n%%DFU-I-READY, UNDELETE command ready");
13166        	  put_disp();
13167        	  if (matstat == TRUE) status = lib$show_timer(0,0,display_stat,0);
13168        	  return(1);
13169        	}
13170        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 43
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (7)

             	
13171        	int make_syslost(struct f_id *l_fid)
13172        	/* 
13173        	    Routine to create the syslost directory on RVN 1
13174        	    Returns 1 on succes, 2 on failure 
13175        	    Routine 'borrowed' from VERIFY.LIS
13176        	*/
13177        	
13178        	{ 
13179        	  char fname[14] = "SYSLOST.DIR;1";
13180        	  struct dsc$descriptor device_descr;
13181        	  struct dsc$descriptor fname_descr;
13182        	  int func;
13183        	  short empty = -1;
13184        	  static unsigned int uchar ,uic;
13185        	  static short attrib[16], fpro, l_chan;
13186        	  static struct fibdef lost_fib;
13187        	  static struct { 
13188        	    unsigned short iosb_1;
13189        	    unsigned int length;
13190        	    short spec; 
13191        	  } 
13192        	  io_stat;
13193        	  static struct { 
13194        	    unsigned short atr_size, atr_type;
13195        	    int *atr_address; 
13196        	  } 
13197        	  acb[5] =  { 
13198        	    { 
13199        	      4, ATR$C_UCHAR, (int *) &uchar    } 
13200        	    , 
13201        	    { 
13202        	      32, ATR$C_RECATTR, (int *) &attrib    }
13203        	    , 
13204        	    { 
13205        	      2, ATR$C_FPRO, (int *) &fpro    }
13206        	    , 
13207        	    {
13208        	      4, ATR$C_UIC, (int *) &uic    }
13209        	    ,
13210        	    {
13211        	      0, 0, 0    } 
13212        	  };
13213        	  static struct {
13214        	    int fiblen;
13215        	    struct fibdef *fibadr;
13216        	  } 
13217        	  fibdescr;
13218        	
13219        	  fname_descr.dsc$w_length = strlen(fname);
13220        	  fname_descr.dsc$a_pointer = (char *) &fname;
13221        	  device_descr.dsc$a_pointer = (char *) &rvt[1].devnam;
13222        	  device_descr.dsc$w_length = rvt[1].devnam_len;
13223        	  status = SYS$ASSIGN(&device_descr, &l_chan, 0, 0);
13224        	  /* Setup fib. First we access the MFD to get the correct attributes,
13225        	       next we create SYSLOST */
13226        	  if ((status & 1) != 1) return(2);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 44
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (7)

13227        	  fibdescr.fiblen = sizeof(lost_fib);
13228        	  fibdescr.fibadr = &lost_fib;
13229        	  lost_fib.fib$w_fid[0] = 4; 
13230        	  lost_fib.fib$w_fid[1] = 4; 
13231        	  lost_fib.fib$w_fid[2] = 1; 
13232        	  lost_fib.fib$w_did[0] = 0; 
13233        	  lost_fib.fib$w_did[1] = 0; 
13234        	  lost_fib.fib$w_did[2] = 0; 
13235        	  status = SYS$QIOW(0, l_chan, IO$_ACCESS, &io_stat,
13236        	  0,0, &fibdescr, 0 , 0, 0, &acb, 0);
13237        	  if ((status & 1) == 1 ) status = io_stat.iosb_1;
13238        	  if ((status & 1) != 1 )
13239        	  { 
13240        	    status = SYS$DASSGN(l_chan); 
13241        	    return(2);
13242        	  }
13243        	  else
13244        	  { 
13245        	    attrib[2] = attrib[3] = attrib[4] = 0;
13246        	    attrib[5] = 2 ; /* Efblk and Hiblk */
13247        	    lost_fib.fib$w_fid[0] = 0; 
13248        	    lost_fib.fib$w_fid[1] = 0; 
13249        	    lost_fib.fib$w_fid[2] = 0; 
13250        	    lost_fib.fib$w_did[0] = 4; 
13251        	    lost_fib.fib$w_did[1] = 4; 
13252        	    lost_fib.fib$w_did[2] = 1; 
13253        	    lost_fib.fib$l_acctl = FIB$M_WRITE | FIB$M_NOWRITE;
13254        	    lost_fib.fib$w_exctl = 
13255        	      FIB$M_EXTEND | FIB$M_ALCON | FIB$M_FILCON;
13256        	    lost_fib.fib$l_exsz = 1;
13257        	    lost_fib.fib$w_nmctl = 0;
13258        	    /* Go on and create this directory */
13259        	    func = IO$_ACCESS | IO$M_CREATE | IO$M_ACCESS;
13260        	    status = SYS$QIOW(0, l_chan, func, &io_stat,
13261        	    0,0, &fibdescr, &fname_descr , 0, 0, &acb, 0);
13262        	    if ((status & 1) == 1 ) status = io_stat.iosb_1;
13263        	    if ((status & 1) != 1 )
13264        	    { 
13265        	      sprintf(outbuf,"%%DFU-E-MKLOST, Error creating/accessing SYSLOST.DIR,");
13266        	      put_disp(); 
13267        	      singlemsg(0,status);
13268        	      status = SYS$DASSGN(l_chan); 
13269        	      return(2);
13270        	    }
13271        	    else
13272        	      if (status == SS$_CREATED)
13273        	      { /* empty the first directory block to fake a new directory */
13274        	        status = SYS$QIOW(0, l_chan, IO$_WRITEVBLK, &io_stat,
13275        	        0,0, &empty, 2, 1 , 0, 0, 0);
13276        	      }
13277        	  }
13278        	  SYS$DASSGN(l_chan);
13279        	  copy_fid(&l_fid->fid_num, &lost_fib.fib$w_fid[0], FALSE);
13280        	  return(1);
13281        	}
13282        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 45
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (8)

             	
13283        	void make_list()
13284        	/* Routine to create a new element in the work list */
13285        	{
13286        	  if (first == NULL )
13287        	  { 
13288        	    list = (struct work *) malloc(sizeof(struct work));
13289        	    first = list; /* pointer to first element */
13290        	  }
13291        	   else
13292        	  { 
13293        	   list->next = (struct work *) malloc(sizeof(struct work));
13294        	   list = list->next;
13295        	  }
13296        	}
13297        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 46
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

             	
13298        	int verify_command(int mask)
13299        	/*
13300        	    Verify disk (like ANALYZE/DISK) and report errors.
13301        	    /FIX fixes some basic errors (like ANA/DISK/REPAI)
13302        	    /REBUILD fixes structure errors (like in BITMAP.SYS) 
13303        	    This routine does not verify individual directories
13304        	    V2.4 : Report multiple allocated blocks sorted by LBN
13305        		   Rebuild MFD if needed
13306        		 : added directory scan (/DIRECTORY_SCAN
13307        	*/
13308        	
13309        	{
13310        	  static char dummy_item[80], fname[80], name[86], bfile[255], fmode[2];
13311        	  struct header_area_struct *hdr;
13312        	  struct ident_area_struct *id;
13313        	  static struct { 
13314        	    unsigned short atr_size, atr_type;
13315        	    int atr_address; 
13316        	  } 
13317        	  atrmfd[2];
13318        	  Boolean dummy, matoutput, matstat, matlock, bitset, matfix, matappend,
13319        	  matreb, matdir, trigger;
13320        	  unsigned short keybuf[9] = {
13321        	    2, DSC$K_DTYPE_LU, 0, 0, 4 ,
13322        	    DSC$K_DTYPE_WU, 1, 9, 2  };
13323        	  static struct _mlt { 
13324        	    unsigned int lbnstart, lbnend;
13325        	    unsigned short fid[3]; 
13326        	  } 
13327        	  sort_rec;
13328        	  static struct { 
13329        	    unsigned int size; 
13330        	    struct _mlt * pointer; 
13331        	  } 
13332        	  sor_descr;
13333        	  int reclen = 14;
13334        	  register int i;
13335        	  int ivbn, bitblk, bitje, bitval, find, rvn, x, y, dir_cnt, maxdir,
13336        	  k, size, free_hdr, a_size, r_size, hdrs, namelen, rtvptr;
13337        	  unsigned int page_cnt, bakfid, syslost, bytes, previous;
13338        	  struct { 
13339        	    int own_uic, flag, rsize, asize, hdr; 
13340        	  } 
13341        	  usage_table[750];
13342        	  struct f_id lost_fid, mfd_fid;
13343        	  static struct fibdef fib;	/* File information block */
13344        	  struct { 
13345        	    int fiblen; 
13346        	    struct fibdef *fibadr; 
13347        	  } 
13348        	  fibdescr;
13349        	  /* Set up list for mutiple allocated blocks */
13350        	  struct mult { 
13351        	    unsigned int lbnstart,lbnend;
13352        	    struct mult *next;
13353        	  } 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 47
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13354        	  *m_first, *m_list;
13355        	  Boolean multalloc;
13356        	  void get_map_pointers(), 
13357        	  add_usage(), dfu_handler(), new_bitmap(), 
13358        	  check_usage(), report_lost_files();
13359        	  /* FAO parameters */
13360        	  unsigned short outlen; 
13361        	  static char mfd_name[] = "000000.DIR;1";
13362        	  $DESCRIPTOR(out_descr , outbuf);
13363        	  $DESCRIPTOR(device_descr , device);
13364        	  $DESCRIPTOR(file_descr , fname);
13365        	  $DESCRIPTOR(dummy_descr , dummy_item);
13366        	  $DESCRIPTOR(name_descr , name);
13367        	  $DESCRIPTOR(badfile , bfile);
13368        	  $DESCRIPTOR(mfd_descr, mfd_name);
13369        	
13370        	  /* Code starts here */
13371        	  /* Parse the various qualifiers */
13372        	
13373        	  dir_cnt = 0;
13374        	  sor_descr.size = 14;
13375        	  sor_descr.pointer = &sort_rec;
13376        	  progress_ind = TRUE;
13377        	  y = 0;
13378        	  status = parse_item("fix", &dummy_descr, 0, &matfix, 2);
13379        	  status = parse_item("rebuild", &dummy_descr, 0, &matreb, 2);
13380        	  status = parse_item("dirscan", &dummy_descr, 0, &matdir, 2);
13381        	  /* Check the privileges */
13382        	  if ( ((matfix) || (matreb)) && (mask > -1))
13383        	  { 
13384        	    singlemsg(0, DFU_NOPRIV);
13385        	    return(SS$_NOPRIV);
13386        	  }
13387        	  /* Get device name */
13388        	  status = parse_item("device", &device_descr, 0, &dummy , 0);
13389        	  if (status == 1) 
13390        	  { 
13391        	    if (strindex(&device,":",64) == -1) 
13392        	    {
13393        	      device[device_descr.dsc$w_length]=':'; 
13394        	      device_descr.dsc$w_length += 1;
13395        	    }
13396        	  }
13397        	  status = parse_item("statistics", &dummy_descr, 0, &matstat, 2);
13398        	  status = parse_item("lock", &dummy_descr, 0, &matlock, 2);
13399        	  if (matreb) matlock = TRUE; /* Lock anyway if rebuild requested */
13400        	  for (i=0; i < 750; i++) usage_table[i].flag = 0;
13401        	  /* Get output file */
13402        	  clean_flags.fopen = 0;
13403        	  strcpy(fmode,"w");
13404        	  status = parse_item("outfile", &file_descr, 0, &matoutput , 0);
13405        	  if (!matoutput)
13406        	    status = parse_item("append", &file_descr, 0, &matappend , 0);
13407        	  if (matappend)
13408        	  { 
13409        	    matoutput = TRUE; 
13410        	    strcpy(fmode,"a");

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 48
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13411        	  }  
13412        	  if (matoutput == FALSE) 
13413        	  {
13414        	    strcpy(fname,"SYS$OUTPUT:"); 
13415        	    file_descr.dsc$w_length = 11;
13416        	  }
13417        	  else
13418        	  {
13419        	    fname[file_descr.dsc$w_length] = '\0'; 
13420        	  }
13421        	  fp = fopen(fname,fmode,"mrs=255","rfm=var","ctx=rec","rat=cr","rop=WBH");	
13422        	  clean_flags.fopen = 1;
13423        	
13424        	  /* Fill in FIB */
13425        	  fibdescr.fiblen = sizeof(fib);
13426        	  fibdescr.fibadr = &fib;
13427        	  syslost = 0;
13428        	
13429        	  /* All qualifiers parsed */
13430        	  first = NULL; 
13431        	  list = NULL;
13432        	  if (matstat == TRUE) status = lib$init_timer();
13433        	  clean_flags.channels = 0;
13434        	  clean_flags.sort = 0;
13435        	  clean_flags.events = 0;
13436        	  clean_flags.expreg = 0;
13437        	
13438        	  if (matfix)
13439        	  { 
13440        	    atrmfd[0].atr_size = ATR$S_BACKLINK;
13441        	    atrmfd[0].atr_type = ATR$C_BACKLINK;
13442        	    atrmfd[0].atr_address = (int) &mfd_fid;
13443        	    atrmfd[1].atr_size = atrmfd[1].atr_type = 0;
13444        	    mfd_fid.fid_num = 4;
13445        	    mfd_fid.fid_seq = 4;
13446        	    mfd_fid.fid_rvn = mfd_fid.fid_nmx = 0;
13447        	  }
13448        	
13449        	  /* Open the volume (set) , read in the home block */
13450        	
13451        	  i = (matlock == TRUE) ? 1 : 0;
13452        	  status = open_device(&device_descr,i);
13453        	  if ((status & 1) != 1) return(status);
13454        	  if ((matlock) && (rvt[1].wlk == TRUE))
13455        	  { 
13456        	    sprintf(outbuf,
13457        	    "%%DFU-W-WRITELK, Cannot rebuild or lock on write-locked device");
13458        	    put_disp();
13459        	    matlock = FALSE; 
13460        	    matreb = FALSE;
13461        	  }
13462        	  if ((matlock == TRUE) && (lock_chan != 0))
13463        	  { /* Setup exit handler to ensure that we unlock the volume */
13464        	    desblk.handler_addr = (int) &dfu_handler;
13465        	    desblk.condition = (int) &status;
13466        	    desblk.arg_count = 1;
13467        	    status = SYS$DCLEXH(&desblk);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 49
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13468        	    if ((status & 1) !=1) 
13469        	    { 
13470        	      singlemsg(DFU_EXHFAIL,status);
13471        	      cleanup(); 
13472        	      return(status);
13473        	    }
13474        	  }  
13475        	
13476        	  curvol = 1; 
13477        	  size = 1;
13478        	  ctx.end = FALSE;
13479        	  if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_OFF);
13480        	  multalloc = FALSE; 
13481        	  while ((curvol <= maxvol) && (!ctx.end))
13482        	  { 
13483        	    ctx.i = -1; 
13484        	    trigger = FALSE;
13485        	    if (rvt[curvol].i_open ==1) 
13486        	    { 
13487        	      if (maxvol == 1)
13488        	      {	
13489        	        sprintf(outbuf,"%%DFU-I-VERIFY, Verifying %.*s (%s) ",
13490        	        device_descr.dsc$w_length, device, &rvt[curvol].fulldevnam[1]); 
13491        	      }
13492        	      else
13493        	      {	
13494        	        sprintf(outbuf,"%%DFU-I-VERIFY, Verifying %.*s (%s) , RVN = %d",
13495        	        rvt[curvol].devnam_len, rvt[curvol].devnam, 
13496        	        &rvt[curvol].fulldevnam[1], curvol); 
13497        	      }
13498        	      put_disp();
13499        	      headers=0;
13500        	      previous = 0;
13501        	      m_list = (struct mult *) malloc (sizeof (struct mult)); 
13502        	      m_first = m_list;
13503        	      m_list->next = NULL;
13504        	      /* Phase 1 : Read and parse INDEXF.SYS */
13505        	      /* Create dynamic array. 
13506        	         Also create space for new bitmap */
13507        	
13508        	      page_cnt = 1 + (rvt[curvol].if_size*sizeof(struct _da))/512;
13509        	      rvt[curvol].addr[0] = 0;
13510        	      rvt[curvol].bmap_addr[0] = 0;
13511        	      status = SYS$EXPREG(page_cnt, &rvt[curvol].addr[0],0,0);
13512        	      if ((status &1) != 1)
13513        	      { 
13514        	        singlemsg(DFU_EXPREG,status); 
13515        	        cleanup(); 
13516        	        return(status);
13517        	      }
13518        	      clean_flags.expreg = 1;
13519        	      dyn_array = (struct _da *) rvt[curvol].addr[0]; 
13520        	      page_cnt = (rvt[curvol].maxblocks/home[curvol].cluster);
13521        	      page_cnt = (page_cnt + 4095 ) / 4096; 
13522        	      status = SYS$EXPREG(page_cnt, &rvt[curvol].bmap_addr[0],0,0);
13523        	      if ((status &1) != 1)
13524        	      { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 50
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13525        	        singlemsg(DFU_EXPREG,status); 
13526        	        cleanup(); 
13527        	        return(status);
13528        	      }
13529        	
13530        	      /* Report home block info */
13531        	      if ((home[curvol].altidxlbn !=0) &&
13532        	        (home[curvol].altidxvbn != 0) &&
13533        	        (home[curvol].cluster != 0) &&
13534        	        (home[curvol].homevbn != 0) &&
13535        	        (home[curvol].ibmapvbn != 0) &&
13536        	        (home[curvol].ibmaplbn != 0) &&
13537        	        (home[curvol].maxfiles != 0) &&
13538        	        (home[curvol].ibmapsize != 0) &&
13539        	        (home[curvol].resfiles != 0) )
13540        	        sprintf(outbuf,"%%DFU-S-CHKHOME, Home block info verified OK");
13541        	      else
13542        	        sprintf(outbuf,"%%DFU-E-ERRHOME, Home block info not OK");
13543        	      put_disp(); 
13544        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
13545        	
13546        	      /* Read in index file bitmap, and return free hdrs + highest bit set */
13547        	      read_indexf_bitmap(&free_hdr);
13548        	
13549        	      status = get_next_header();
13550        	      if ((status & 1) != 1) return(status);
13551        	      while (! ctx.end) /* Loop until end of INDEXF or CTRL C entered */
13552        	      { 
13553        	        hdr = ctx.hdr;
13554        	        id = ctx.id;
13555        	        /* Setup fields in dynamic array */
13556        	        bakfid = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx << 16;
13557        	        bakfid += hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num;
13558        	        (dyn_array+headers)->bitje = 0;
13559        	        (dyn_array+headers)->a_size = 0;
13560        	        (dyn_array+headers)->f_link = 0;
13561        	        (dyn_array+headers)->bakfid = bakfid;
13562        	
13563        	        /* Check corresponding bitmap bit (must be set) */
13564        	        bitblk = (headers + 4095) / 4096 - 1;
13565        	        bitje = (headers - 1 - bitblk*4096) / 32;
13566        	        bitval = (headers - 1) % 32;
13567        	        status = lib$ffs(&bitval,&size,&bitmap[bitblk+1].block[bitje*4],
13568        	        &find);
13569        	        if (status == LIB$_NOTFOU) 
13570        	          bitset = FALSE;
13571        	        else bitset = TRUE;
13572        	        rvn = curvol;
13573        	        status = verify_header(hdr);
13574        	        if (status != SS$_NORMAL)
13575        	        { 
13576        	          if (bitset == TRUE) 
13577        	          { 
13578        	            sprintf(outbuf,"%%DFU-W-NOBITCLR, file (%d,%d,%d) deleted file header marked BUSY in Index File bitmap"
13579        	              ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol);
13580        	            put_disp(); 
13581        	            if (matoutput) fprintf(fp,"%s\n",outbuf);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 51
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13582        	            /* Clear the indexf bitmap bit */
13583        	            if (matreb)
13584        	            { 
13585        	              trigger = TRUE; 
13586        	              lib$insv(&y, &bitval, &size, &bitmap[bitblk+1].block[bitje*4]);
13587        	            }
13588        	          }
13589        	          goto next_ver ; /* Not a valid header */
13590        	        }
13591        	
13592        	        /* We have a valid header, proceed...*/
13593        	        /* Set up new bitmap and report multiple allocated blocks */
13594        	        new_bitmap(rvt[curvol].bmap_addr[0], hdr, home[curvol].cluster,
13595        	        curvol, fp, 1, &m_list, &multalloc, matoutput);
13596        	        m_list->next = NULL;
13597        	        if (hdr->seg_num !=0) goto next_ver ; /* Skip extension header */
13598        	        /*Set lost file and valid file bit */
13599        	        (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 1;
13600        	        (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 16;
13601        	        copy_fid(&(dyn_array+headers)->fid,
13602        	        &hdr->fid_overlay.fid_fields.fid_num,FALSE);
13603        	        /* Get size fields (NOTE : they are stored in reverse order ! */
13604        	        a_size = hdr->hiblk_overlay.hiblk_fields.hiblkh << 16;
13605        	        a_size += hdr->hiblk_overlay.hiblk_fields.hiblkl;
13606        	        (dyn_array+headers)->a_size = a_size;
13607        	        r_size = hdr->efblk_overlay.efblk_fields.efblkh << 16;
13608        	        r_size += hdr->efblk_overlay.efblk_fields.efblkl;
13609        	        if (r_size > 0) 
13610        	          if (hdr->ffbyte == 0) r_size--; /* Correct size on block boundary*/
13611        	        /* Get name */
13612        	        memcpy(&name[0],id->filename,20);
13613        	        if (name[19] != ' ') memcpy(&name[20],id->filenamext,66);
13614        	        namelen = strindex(&name[0]," ",86); 
13615        	
13616        	        /* Check marked for delete bit */
13617        	        if ((hdr->filechar & FH2$M_MARKDEL) == FH2$M_MARKDEL)
13618        	        { 
13619        	          (dyn_array+headers)->bitje = 0;
13620        	          sprintf(outbuf,
13621        	          "%%DFU-W-DELETED, file (%d,%d,%d) %.*s marked for delete"
13622        	            ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol
13623        	            ,namelen,name);
13624        	          put_disp(); 
13625        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13626        	          /* If /FIX entered we enter this file in the work list */
13627        	          if (matfix)
13628        	          { 
13629        	            make_list();
13630        	/* Fill in File id */
13631        	            copy_fid(&list->fid_num, &hdr->fid_overlay.fid_fields.fid_num, 
13632        	              FALSE);
13633        	            if (list->fid_rvn == 0) list->fid_rvn = curvol;
13634        	            list->function = 1; 
13635        	            list->next = NULL;
13636        	          }
13637        	          goto add_usage; /* Skip other tests */
13638        	        }

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 52
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13639        	
13640        	        /* Check locked bit */
13641        	        if ((hdr->filechar & FH2$M_LOCKED) == FH2$M_LOCKED)
13642        	        { 
13643        	          sprintf(outbuf,
13644        	          "%%DFU-W-LOCKED, file (%d,%d,%d) %.*s is deaccess locked "
13645        	            ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol,namelen,name);
13646        	          put_disp(); 
13647        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13648        	        }
13649        	
13650        	        /* Check badblock bit */
13651        	        if ((hdr->filechar & FH2$M_BADBLOCK) == FH2$M_BADBLOCK)
13652        	        { 
13653        	          sprintf(outbuf,
13654        	          "%%DFU-W-BADBLOCK, file (%d,%d,%d) %.*s has suspected bad blocks"
13655        	            ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol,namelen,name);
13656        	          put_disp(); 
13657        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13658        	        }
13659        	
13660        	        /* Check directory bit */
13661        	        if ((hdr->filechar & FH2$M_DIRECTORY) == FH2$M_DIRECTORY)
13662        	        { 
13663        	          (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 4;
13664        	          /* Fill in forward link */
13665        	          if (previous !=0) (dyn_array+previous)->f_link = headers;
13666        	          previous = headers;
13667        	          dir_cnt++;
13668        	          /* On volume sets check the link to MFD */
13669        	          if (maxvol > 1)
13670        	          { 
13671        	            y = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn;
13672        	            if ((y ==0) && (headers !=4)) y = curvol;
13673        	            if ((bakfid == 4) && (y > 1))
13674        	            { 
13675        	              sprintf(outbuf,"%%DFU-W-BADMFDLNK, directory %.*s has backlink to 000000.DIR on RVN %d"
13676        	                , namelen,name, y);
13677        	              put_disp(); 
13678        	              if (matoutput) fprintf(fp,"%s\n",outbuf);
13679        	            }
13680        	            y = 0;
13681        	          }
13682        	        }
13683        	
13684        	        /* Check corresponding bit in bitmap */
13685        	        if (bitset == FALSE)
13686        	        { 
13687        	          sprintf(outbuf,"%%DFU-W-NOBITSET, file (%d,%d,%d) %.*s Index File bitmap bit not set"
13688        	            ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol,namelen,name);
13689        	          put_disp(); 
13690        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13691        	          if (matreb)
13692        	          { 
13693        	            y = 1; /* Now set this bit in the indexf bitmap */
13694        	
13695        	            lib$insv(&y, &bitval, &size, &bitmap[bitblk+1].block[bitje*4]);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 53
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13696        	            y = 0; 
13697        	            trigger = TRUE;
13698        	          }
13699        	        }
13700        	
13701        	        /* Check file owner */
13702        	        if (hdr->fileowner_overlay.fileowner == 0)
13703        	        { 
13704        	          sprintf(outbuf,"%%DFU-W-NOOWNER, file (%d,%d,%d) %.*s has no owner"
13705        	            ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol,namelen,name);
13706        	          put_disp(); 
13707        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13708        	        }
13709        	
13710        	        /* Check backlink ; special case for the MFD */
13711        	        if ( (bakfid == 0) || ((headers == 4) && (bakfid != 4)) )
13712        	        { 
13713        	          sprintf(outbuf,
13714        	          "%%DFU-E-INVBAKFID, file (%d,%d,%d) %.*s has invalid backlink"
13715        	            ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol,namelen,name);
13716        	          put_disp(); 
13717        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13718        	          /* Set invalid backlink bit */
13719        	          if ((bakfid ==0) && (headers !=4)) 
13720        	            (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 2;
13721        	          if (matfix)
13722        	          { 
13723        		    make_list();
13724        	/* Fill in File id */
13725        	            copy_fid(&list->fid_num,&hdr->fid_overlay.fid_fields.fid_num
13726        	              , FALSE);
13727        	            list->fid_rvn = curvol;
13728        	            if (headers != 4) list->function = 2; 
13729        	            else list->function = 5;
13730        	            list->next = NULL;
13731        	            strncpy(list->name,name,namelen);
13732        	          }
13733        	        }
13734        	        if ((bakfid == headers) && (headers !=4)) /* File backlinks to itself */
13735        	          /* need to check volume set*/
13736        	          if (hdr->fid_overlay.fid_fields.fid_rvn ==
13737        	            hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn)
13738        	          { 
13739        	            sprintf(outbuf,
13740        	            "%%DFU-E-SLFBAKFID, file (%d,%d,%d) %.*s backlink points to itself"
13741        	              ,headers,hdr->fid_overlay.fid_fields.fid_seq,curvol,namelen,name);
13742        	            put_disp(); 
13743        	            if (matoutput) fprintf(fp,"%s\n",outbuf);
13744        	            if (matfix)
13745        	            { 
13746        	              make_list();
13747        	/* Fill in File id */
13748        	              copy_fid(&list->fid_num,
13749        	                &hdr->fid_overlay.fid_fields.fid_num, FALSE);
13750        	              copy_fid(&list->did_num,
13751        	                &hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num, FALSE);
13752        	              list->fid_rvn = curvol;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 54
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13753        	              list->function = 4; 
13754        	              list->next = NULL;
13755        	              strncpy(list->name,name,namelen);
13756        	            }
13757        	          }
13758        	        /* If backlink points to other disk we must save this RVN */
13759        	        if (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn == 0)
13760        	          hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn = curvol;
13761        	        if (hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn != curvol)
13762        	        { 
13763        	          (dyn_array+headers)->rvn =
13764        	            hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn;
13765        	          (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 8;
13766        	        }
13767        	add_usage:
13768        	        hdrs = 1; 
13769        	        rtvptr = 0;
13770        	        if (hdr->ext_fid_overlay.ext_fid[0] !=0)
13771        	          status = follow_extents(hdr, &rtvptr, &hdrs);
13772        	        /* Update usage table */
13773        	        if (headers > 3) /* Skip first 3 reserved files */
13774        	          add_usage(&usage_table, hdr->fileowner_overlay.fileowner, 
13775        	          r_size, a_size, hdrs);
13776        	        /* Next header */
13777        	next_ver : 
13778        	        status = get_next_header();
13779        	        if ((status & 1) != 1) return(status);
13780        	      }
13781        	    }
13782        	    /* Save array bounds */
13783        	    dyn_array->fid[0] = headers % 65536;
13784        	    dyn_array->fid[1] = headers / 65536;
13785        	    dyn_array->bakfid = headers;
13786        	
13787        	    /* Phase 1A If we have multiple allocated blocks we will make
13788        	       a new (empty) bitmap with the bits set for the blocks reported
13789        	       in the dynamic array m_list. Thus, a second pass thru INDEXF.SYS
13790        	       and the routine new_bitmap will report ALL files involved. */
13791        	    if (multalloc)
13792        	    { /* Recreate the new bitmap */
13793        	      sprintf(outbuf,"%%DFU-W-MULTFND, reporting multiple allocated blocks...");
13794        	      put_disp(); 
13795        	      if (matoutput) fprintf(fp,"%s\n",outbuf);
13796        	      status = SYS$DELTVA(&rvt[curvol].bmap_addr[0], 
13797        	      &rvt[curvol].bmap_addr[0], 0);
13798        	      rvt[curvol].bmap_addr[0] = 0;
13799        	      page_cnt = (rvt[curvol].maxblocks/home[curvol].cluster);
13800        	      page_cnt = (page_cnt + 4095 ) / 4096; 
13801        	      status = SYS$EXPREG(page_cnt, &rvt[curvol].bmap_addr[0],0,0);
13802        	      if ((status &1) != 1)
13803        	      { 
13804        	        singlemsg(DFU_EXPREG,status); 
13805        	        cleanup(); 
13806        	        return(status);
13807        	      }
13808        	      /* Now fill in the multiple allocated blocks */
13809        	      while (m_first->next != NULL)

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 55
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13810        	      { 
13811        	        m_list = m_first;
13812        	        set_bitmap(rvt[curvol].bmap_addr[0], home[curvol].cluster,
13813        	        m_list->lbnstart, m_list->lbnend, TRUE);
13814        	        m_first = m_list->next;
13815        	        free(m_list);
13816        	      }
13817        	
13818        	      /* Set up sort context so we can report the files sorted by LBN's */
13819        	      status = sor$begin_sort(&keybuf,&reclen,SOR$M_STABLE,
13820        	      0,0,0,SOR$GK_RECORD,0,0);
13821        	      if ((status &1 ) != 1)
13822        	      { 
13823        	        singlemsg(0,status); 
13824        	        cleanup(); 
13825        	        return(status); 
13826        	      }
13827        	      clean_flags.sort = 1;
13828        	
13829        	      /* Now rescan INDEXF.SYS */
13830        	      ctx.end = FALSE; 
13831        	      ctx.i = -1;
13832        	      status = get_next_header();
13833        	      if ((status & 1) != 1) return(status);
13834        	      while (! ctx.end) /* Loop until end of INDEXF or CTRL C entered */
13835        	      { 
13836        	        hdr = ctx.hdr;
13837        	        rvn = curvol;
13838        	        status = verify_header(hdr);
13839        	        if (status != SS$_NORMAL) goto next_ver2 ; 
13840        	
13841        	        /* We have a valid header, proceed...*/
13842        	        /* Set up new bitmap and report multiple allocated blocks */
13843        	        new_bitmap(rvt[curvol].bmap_addr[0], hdr, home[curvol].cluster,
13844        	        curvol, fp, 2, NULL, &multalloc, matoutput);
13845        	
13846        	next_ver2 : 
13847        	        status = get_next_header();
13848        	        if ((status & 1) != 1) return(status);
13849        	      }
13850        	      /* Sort the results and report them */
13851        	      status = sor$sort_merge();
13852        	      if ((status & 1 ) != 1)
13853        	      { 
13854        	        sprintf(outbuf,"%%DFU-E-SORTERR, Error sorting output,\n");
13855        	        put_disp(); 
13856        	        singlemsg(0,status);
13857        	      }
13858        	      else
13859        	      { 
13860        	        status = sor$return_rec(&sor_descr, &reclen);
13861        	        while (status != SS$_ENDOFFILE)
13862        	        { 
13863        	          status = lib$fid_to_name(&device_descr, &sort_rec.fid[0], &badfile,
13864        	          &reclen, 0, 0);
13865        	          x = strindex(bfile,"[",255);
13866        	          reclen -=x;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 56
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13867        	          sprintf(outbuf,"%%DFU-E-MULTALLOC, file (%d,%d,%d) %.*s , ",
13868        	          sort_rec.fid[0],sort_rec.fid[1],curvol,reclen,&bfile[x] );
13869        	          put_disp(); 
13870        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13871        	          sprintf(outbuf,"   blocks LBN %d through %d multiple allocated",
13872        	          sort_rec.lbnstart, sort_rec.lbnend);
13873        	          put_disp(); 
13874        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13875        	          status = sor$return_rec(&sor_descr, &reclen);
13876        	        }
13877        	      }
13878        	    } /*end multalloc */
13879        	    free(m_first); 
13880        	    multalloc = FALSE;
13881        	
13882        	    if (ctrlc != 1)
13883        	      if ((matreb) && (trigger))
13884        	        /* Rewrite the indexf bitmap at this point */
13885        	      { 
13886        	        bytes = 512 * home[curvol].ibmapsize;
13887        	        status = SYS$QIOW(0,rvt[curvol].channel,IO$_WRITEVBLK,&iostat[0],
13888        	        0,0,&bitmap[1],bytes,home[curvol].ibmapvbn,0,0,0);
13889        	        if ((status & 1) == 1) status = iostat[0].iosb_1;
13890        	        if ((status & 1) == 1)
13891        	        { 
13892        	          sprintf(outbuf,"%%DFU-S-REBIFMAP, Indexfile bitmap rebuild");
13893        	          put_disp(); 
13894        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
13895        	        }
13896        	        else
13897        	        { 
13898        	          sprintf(outbuf,"%%DFU-E-REBIFMAP, Indexf Bitmap rebuild failed,");
13899        	          put_disp(); 
13900        	          singlemsg(0,status);
13901        	        }
13902        	      }
13903        	
13904        	    if (ctrlc !=1)
13905        	    { 
13906        	      /* Phase 2: Now continue with bitmap processing */
13907        	      sprintf(outbuf,"     Progress : 100%%     Status : READY");
13908        	      put_status(1);
13909        	      strcpy(device, rvt[curvol].devnam);
13910        	      device_descr.dsc$w_length = rvt[curvol].devnam_len;
13911        	      rvt[curvol].bchan = 0;
13912        	      status = SYS$ASSIGN(&device_descr, &rvt[curvol].bchan, 0, 0);
13913        	      if ((status & 1) != 1) 
13914        	      { 
13915        	        singlemsg(DFU_ASSIGN,status); 
13916        	        cleanup(); 
13917        	        return(status);
13918        	      }      
13919        	      sprintf(outbuf,"     Progress :   0%%     Status : Processing BITMAP.SYS");
13920        	      put_status(1);
13921        	      page_cnt = (rvt[curvol].maxblocks / home[curvol].cluster) ;
13922        	      /* Check for incorrect blocks in BITMAP.SYS and rebuild on request */
13923        	      status = compare_bitmap(rvt[curvol].bchan, rvt[curvol].bmap_addr[0], 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 57
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13924        	      page_cnt, rvt[curvol].wlk, home[curvol].cluster, 
13925        	      fp, matreb, matoutput);
13926        	      sprintf(outbuf,"     Progress : 100%%     Status : READY");
13927        	      put_status(1);
13928        	      if ((status &1) !=1) 
13929        	      { 
13930        	        cleanup(); 
13931        	        return(status);
13932        	      }
13933        	      /* Free the new bitmap space, we don't need it any more */
13934        	      status = SYS$DELTVA(&rvt[curvol].bmap_addr[0], 
13935        	      &rvt[curvol].bmap_addr[0], 0);
13936        	      rvt[curvol].bmap_addr[0] = 0;
13937        	    } 
13938        	    if (ctrlc == 1)
13939        	    { 
13940        	      ctx.end = TRUE;
13941        	    }
13942        	    else
13943        	    { 
13944        	      curvol++; 
13945        	      ctx.end = FALSE; /* Next volume */
13946        	      if (clean_flags.events == 1) 
13947        	      { 
13948        	        for (i=1; i <= iocnt ; i++) status = lib$free_ef(&efn[i-1]);
13949        	        clean_flags.events = 0; 
13950        	      }
13951        	      if (curvol <= maxvol) 
13952        	      { 
13953        	        sprintf(outbuf," "); 
13954        	        put_disp();
13955        	      }
13956        	    }
13957        	  }
13958        	  curvol = 1;
13959        	  /* Phase 3 : check diskquota */
13960        	  if (ctrlc != 1) 
13961        	  { 
13962        	    sprintf(outbuf,"     Progress :   0%%     Status : Processing QUOTA.SYS");
13963        	    put_status(1);
13964        	    check_usage(&usage_table, rvt[curvol].bchan, fp, matreb, matoutput);
13965        	    sprintf(outbuf,"     Progress : 100%%     Status : READY");
13966        	    put_status(1);
13967        	  }
13968        	
13969        	  /* Now we can unlock the volume */
13970        	  if (matlock)
13971        	  { 
13972        	    dfu_handler();
13973        	    SYS$CANEXH(&desblk);
13974        	  }
13975        	
13976        	  /* Phase 4 : check directories (if requested via /DIRECTORY_SCAN) */
13977        	  if (ctrlc !=1) 
13978        	    if (matdir)
13979        	    { 
13980        	      sprintf(outbuf,"%%DFU-I-DIRSCAN, Scanning %d directories...",dir_cnt);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 58
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

13981        	      put_disp();
13982        	      /* Now scan the directories */
13983        	      maxdir = dir_cnt;
13984        	      dir_cnt = 0;
13985        	      if (!matfix) k = 1; 
13986        	      else k = 2;
13987        	      for (i = 1; i <= maxvol; i++)
13988        	        if (ctrlc !=1) 
13989        	          dir_cnt += scan_directories(&rvt[0], i, dir_cnt, maxdir, matoutput, k);
13990        	      sprintf(outbuf,"     Progress : 100%%     Status : READY");
13991        	      put_status(1);
13992        	    }
13993        	
13994        	  /* Phase 5 : check lost files */
13995        	  if (ctrlc != 1) report_lost_files(matfix, matoutput, matdir);
13996        	
13997        	  /* Phase 6 : fix errors 
13998        	     Function 1: Delete this file
13999        	  	    2: Enter file in [SYSLOST]
14000        	  	    3: Clear out previous backlink (reset to 0,0,0)
14001        	  	    4: Remove file from directory (only for 'looping' directories)
14002        	  	    5: Reset MFD in MFD
14003        	  	    6: Enter file in the correct directory
14004        		    7: Remove invalid file entry
14005        	  */
14006        	  if (matfix && (first != NULL))
14007        	  { 
14008        	    for (i=1; i <=maxvol ; i++)
14009        	      status = SYS$QIOW(0,rvt[i].channel,IO$_DEACCESS,&iostat[iocnt],
14010        	      0,0,0,0,0,0,0,0); 
14011        	    if (!ctrlc) 
14012        	    { 
14013        	      sprintf(outbuf,"%%DFU-I-REPAIR, Fixing errors...");
14014        	      put_disp();
14015        	    }
14016        	    while (first != NULL)
14017        	    { 
14018        	      list = first; 
14019        	      if (!ctrlc) 
14020        	      { 
14021        	        if (list->function == 1) /* Delete file */
14022        	          status = delete_file(&list->fid_num, rvt[list->fid_rvn].channel, 
14023        	          TRUE, FALSE, FALSE, FALSE);
14024        	        if (list->function == 4) /* Remove file entry, then enter file*/
14025        	        { 
14026        	          status = remove_file(&list->fid_num, &list->did_num, 
14027        	          rvt[1].channel);
14028        	          list->function = 2;
14029        	        }
14030        	        if (list->function == 3) /* Remove file entry*/
14031        	          status = delete_file(&list->fid_num, rvt[1].channel, 
14032        	          TRUE, FALSE, TRUE, TRUE);
14033        	        if (list->function == 2) /* Enter file in SYSLOST */
14034        	        { 
14035        	          if (syslost == 0) /* Create the [SYSLOST] if needed */ 
14036        	          { 
14037        	            syslost = make_syslost(&lost_fid);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 59
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

14038        	            copy_fid(&fib.fib$w_did[0], &lost_fid.fid_num, FALSE);
14039        	          }
14040        	          if (syslost == 1)
14041        	          { 
14042        	            copy_fid(&fib.fib$w_did[0], &lost_fid.fid_num, FALSE);
14043        	            copy_fid(&fib.fib$w_fid[0], &list->fid_num, FALSE);
14044        	            strcpy(name,list->name); 
14045        	            name_descr.dsc$w_length = strlen(name);
14046        	            status = enter_file(rvt[1].channel, &fib, &name_descr);
14047        	          }
14048        	        }
14049        	        if (list->function == 5) /* Reset MFD backlink */
14050        	        { 
14051        	          copy_fid(&fib.fib$w_fid[0], &list->fid_num, FALSE);
14052        	          fib.fib$w_did[0] = fib.fib$w_did[1] = 4;
14053        	          fib.fib$w_did[2] = 0;
14054        	          fib.fib$w_nmctl = 0;
14055        	          /* create entry in MFD */
14056        	          status = enter_file(rvt[1].channel, &fib, &mfd_descr);
14057        	          /* Now reset the backlink */
14058        	          status = SYS$QIOW(0, rvt[1].channel, IO$_MODIFY, 
14059        	          &iostat[ctx.thread],0,0, &fibdescr, &mfd_descr , 0, 0, &atrmfd, 0);
14060        	          if ((status & 1) == 1) status = iostat[ctx.thread].iosb_1;
14061        	          if ((status & 1) == 1)
14062        	          { 
14063        	            sprintf(outbuf,
14064        	            "%%DFU-S-MFDFIX, %s backlink fixed",mfd_name);
14065        	            put_disp();
14066        	          }
14067        	        }
14068        	        if (list->function == 6) /* Enter file in original directory */
14069        	        {  
14070        	          rvn = list->fid_rvn; 
14071        	          if (rvn == 0) rvn = 1;
14072        	          copy_fid(&fib.fib$w_did[0], &list->did_num, FALSE);
14073        	          copy_fid(&fib.fib$w_fid[0], &list->fid_num, FALSE);
14074        	          strcpy(name,list->name); 
14075        	          name_descr.dsc$w_length = strlen(name);
14076        	          status = enter_file(rvt[rvn].channel, &fib, &name_descr);
14077        	          if ((status & 1) != 1) 
14078        	          { 
14079        	            sprintf(outbuf,"%%DFU-E-NOTENTER, File %s not entered",name);
14080        	            put_disp(); 
14081        	            singlemsg(0,status);
14082        	          }
14083        	        }
14084        	        if (list->function == 7) /* Remove file entrye*/
14085        	        { 
14086        	          status = remove_file(&list->fid_num, &list->did_num, 
14087        	          rvt[1].channel);
14088        		  if (status == 1)
14089        		  {
14090        	            sprintf(outbuf,"%%DFU-S-REMOVED, File %s removed",list->name);
14091        	            put_disp();
14092        		  }
14093        	          else
14094        	          { 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 60
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (9)

14095        	            sprintf(outbuf,"%%DFU-E-NOTREM, File %s not removed",list->name);
14096        	            put_disp(); singlemsg(0,status);
14097        	          }
14098        	        }
14099        	      }
14100        	      first = list->next;
14101        	      free(list); /*Return dynamic space to pool */
14102        	    }
14103        	  }
14104        	  if (ctrlc) do_abort();
14105        	
14106        	  cleanup();  
14107        	  sprintf(outbuf,"\n%%DFU-I-READY, VERIFY command ready");
14108        	  put_disp();
14109        	  if (matstat == TRUE) status = lib$show_timer(0,0,display_stat,0);
14110        	  return(1);
14111        	}
14112        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 61
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (10)

             	
14113        	void report_lost_files(Boolean matfix, Boolean matoutput, Boolean matdir)
14114        	/* The dynamic tables build up in Phase 1 of verify will be used
14115        	   to check for lost files. If the backlink = 0 or points to an
14116        	   invalid or vanished directory we have a lost file. In case of a
14117        	   volume set we must use the RVN field in the dynamic array to
14118        	   check the backlink on another disk */
14119        	
14120        	{ 
14121        	  struct _da *temp;
14122        	  struct header_area_struct *hdr, *hdr1;
14123        	  struct ident_area_struct *id;
14124        	  register int i;
14125        	  int j, k, maxi, rvn, xrvn, status, namelen, dirlen, function;
14126        	  char name[86], dirname[86];
14127        	
14128        	  sprintf(outbuf,"%%DFU-I-CHKLOST, Checking for lost files...");
14129        	  put_disp(); 
14130        	  if (matoutput) fprintf(fp,"%s\n",outbuf);
14131        	  hdr = (struct header_area_struct *) &header[0];
14132        	  hdr1 = (struct header_area_struct *) &header[1];
14133        	  for (j = 1; j <= maxvol; j++)
14134        	  { 
14135        	    dyn_array = (struct _da *) rvt[j].addr[0]; /* Pointer to correct table */
14136        	    maxi = dyn_array->bakfid; /* We saved to highest found header here */
14137        	    for (i = 1; i<=maxi; i++)
14138        	    { 
14139        	      if (i == 4) goto skip; /* Skip MFD */
14140        	
14141        	      /* Lost file bit must be set*/
14142        	      if (( (dyn_array+i)->bitje & 1) != 1) goto skip; 
14143        	      /* Invalid backlink already reported */
14144        	      if (( (dyn_array+i)->bitje & 2) == 2) goto skip; 
14145        	      /* Check if backlink on other volume */
14146        	      k = (dyn_array+i)->bakfid;
14147        	      if (( (dyn_array+i)->bitje & 8) == 8) 
14148        	      { 
14149        	        xrvn = (dyn_array+i)->rvn; /* get rvn */
14150        	        temp = (struct _da *) rvt[xrvn].addr[0];  /* point to correct table */
14151        	        temp = (temp+k); /* Get backlink record */
14152        	      }
14153        	      else 
14154        	      { 
14155        	        xrvn = j;
14156        	        temp = (dyn_array+k); /*Get backlink record */
14157        	      }
14158        	      /* Temp now points to the file backlink file header (parent directory). 
14159        	         If this file is not valid we have a lost header */
14160        	      /* case 1 : Valid file bit clear. Probably this directory is deleted*/
14161        	      namelen = -1;
14162        	      function = 2;
14163        	      if ( (temp->bitje & 16) != 16) 
14164        	      { 
14165        	        vbn = i - 1 + rvt[j].vbn_file_1; /*Read this header */
14166        	        status = SYS$QIOW(0,rvt[j].channel,IO$_READVBLK,
14167        	        &iostat[0],0,0,&header[0],512,vbn,0,0,0);
14168        	        id = (struct ident_area_struct *) 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 62
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (10)

14169        	          &header[0].block[2*(hdr->idoffset)];  /* Ident area */
14170        	        memcpy(&name[0], id->filename,20);
14171        	        if (name[19] != ' ') memcpy(&name[20], id->filenamext,66);
14172        	        namelen = strindex(&name[0]," ", 86);        
14173        	        sprintf(outbuf,
14174        	        "%%DFU-W-LOSTHDR1, file (%d,%d,%d) %.*s found in nonexistent directory"
14175        	          ,i ,hdr->fid_overlay.fid_fields.fid_seq,j,namelen,name);
14176        	        put_disp(); 
14177        	        if (matoutput) fprintf(fp,"%s\n",outbuf);
14178        	      }
14179        	      else
14180        	
14181        	        /* case 2 and 3 : directory has invalid backlink, or directory bit not set */
14182        	
14183        	      { 
14184        	        if ( ((temp->bitje & 2) == 2) || ((temp->bitje & 4) != 4) )
14185        	        { 
14186        	          vbn = i - 1 + rvt[j].vbn_file_1; /*Read this header */
14187        	          status = SYS$QIOW(0,rvt[j].channel,IO$_READVBLK,
14188        	          &iostat[0],0,0,&header[0],512,vbn,0,0,0);
14189        	          id = (struct ident_area_struct *) 
14190        	            &header[0].block[2*(hdr->idoffset)];  /* Ident area */
14191        	          memcpy(&name[0], id->filename,20);
14192        	          if (name[19] != ' ') memcpy(&name[20], id->filenamext,66);
14193        	          namelen = strindex(&name[0]," ", 86);        
14194        	          vbn = k - 1 + rvt[xrvn].vbn_file_1; /*Read backlink header */
14195        	          status = SYS$QIOW(0,rvt[xrvn].channel,IO$_READVBLK,
14196        	          &iostat[0],0,0,&header[1],512,vbn,0,0,0);
14197        	          id = (struct ident_area_struct *) 
14198        	            &header[1].block[2*(hdr1->idoffset)];  /* Ident area */
14199        	          memcpy(&dirname[0], id->filename,20);
14200        	          if (dirname[19] != ' ') memcpy(&dirname[20], id->filenamext,66);
14201        	          dirlen = strindex(&dirname[0]," ", 86);        
14202        	          if ((temp->bitje & 2) == 2)
14203        	            sprintf(outbuf,"%%DFU-W-LOSTHDR2, file (%d,%d,%d) %.*s in directory with bad backlink (%d,%d,%d) %.*s"
14204        	              ,i ,hdr->fid_overlay.fid_fields.fid_seq,j,namelen,name,
14205        	            k ,hdr1->fid_overlay.fid_fields.fid_seq,xrvn,dirlen,dirname);
14206        	          else
14207        	            sprintf(outbuf,"%%DFU-W-LOSTHDR3, file (%d,%d,%d) %.*s found in invalid directory (%d,%d,%d) %.*s"
14208        	              ,i ,hdr->fid_overlay.fid_fields.fid_seq,j,namelen,name,
14209        	            k ,hdr1->fid_overlay.fid_fields.fid_seq,xrvn,dirlen,dirname);
14210        	          put_disp(); 
14211        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
14212        	        }
14213        	        else if(matdir) /* Case 4, file not found in a directory */
14214        	        { 
14215        	          function = 6;
14216        	          vbn = i - 1 + rvt[j].vbn_file_1; /*Read this header */
14217        	          status = SYS$QIOW(0,rvt[j].channel,IO$_READVBLK,
14218        	          &iostat[0],0,0,&header[0],512,vbn,0,0,0);
14219        	          id = (struct ident_area_struct *) 
14220        	            &header[0].block[2*(hdr->idoffset)];  /* Ident area */
14221        	          memcpy(&name[0], id->filename,20);
14222        	          if (name[19] != ' ') memcpy(&name[20], id->filenamext,66);
14223        	          namelen = strindex(&name[0]," ", 86);        
14224        	          sprintf(outbuf,
14225        	          "%%DFU-W-LOSTHDR4, file (%d,%d,%d) %.*s not found in a directory"

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 63
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (10)

14226        	            ,i ,hdr->fid_overlay.fid_fields.fid_seq,j,namelen,name);
14227        	          put_disp(); 
14228        	          if (matoutput) fprintf(fp,"%s\n",outbuf);
14229        	        }
14230        	      }
14231        	      if (matfix && ( namelen != -1))
14232        	      { 
14233        		make_list();
14234        	/* Fill in File id ;  First we remove the old entry 
14235        	            next we enter the file in syslost */
14236        	        if (function !=6)
14237        	        { 
14238        	          list->fid_rvn = j;
14239        	          list->fid_num = i % 65536;
14240        	          list->fid_seq = hdr->fid_overlay.fid_fields.fid_seq;
14241        	          list->fid_nmx = i / 65536;
14242        	          list->function = 3; 
14243        	          list->next = NULL;
14244        	          list->next = (struct work *) malloc(sizeof(struct work));
14245        	          list = list->next;
14246        	        }
14247        	        list->fid_rvn = j;
14248        	        list->fid_num = i % 65536;
14249        	        list->fid_seq = hdr->fid_overlay.fid_fields.fid_seq;
14250        	        list->fid_nmx = i / 65536;
14251        	        list->function = function; 
14252        	        if (function == 6) /* Also enter directory backlink */
14253        	          copy_fid(&list->did_num ,&hdr->bk_fid_overlay.backlink[0], FALSE) ;
14254        	        if (list->did_rvn == 0) list->did_rvn = j;
14255        	        list->next = NULL;
14256        	        strncpy(list->name,name,namelen);
14257        	      }
14258        	skip: 
14259        	      ; /* Next header */
14260        	      if (ctrlc ==1) i = maxi; /* Dumb method to break off the report */
14261        	    } /* End i loop */
14262        	    if (ctrlc == 1) j = maxvol;
14263        	  } /* End j loop */
14264        	}
14265        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 64
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (11)

             	
14266        	int build_dir_table(char *dev_str, Boolean matoutput)
14267        	/*
14268        	    Build directory table needed for DIR/VERSION, DIR/EMPTY
14269        		and DIR/ALIAS
14270        	*/
14271        	
14272        	{
14273        	  static char dummy_item[80], name[86];
14274        	  struct header_area_struct *hdr;
14275        	  struct ident_area_struct *id;
14276        	  Boolean dummy, bitset;
14277        	  register int i;
14278        	  int ivbn, bitblk, bitje, bitval, find, rvn, x, maxdir, previous,
14279        	  k, size, free_hdr, a_size, r_size, hdrs, namelen, rtvptr;
14280        	  unsigned int page_cnt, dir_cnt, bakfid;
14281        	  void get_map_pointers(), dfu_handler();
14282        	  /* FAO parameters */
14283        	  unsigned short outlen; 
14284        	  $DESCRIPTOR(out_descr , outbuf);
14285        	  $DESCRIPTOR(device_descr , device);
14286        	  $DESCRIPTOR(dummy_descr , dummy_item);
14287        	
14288        	  /* Code starts here */
14289        	  /* Parse the various qualifiers */
14290        	
14291        	  /* Get device name */
14292        	  strcpy(device, dev_str);
14293        	  device_descr.dsc$w_length = strlen(device);
14294        	  if (strindex(&device,":",64) == -1) 
14295        	  {
14296        	    device[device_descr.dsc$w_length]=':'; 
14297        	    device_descr.dsc$w_length += 1;
14298        	  }
14299        	
14300        	  progress_ind = TRUE;
14301        	  /* All qualifiers parsed */
14302        	  clean_flags.fopen = 0;
14303        	  clean_flags.sort = 0;
14304        	  clean_flags.channels = 0;
14305        	  clean_flags.events = 0;
14306        	  clean_flags.expreg = 0;
14307        	  dir_cnt = 0;
14308        	
14309        	  /* Open the volume (set) , read in the home block */
14310        	
14311        	  status = open_device(&device_descr,0);
14312        	  if ((status & 1) != 1) return(status);
14313        	
14314        	  curvol = 1; 
14315        	  size = 1;
14316        	  ctx.end = FALSE;
14317        	  if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id,&SMG$M_CURSOR_OFF);
14318        	  while ((curvol <= maxvol) && (!ctx.end))
14319        	  { 
14320        	    ctx.i = -1;
14321        	    if (rvt[curvol].i_open ==1) 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 65
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (11)

14322        	    { 
14323        	      if (maxvol == 1)
14324        	      {	
14325        	        sprintf(outbuf,"%%DFU-I-INDSCAN, Making directory table for %.*s (%s) ",
14326        	        device_descr.dsc$w_length, device, &rvt[curvol].fulldevnam[1]); 
14327        	      }
14328        	      else
14329        	      {	
14330        	        sprintf(outbuf,"%%DFU-I-INDSCAN, Making directory table for %.*s (%s) , RVN = %d",
14331        	        rvt[curvol].devnam_len, rvt[curvol].devnam, 
14332        	        &rvt[curvol].fulldevnam[1], curvol); 
14333        	      }
14334        	      put_disp();
14335        	      headers=0; 
14336        	      previous = 0;
14337        	      /* Phase 1 : Read and parse INDEXF.SYS */
14338        	      /* Create dynamic array. each entry = 20 bytes. */
14339        	
14340        	      page_cnt = 1 + (rvt[curvol].if_size*sizeof(struct _da))/512;
14341        	      rvt[curvol].addr[0] = 0;
14342        	      rvt[curvol].bmap_addr[0] = 0;
14343        	      status = SYS$EXPREG(page_cnt, &rvt[curvol].addr[0],0,0);
14344        	      if ((status &1) != 1)
14345        	      { 
14346        	        singlemsg(DFU_EXPREG,status); 
14347        	        cleanup(); 
14348        	        return(status);
14349        	      }
14350        	      clean_flags.expreg = 1;
14351        	      dyn_array = (struct _da *) rvt[curvol].addr[0]; /* Setup pointer to array */
14352        	
14353        	      /* Read in index file bitmap, and return free hdrs + highest bit set */
14354        	      read_indexf_bitmap(&free_hdr);
14355        	
14356        	      status = get_next_header();
14357        	      if ((status & 1) != 1) return(status);
14358        	      while (! ctx.end) /* Loop until end of INDEXF or CTRL C entered */
14359        	      { 
14360        	        hdr = ctx.hdr;
14361        	        id = ctx.id;
14362        	        status = verify_header(hdr);
14363        	        if (status != SS$_NORMAL) goto next_file; 
14364        	        /* Setup fields in dynamic array */
14365        	        (dyn_array+headers)->fid[0] = hdr->fid_overlay.fid[0];
14366        	        (dyn_array+headers)->fid[1] = hdr->fid_overlay.fid[1];
14367        	        (dyn_array+headers)->fid[2] = hdr->fid_overlay.fid[2];
14368        	        bakfid = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx << 16;
14369        	        bakfid += hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num;
14370        	        (dyn_array+headers)->bakfid = bakfid;
14371        	        (dyn_array+headers)->a_size = 0;
14372        	        (dyn_array+headers)->f_link = 0;
14373        	        a_size = hdr->hiblk_overlay.hiblk_fields.hiblkh << 16;
14374        	        a_size += hdr->hiblk_overlay.hiblk_fields.hiblkl;
14375        	        (dyn_array+headers)->a_size = a_size;
14376        	
14377        	        /* We have a valid header, proceed...*/
14378        	        if (hdr->seg_num !=0) goto next_file; /* Skip extension header */

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 66
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (11)

14379        	
14380        	        /* Check marked for delete bit */
14381        	        if ((hdr->filechar & FH2$M_MARKDEL) == FH2$M_MARKDEL) goto next_file;
14382        	
14383        	        /* Use bit 4 as a valid file indicator */
14384        	        (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 16;
14385        	
14386        	        /* Check if this is a directory and if yes set bit 2 */
14387        	        if ((hdr->filechar & FH2$M_DIRECTORY) == FH2$M_DIRECTORY)
14388        	        { 
14389        	          if ((hdr->filechar & FH2$M_CONTIG) != FH2$M_CONTIG) goto next_file;
14390        	          if ((hdr->rattrib & FAT$M_NOSPAN) != FAT$M_NOSPAN) goto next_file;
14391        	          memcpy(&name[0],id->filename,20);
14392        	          if (name[19] != ' ') memcpy(&name[20],id->filenamext,66);
14393        	          if (strstr(name,".DIR;1") == 0) goto next_file; 
14394        	          /* Fill in forward link */
14395        	          if (previous !=0) (dyn_array+previous)->f_link = headers;
14396        	          previous = headers;
14397        	          (dyn_array+headers)->bitje = (dyn_array+headers)->bitje | 4;
14398        	          dir_cnt++;
14399        	        }
14400        	        /* Next header */
14401        	next_file: 
14402        	        status = get_next_header();
14403        	        if ((status & 1) != 1) return(status);
14404        	      }
14405        	    }
14406        	    /* Save array bounds */
14407        	    dyn_array->fid[0] = headers % 65536;
14408        	    dyn_array->fid[1] = headers / 65536;
14409        	    if (ctrlc == 1)
14410        	    { 
14411        	      ctx.end = TRUE;
14412        	    }
14413        	    else
14414        	    { 
14415        	      curvol++; 
14416        	      ctx.end = FALSE; /* Next volume */
14417        	      if (clean_flags.events == 1) 
14418        	      { 
14419        	        for (i=1; i <= iocnt ; i++) status = lib$free_ef(&efn[i-1]);
14420        	        clean_flags.events = 0;
14421        	      }
14422        	      if (curvol <= maxvol) 
14423        	      { 
14424        	        sprintf(outbuf," ");
14425        	        put_disp();
14426        	      }
14427        	    }
14428        	  }
14429        	  curvol = 1;
14430        	  /* Now scan all the directories */
14431        	  sprintf(outbuf,"     Progress : 100%%     Status : READY");
14432        	  put_status(1);
14433        	  if (ctrlc !=1) 
14434        	  { 
14435        	    sprintf(outbuf,"%%DFU-I-DIRSCAN, Scanning %d directories...",

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 67
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (11)

14436        	    dir_cnt);
14437        	    put_disp();
14438        	  }
14439        	  /* First close the channels as we need them in SCAN_DIRECTORIES */
14440        	  for (i = 1; i <= maxvol; i++)
14441        	    status = SYS$QIOW(0,rvt[i].channel,IO$_DEACCESS,&iostat[iocnt],
14442        	    0,0,0,0,0,0,0,0); 
14443        	  /* Now scan the directories */
14444        	  maxdir = dir_cnt;
14445        	  dir_cnt = 0;
14446        	  for (i = 1; i <= maxvol; i++)
14447        	    if (ctrlc !=1) 
14448        	      dir_cnt += scan_directories(&rvt[0] , i, dir_cnt, maxdir, matoutput, 0);
14449        	  sprintf(outbuf,"     Progress : 100%%     Status : READY");
14450        	  put_status(1);
14451        	
14452        	  sprintf(outbuf," "); 
14453        	  put_disp();
14454        	  if (ctrlc == 1) do_abort();
14455        	  sprintf(outbuf,"%%DFU-S-DONE, Directories scanned : %d",dir_cnt);
14456        	  put_disp();
14457        	  cleanup();  
14458        	  return(1);
14459        	}
14460        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 68
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (12)

             	
14461        	int parse_item(char *inp, struct dsc$descriptor *return_descr,
14462        	int *convert, Boolean *flag, int typ) 
14463        	/* Check presence of parameter  in command line
14464        	     Called to verify all command qualifiers
14465        		Outputs :
14466        		  result string and length
14467        		  flag set to true or false
14468        		  value converted to integer in *convert if typ indicates integer
14469        	  */
14470        	
14471        	{
14472        	  int stat, i, j, x, *y;
14473        	  static char item[80], uic_s[30], uic_x[30];
14474        	  struct _flist *tmp;
14475        	  struct _quad *tmpdat;
14476        	  char date[23];
14477        	  $DESCRIPTOR(item_descr , item);
14478        	  $DESCRIPTOR(uic_descr , uic_s);
14479        	
14480        	  strcpy(item,inp);
14481        	  item_descr.dsc$w_length = strlen(item);
14482        	  *flag = FALSE;	/* Assume item not present */
14483        	
14484        	  stat = CLI$PRESENT(&item_descr); 
14485        	  if ((stat == CLI$_PRESENT ) || (stat == CLI$_NEGATED))
14486        	  { 
14487        	    *flag = TRUE;
14488        	    switch(typ)
14489        	    { 
14490        	    case 0 : /* Get the string */
14491        	      stat = CLI$GET_VALUE(&item_descr,return_descr,
14492        	      &return_descr->dsc$w_length);
14493        	      if ((stat & 1) != 1) return(stat); 
14494        	      break;
14495        	    case 1 : /* Convert to integer */
14496        	      *convert = 0;
14497        	      return_descr->dsc$w_length = 80; 
14498        	      stat = CLI$GET_VALUE(&item_descr,return_descr,
14499        	      &return_descr->dsc$w_length);
14500        	      if ((stat & 1) != 1) return(stat); 
14501        	      *convert = atoi(return_descr->dsc$a_pointer); 
14502        	      if (*convert < 0) 
14503        	      { 
14504        	        sprintf(outbuf,"%%DFU-E-PARSEERR, Value must be a positive integer");
14505        	        put_disp(); 
14506        	        *flag = FALSE;
14507        	        return(0);
14508        	      }
14509        	      break; 
14510        	    case 2 : /* Only check the presence */
14511        	      break;
14512        	    case 3 : /* List processing for /file and /exclude */
14513        	      tmp = (struct _flist *)convert;  
14514        	      /* convert used as address to list */
14515        	      y = (int *) return_descr->dsc$a_pointer; /* list counter */
14516        	      *y = 0;

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 69
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (12)

14517        	      return_descr->dsc$a_pointer = (char *) &tmp->name;
14518        	      stat = CLI$GET_VALUE(&item_descr, return_descr, &i);
14519        	      tmp->flen = i;
14520        	      while (stat != CLI$_ABSENT)
14521        	      { 
14522        	        x = strindex(tmp->name,";",86);
14523        	        if (x == -1) 
14524        	        { 
14525        	          x = strindex(tmp->name," ",86);
14526        	          memset(&tmp->name[x],'\0',1);
14527        	          strcat(tmp->name,";*"); 
14528        	          tmp->flen += 2;
14529        	        }
14530        	        else 
14531        	          if (tmp->name[x+1] == ' ')
14532        	          { 
14533        	            memset(&tmp->name[x+1],'*',1) ; 
14534        	            tmp->flen += 1;
14535        	          }
14536        	        *y = *y + 1;
14537        	        tmp++; /* next item*/
14538        	        return_descr->dsc$a_pointer = (char *) &tmp->name;
14539        	        stat = CLI$GET_VALUE(&item_descr, return_descr, &i);
14540        	        tmp->flen = i;
14541        	      }
14542        	      return_descr->dsc$a_pointer = (char *) y;
14543        	      break;
14544        	    case 4: /* Date and time options */
14545        	      return_descr->dsc$a_pointer = (char *) &date;
14546        	      return_descr->dsc$w_length = 23;
14547        	      tmpdat = (struct _quad *) convert;
14548        	      if (stat == CLI$_NEGATED)
14549        	      { 
14550        	        tmpdat->date[0] = 0;
14551        	        tmpdat->date[1] = 0;
14552        	      }
14553        	      else
14554        	      { 
14555        	        stat = CLI$GET_VALUE(&item_descr,return_descr, 
14556        	        &return_descr->dsc$w_length);
14557        	        if ((stat & 1) != 1) return(stat); 
14558        	        stat = SYS$BINTIM(return_descr, &tmpdat->date[0]);
14559        	      }
14560        	      break;
14561        	    case 5 : /* Bit set options */
14562        	      y = (int *) return_descr->dsc$a_pointer; /* Characteristics */
14563        	      *y = *y | *convert;
14564        	      break;
14565        	    case 6 : /* UIC parsing */
14566        	      j = 0;
14567        	      stat = CLI$GET_VALUE(&item_descr, &uic_descr,
14568        	      &uic_descr.dsc$w_length);
14569        	      if (stat != CLI$_ABSENT)
14570        	      { 
14571        	        status = parse_uic(&uic_descr, &j);
14572        	        if ((status &1) != 1) return(status);
14573        	      } 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 70
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (12)

14574        	      else j = 0;
14575        	      *convert = j;
14576        	      break;
14577        	    case 7 : /* Check if negated */
14578        	      *convert = 0;
14579        	      if (stat == CLI$_NEGATED) *convert = -1;
14580        	      break;
14581        	    }
14582        	    return(1);
14583        	  }
14584        	  else return(1);
14585        	}
14586        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 71
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (13)

             	
14587        	void fid_to_name(char * ret_dir)
14588        	/* 
14589        	   Get the filename from the file-id or the file header 
14590        	   Implicit input : ctx block
14591        	   V2.2 : fixed volume set problem
14592        	*/
14593        	{ 
14594        	  Boolean error;
14595        	  struct header_area_struct *hdr;
14596        	  struct ident_area_struct *id;
14597        	  static struct fibdef fib;	/* File information block */
14598        	  struct { 
14599        	    int fiblen; 
14600        	    struct fibdef *fibadr; 
14601        	  } 
14602        	  fibdescr;
14603        	  int x, bakfid, rrvn;
14604        	  char name[86], *tmp;
14605        	
14606        	  /* Fill in FIB */
14607        	  fibdescr.fiblen = sizeof(fib);
14608        	  fibdescr.fibadr = &fib;
14609        	
14610        	  error = FALSE;
14611        	  hdr = ctx.hdr;
14612        	  bakfid = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_nmx << 16;
14613        	  bakfid += hdr->bk_fid_overlay.bk_fid_fields.bk_fid_num;
14614        	  rrvn = hdr->bk_fid_overlay.bk_fid_fields.bk_fid_rvn;
14615        	  if (rrvn == 0) rrvn = curvol;
14616        	  if (bakfid == 0 ) 
14617        	    /* invalid backlink */
14618        	    error = TRUE;
14619        	  else /* Get the full file name via an ACP call */
14620        	  { 
14621        	    copy_fid(&fib.fib$w_fid[0], &hdr->fid_overlay.fid_fields.fid_num,
14622        	    TRUE);
14623        	    fib.fib$w_did[0] = 0;
14624        	    fib.fib$w_did[1] = 0;
14625        	    fib.fib$w_did[2] = 0;
14626        	    fib.fib$w_nmctl = 0;
14627        	    fib.fib$l_acctl = 0;
14628        	    status = SYS$QIOW(0,rvt[curvol].channel,IO$_ACCESS,
14629        	    &iostat[iocnt],0,0,&fibdescr,0,0,0,&acb,0);
14630        	    if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
14631        	    if ((status & 1) !=1)
14632        	    { 
14633        	      error = TRUE;
14634        	      /*     singlemsg(0,status); */
14635        	    }
14636        	    else 
14637        	    { 
14638        	      x = strindex(&dirrec.dirnam,"[",198);
14639        	      /* Make sure we use the correct device name on voluem sets */
14640        	      if (bakfid == 4) 
14641        	        strcpy(ret_dir,&rvt[rrvn].fulldevnam[1]); 
14642        	      else strcpy(ret_dir,&rvt[1].fulldevnam[1]); 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 72
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (13)

14643        	      if (x != -1) strcat(ret_dir,&dirrec.dirnam[x]);
14644        	    }    
14645        	  }
14646        	  if (error)
14647        	  { 
14648        	    id = ctx.id;
14649        	    memcpy(&name[0],id->filename,20);
14650        	    if (name[19] != ' ') memcpy(&name[20],id->filenamext,66);
14651        	    tmp = (char *) strstr(&name," ");
14652        	    if (tmp != NULL) *tmp = 0;
14653        	    strcpy(ret_dir,"[]"); 
14654        	    strcat(ret_dir,name); 
14655        	    strcpy(dirrec.dirnam,ret_dir); 
14656        	    dirrec.lendir = strindex(ret_dir," ",200);
14657        	  } 
14658        	}
14659        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 73
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (14)

             	
14660        	int open_device(struct dsc$descriptor *device_descr, int flag)
14661        	/* Open the device or volume set.
14662        	   Outputs :
14663        		All fields in RVT (relative volume table)
14664        		Flags : 0 -> process volume set
14665        			1 -> process volume set and lock the volumes on LOCK_CHAN
14666        			2 -> ignore volume set processing (INDEXF command only)
14667        		V2.4: Flush extent cache
14668        	*/
14669        	
14670        	{
14671        	  register int i;
14672        	  static struct fibdef if_fib;	/* File information block */
14673        	  struct { 
14674        	    int fiblen; 
14675        	    struct fibdef *fibadr; 
14676        	  } 
14677        	  fibdescr;
14678        	  struct _it3 item_list[10];
14679        	  int bytes, stat, devclass, devchar, func_code, efblk, volnum, 
14680        	  devtype, acptype;
14681        	  struct header_area_struct *hdr_area;   
14682        	
14683        	  /* Fill in FIB */
14684        	  fibdescr.fiblen = 10; /* Short FIB */
14685        	
14686        	  fibdescr.fibadr = &if_fib; 
14687        	  if_fib.fib$l_acctl = FIB$M_WRITE | FIB$M_NOLOCK;
14688        	  if_fib.fib$w_fid[0] = 1;
14689        	  if_fib.fib$w_fid[1] = 1;
14690        	  if_fib.fib$w_fid[2] = 0;
14691        	  maxvol = 0; 
14692        	  curvol = 1;
14693        	  strcpy(rvt[1].devnam," ");
14694        	
14695        	  /* Set up itemlist for GETDVI */
14696        	  add_item(&item_list[0].buflen, 64, DVI$_ROOTDEVNAM, 
14697        	  &rvt[1].devnam, &rvt[1].devnam_len);
14698        	  add_item(&item_list[1].buflen,4, DVI$_VOLCOUNT, &volcount, 0);
14699        	  add_item(&item_list[2].buflen,4, DVI$_VOLNUMBER, &orig_rvn, 0);
14700        	  add_item(&item_list[3].buflen,4, DVI$_DEVCLASS, &devclass, 0);
14701        	  add_item(&item_list[4].buflen,4, DVI$_DEVCHAR, &devchar, 0);
14702        	  add_item(&item_list[5].buflen,4, DVI$_MAXBLOCK, &rvt[1].maxblocks, 0);
14703        	  add_item(&item_list[6].buflen,4, DVI$_DEVTYPE, &devtype, 0);
14704        	  add_item(&item_list[7].buflen,64,DVI$_FULLDEVNAM,
14705        	  &rvt[1].fulldevnam, &rvt[1].fulldevnam_len);
14706        	  add_item(&item_list[8].buflen,4,DVI$_ACPTYPE, &acptype, 0);
14707        	  add_item(&item_list[9].buflen,0,0,0,0);
14708        	
14709        	  stat = SYS$GETDVIW(0,0,device_descr,&item_list,&iostat[0],0,0,0);
14710        	  if ((stat & 1) == 1) stat = iostat[0].iosb_1; 
14711        	  if ((stat & 1) != 1) 
14712        	  { 
14713        	    singlemsg(0,stat);
14714        	    return(stat);
14715        	  }

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 74
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (14)

14716        	  /* Now check for some errors */
14717        	  if ((devchar & DEV$M_MNT) != DEV$M_MNT) 
14718        	  { 
14719        	    sprintf(outbuf,"%%DFU-E-NOTMNT, Device is not mounted or not available");
14720        	    put_disp();
14721        	    return(SS$_NOSUCHDEV);
14722        	  }
14723        	  if (devclass != DC$_DISK) 
14724        	  { 
14725        	    sprintf(outbuf,"%%DFU-E-NODISK, Device is not a disk device");
14726        	    put_disp();
14727        	    return(SS$_NOSUCHDEV);
14728        	  }
14729        	  if (acptype != DVI$C_ACP_F11V2)
14730        	  { 
14731        	    sprintf(outbuf,"%%DFU-E-NOTF11, Device does not have an ODS2 filesystem");
14732        	    put_disp();
14733        	    return(SS$_NOSUCHDEV);
14734        	  }
14735        	  if (flag == 2) volcount = 1;
14736        	  if (volcount > 32)
14737        	  { 
14738        	    sprintf(outbuf,"%%DFU-F-TOOMANYVOL, DFU does not allow > 32 volumes");
14739        	    put_disp();
14740        	    return(SS$_NOSUCHDEV);
14741        	  }
14742        	
14743        	  /* So we have a valid device, proceed... */
14744        	
14745        	  if ((devtype == 34) || (devtype == 53) || (devtype ==72))
14746        	    rvt[1].slow = TRUE;
14747        	  else rvt[1].slow = FALSE; /* Decide if we have a CD ROM */
14748        	  if ((devchar & DEV$M_SWL) == DEV$M_SWL) /* We have a write locked device */
14749        	  { 
14750        	    if_fib.fib$l_acctl = FIB$M_NOLOCK;
14751        	    rvt[1].wlk = TRUE;
14752        	  } 
14753        	  else rvt[1].wlk = FALSE;
14754        	  maxvol=volcount;
14755        	  if (volcount > 1)  /* Use root device name in case of volume set */
14756        	  { 
14757        	    strcpy(device_descr->dsc$a_pointer , rvt[1].devnam);
14758        	    device_descr->dsc$w_length = rvt[1].devnam_len;
14759        	  }
14760        	  else /* Reset original name entered on command line */
14761        	  { 
14762        	    strncpy(rvt[1].devnam , device_descr->dsc$a_pointer, 
14763        	    device_descr->dsc$w_length);
14764        	    rvt[1].devnam_len = device_descr->dsc$w_length;
14765        	  }
14766        	
14767        	  /* Make sure we have the correct maxblocks for the root device name */
14768        	  if ((volcount > 1) && (orig_rvn != 1))
14769        	  { 
14770        	    add_item(&item_list[0].buflen, 4, DVI$_MAXBLOCK, &rvt[1].maxblocks, 0);
14771        	    add_item(&item_list[1].buflen, 64,DVI$_FULLDEVNAM, 
14772        	    &rvt[1].fulldevnam, &rvt[1].fulldevnam_len);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 75
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (14)

14773        	    add_item(&item_list[2].buflen,0,0,0,0);
14774        	
14775        	    stat = SYS$GETDVIW(0,0,device_descr,&item_list,&iostat[0],0,0,0);
14776        	    if ((stat & 1) == 1) stat = iostat[0].iosb_1; 
14777        	    if ((stat & 1) != 1) 
14778        	    { 
14779        	      singlemsg(0,stat);
14780        	      return(stat);
14781        	    }
14782        	  }  
14783        	
14784        	  /* Lock volume if requested (flag=1) */
14785        	  lock_chan = 0;
14786        	  if ((flag ==1) && (rvt[1].wlk == FALSE))
14787        	  { 
14788        	    stat = SYS$ASSIGN(device_descr, &lock_chan,0,0);
14789        	    if ((stat & 1) != 1) 
14790        	    { 
14791        	      singlemsg(DFU_ASSIGN,stat); 
14792        	      cleanup(); 
14793        	      return(stat); 
14794        	    }
14795        	    stat = flush_cache(lock_chan,1);
14796        	    if_fib.fib$w_exctl = FIB$C_LOCK_VOL;
14797        	    fibdescr.fiblen = sizeof(if_fib); 
14798        	    stat = SYS$QIOW(0,lock_chan,IO$_ACPCONTROL,&iostat[0],
14799        	    0,0,&fibdescr,0,0,0,0,0);
14800        	    if_fib.fib$w_exctl = 0;
14801        	    fibdescr.fiblen = 10; /* Short FIB */
14802        	
14803        	    if ((stat & 1) == 1) stat = iostat[0].iosb_1;
14804        	    if ((stat & 1) != 1) 
14805        	    { 
14806        	      sprintf(outbuf,"%%DFU-E-LOCKERR, Error locking volume,");
14807        	      put_disp(); 
14808        	      singlemsg(0,stat);
14809        	      cleanup(); 
14810        	      return(stat);
14811        	    }
14812        	    sprintf(outbuf,"%%DFU-W-LOCKED, Volume now write locked");
14813        	    put_disp();
14814        	  }
14815        	
14816        	  /* Now loop for all members in volume set */
14817        	  func_code = IO$_ACCESS | IO$M_ACCESS;
14818        	  i=1; 
14819        	  if (maxvol ==0) maxvol = 1;
14820        	  while (i <= maxvol) 
14821        	  {
14822        	    rvt[i].i_open = 0; /* First assign a channel for this volume */
14823        	    stat = SYS$ASSIGN(device_descr,&rvt[i].channel,0,0);
14824        	    if ((stat & 1) != 1) 
14825        	    { 
14826        	      rvt[i].maxblocks=0;
14827        	      singlemsg(DFU_ASSIGN,stat); 
14828        	      cleanup();
14829        	      return(stat); 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 76
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (14)

14830        	    }
14831        	    stat = flush_cache(rvt[i].channel,0);
14832        	    clean_flags.channels = 1;
14833        	    rvt[i].i_open = 1; 
14834        	    rvt[i].vbn_file_1 = 0; 
14835        	    if (flag !=2) if_fib.fib$w_fid[2] = i; /* Fill in RVN */
14836        	    else if_fib.fib$w_fid[2] = orig_rvn;
14837        	
14838        	    /* Open the file on ACP level */
14839        	    stat = SYS$QIOW(0,rvt[i].channel,func_code,
14840        	    &iostat[0],0,0,&fibdescr,0,0,0,0,0);
14841        	    if ((stat & 1) == 1) stat = iostat[0].iosb_1; 
14842        	    if ((stat & 1) != 1) 
14843        	    { 
14844        	      singlemsg(DFU_INDEXERR,stat);
14845        	      cleanup(); 
14846        	      return(stat);
14847        	    }
14848        	
14849        	    /* Read in the home block (VBN 2) */
14850        	    stat = SYS$QIOW(0,rvt[i].channel,IO$_READVBLK,
14851        	    &iostat[0],0,0,&home[i],512,2,0,0,0);
14852        	    if ((stat & 1) == 1) stat = iostat[0].iosb_1; 
14853        	    if ((stat & 1) != 1) 
14854        	    { 
14855        	      singlemsg(0,stat);
14856        	      cleanup();
14857        	      return(stat);
14858        	    }
14859        	    if (home[i].struclev_overlay.strucver_fields.struclev != 2)
14860        	    { /* Not an ODS2 disk */
14861        	      sprintf(outbuf,"%%DFU-NOTODS2, Device is not an ODS2 disk");
14862        	      put_disp(); 
14863        	      cleanup();
14864        	      return(1);
14865        	    }
14866        	    /* read in Indexf.Sys header, we need the file size */
14867        	    rvt[i].vbn_file_1 = home[i].ibmapvbn + home[i].ibmapsize;
14868        	    stat = SYS$QIOW(0,rvt[i].channel, IO$_READVBLK,
14869        	    &iostat[0],0,0,block,512,rvt[i].vbn_file_1,0,0,0);
14870        	    if ((stat & 1) == 1) stat = iostat[0].iosb_1; 
14871        	    if ((stat & 1) != 1) 
14872        	    { 
14873        	      singlemsg(0,stat);
14874        	      cleanup();
14875        	      return(stat);
14876        	    }
14877        	    hdr_area = (struct header_area_struct *) &block[0];
14878        	    efblk = hdr_area->efblk_overlay.efblk_fields.efblkh << 16;
14879        	    efblk += hdr_area->efblk_overlay.efblk_fields.efblkl;
14880        	    rvt[i].if_size = efblk - rvt[i].vbn_file_1;
14881        	    i++;
14882        	    if (i <= maxvol) 	/*Next volume in set */
14883        	    { 
14884        	      add_item(&item_list[0].buflen, 64, DVI$_NEXTDEVNAM, 
14885        	      &rvt[0].devnam, &rvt[0].devnam_len);
14886        	      add_item(&item_list[1].buflen, 0,0,0,0);

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 77
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (14)

14887        	      stat = SYS$GETDVIW(0,0,device_descr,&item_list,&iostat[0],0,0,0);
14888        	      device_descr->dsc$w_length = rvt[0].devnam_len;
14889        	      strcpy(device_descr->dsc$a_pointer , rvt[0].devnam);
14890        	
14891        	      /* Get actual volume number and maximum blocks */
14892        	      add_item(&item_list[0].buflen, 4, DVI$_VOLNUMBER, &volnum, 0);
14893        	      add_item(&item_list[1].buflen, 4, DVI$_MAXBLOCK, &rvt[0].maxblocks, 0);
14894        	      add_item(&item_list[2].buflen, 4, DVI$_DEVCHAR, &devchar, 0);
14895        	      add_item(&item_list[3].buflen,64, DVI$_FULLDEVNAM, 
14896        	      &rvt[i].fulldevnam, &rvt[i].fulldevnam_len);
14897        	      add_item(&item_list[4].buflen,0,0,0,0);
14898        	
14899        	      stat = SYS$GETDVIW(0,0,device_descr,&item_list,&iostat[0],0,0,0);
14900        	      if ((stat & 1) == 1) stat = iostat[0].iosb_1; 
14901        	      if ((stat & 1) != 1) 
14902        	      { 
14903        	        sprintf(outbuf,"%%DFU-E-NOVOLSET, One ore more volume set members missing");
14904        	        put_disp(); 
14905        	        cleanup();
14906        	        return(stat);
14907        	      }
14908        	      i=volnum; 
14909        	      rvt[i].maxblocks = rvt[0].maxblocks;
14910        	      if ((devchar & DEV$M_SWL) == DEV$M_SWL) 
14911        	      { 
14912        	        rvt[i].wlk = TRUE; 
14913        	      }
14914        	      else
14915        	      { 
14916        	        rvt[i].wlk = FALSE; 
14917        	      }
14918        	      rvt[i].devnam_len = rvt[0].devnam_len;
14919        	      strncpy(rvt[i].devnam , rvt[0].devnam, rvt[0].devnam_len);
14920        	    }
14921        	  }
14922        	
14923        	  return(1);
14924        	}
14925        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 78
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (15)

             	
14926        	void read_indexf_bitmap(int *free_hdr)
14927        	/*
14928        	   Read in Indexf.Sys Bitmap.
14929        	   Return: Free Headers in this bitmap
14930        	           Highest bit set in this bitmap. This functions as
14931        		   a kind of logical EOF for the INDEXF.SYS.
14932        	*/
14933        	{
14934        	  register int i, j;
14935        	  char size;
14936        	  int k, endi, bitval, find, bytes;
14937        	  unsigned long int stat;
14938        	  Boolean found;
14939        	
14940        	  bytes = 512 * home[curvol].ibmapsize;
14941        	  stat = SYS$QIOW(0,rvt[curvol].channel,IO$_READVBLK,&iostat[0],
14942        	  0,0,&bitmap[1],bytes,home[curvol].ibmapvbn,0,0,0);
14943        	  endi = 1+rvt[curvol].if_size/4096; /* Maximum # of blocks used in bitmap */
14944        	  *free_hdr = 0;
14945        	  for (i=1; i <= endi; i++) /* All blocks */
14946        	    for (j=1; j <= 128; j++) /* All longwords in block i */
14947        	    { 
14948        	      bitval=0; 
14949        	      size=32;
14950        	      while (bitval < 32)    /* Search for clear bits in this longword */
14951        	      { 
14952        	        stat = lib$ffc(&bitval,&size,&bitmap[i].block[(j-1)*4],&find);
14953        	        if (stat != LIB$_NOTFOU)
14954        	        {  
14955        	          *free_hdr = *free_hdr + 1;
14956        	          bitval = find + 1;
14957        	          size = 32 - bitval;
14958        	        }
14959        	        else 
14960        	          bitval = 32; /* No free bits found */
14961        	      }
14962        	    }
14963        	
14964        	  /* Now subtract all bits in the bitmap which cannot be used
14965        	     because INDEXF.SYS is not large enough */
14966        	
14967        	  *free_hdr = *free_hdr - (endi*4096 - rvt[curvol].if_size);
14968        	
14969        	  /* We calculate the highest bit set in the bitmap. This is an 
14970        	     artificial way to detect the highest used file header in
14971        	     INDEXF.SYS so we can limit the search time */ 
14972        	  found = FALSE;
14973        	  i = endi; /* Search backwards ! */
14974        	  j = 512;
14975        	  highbit = 0; 
14976        	  size = 1;
14977        	  while (!found) 
14978        	    if (bitmap[i].block[j-1] == 0) 
14979        	    { 
14980        	      j--; 
14981        	      if (j==0) {

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 79
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (15)

14982        	        i--; 
14983        	        j = 512;
14984        	      } /* Next Block */
14985        	      if (i==0) found = TRUE; /* End of bitmap */
14986        	    }
14987        	    else
14988        	    { 
14989        	      k = 31; /* Scan longword backwards */
14990        	      while (!found)
14991        	        if (lib$extzv(&k,&size,&bitmap[i].block[j-1]) == 1) 
14992        	        { 
14993        	          found = TRUE;
14994        	        }
14995        	        else
14996        	        { 
14997        	          k--; 
14998        	          if (k==0) found = TRUE; 
14999        	        }
15000        	    }
15001        	  highbit = (i-1)*4096 + (j-1)*8 + k + 1;
15002        	  iosize = (highbit < 1500) ? (highbit/3) : 500; 
15003        	  if (rvt[1].slow) iosize = 125;
15004        	}  
15005        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 80
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (16)

             	
15006        	int read_indexf_multi()
15007        	/* Read IOSIZE file headers with IOCNT threads. 
15008        	   Return VBN where next READ IO should resume
15009        	*/
15010        	{
15011        	  int i,stat;
15012        	
15013        	  vbn = rvt[curvol].vbn_file_1; /* First file header is here */
15014        	  for (i=1; i<=iocnt; i++)	    /* Fire off 2 QIO's */
15015        	  { 
15016        	    stat = lib$get_ef(&efn[i-1]);
15017        	    if ((stat & 1) != 1) 
15018        	    { 
15019        	      sprintf(outbuf,"%%DFU-E-GETEF, Error getting event flag,");
15020        	      put_disp(); 
15021        	      singlemsg(0,stat);
15022        	      return(stat);
15023        	    }
15024        	    /* Read 500 file headers */
15025        	    stat = SYS$QIO(efn[i-1],rvt[curvol].channel,IO$_READVBLK,
15026        	    &iostat[i-1],0,0,&header[(i-1)*iosize+1],
15027        	    (iosize*512),vbn,0,0,0);
15028        	    if ((stat & 1) != 1) 
15029        	    { 
15030        	      singlemsg(DFU_IOERR,stat);
15031        	      return(stat);
15032        	    }
15033        	    if (i != iocnt) vbn += iosize ;
15034        	  }
15035        	  return(1);
15036        	}    
15037        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 81
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (17)

             	
15038        	int get_next_header()
15039        	/*
15040        	   This routine is responsible for returning the next
15041        	   file header to the calling procedure . The context is kept
15042        	   in the ctx context block, so we do not need to pass
15043        	   any arguments.
15044        	*/
15045        	{ 
15046        	  unsigned int progress;
15047        	
15048        	  if (ctx.i == -1) /*start of I/O processing */
15049        	  { 
15050        	    ctx.i = 0;
15051        	    /* Fire off the first 2 asynchrouous IO's */
15052        	    progress = 0;
15053        	    if (progress_ind)
15054        	    { 
15055        	      sprintf(outbuf,"     Progress : %3d%%     Status : Scanning INDEXF.SYS",
15056        	      progress);
15057        	      put_status(1);
15058        	    }
15059        	    headers=0;
15060        	    status = read_indexf_multi(&vbn);
15061        	    if ((status & 1) != 1) 
15062        	    { 
15063        	      cleanup(); 
15064        	      return(status); 
15065        	    }
15066        	    ctx.thread = 1;
15067        	    clean_flags.events = 1;
15068        	    status = SYS$WAITFR(efn[ctx.thread-1]); /* Wait for IO completion */
15069        	    status = iostat[ctx.thread-1].iosb_1;
15070        	    if ((status & 1) != 1) 
15071        	      if (status != SS$_ENDOFFILE)
15072        	      { 
15073        	        cleanup();
15074        	        return(status); 
15075        	      }
15076        	    ctx.starti = (ctx.thread-1)*iosize + 1;
15077        	    ctx.endi = iostat[ctx.thread-1].length/512 + ctx.starti - 1;
15078        	    ctx.i = ctx.starti - 1;
15079        	  }
15080        	  /* now get the next header */
15081        	  { 
15082        	    headers++; 
15083        	    if ((headers % 65536) ==0) 
15084        	    { 
15085        	      headers++; 
15086        	      (ctx.i)++;
15087        	    }
15088        	    (ctx.i)++; 
15089        	    if (ctx.i > ctx.endi) /* Next IOSIZE headers */
15090        	    { 
15091        	      if (ctrlc ==1) ctx.end = TRUE;
15092        	      if (iostat[ctx.thread-1].length < (iosize*512)) ctx.end = TRUE;
15093        	      if (vbn > (rvt[curvol].if_size+rvt[curvol].vbn_file_1 -1)) 

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 82
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (17)

15094        	        ctx.end = TRUE;
15095        	      if (ctx.end == FALSE) /* Read next IOSIZE headers */
15096        	      { 
15097        	        vbn += iosize;
15098        	        status = SYS$QIO(efn[ctx.thread-1],rvt[curvol].channel,IO$_READVBLK,
15099        	        &iostat[ctx.thread-1],0,0,&header[(ctx.thread-1)*iosize+1],
15100        	        (iosize*512),vbn,0,0,0);
15101        	        if ((status & 1) != 1) 
15102        	        { 
15103        	          singlemsg(DFU_IOERR,status); 
15104        	          cleanup();
15105        	          return(status);
15106        	        }
15107        	        (ctx.thread)++; 
15108        	        if (ctx.thread > iocnt) ctx.thread = 1;
15109        	      }
15110        	      if (!(ctx.end)) /* Wait for IO completion for this thread */
15111        	      { 
15112        	        status = SYS$WAITFR(efn[ctx.thread-1]); /* Wait for IO completion */
15113        	        status = iostat[ctx.thread-1].iosb_1;
15114        	        if ((status & 1) != 1) 
15115        	          if (status != SS$_ENDOFFILE)
15116        	          { 
15117        	            cleanup(); 
15118        	            ctx.end = TRUE;
15119        	            return(status); 
15120        	          }
15121        	        ctx.starti = (ctx.thread-1)*iosize + 1;
15122        	        ctx.endi = iostat[ctx.thread-1].length/512 + ctx.starti - 1;
15123        	        ctx.i = ctx.starti;
15124        	      }
15125        	      if (progress_ind)
15126        	      { 
15127        	        progress = (100*headers / highbit);
15128        	        sprintf(outbuf,"     Progress : %3d%%     Status : Scanning INDEXF.SYS",
15129        	        progress);
15130        	        put_status(1);
15131        	      }
15132        	    }
15133        	    if (ctrlc == 1) 
15134        	    { 
15135        	      ctx.end = TRUE; 
15136        	      return(1);
15137        	    }
15138        	    if (headers > highbit)         /* Do not proceed further than this */
15139        	    { 
15140        	      ctx.end = TRUE;
15141        	      return(1);
15142        	    }
15143        	    ctx.hdr = (struct header_area_struct *) &header[ctx.i];
15144        	    ctx.id = (struct ident_area_struct *) 
15145        	      &header[ctx.i].block[2*((ctx.hdr)->idoffset)];
15146        	  }
15147        	  return(1);
15148        	}
15149        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 83
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (18)

             	
15150        	void cleanup()
15151        	/*
15152        	   Various cleanup actions depending on flags
15153        	*/
15154        	{
15155        	  int i, stat;
15156        	  void dfu_handler();
15157        	
15158        	  if (clean_flags.fopen == 1) 
15159        	  { 
15160        	    stat = fclose(fp);
15161        	  }
15162        	
15163        	  if (clean_flags.sort == 1) 
15164        	  { 
15165        	    stat = sor$end_sort();
15166        	  }
15167        	
15168        	  if (clean_flags.events == 1) 
15169        	    for (i=1; i <= iocnt ; i++) 
15170        	    { 
15171        	      stat = lib$free_ef(&efn[i-1]);
15172        	    }
15173        	
15174        	  if (clean_flags.channels == 1)
15175        	    for (i=1; i <=maxvol ; i++)
15176        	    { 
15177        	      stat = SYS$QIOW(0,rvt[i].channel,IO$_DEACCESS,&iostat[iocnt],
15178        	      0,0,0,0,0,0,0,0); 
15179        	      stat = SYS$DASSGN(rvt[i].channel);
15180        	      rvt[i].channel = 0;
15181        	      if (rvt[i].bchan != 0) 
15182        	      { 
15183        	        stat = SYS$QIOW(0,rvt[i].bchan,IO$_DEACCESS,&iostat[iocnt],
15184        	        0,0,0,0,0,0,0,0); 
15185        	        stat = SYS$DASSGN(rvt[i].bchan);
15186        	        rvt[i].bchan = 0; 
15187        	      }
15188        	      if (lock_chan != 0) 
15189        	      { 
15190        	        dfu_handler();
15191        	        stat = SYS$CANEXH(&desblk);
15192        	      }
15193        	    }
15194        	
15195        	  if (clean_flags.expreg == 1)
15196        	    for (i=1; i <=maxvol ; i++)
15197        	    { 
15198        	      if (rvt[i].addr[0] != 0) 
15199        	        stat = SYS$DELTVA(&rvt[i].addr[0], &rvt[i].addr[0], 0);
15200        	      if (rvt[i].bmap_addr[0] != 0) 
15201        	        stat = SYS$DELTVA(&rvt[i].bmap_addr[0], &rvt[i].bmap_addr[0], 0);
15202        	    }
15203        	}
15204        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 84
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (19)

             	
15205        	void copy_fid(struct f_id *target,struct f_id *from, Boolean check_rvn)
15206        	/*
15207        	    Procedure to copy FID's from one structure to
15208        	    another. If check_rvn is true the rvn field will
15209        	    be filled with the value of CURVOL if it is 0
15210        	*/
15211        	{
15212        	  struct f_id *p1,*p2; /* Two dummy pointers */
15213        	
15214        	  p1 = target;
15215        	  p2 = from;
15216        	  p1->fid_num = p2->fid_num;
15217        	  p1->fid_seq = p2->fid_seq;
15218        	  p1->fid_nmx = p2->fid_nmx;
15219        	  p1->fid_rvn = p2->fid_rvn;
15220        	  if (check_rvn)
15221        	    if (p1->fid_rvn ==0) p1->fid_rvn = curvol;
15222        	}
15223        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 85
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (20)

             	
15224        	int verify_header (struct header_area_struct *fh2) 
15225        	/*
15226        	   Validate if a file header is valid. See File System
15227        	   Internals for the definition of a valid file header.
15228        	   Warning : does not check the file headers checksum
15229        	*/
15230        	{
15231        	  int highwater = 76; /* from $FH2DEF */
15232        	  if (fh2->struclev_overlay.struclev_fields.struclev != 2)
15233        	    return (SS$_BADFILEHDR);
15234        	  if (fh2->struclev_overlay.struclev_fields.strucver < 1)
15235        	    return (SS$_BADFILEHDR);
15236        	  if (fh2->idoffset < (highwater/2)) return (SS$_BADFILEHDR);
15237        	  if (fh2->idoffset > fh2->mpoffset ) return (SS$_BADFILEHDR);
15238        	  if (fh2->mpoffset > fh2->acoffset ) return (SS$_BADFILEHDR);
15239        	  if (fh2->acoffset > fh2->rsoffset ) return (SS$_BADFILEHDR);
15240        	  if (fh2->map_inuse > (fh2->acoffset - fh2->mpoffset)) return (SS$_BADFILEHDR);
15241        	  if (fh2->fid_overlay.fid_fields.fid_num == 0) return (SS$_BADFILEHDR);
15242        	  if (fh2->fid_overlay.fid_fields.fid_seq == 0) return (SS$_BADFILEHDR);
15243        	  return (SS$_NORMAL);
15244        	}
15245        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 86
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (21)

             	
15246        	void get_map_pointers(struct header_area_struct *hdr, unsigned int *ptrs)
15247        	/*
15248        	   Count retrieval pointers in file header 
15249        	   Do not count a placement pointer a s a real pointer 
15250        	*/
15251        	{ 
15252        	  unsigned int i, format, offset, map_bytes, size;
15253        	  struct _hd { 
15254        	    unsigned short block[256] ; 
15255        	  } 
15256        	  *head;
15257        	
15258        	  head = (struct _hd *) hdr; /* We can now view the header as a 256 word strcuture */
15259        	  offset    = hdr->mpoffset ;
15260        	  map_bytes = hdr->map_inuse;
15261        	  size = 0;
15262        	  *ptrs = 0;
15263        	  for (i = offset; i < offset + map_bytes;) 
15264        	  { 
15265        	    format = head->block[i] >> 14;
15266        	    (*ptrs)++;
15267        	    switch (format) {
15268        	    case 0: 
15269        	      (*ptrs)--;
15270        	      break;
15271        	
15272        	    case 1: 
15273        	      size += (head->block[i] & 255) + 1;
15274        	      break;
15275        	
15276        	    case 2: 
15277        	      size += (head->block[i] & 0x3fff) + 1;
15278        	      break;
15279        	
15280        	    case 3: 
15281        	      size += ((head->block[i] & 0x3fff) << 16);
15282        	      size += head->block[i + 1] + 1;
15283        	      break;
15284        	    }
15285        	    i += format + 1;
15286        	  }
15287        	}
15288        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 87
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (22)

             	
15289        	void disass_map_ptr(struct header_area_struct *hdr, int *j) 
15290        	/* 
15291        	    Disassemble mapping pointer. Return start lbn, count and offset to
15292        	    next ptr.
15293        	*/
15294        	{ 
15295        	  unsigned short format;
15296        	  unsigned int i;
15297        	  struct _hd { 
15298        	    unsigned short block[256] ; 
15299        	  } 
15300        	  *head;
15301        	
15302        	  head = (struct _hd *) hdr; /* We can now view the header as a 256 word strcuture */
15303        	  i = *j;
15304        	  format = head->block[i] >> 14;
15305        	  switch (format) 
15306        	  { 
15307        	  case 0: 
15308        	    lbncount = 0;
15309        	    lbnstart = 0;
15310        	    break;
15311        	  case 1: 
15312        	    lbncount = (head->block[i] & 255) + 1;
15313        	    lbnstart = ((head->block[i] & 0x3f00) << 8) 
15314        	      + head->block[i+1];
15315        	    break;
15316        	  case 2: 
15317        	    lbncount = (head->block[i] & 0x3fff) + 1;
15318        	    lbnstart = (head->block[i+2] << 16) + head->block[i+1];
15319        	    break;
15320        	  case 3: 
15321        	    lbncount = ((head->block[i] & 0x3fff) << 16) 
15322        	      + head->block[i+1] + 1;
15323        	    lbnstart = (head->block[i+3] << 16) + head->block[i+2];
15324        	    break;
15325        	  }	/* End switch */
15326        	  *j = *j + format + 1;
15327        	}
15328        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 88
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (23)

             	
15329        	int follow_extents(struct header_area_struct *hdr, int *rtv, int *num_hdrs)
15330        	/*
15331        	   Follow extension links and get the retrieval pointers
15332        	*/
15333        	
15334        	{ 
15335        	  unsigned int rtvptr, ivbn, rvn, fidnum;
15336        	  static struct header_area_struct head;
15337        	
15338        	  head.ext_fid_overlay.ext_fid[0] = hdr->ext_fid_overlay.ext_fid[0];
15339        	  head.ext_fid_overlay.ext_fid[1] = hdr->ext_fid_overlay.ext_fid[1];
15340        	  head.ext_fid_overlay.ext_fid[2] = hdr->ext_fid_overlay.ext_fid[2];
15341        	  while (head.ext_fid_overlay.ext_fid[0] !=0)
15342        	  { 
15343        	    rvn = head.ext_fid_overlay.ext_fid_fields.ext_fid_rvn;
15344        	    if (rvn == 0) rvn = curvol;
15345        	    fidnum = head.ext_fid_overlay.ext_fid_fields.ext_fid_nmx << 16;
15346        	    fidnum += head.ext_fid_overlay.ext_fid[0];
15347        	    ivbn = rvt[rvn].vbn_file_1 + fidnum - 1; 
15348        	    status = SYS$QIOW(0,rvt[rvn].channel,IO$_READVBLK,
15349        	    &iostat[iocnt],0,0,&head,512,ivbn,0,0,0);
15350        	    if ((status & 1) == 1) status = iostat[iocnt].iosb_1;
15351        	    if ((status & 1) != 1) 
15352        	    { 
15353        	      sprintf(outbuf,"%%DFU-E-READERR, Error reading extension header,");
15354        	      put_disp(); 
15355        	      singlemsg(0,status);
15356        	      head.ext_fid_overlay.ext_fid[0] = 0;
15357        	      return(status);
15358        	    }
15359        	    else
15360        	    { 
15361        	      get_map_pointers(&head, &rtvptr);
15362        	      *rtv += rtvptr;
15363        	      *num_hdrs += 1;
15364        	    }
15365        	  }
15366        	  return(1);
15367        	}
15368        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 89
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (24)

             	
15369        	void dfu_handler()
15370        	/* Exit handler to unlock volume */
15371        	
15372        	{ 
15373        	  static struct fibdef i_fib;	/* File information block */
15374        	  struct { 
15375        	    int fiblen; 
15376        	    struct fibdef *fibadr; 
15377        	  } 
15378        	  fibdescr;
15379        	  int stat;
15380        	
15381        	  fibdescr.fiblen = sizeof(i_fib); 
15382        	  fibdescr.fibadr = &i_fib;
15383        	  i_fib.fib$w_exctl = FIB$C_UNLK_VOL;
15384        	  if (lock_chan !=0)
15385        	  { 
15386        	    stat = SYS$QIOW(0,lock_chan,IO$_ACPCONTROL,&iostat[0],
15387        	    0,0,&fibdescr,0,0,0,0,0);
15388        	    sprintf(outbuf,"%%DFU-I-UNLOCK, Volume unlocked");
15389        	    put_disp();
15390        	    stat = SYS$DASSGN(lock_chan); 
15391        	    lock_chan = 0;
15392        	  }
15393        	}
15394        	

DFU_IFSCAN                                                      22-AUG-1996 11:34:54    DEC C      V5.2-003                 Page 90
V1.0                                                            22-AUG-1996 11:21:44    DFU_IFSCAN.C;1 (25)

             	
15395        	void add_item(struct _it3 *i_list, int len, int itm, int bufadr, int ret)
15396        	/*
15397        	   Routine to fill an item in an VMS item_list 
15398        	*/
15399        	
15400        	{ 
15401        	  i_list->buflen = len;
15402        	  i_list->itemcode = itm;
15403        	  i_list->bufadr = (unsigned int *) bufadr;
15404        	  i_list->retlen = (unsigned int *) ret;
15405        	}

 
 
Command Line
------------
 
CC/DECC/EXTERN=COMMON/SHARE/WARN=NOINFO DFU_IFSCAN/LIS

