Extracts archive log header information

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*
20010123/FLIX
alexandre@neutrinos.org
To compile the source:
just do: gcc -Wall -O2 archivelog_magic.c -o archivelog_magic
To use it: 
1. archivelog_magic /path/to/my/archivelog
2. cat /path/to/my/archivelog | archivelog_magic
What does it do:
for earch file, it search for the magic cookie of oracle (AFAIK bits 12-15)
then output:
the filename,
the blocksize,
the number of block
the total size of the file
the dbname of the archive
the thread that created the file
the SCN (start & stop)
the number of commit in the archivelog (SCN stop - start) (-1 if the redo log is still in use stop=0xffffffffffff)
eg. : archivelog/filename: redo01.log ,blocksize: 512 ,nbblock: 1001 ,size: 512512 ,dbname: ORAX ,thread_num: 0001 ,seq_num: 0000001907 ,scn_start: 0x000000044fa5 ,scn_stop: 0xffffffffffff ,#request: -1 ,OK!	
ps: if the file being parsed is not a archivelog, but still an Oracle file the output will be
filename: /usr/local/oracle/data/oradata/orax/control01.ctl ,blocksize: 2048 ,nbblock: 2107 ,size: 4315136 , OK!
archivelog has been supressed from the start
Why use it:
if you got an archivelog (eg. file1.arc) but can't remeber who make it.
if you want to graph the number of commit per archivelog
if you want to crontol the file size (after multiple transfert)
if you are using raw device and would like to know how many space in the 
raw device is use (in the case of size differ the last arg will be BAD instead of OK!)
*/
/* functions */
int main(int argc, char **argv);
int get_size(int fd, char *filename);
/* variables */
typedef struct {
char undef1[4]; /* 0-3 */
uint blocksize; /* 4-7 size of one block in octect */
uint nbblock; /* 8-11 number of block */
uint magic; /* 12-15 magic code AFAIL */
char undef2[480];
char undef3[44];
char dbname[8]; /* "XXXXXXXX" */
char undef4[56];
char thread_text[7]; /* "Thread " */ 
char thread_num[4]; /* "9999" */
char pad1[2]; /* ", " */
char seq_text[5]; /* "seq # " */
char seq_num[10]; /* "9999999999" */
char pad2[2]; /* ", " */
char scn_text[4]; /* "SCN " */
char scn_start[14]; /* "0xffffffffffff" */
char scn_pad[1]; /* "-" */
char scn_stop[14]; /* "0xffffffffffff" */
char end_pad[356];
} ARC_STRUCT;
/**
**/
int main(int argc, char **argv)
{
int fd;
if (argc==1) 
{
fd=STDIN_FILENO;
get_size(fd,"(stdin)");
} 
else
{
while (--argc > 0)
if ( (fd=open(*++argv,O_RDONLY)) == -1)
{
perror(argv[0]);
continue;
}
else
{
get_size(fd, *argv);
close(fd);
}
}
exit(0);
}
int get_size(int fd, char *filename)
{
long scn_b;
long scn_e;
struct stat fsb;
ARC_STRUCT arc, *p_arc;
p_arc=&arc;
if ( (read(fd,&arc,1024)) != 1024)
{
perror("get_size");
return(0); 
}
if (p_arc->magic != 1515936861) 
{
return(0);
}
if ( strncmp(p_arc->thread_text,"Thread",6) ==0)
{
printf("archivelog/");
}
printf("filename: %s ,", filename);
printf("blocksize: %d ,", p_arc->blocksize);
printf("nbblock: %d ,", (p_arc->nbblock)+1);
printf("size: %d ,", (p_arc->blocksize * ((p_arc->nbblock)+1)));
if ( strncmp(p_arc->thread_text,"Thread",6) ==0)
{
printf("dbname: %.*s ,", (int)sizeof(p_arc->dbname), p_arc->dbname);
printf("thread_num: %.*s ,", (int)sizeof(p_arc->thread_num), p_arc->thread_num );
printf("seq_num: %.*s ,", (int)sizeof(p_arc->seq_num), p_arc->seq_num);
printf("scn_start: %.*s ,", (int)sizeof(p_arc->scn_start),p_arc->scn_start);
printf("scn_stop: %.*s ,", (int)sizeof(p_arc->scn_stop),p_arc->scn_stop);
scn_b = strtol(p_arc->scn_start,NULL,16);
scn_e = strtol(p_arc->scn_stop, NULL,16);
if ( strncmp(p_arc->scn_stop, "0xffffffffffff", 14) != 0)
{
printf("#request: %ld ,", scn_e-scn_b);
}
else
{
printf("#request: -1 ,");
}
}
else
{
printf(" ");
}
if (fd != STDIN_FILENO)
{
if ( (fstat(fd,&fsb)) == -1) 
{
perror("fstat");
printf("\n");
}
else
{
if (fsb.st_size !=  (p_arc->blocksize * ((p_arc->nbblock)+1)) )
{
printf("BAD\n");
}
else
{	
printf("OK!\n");
}
}
}
else
{
printf("\n");
}
return 1;
}

Syed