[OpenVMS-Alpha] Example-C How to Get the Files Retreival Pointers
EXAMPLE TEMPLATE:
PRODUCT: Compaq C Version 6.5
OP/SYS: OpenVMS Alpha Version 7.3-1
COMPONENT: Disk ACP
SOURCE: Philippe Vouters Fontainebleau/France
HIGH QUALITY MOBILES+TABLETS: http://android-land.fr
OVERVIEW: This program shows how to get the number and content of the retreival pointers that can otherwise been seen with the command: $ DUMP/HEADER/BLOCK=END:0 disk:[directory]file.ext
*** CAUTION *** This sample program has been tested using Compaq C V6.5 on OpenVMS Alpha V7.3-1. However, we cannot guarantee its effectiveness because of the possibility of error in transmitting or implementing it. It is meant to be used as a template for writing your own program, and may require modification for use on your system.
PROGRAM NOTES: Extract the program to a file named FILE_EXTENT.C Compile and link the following way: $ CC FILE_EXTENT + ALPHA$LIBRARY:SYS$LIB_C/LIBRARY $ LINK FILE_EXTENT Define a foreign command: $ FILE_EXTENT :== $disk:[directory]FILE_EXTENT.EXE Activate it the following way: $ FILE_EXTENT [path:]file.ext[;version] The full filename accepts the VMS wildcards stars '*' and percent '%'. For example: $ FILE_EXTENT SYS$LIBRARY:STARLET.OLB file DSA756:[SYS14.SYSCOMMON.][SYSLIB]STARLET.OLB;24 has 8 retrieval pointers [0,1,0,30128] count = 108 LBN=3181194 [0,2,4,30128] count = 45414 LBN=8306037 [0,3,12,30128] count = 36 LBN=5059602 [0,4,18,30128] count = 39132 LBN=981603 [0,5,26,30128] count = 45 LBN=2902671 [0,6,30,30128] count = 522 LBN=1138329 [0,7,36,30128] count = 126 LBN=1145529 [0,8,40,30128] count = 36 LBN=5066784
PROGRAM: /* * COPYRIGHT (C) 2003 BY * HEWLETT-PACKARD COMPANY * ALL RIGHTS RESERVED. * * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED * ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION * OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES * THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER * PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED. * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY HEWLETT-PACKARD COMPANY. * * HP ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS * SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY HP. * * NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE * ON EQUIPMENT THAT IS NOT SUPPLIED BY HEWLETT-PACKARD COMPANY. * * SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY HP SOFTWARE * PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE * CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED. */ #ifndef __NEW_STARLET #define __NEW_STARLET #endif #include <stdio.h> #include <stdlib.h> #include <time.h> #include <errno.h> #include <string.h> #include <stddef.h> #include <iosbdef.h> #include <descrip.h> /* Descriptor Structure and Constant Definitions */ #include <fibdef.h> /* File Information Block Definitions */ #include <f11cdef.h> #include <fiddef.h> /* File identification Definitions */ #include <fatdef.h> #include <iodef.h> /* I/O function code Definitions */ #include <lib$routines.h> /* Library (LIB$) routine definitions */ #include <rms.h> /* All RMS Structure & Return Status Definitions */ #include <ssdef.h> /* System Service Return Status Value Definitions */ #include <starlet.h> /* System routine definitions*/ #include <psldef.h> #include <atrdef.h> #include <fh2def.h> #include <fh1def.h> #include <fm2def.h> #include <fm1def.h> #include <syidef.h> #include <secdef.h> #include <jpidef.h> #include <efndef.h> /* ** ** MACRO DEFINITIONS ** */ #define FM2_SIZE(x) ((x<<16) + (x>>16)) & 0x3FFFFFFF /* ** The following macro defines a status check which ** occurs numerous times throughout the program. */ #define check_s(status) \ if ( ! (status & 1) ) exit(status) #ifdef __DECC #pragma member_alignment save #pragma nomember_alignment word #endif typedef struct { unsigned short buflen; unsigned short code; void *buffer; int *retlen; } item_t; #ifdef __DECC #pragma member_alignment restore #endif typedef struct{ unsigned int segnum; unsigned int rtrcnt; unsigned int offset; unsigned int rtrptr; unsigned int count; unsigned int LBN; } retrieval_pointer_t; typedef struct { char *buffer; /* The buffer that holds the data */ int para1; /* Loops indicator for filling buffer */ int startlbn; /* File starting logical block number */ unsigned long recnum; /* Total size of information recorded */ IOSB io_status; /* $QIO I/O Status Block */ unsigned short device_channel; } ast_param_t; main(int argc, char **argv) { int rtrcnt; char esa[NAM$C_MAXRSS]; char rsa[NAM$C_MAXRSS]; char device[NAM$C_MAXRSS]; char *defaultspec = "*.BID;"; char block_fib[FIB$K_LENGTH]; char block[ISO$K_LOGICAL_BLOCK_SIZE]; FH2 * file_hdr; FM2 *fm1,*map_area; retrieval_pointer_t *retrieval_ptr=NULL, *ptr; int retrieval_count; ATRDEF atr[2]; ast_param_t ast_param; /* Declare RMS control blocks */ struct FAB fab; /* File Access Block */ FIBDEF *fib; /* File Information Block */ struct NAM nam; /* Name Block */ /* Declare Bits and Pieces for File Access */ unsigned long int status; /* Status Return */ unsigned int func; struct dsc$descriptor_s device_descr = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0}; /* Device descriptor */ struct { /* File Information Block Descriptor */ unsigned int length; FIBDEF *addr; } fib_descr; if(argc != 2){ printf("Usage $ file_extent file_name\n"); exit(1); } fib = (FIBDEF *)block_fib; file_hdr = (FH2 *)block; fib_descr.length=offsetof(FIBDEF,fib$r_did_overlay); fib_descr.addr = fib; /* ** First, fill the necessary fields in the FAB. */ /* * Set up RMS structures for the input file */ fab = cc$rms_fab; /* Begin by using the initialized */ /* template provided by the system */ fab.fab$l_fop = FAB$M_NAM; /* Use NAM Block inputs */ fab.fab$l_fna = argv[1]; /* File name string address */ fab.fab$b_fns = strlen(argv[1]); /* File name string size */ fab.fab$l_dna = defaultspec; /* File name string address */ fab.fab$b_dns = strlen(defaultspec); /* File name string size */ fab.fab$l_nam = &nam; /* File name block address */ /* ** Initialize the name block using the initialized template ** provided by the system. */ nam = cc$rms_nam; nam.nam$l_esa = esa; nam.nam$b_ess = NAM$C_MAXRSS; nam.nam$l_rsa = rsa; nam.nam$b_rss = NAM$C_MAXRSS; nam.nam$b_nop = NAM$M_NOCONCEAL; nam.nam$b_ess = NAM$C_MAXRSS; status = sys$parse(&fab,0,0); check_s (status); for (;;) { /* * Search all files and exit loop when no-more-files. */ status = sys$search (&fab, 0, 0); if (status == RMS$_NMF) break; /* * We begin by using $ASSIGN to assign a channel to * the file device. */ device_descr.dsc$w_length = nam.nam$b_dev; device_descr.dsc$a_pointer = nam.nam$l_dev; status = sys$assign (&device_descr, /* Device descriptor */ &ast_param.device_channel, /* Channel number */ 0, /* Default access mode */ 0); /* No mailbox */ check_s(status); /* Exit if error */ memset(block_fib,0,sizeof(block_fib)); fib->fib$w_fid_num=nam.nam$w_fid_num; fib->fib$w_fid_seq=nam.nam$w_fid_seq; fib->fib$w_fid_rvn=nam.nam$w_fid_rvn; /* * Also request for file header. */ memset(atr,0,2*sizeof(ATRDEF)); atr[0].atr$w_size = ATR$S_HEADER; atr[0].atr$w_type = ATR$C_HEADER; atr[0].atr$l_addr = file_hdr; if (retrieval_ptr) free(retrieval_ptr); retrieval_ptr = NULL; retrieval_count=0; func = IO$_ACCESS|IO$M_ACCESS; while (1) { #ifdef __DEBUG printf ("Accessing File ID (%1u,%1u,%1u)\n", fib->fib$w_fid_num, fib->fib$w_fid_seq, fib->fib$w_fid_rvn); #endif status = sys$qiow (EFN$C_ENF, /* event flag number */ ast_param.device_channel, /* Channel */ func, /* Access the file */ &ast_param.io_status, /* IO status block */ 0, /* No AST completion routine */ 0, /* So no AST routine parameters */ &fib_descr,/* P1 = address of FIB descriptor */ 0,0,0, /* No P2-P4 */ (__int64)atr,0);/* P5=attributes, no P6 */ check_s(status); /* Close and exit if error */ /* Close and exit if error */ check_s(ast_param.io_status.iosb$w_status); func = IO$_ACCESS; rtrcnt=0; fm1 = map_area = (FM2 *)((short *)file_hdr + file_hdr->fh2$b_mpoffset); /* * Get file's logical block numbers (LBNs) and counts. */ while (fm1<(FM2 *)((short *)map_area + file_hdr->fh2$b_map_inuse)){ if (fm1->fm2$v_format == FM2$C_PLACEMENT) fm1 = (FM2 *)((char *)fm1 + 2); else { retrieval_ptr=realloc(retrieval_ptr, (retrieval_count+1)*sizeof(retrieval_pointer_t)); ptr=retrieval_ptr+retrieval_count; ptr->segnum=file_hdr->fh2$w_seg_num; ptr->rtrcnt=++rtrcnt; ptr->offset=(unsigned int)fm1 - (unsigned int)map_area; ptr->rtrptr=(unsigned int)map_area; switch (fm1->fm2$v_format){ case FM2$C_FORMAT1: ptr->count=fm1->fm2$b_count1; ptr->LBN = fm1->fm2$w_lowlbn; ptr->LBN += fm1->fm2$v_highlbn << 16; fm1 = (FM2 *)((char *)fm1 + 4); break; case FM2$C_FORMAT2: ptr->count=fm1->fm2$v_count2; ptr->LBN = ((FM2_1 *)fm1)->fm2$l_lbn2; fm1 = (FM2 *)((char *)fm1 + 6); break; case FM2$C_FORMAT3: ptr->count=FM2_SIZE(*(unsigned int *)fm1); ptr->LBN = ((FM2_2 *)fm1)->fm2$l_lbn3; fm1 = (FM2 *)((char *)fm1 + 8); } retrieval_count++; }/* end else */ } /* end while */ /* * Get the file ID of the next extension header, if any. */ if ((file_hdr->fh2$b_struclev == 2) || (file_hdr->fh2$b_struclev == 5) || (file_hdr->fh2$b_struclev == 64)){ fib->fib$w_fid_num=file_hdr->fh2$w_ex_fidnum; fib->fib$w_fid_seq=file_hdr->fh2$w_ex_fidseq; fib->fib$b_fid_nmx=file_hdr->fh2$b_ex_fidnmx; if (file_hdr->fh2$b_ex_fidrvn) fib->fib$b_fid_rvn= file_hdr->fh2$b_ex_fidrvn; else fib->fib$b_fid_rvn=nam.nam$b_fid_rvn; } else{ FM1 *map_area; map_area = (FM1 *)((short *)file_hdr + ((FH1 *)file_hdr)->fh1$b_mpoffset); fib->fib$w_fid_num=map_area->fm1$w_ex_filnum; fib->fib$w_fid_seq=map_area->fm1$w_ex_filseq; } if (!fib->fib$w_fid_num) break; }/* end while (1) */ sys$dassgn (ast_param.device_channel);/* Deassign the device channel */ printf ("file %.*s%.*s%.*s%.*s%.*s has %1d retrieval pointer%c\n", nam.nam$b_dev,nam.nam$l_dev, nam.nam$b_dir,nam.nam$l_dir, nam.nam$b_name,nam.nam$l_name, nam.nam$b_type,nam.nam$l_type, nam.nam$b_ver,nam.nam$l_ver, retrieval_count, retrieval_count>1?'s':' '); for (;retrieval_count > 0;retrieval_count--){ sprintf(block,"[%1u,%1u,%1u,%1x]", retrieval_ptr->segnum, retrieval_ptr->rtrcnt, retrieval_ptr->offset, retrieval_ptr->rtrptr); rtrcnt=strlen(block); while (rtrcnt % 10 < 9){ strcat(block," "); rtrcnt++; } printf("%s count = %1u,\tLBN=%1u\n", block, retrieval_ptr->count+1, retrieval_ptr->LBN); retrieval_ptr++; } }/* end for(;;) */ }
REFERENCE(S): OpenVMS I/O User's Reference Manual Order Number: AA-PV6SE-TK Chapter 1: ACP-QIO Interface