              <<< NOTED::NOTES$7:[NOTES$LIBRARY]HACKERS.NOTE;1 >>>
                               -< ** Hackers ** >-
================================================================================
Note 1815.0       Quick hack to recover VMS$COMMON.DIR Backlink       No replies
UTRTSC::DORLAND "There's always one more bug!"      172 lines  10-SEP-1996 09:58
--------------------------------------------------------------------------------
    	After having to fix a 'corrupted' VMS$COMMON.DIR backlink
    	for the n'th time I wrote the program below
    	to fix this with one go.
    	Should do the job as long as there still
    	is a VMS$COMMON.DIR in the [000000] directory.
    
    	Have fun (use at your own risk).
    
    	Ton
    
    	PS: On Alpha compile with /NOMEMBER !!!!!
    
/* Program SET_COMMON.C */
    
#include fibdef
#include atrdef
#include iodef
#include ssdef
#include descrip
#include rms

main()
/* 
	This program makes sure that the backlink
	to VMS$COMMON.DIR is correct.
	This is done by calling the write attributes 
	function of the XQP . 
	This way the filename is reset to VMS$COMMON.DIR;1
	and the Backlink is set to 4,4,0 (the MFD).
*/

{ 
  static char res_str[255], exp_str[255], fname[100], devnam[15],
    old_name[86],  new_name[86] = "VMS$COMMON.DIR;1";
  static unsigned short chan, mfd_link[3];
  unsigned int status, func, i;
  struct FAB fab;
  struct NAM nam;
  static struct fibdef fib;
  struct {
    int fiblen; 
    struct fibdef *fibadr;
  } fibdescr;
  static struct {
    unsigned short iosb_1; 
    unsigned int length; 
    short spec; 
  } 
    iostat;
  static struct { 
    unsigned short atr_size, atr_type;
    int atr_address; 
  } 
  acb[3] =  { 
    {
      6, ATR$C_BACKLINK, (int) &mfd_link     }
    , 
    { 
      86, ATR$C_ASCNAME, (int) &old_name     } 
    , 
    { 0, 0, 0     } 
  };

  $DESCRIPTOR(new_name_descr, new_name);
  $DESCRIPTOR(devnam_descr, devnam);

/* Code starts here */
  strcpy(fname,"SYS$SYSDEVICE:[000000]VMS$COMMON.DIR;1");

  fibdescr.fiblen = sizeof(fib);
  fibdescr.fibadr = &fib;

/* fill in FAB and NAM blocks */

  fab = cc$rms_fab;
  fab.fab$l_fna = (char *) &fname;
  fab.fab$b_fns = strlen(fname);
  fab.fab$l_nam = &nam;

  nam = cc$rms_nam;
  nam.nam$b_rss = NAM$C_MAXRSS;
  nam.nam$l_rsa = (char *) &res_str;
  nam.nam$b_ess = NAM$C_MAXRSS;
  nam.nam$l_esa = (char *) &exp_str;

/* get the rest of the fab fields */

  status = SYS$PARSE(&fab , 0 , 0);
  if ((status & 1 ) != 1) 
  { 
    printf("PARSEERR, Error parsing filename from %s,"
      , fname); 
    LIB$SIGNAL(status); 
    return(0);
  }

/* now search for the file */

  status = SYS$SEARCH(&fab , 0 , 0);
  res_str[nam.nam$b_rsl] = '\0';
  if ((status & 1 ) != 1) 
  { 
    printf("SEARCHERR, Error searching file %s,"
      , res_str); 
    LIB$SIGNAL(status); 
    return(0);
  }
  res_str[nam.nam$b_rsl] = '\0';

/* Open a channel to the device */
  devnam_descr.dsc$w_length = nam.nam$t_dvi[0];
  strcpy(devnam,&nam.nam$t_dvi[1]);
  status = SYS$ASSIGN(&devnam_descr, &chan, 0 , 0);
  if ((status & 1 ) != 1) 
  { 
    LIB$SIGNAL(status);
    return(0);
  }

/* Now fill in File id and function code for the ACP call */
  fib.fib$w_fid[0] = nam.nam$w_fid_num;
  fib.fib$w_fid[1] = nam.nam$w_fid_seq;
  fib.fib$w_fid[2] = nam.nam$w_fid_rvn;
  fib.fib$l_acctl = 
    FIB$M_WRITE | FIB$M_WRITETHRU | FIB$M_NOWRITE | FIB$M_NOREAD |
     FIB$M_NORECORD | FIB$M_NOLOCK; 
  func = IO$_ACCESS | IO$M_ACCESS;
  status = SYS$QIOW(0, chan, func, &iostat, 0,0,
    &fibdescr, 0 ,0 ,0 , acb, 0);
  if ((status & 1) == 1) status = iostat.iosb_1;
  if ((status & 1) != 1) 
  { 
    printf("OPENERR, Error accesing file %s,", res_str);
      LIB$SIGNAL(status); 
    return(0);
  }

/* Check if we need to do anything */
  
  if ( (strncmp(old_name,"VMS$COMMON.DIR;1",16) == 0)
	&& (mfd_link[0] == 4)
	&& (mfd_link[1] == 4)
	&& (mfd_link[2] == 0) )
  {
    printf("NOCHANGE, VMS$COMMON.DIR backlink is oke\n");
    goto normal_exit;
  }
 
  for (i = 0; i < 86; i++) old_name[i] = ' ';
  memcpy(&old_name, &new_name, 16);
  mfd_link[0] = mfd_link[1] = 4;
  mfd_link[2] = 0; 

/* Now rewrite the file header attributes*/
  status = SYS$QIOW(0, chan, IO$_MODIFY, &iostat, 0,0,
    &fibdescr, 0, 0, 0, acb, 0);
  if ((status & 1) == 1) status = iostat.iosb_1;
  if ((status & 1) != 1) 
  { 
    printf("SETERR, Error modifying file %s,", res_str);
      LIB$SIGNAL(status); return(0); 
  }
   else
  { 
    printf("MODIFIED, File %s modified ",res_str);
  }
normal_exit:
  status = SYS$QIOW(0, chan, IO$_DEACCESS, &iostat ,0,0,
    &fibdescr,0,0,0,0,0);
  SYS$DASSGN(chan);
  return(1);
}
