IUS@DACTH51.BITNET (Eberhard W. Lisse) (01/11/88)
Hi, here is the promised public domaine tar. I have made two parts with Michael Bednarek's vms_shar. the other one follows. regards, el ...................... Cut between dotted lines and save ...................... $!.............................................................................. $! VAX/VMS archive file created by VMS_SHAR V-5.01 01-Oct-1987 $! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au) $! To unpack, simply save and execute (@) this file. $! $! This archive was created by AMSD::LISSE $! on Monday 11-JAN-1988 13:33:44.53 $! $! ATTENTION: To keep each article below 65024 bytes, this program $! has been transmitted in 2 parts. $! You should concatenate ALL parts to ONE file and execute (@) that file. $! $! It contains the following 6 files: $! BLKLOOK.C TAR2VMS.C TAR2VMS.DOC TGTAR.C VMS2TAR.C VMS2TAR.DOC $!============================================================================== $ Set Symbol/Scope=(NoLocal,NoGlobal) $ Version=F$GetSYI("VERSION") ! See what VMS version we have here: $ If Version.ges."V4.4" then goto Version_OK $ Write SYS$Output "Sorry, you are running VMS ",Version, - ", but this procedure requires V4.4 or higher." $ Exit 44 $Version_OK: CR[0,8]=13 $ Pass_or_Failed="failed!,passed." $ Goto Start $Convert_File: $ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd $No_Error1: Define/User_Mode SYS$Output NL: $ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' - VMS_SHAR_DUMMY.DUMMY f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f); o:=Get_Info(Command_Line,"Output_File");Set(Output_File,b,o); Position(Beginning_of(b));Loop x:=Erase_Character(1);Loop ExitIf x<>"V"; Move_Vertical(1);x:=Erase_Character(1);Append_Line; Move_Horizontal(-Current_Offset);EndLoop;Move_Vertical(1); ExitIf Mark(None)=End_of(b) EndLoop;Position(Beginning_of(b));Loop x:=Search("`",Forward,Exact);ExitIf x=0;Position(x);Erase_Character(1); If Current_Character='`' then Move_Horizontal(1);else Copy_Text(ASCII(INT(Erase_Character(3))));EndIf;EndLoop;Exit; $ Delete VMS_SHAR_DUMMY.DUMMY;* $ Checksum 'File_is $ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR $ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd $No_Error2: Return $Start: $ File_is="BLKLOOK.C" $ Check_Sum_is=1345803428 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X /* X This program attempts to find out the blocksize of a tape X */ X X#include descrip X#include stdio X#include iodef X#include file X Xmain() X{ X#define MNT$M_FOREIGN 1 X#define MNT$_DEVNAM 1 X#define MNT$_BLOCKSIZE 8 X#define MNT$_RECORDSIZ 16 X#define MNT$_FLAGS 4 X X#define DMT$M_NOUNLOAD 1 X Xtypedef struct X { X short cond_value; X short count; X int info; X } status_block; X Xtypedef struct X { X short buffer_len; X short item_code; X int buffer_addr; X int ret_len_addr; X } item_desc; X Xstruct X { X item_desc dev_name; X item_desc block_size; X item_desc flags_item; X int terminator; X } mnt_list; X Xchar tape[] = "MRA0:", line[65534]; Xint flags = MNT$M_FOREIGN, X blocks = 65532, X status; X Xshort channel; Xstatus_block iosb; X$DESCRIPTOR(tape_desc, tape); X X/* set up mnt_list */ Xmnt_list.dev_name.buffer_len = strlen(tape); Xmnt_list.dev_name.item_code = MNT$_DEVNAM; Xmnt_list.dev_name.buffer_addr = tape; Xmnt_list.dev_name.ret_len_addr = 0; X Xmnt_list.block_size.buffer_len = 4; Xmnt_list.block_size.item_code = MNT$_BLOCKSIZE; Xmnt_list.block_size.buffer_addr = &blocks; Xmnt_list.block_size.ret_len_addr = 0; X Xmnt_list.flags_item.buffer_len = 4; Xmnt_list.flags_item.item_code = MNT$_FLAGS; Xmnt_list.flags_item.buffer_addr = &flags; Xmnt_list.flags_item.ret_len_addr = 0; X Xmnt_list.terminator = 0; X X/* mount the tape */ Xif (((status = SYS$MOUNT(&mnt_list)) &1) != 1) X LIB$STOP(status); X Xif (((status = SYS$ASSIGN(&tape_desc,&channel,0,0)) &1) !=1) X LIB$STOP(status); X X/* read a block */ Xif (((status = SYS$QIOW(0, channel, IO$_READLBLK, &iosb, 0, 0, X line, blocks, 0,0,0,0)) &1) != 1) X LIB$STOP(status); Xif ((iosb.cond_value &1) != 1) X LIB$STOP(iosb.cond_value); X Xprintf(" Block Size = %d bytes\n",iosb.count); X X Xif (((status = SYS$DISMOU(&tape_desc, DMT$M_NOUNLOAD)) &1) != 1) X LIB$STOP(status); X} $ GoSub Convert_File $ File_is="TAR2VMS.C" $ Check_Sum_is=1685857467 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X/* Read a TAR format tape or file , move files into VMS directories */ X/* Copyright 1986, Sid Penstone, X* Department of Electrical Engineering, X* Queen's University, X* Kingston, Ontario, Canada K7L3N6 X* (613)-545-5925 X* BITNET: PENSTONE@QUCDNEE1 (Preferred) X* or PENSTONE@QUCDN X* X* Version 2.2, Oct.21,1986 X* mods: - corrected header size (thanks to Eric Gisin, U .of Waterloo) X* - No more of the dreaded QIO's ( " " " ) X* - tried to sort out link flag format X* - uses a tape or a file as input X* - NOTE: default is NO conversion to vms standard text format (cr) X* 2.1 - trapped commas in file names, converted to '_' X* 2.2 - reported translations of names X* - continued after error in opening output file X* - exit correctly on cannot open input file X*/ X X X/* The input data is in record format, length 512, blocks of 10240 bytes; X */ X X X#include stdio X#include time X#include ssdef X#include iodef X#include descrip X#include ctype X X#define ERROR1 -1 X#define BUFFSIZE 512 X#define ISDIRE 1 X#define ISFILE 0 X#define NAMSIZE 100 X#define SIZE 10240 /* Block size */ X#define DSIZE 512 /* Data block size */ X Xstruct /* A Tar header */ X { X char title[NAMSIZE]; X char protection[8]; X char field1[8]; /* this is the user id */ X char field2[8]; /* this is the group id */ X char count[12]; /* was 11 in error */ X char time[12]; /* UNIX format date */ X char chksum[8]; /* Header Checksum (ignored) */ X char linkcount; /* hope this is right */ X char linkname[NAMSIZE]; /* Space for the name of the link */ X char dummy[255]; /* and the rest */ X } header; X Xstatic char buffer[DSIZE]; /* BUFFER for a record */ X X/* Function flags, options:*/ Xint extract, /* x option (default) */ X list, /* t option : list tape contents */ X verbose, /* v option, report actions */ X wait; X X/* Miscellaneous globals, etc. */ X Xchar *tarfile = "tape", /* Input file name */ X pathname[NAMSIZE], /* File name as found on tape (UNIX) */ X directory[NAMSIZE], /* Current directory */ X new_directory[NAMSIZE], /* Directory of current file */ X top[NAMSIZE], /* Top level or root */ X newfile[NAMSIZE], /* VMS format of file name */ X outfile[NAMSIZE], /* Complete output file specification */ X temp[256], /* Scratch */ X creation[NAMSIZE], /* Date as extracted from the TAR file */ X *ctime(), /* System function */ X linkname[NAMSIZE]; /* Linked file name */ X Xint bytecount, mode, uic1, uic2, linktype;/* Data from header */ Xint tarfd; /* The input file descriptor */ X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ Xint isterm,status,file_type,j,c, flag; Xchar *make_directory(), *cp; X X/* Decode the options and parameters: */ X X if(argc ==1) X { X extract = 1; /* Default for now */ X verbose = 1; X wait = 0; /* Don't wait for prompt */ X } X while(--argc > 0) X { X cp = argv[1]; X while(c = *cp++) X { X switch(c) X { X case 't': X list=1; X break; X case 'x': X extract=1; X break; X case 'v': X verbose=1; X break; X case 'w': X wait=1; X break; X default: X printf("Option '%c' not recognized.\n",c); X } X } X } X X X/* Find if this is a terminal */ X isterm = isatty(0); X X/* Set up directory names */ X strcpy(top,getenv("PATH")); X X/* Start with the default as the top */ X strcpy(directory,top); X X/* open the file for reading */ X if((tarfd = opentar()) <= 0) X { X printf("Error opening the Tar tape\n"); X exit(2); X } X/* Now keep reading headers from this file, and decode the names, etc. */ X X while((status=hdr_read(&header))==DSIZE) /* 0 on end of file */ X { X if(strlen(header.title)!=0) /* Valid header */ X { X decode_header(); X if(extract) X { X file_type=scan_title(pathname,new_directory,newfile); X if( make_new(new_directory)!=0) X printf("Error creating %s\n",new_directory); X if(file_type == ISDIRE) X {} X if(file_type == ISFILE) X/* Now move the data into the output file */ X if(bytecount>0) X { X strcpy(outfile,new_directory); X strcat(outfile,newfile); X if((j=copyfile(outfile,bytecount))<0) X printf("Error writing file %s\n",outfile); X } X } X else /* listing only */ X { X printf("%o %6d %s %s\n", X mode,bytecount,creation+4,pathname); X if(linktype == 0) X tarskip(bytecount); X else X printf(" *****( Linked to file: %s)\n",linkname); X } X } X else /* Empty header means the end!!! */ X { X status = 1; X printf("End of Tar file found.\n"); X break; X } X X } /* end while */ X if(status == 1) /* Empty header */ X { X printf("Do you wish to move past the EOF mark ? y/n\n"); X gets(temp); X if(tolower(temp[0]) == 'y') X while((status=hdr_read(&header)) >0); X else X exit(SS$_NORMAL); X } X if(status==0) /* End of tar file */ X { X printf("End of file encountered\n"); X exit(SS$_NORMAL); X } X if(status<0) /* An error */ X { X printf("Error reading input.\n"); X exit(2); X } X} X X X/* This function simply copies the file to the output, no conversion */ X Xint copyfile(outfile,nbytes) Xchar outfile[]; /* name of output version */ Xint nbytes; X X{ Xint inbytes, fil; X/* Open the output file */ X if((fil=creat(outfile,0)) == ERROR1) X { X printf(" Creation error in opening %s \n",outfile); X tarskip(bytecount); X return(-2); X } X if(linktype !=0) X { X sprintf(buffer,"This file is linked to %s\n",linkname); X write(fil,buffer,strlen(temp)); X } X else X { X while(nbytes>0) X { X if((inbytes=read(tarfd,buffer,DSIZE)) > 0) X { X write(fil,buffer,(nbytes > DSIZE)? DSIZE:nbytes); X nbytes -= inbytes; X } X else X { X printf("End of input file detected\n"); X close(fil); X return(-1); X } X } X } X/* Close the file */ X close(fil); X if(verbose) X { X printf("CREATED: %s\n",outfile); X if(linktype!=0) X printf(" *** REAL DATA IS IN: %s\n",linkname); X } X return(0); X} X X/* Decode a file name into the directory, and the name, return X* a value to indicate if this is a directory name, or another file X* We return the extracted directory string in "dire", and the X* filename (if it exists) in "fname". The full title is in "line" X* at input. X*/ X Xint scan_title(line,dire,fname) Xchar line[],dire[],fname[]; X{ Xchar temp[NAMSIZE],*end1; Xint len,len2,i,ind; X/* The format will be UNIX at input, so we have to scan for the X* UNIX directory separator '/' X* If the name ends with '/' then it is actually a directory name. X* If the directory consists only of '.', then don't add a subdirectory X* The output directory will be a complete file spec, based on the default X* directory. X*/ X strcpy(dire,top); /* Start with the top level */ X if(strncmp(line,"./",2)==0) X strcpy(line,line+2); /* ignore "./" */ X strcpy(temp,line); /* Start in local buffer */ X ind=vms_cleanup(temp); /* Remove illegal vms characters */ X if((end1=strrchr(temp,'/'))==0) /* No directory at all ? */ X strcpy(fname,temp); /* Only a file name */ X else X { /* End of directory name is '/' */ X *end1 = 0; /* Terminate directory name */ X strcpy(fname,end1+1); /* File name without directory */ X for (i=0;temp[i];i++) /* Change '/' to '.' in directory */ X if(temp[i]=='/') X temp[i]='.'; X dire[strlen(dire)-1] = (temp[0]=='.')?0:'.' ; X /* "." to indicate a subdirectory (unless already there )*/ X strcat(dire,temp); /* Add on the new directory */ X strcat(dire,"]") ; /* And close with ']' */ X } X if(strlen(fname)==0) /* Could this cause problems ? */ X { X return(ISDIRE); X } X else X for(i=0,end1=fname;*end1;end1++) /* Replace multiple . */ X if(*end1 == '.') X if(i++)*end1 = '_'; /* After the first */ X if((i>1||ind)&& verbose ) /* Any translations ? */ X printf("****RENAMED: %s \n TO: %s\n",line,fname); X return(ISFILE); X} X X/* Create a new directory, finding out any higher levels that are missing */ X X/* We will parse the directory name into the next higher directory, and the X* desired directory as "desired.dir". X* Thus: "DEV:[top.sub1.sub2]" is made into "DEV:[top.sub1]sub2.dir" . If X* the directory does not exist , then create the original directory. There X* may be higher levels missing, so we can recurse until we reach the top X* level directory, then work our way back, creating directories at each X* successive level. X*/ X Xint make_new(want) Xchar want[]; X{ Xint i,len; Xchar a[NAMSIZE],parent[NAMSIZE],*end,name[NAMSIZE]; X strcpy(parent,want); X len = strlen(parent); X parent[len-1] =0 ; /* Get rid of the "]" */ X end = strrchr(parent,'.'); /* Find the last '.' */ X if(end != NULL) X { X strcpy(a,end+1); /* Get the last parent */ X strcat(a,".dir"); /* Add the extension */ X *end++ = ']' ; /* Reduce the directory parent */ X *end = 0; /* Terminate the directory */ X strcpy(name,parent); X strcat(name,a); X } X X if(access(name,0) <0) /* Does the directory exist ? */ X { X if(strcmp(parent,top)!=0) /* No, are we at the top? */ X if(make_new(parent)) /* No, look again */ X return(-1); /* recurse */ X if(mkdir(want,0755,0,0,0)) /* make it */ X return(-1); /* Leave on error */ X else X if(verbose) X printf("CREATED: %s\n",want); X return(0); X } X return(0); X} X X /* Function to open and get data from the blocked input file */ Xint opentar() X{ Xint fd; X fd = open(tarfile, 0, "rfm = fix","mrs = 512"); X if(fd < 0) X { X printf("Can't open input file \n"); X return(0); X } X return(fd); X} X X/* Get the next file header from the input file buffer. We will always X* move to the next 512 byte boundary. X*/ Xint hdr_read(buffer) Xchar *buffer; X{ Xint stat; X stat = read(tarfd,buffer,DSIZE); /* read the header */ X return(stat); /* Catch them next read ? */ X} X X X/* This is supposed to skip over data to get to the desired position */ X/* Position is the number of bytes to skip. We should never have to use X* this during data transfers; just during listings. */ Xint tarskip(bytes) Xint bytes; X{ Xint i=0; X while(bytes > 0) X { X if((i=read(tarfd,buffer,DSIZE)) == 0) X { X printf("End of file encountered while skipping.\n"); X return(-1); X } X bytes -= i; X } X return(0); X} X X/* Decode the fields of the header */ X Xint decode_header() X{ Xint idate, *bintim; Xchar ll; Xbintim = &idate; X linktype=0; strcpy(linkname,""); X strcpy(pathname,header.title); X sscanf(header.time,"%o",bintim); X strcpy(creation,ctime(bintim)); /* Work on this! */ X creation[24]=0; X sscanf(header.count,"%o",&bytecount); X sscanf(header.protection,"%o",&mode); X sscanf(header.field1,"%o",&uic1); X sscanf(header.field2,"%o",&uic2); X /* We may have the link written as binary or as character: */ X linktype = isdigit(header.linkcount)? X (header.linkcount - '0'):header.linkcount; X if(linktype != 0) X sscanf(header.linkname,"%s",linkname); X return(0); X} X X X/* remove illegal characters from directory and file names; replace X* hyphens and commas with underscores.Returns number of translations X* that were made. X*/ Xvms_cleanup(string) Xchar string[]; X{ Xint i,flag=0; Xchar c; X for(i=0;c=string[i];i++) X { X switch (c) X { X case '-': /* No hyphens in file names */ X case ',': /* No commas in file names */ X string[i]= '_'; X flag++; /* Record if any changes were made */ X break; X default: X break; X } X } X return(flag); X} $ GoSub Convert_File $ File_is="TAR2VMS.DOC" $ Check_Sum_is=824507747 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X Dec.15/86 XGreetings: X X Here is the program to extract files from a Tar format tape or Xfile into a VMS system. This is a major update on version 1.xx Xthat I distributed earlier. The major changes: X X(1) It reads from either a tape or a file image of a tar tape X(2) It transfers files as is, does NOT translate UNIX stream files to X the format that the VMS editor likes, but this is not a X problem unless you intend to edit the files. See below. X (The old "s" option is now the default). X(3) It can usually leave the tape positioned ready to read another X Tar file from the tape. NOTE: there is a SET MAGTAPE/ X option in VMS 4.x that will skip files to start reading in X the middle of a tape. The TAR2VMS program does not do any rewinds. X(4) UNIX "linked" files are handled. X X I will be glad to hear of your experiences with the code, since Xoften when we get a Tar tape from a different system, we find something Xthat I hadn't anticipated. The program was developed by looking at DUMP Xoutput from various tar format tapes on a VMS system, so there are Xundoubtedly variations that I haven't seen. ( I am not a UNIX expert..) XWe looked at UNIX manuals as well, but found some discrepancies in real Xtapes, so went with what seemed to work. X X I also have a partially debugged version of a Tar writer; ask Xfor it if you are willing to be a guinea pig, or need to transfer some Xfiles to a UNIX system from VMS. X X XSid Penstone, XVLSI Group, XDepartment of Electrical Engineering, XQueen's University, XKingston, Ontario, Canada, K7L3N6 Xphone (613) 545-2925 X XBITNET: PENSTONE@QUCDNEE1 (Preferred) X PENSTONE@QUCDN (If the other doesn't work) X X X X XNOTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! XNOTE!!! The program must be separated at the "** CUT HERE **" lines XNOTE!!! below before compiling. XNOTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! X XIntroduction: X X The program TAR2VMS.C reads from a /foreign tape,or a file Xwhich is an image of a Tar format tape, and extracts the files into Xa directory tree starting in the current default directory. XDirectories will be created automatically. XFor example, if your default is [JONES.MAIN], then the file X"electric/sub/test.c" will be written into [JONES.MAIN.ELECTRIC.SUB]TEST.C . X For the simplest operation, just RUN it after defining the Xlogical "TAPE" to be the the Tar source and doing a XMOUNT/FOREIGN/BLOCK=10240/RECORD=512 (if it is a tape); this Xdoes the extraction automatically, reporting on stdout as it does. X X The extracted files will be written to your system as C stream files. XThe VMS editor EDT will complain about the format, but EVE will not. X X To convert a text file to standard VMS format: X(Thanks to Eric Gisin at U. of Waterloo:) X You can use the VMS CONVERT utility by first creating a xxxx.FDL file Xcontaining: X XFILE X ORGANIZATION sequential XRECORD X BLOCK_SPAN yes X CARRIAGE_CONTROL carriage_return X FORMAT variable X XThen run Convert with the regular DCL: XCONVERT/FDL=xxxx input-file output-file X------------------------------------------------------------------------- X XUsage: X X -Define the logical variable "TAPE" to be the desired tape X unit or the file containing the Tar data. X X -Mount the tape /FOREIGN/BLOCK=10240/RECORD=512 X X -Set the default directory below which the tree will be created X before calling the program. Thus: if your default directory X is SYS$SYSDEVICE:[MYDIRE], the file "electric/dbase.c" will X be written in SYS$DEVICE:[MYDIRE.ELECTRIC]DBASE.C X X -Then run TAR2VMS: (either by RUN or as a command) X if you use RUN, the operation is (extract, verbose) X otherwise: X'command' [options] X where the options are: X "t" (listing only) Listing of files on tape X "x" (extract) Extract files from the tape X "v" (verbose): Report activity X "w" (wait) ...Not implemented X -to use the options, the program must be executed using the X foreign command feature of VMS, by defining a command: Xcommand :== $path:tar2vms !where path=complete location of tar2vms.exe X X Example: XIf the command is 'tar2vms', then: Xtar2vms t will list the contents of the tar file Xtar2vms xv will extract all of the files, reporting X XThe listing reports the UNIX protection (in octal), the file size in bytes, Xthe modification date on the tape, and the file name. X XERRORS: Most probable causes: X "Can't open input file" - likely forgot to define TAPE, or mount X the tape. X "Error reading input" - unexpected Tar format, or bad file. X "Error writing output " - directory access error X "Creation Error... " - illegal directory or file name X X-------------------------------------------------------------------------- XImportant assumptions for this version (2.1): X X The defaults are (no options): X -Extract all of the files, reporting as each file is created X X -Read from a tape, mounted foreign, or a fixed record length X file,with block size of 10240 bytes or less . If larger block X size, change the definition of SIZE. X X -Stop on the special (blank header) block written by UNIX. X (Note, like UNIX Tar, it does not move to the file mark at X the end of the file. Answer "y" to the prompt to get to another X tar file on the same tape.)THIS MIGHT NOT WORK... X X -All files are assumed to be UNIX stream and are X just copied. The vms file-attribute will be "stream". This may X have to be changed in certain cases with CONVERT, or by writing X a little C program to read the file and rewrite it. X X -When a UNIX linked file is encountered, there will be another X file on the tape that contains the actual data. It may not be an X earlier file that was the original file, since the files X are written on in alphabetical order. The program will create a X file under the name of the linked file, but it will contain only X a text messsage reporting the name of the file that contains the X data. X X X This version converts the path names to VMS format before creating Xthe files. Some special cases: X X (1) File names with more than one period (".") in the name have those X after the first converted to underscores (e.g. "mults.s.c" is X written out under the name "mults.s_c" X (2) It is assumed that all of the pathnames on the Tar tape have X complete directory info, with no device parts. X (3) Commas and hyphens in file or directory names are converted to X underscores. If this causes any problems, you can modify the X code in vms_cleanup().Any such translations are reported in X "verbose" mode. X (4) Files are created with the user's default protection. The mode on X the tape is ignored. X (5) The dates of files extracted are the date of the extraction, not the X date of the Tar version. X (6) unix FILES THAT HAVE NO EXTENSION, AND END IN A LETTER WILL HAVE X A "." ADDED TO THE NAME AUTOMATICALLY. tHIS CAN CAUSE SOME X MYSTERIES WITH LARGE PROGRAMS THAT LOOK FOR OTHER FILES WITH X AN EXACT STRING SEARCH. aLSO, IF THE FILES ARE WRITTEN OUT X TO unix AS A tar TAPE FROM vms, THE "." GOES ALONG WITH THE FILE X name. X X------------------------------------------------------------------------ XKnown Bugs: X X - Can't always read another file on the same tape. The program X only works correctly when the tape had regular EOF marks on it, X which apparently is not always true. X - Can't selectively extract files from the tape. The "wait" option X could be useful, but haven't got around to it.. X X X $ GoSub Convert_File $ File_is="TGTAR.C" $ Check_Sum_is=1685857467 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X/* Read a TAR format tape or file , move files into VMS directories */ X/* Copyright 1986, Sid Penstone, X* Department of Electrical Engineering, X* Queen's University, X* Kingston, Ontario, Canada K7L3N6 X* (613)-545-5925 X* BITNET: PENSTONE@QUCDNEE1 (Preferred) X* or PENSTONE@QUCDN X* X* Version 2.2, Oct.21,1986 X* mods: - corrected header size (thanks to Eric Gisin, U .of Waterloo) X* - No more of the dreaded QIO's ( " " " ) X* - tried to sort out link flag format X* - uses a tape or a file as input X* - NOTE: default is NO conversion to vms standard text format (cr) X* 2.1 - trapped commas in file names, converted to '_' X* 2.2 - reported translations of names X* - continued after error in opening output file X* - exit correctly on cannot open input file X*/ X X X/* The input data is in record format, length 512, blocks of 10240 bytes; X */ X X X#include stdio X#include time X#include ssdef X#include iodef X#include descrip X#include ctype X X#define ERROR1 -1 X#define BUFFSIZE 512 X#define ISDIRE 1 X#define ISFILE 0 X#define NAMSIZE 100 X#define SIZE 10240 /* Block size */ X#define DSIZE 512 /* Data block size */ X Xstruct /* A Tar header */ X { X char title[NAMSIZE]; X char protection[8]; X char field1[8]; /* this is the user id */ X char field2[8]; /* this is the group id */ X char count[12]; /* was 11 in error */ X char time[12]; /* UNIX format date */ X char chksum[8]; /* Header Checksum (ignored) */ X char linkcount; /* hope this is right */ X char linkname[NAMSIZE]; /* Space for the name of the link */ X char dummy[255]; /* and the rest */ X } header; X Xstatic char buffer[DSIZE]; /* BUFFER for a record */ X X/* Function flags, options:*/ Xint extract, /* x option (default) */ X list, /* t option : list tape contents */ X verbose, /* v option, report actions */ X wait; X X/* Miscellaneous globals, etc. */ X Xchar *tarfile = "tape", /* Input file name */ X pathname[NAMSIZE], /* File name as found on tape (UNIX) */ X directory[NAMSIZE], /* Current directory */ X new_directory[NAMSIZE], /* Directory of current file */ X top[NAMSIZE], /* Top level or root */ X newfile[NAMSIZE], /* VMS format of file name */ X outfile[NAMSIZE], /* Complete output file specification */ X temp[256], /* Scratch */ X creation[NAMSIZE], /* Date as extracted from the TAR file */ X *ctime(), /* System function */ X linkname[NAMSIZE]; /* Linked file name */ X Xint bytecount, mode, uic1, uic2, linktype;/* Data from header */ Xint tarfd; /* The input file descriptor */ X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ Xint isterm,status,file_type,j,c, flag; Xchar *make_directory(), *cp; X X/* Decode the options and parameters: */ X X if(argc ==1) X { X extract = 1; /* Default for now */ X verbose = 1; X wait = 0; /* Don't wait for prompt */ X } X while(--argc > 0) X { X cp = argv[1]; X while(c = *cp++) X { X switch(c) X { X case 't': X list=1; X break; X case 'x': X extract=1; X break; X case 'v': X verbose=1; X break; X case 'w': X wait=1; X break; X default: X printf("Option '%c' not recognized.\n",c); X } X } X } X X X/* Find if this is a terminal */ X isterm = isatty(0); X X/* Set up directory names */ X strcpy(top,getenv("PATH")); X X/* Start with the default as the top */ X strcpy(directory,top); X X/* open the file for reading */ X if((tarfd = opentar()) <= 0) X { X printf("Error opening the Tar tape\n"); X exit(2); X } X/* Now keep reading headers from this file, and decode the names, etc. */ X X while((status=hdr_read(&header))==DSIZE) /* 0 on end of file */ X { X if(strlen(header.title)!=0) /* Valid header */ X { X decode_header(); X if(extract) X { X file_type=scan_title(pathname,new_directory,newfile); X if( make_new(new_directory)!=0) X printf("Error creating %s\n",new_directory); X if(file_type == ISDIRE) X {} X if(file_type == ISFILE) X/* Now move the data into the output file */ X if(bytecount>0) X { X strcpy(outfile,new_directory); X strcat(outfile,newfile); X if((j=copyfile(outfile,bytecount))<0) X printf("Error writing file %s\n",outfile); X } X } X else /* listing only */ X { X printf("%o %6d %s %s\n", X mode,bytecount,creation+4,pathname); X if(linktype == 0) X tarskip(bytecount); X else X printf(" *****( Linked to file: %s)\n",linkname); X } X } X else /* Empty header means the end!!! */ X { X status = 1; X printf("End of Tar file found.\n"); X break; X } X X } /* end while */ X if(status == 1) /* Empty header */ X { X printf("Do you wish to move past the EOF mark ? y/n\n"); X gets(temp); X if(tolower(temp[0]) == 'y') X while((status=hdr_read(&header)) >0); X else X exit(SS$_NORMAL); X } X if(status==0) /* End of tar file */ X { X printf("End of file encountered\n"); X exit(SS$_NORMAL); X } X if(status<0) /* An error */ X { X printf("Error reading input.\n"); X exit(2); X } X} X X X/* This function simply copies the file to the output, no conversion */ X Xint copyfile(outfile,nbytes) Xchar outfile[]; /* name of output version */ Xint nbytes; X X{ Xint inbytes, fil; X/* Open the output file */ X if((fil=creat(outfile,0)) == ERROR1) X { X printf(" Creation error in opening %s \n",outfile); X tarskip(bytecount); X return(-2); X } X if(linktype !=0) X { X sprintf(buffer,"This file is linked to %s\n",linkname); X write(fil,buffer,strlen(temp)); X } X else X { X while(nbytes>0) X { X if((inbytes=read(tarfd,buffer,DSIZE)) > 0) X { X write(fil,buffer,(nbytes > DSIZE)? DSIZE:nbytes); X nbytes -= inbytes; X } X else X { X printf("End of input file detected\n"); X close(fil); X return(-1); X } X } X } X/* Close the file */ X close(fil); X if(verbose) X { X printf("CREATED: %s\n",outfile); X if(linktype!=0) X printf(" *** REAL DATA IS IN: %s\n",linkname); X } X return(0); X} X X/* Decode a file name into the directory, and the name, return X* a value to indicate if this is a directory name, or another file X* We return the extracted directory string in "dire", and the X* filename (if it exists) in "fname". The full title is in "line" X* at input. X*/ X Xint scan_title(line,dire,fname) Xchar line[],dire[],fname[]; X{ Xchar temp[NAMSIZE],*end1; Xint len,len2,i,ind; X/* The format will be UNIX at input, so we have to scan for the X* UNIX directory separator '/' X* If the name ends with '/' then it is actually a directory name. X* If the directory consists only of '.', then don't add a subdirectory X* The output directory will be a complete file spec, based on the default X* directory. X*/ X strcpy(dire,top); /* Start with the top level */ X if(strncmp(line,"./",2)==0) X strcpy(line,line+2); /* ignore "./" */ X strcpy(temp,line); /* Start in local buffer */ X ind=vms_cleanup(temp); /* Remove illegal vms characters */ X if((end1=strrchr(temp,'/'))==0) /* No directory at all ? */ X strcpy(fname,temp); /* Only a file name */ X else X { /* End of directory name is '/' */ X *end1 = 0; /* Terminate directory name */ X strcpy(fname,end1+1); /* File name without directory */ X for (i=0;temp[i];i++) /* Change '/' to '.' in directory */ X if(temp[i]=='/') X temp[i]='.'; X dire[strlen(dire)-1] = (temp[0]=='.')?0:'.' ; X /* "." to indicate a subdirectory (unless already there )*/ X strcat(dire,temp); /* Add on the new directory */ X strcat(dire,"]") ; /* And close with ']' */ X } X if(strlen(fname)==0) /* Could this cause problems ? */ X { X return(ISDIRE); X } X else X for(i=0,end1=fname;*end1;end1++) /* Replace multiple . */ X if(*end1 == '.') X if(i++)*end1 = '_'; /* After the first */ X if((i>1||ind)&& verbose ) /* Any translations ? */ X printf("****RENAMED: %s \n TO: %s\n",line,fname); X return(ISFILE); X} X X/* Create a new directory, finding out any higher levels that are missing */ X X/* We will parse the directory name into the next higher directory, and the X* desired directory as "desired.dir". X* Thus: "DEV:[top.sub1.sub2]" is made into "DEV:[top.sub1]sub2.dir" . If X* the directory does not exist , then create the original directory. There X* may be higher levels missing, so we can recurse until we reach the top X* level directory, then work our way back, creating directories at each X* successive level. X*/ X Xint make_new(want) Xchar want[]; X{ Xint i,len; Xchar a[NAMSIZE],parent[NAMSIZE],*end,name[NAMSIZE]; X strcpy(parent,want); X len = strlen(parent); X parent[len-1] =0 ; /* Get rid of the "]" */ X end = strrchr(parent,'.'); /* Find the last '.' */ X if(end != NULL) X { X strcpy(a,end+1); /* Get the last parent */ X strcat(a,".dir"); /* Add the extension */ X *end++ = ']' ; /* Reduce the directory parent */ X *end = 0; /* Terminate the directory */ X strcpy(name,parent); X strcat(name,a); X } X X if(access(name,0) <0) /* Does the directory exist ? */ X { X if(strcmp(parent,top)!=0) /* No, are we at the top? */ X if(make_new(parent)) /* No, look again */ X return(-1); /* recurse */ X if(mkdir(want,0755,0,0,0)) /* make it */ X return(-1); /* Leave on error */ X else X if(verbose) X printf("CREATED: %s\n",want); X return(0); X } X return(0); X} X X /* Function to open and get data from the blocked input file */ Xint opentar() X{ Xint fd; X fd = open(tarfile, 0, "rfm = fix","mrs = 512"); X if(fd < 0) X { X printf("Can't open input file \n"); X return(0); X } X return(fd); X} X X/* Get the next file header from the input file buffer. We will always X* move to the next 512 byte boundary. X*/ Xint hdr_read(buffer) Xchar *buffer; X{ Xint stat; X stat = read(tarfd,buffer,DSIZE); /* read the header */ X return(stat); /* Catch them next read ? */ X} X X X/* This is supposed to skip over data to get to the desired position */ X/* Position is the number of bytes to skip. We should never have to use X* this during data transfers; just during listings. */ Xint tarskip(bytes) Xint bytes; X{ Xint i=0; X while(bytes > 0) X { X if((i=read(tarfd,buffer,DSIZE)) == 0) X { X printf("End of file encountered while skipping.\n"); X return(-1); X } X bytes -= i; X } X return(0); X} X X/* Decode the fields of the header */ X Xint decode_header() X{ Xint idate, *bintim; Xchar ll; Xbintim = &idate; X linktype=0; strcpy(linkname,""); X strcpy(pathname,header.title); X sscanf(header.time,"%o",bintim); X strcpy(creation,ctime(bintim)); /* Work on this! */ X creation[24]=0; X sscanf(header.count,"%o",&bytecount); X sscanf(header.protection,"%o",&mode); X sscanf(header.field1,"%o",&uic1); X sscanf(header.field2,"%o",&uic2); X /* We may have the link written as binary or as character: */ X linktype = isdigit(header.linkcount)? X (header.linkcount - '0'):header.linkcount; X if(linktype != 0) X sscanf(header.linkname,"%s",linkname); X return(0); X} X X X/* remove illegal characters from directory and file names; replace X* hyphens and commas with underscores.Returns number of translations X* that were made. X*/ Xvms_cleanup(string) Xchar string[]; X{ Xint i,flag=0; Xchar c; X for(i=0;c=string[i];i++) X { X switch (c) X { X case '-': /* No hyphens in file names */ X case ',': /* No commas in file names */ X string[i]= '_'; X flag++; /* Record if any changes were made */ X break; X default: X break; X } X } X return(flag); X} $ GoSub Convert_File $ File_is="VMS2TAR.C" $ Check_Sum_is=1763549126 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X/* Write a TAR format tape or file , from files in VMS directories */ X/* Copyright 1986,Sid Penstone, X* Department of Electrical Engineering, X* Queen's University, X* Kingston, Ontario, Canada K7L3N6 X* (613)-545-2925 X* BITNET: PENSTONE@QUCDNEE1 X* Version 1.7, Nov.3,1986 X* X* Modifications: X* - used the C call stat() to get file information X* - now propagates directory specs to subsequent file-specs X* 1.4 - starts pathnames at current default directory X* 1.5 - corrected error in scan_name for directories outside tree X* - did immediate close of file-descriptor version in out_file X* to get around overflow of file operations ??? X* 1.6 - added cleanup_dire() to correctly handle rooted directory specs X* 1.6b - corrected typing error in scan_name "-" should be "=" X* - looked past nodename in getting rid of device in scan_name() X* - reject access to other nodes by trapping "::" in initsearch() X* 1.7 - set resultant string size to 0 in search(), because of problems X* with rooted directories X*/ X X X/* The input data is in VMS format,. The output will be X* blocks of 10240 bytes, with 512 byte internal blocks of header X* and data. Unfilled 512 blocks will be packed with garbage. X* The output will be padded out to a full block of size BLKSIZE at X* the end of the Tar file. X */ X X X#include stdio X#include time X#include ssdef X#include descrip X#include ctype X#include rms X#include stsdef X#include file X#include stat X#include types X X X#define ISDIRE 1 X#define ISFILE 0 X#define FIXED FAB$C_FIX X#define NAMSIZE 100 X#define BLKSIZE 10240 /* Block size on tape*/ X#define DSIZE 512 /* data block */ X Xstatic struct tarhdr /* A Tar header */ X { X char title[NAMSIZE]; X char protection[8]; X char uid[8]; X char gid[8]; X char count[12]; X char time[12]; X char chksum[8]; X char linkmode; /* hope this is right */ X char linkname[NAMSIZE]; /* Space for the name of the link */ X char dummy[255]; /* and the rest */ X } header; X Xstruct tarhdr *empty; /* buffer of nulls */ Xchar *dbuffer; /* for buffering output data */ X Vstatic int bufferpointer; /* Position of next byte in the block * X/ Xstatic struct FAB fblock,fblock2; /* File attribute block */ Xstatic struct NAM nblock,nblock2; /* Name attribute block for rms */ Xstruct stat *sblock; /* for stat() call */ X X/* Function flags, options:*/ Xint create, /* c operation (default) */ X list, /* t operation */ X verbose, /* v option, report actions */ X wait; X X/* Miscellaneous globals, etc. */ X Xchar *strindex(); /* String search function */ X Xchar *tarfile = "tape" , /* Output file */ X operation = ' ', /* Current operation c,t */ X pathname[NAMSIZE], /* File name as written on tape (UNIX) */ X directory[NAMSIZE], /* The current root directory */ X new_directory[NAMSIZE], /* Directory of current file */ X newfile[NAMSIZE], /* VMS format of file name */ X outfile[NAMSIZE], /* stripped format of file name */ X filetime[32], /* Modification date as from vms */ X searchname[NAMSIZE]; /* for the NAM block */ X X/* Global file characteristics */ XFILE *vmsfile; Xint vmsfd, outfd, temfd; Xunsigned vmsmrs, vmstime; /* maximum record size */ Xint vmsrat,vmsorg,vmsrfm; /* Other format (as integers) */ X X Xint bytecount, mode, uid , gid , links;/* Data in the header */ Xdefault_name = "*.*"; /* Only get the most recent version */ Xint i; X X X/* ******************** start here *************************** */ Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ Xint status,file_type,j,c,len; Xchar *cp, *indx, names[NAMSIZE]= "", string[NAMSIZE]= ""; XFILE *temfile; X X initialize(); X X/* Decode the options and parameters: */ X if(argc ==1) X { X create = 1; /* Default for now */ X operation = 'c'; X list = 0; X verbose = 1; X wait = 0; /* Don't wait for prompt */ X } X if(--argc > 0) X { X cp = argv[1]; X while(c = *cp++) X { X switch(c) X { X case 'c': /* c and t exclusive */ X create = 1; X operation = 'c'; X list = 0; X break; X case 't': X create = 0; X list = 1; X operation = 't'; X verbose = 1; /* t means report */ X break; X case 'v': X verbose=1; X break; X case 'w': X wait=1; X break; X default: X printf("Option '%c' not recognized.\n",c); X } X } X } X X X X/* Use the parse operation to fill in missing specifications, and X* set up for repeated searching. The multiple file search described X* in the RMS manual does not seem to work, so we will have to sort out X* the items separated by commas. X */ X if(--argc > 0) X strcpy(names,argv[2]); /* Assume file name is next */ X else X { X strcpy(names,"[...]*.*"); X/******** COMMENTED OUT.. otherwise asks the user for file names X printf(" File name(s)?"); X gets(names); X************ */ X } X if(create) /* Open the output and scratch files */ X { X outfd = creat(tarfile,0600,"rfm=fix","mrs=512"); X temfile = tmpfile(); X temfd = fileno(temfile); X if(outfd < 0 || temfd < 0 ) X { X printf( X "Couldn't open output tar or scratch file. Bye,bye.\n"); X exit(2); X } X } X /* Now we will extract search strings from the names string. Assume X * they are separated by commas. X */ X while(strlen(names)!=0) /* Get the file name argument */ X { X if(indx=strchr(names,',')) X *indx = 0; /* Replace , by terminator */ X if(strchr(names,']')) /* Always include a directory spec */ X strcpy(string,names); /* Get the new part */ X else /* If no directory, keep the old one */ X if((cp = strchr(string,']'))) X strcpy(cp+1,names); X else X strcpy(string,names); X if(initsearch(string) <= 0) X printf("***** No files found while searching for:%s\n",string); X else X while(search(newfile,100)!=0) X { X chgcase(newfile); /* all lower case, please */ X cleanup_dire(newfile); X file_type = scan_name(newfile,new_directory,outfile); X strcpy(pathname,new_directory); X strcat(pathname,outfile); X get_attributes(newfile); X if(create) X { X if(file_type == ISDIRE) X { X bytecount = 0; X mode = 0755; X fill_header(pathname); X write_header(outfd); X } X if(file_type == ISFILE) X { X mode = 0644; X if(addfile(newfile, pathname) < 0) X printf("ERROR: %s NOT COPIED\n",newfile); X } X } X if(verbose || list) X { X if(bytecount || file_type == ISDIRE) X printf("%c: %-40s %6d %26s", X operation,pathname,bytecount,ctime(&vmstime)); X else X printf("IGNORED: %s\n",pathname); X } X } X if(indx) /* any more in the string ? */ X strcpy(names,indx+1); /* Yes, work on it */ X else X break; X } X if(create) X { X write_trailer(outfd); X close(outfd); X } X exit(SS$_NORMAL); X} X X/* Copy the vms file to the output file. X* X*/ X Xint addfile(vmsname,unixname) Xchar vmsname[],unixname[]; X{ Xint ind; X if(bytecount == 0) /* We don't output null files */ X return(0); X if((ind=out_file(vmsname,bytecount,outfd)) < 0) X return(ind); X bufferpointer = bufferpointer%BLKSIZE; X return(1); X} X X X/* Write out the file. X* move nbytes of data from "fdin" to "fdout"; X* Always pad the output to a full DSIZE X* If it a vms text file, it may be various formats, so we will X* write into a temporary file first, then copy to the output X* so that we get the correct byte count. X* We set the bytecount=0 if this is funny file. X*/ Xint out_file(filename,nbytes,fdout) Xchar filename[]; Xint fdout, nbytes; X{ Xint i, n, pos, fdin; XFILE *filein; X if(vmsrfm == FIXED) X { X if((fdin=open(filename,0)) <=0) X { X printf("Error opening input file %s\n",filename); X return(-1); X } X fill_header(pathname); /* We have all of the information */ X write_header(outfd); /* So write to the output */ X while(nbytes > 0) X { X n = read(fdin,dbuffer,nbytes>DSIZE? DSIZE:nbytes); X if(n<0) X { X close(fdin); X printf("Read error on input file\n"); X return(-1); X } X nbytes -= n; X write(fdout,dbuffer,DSIZE); X bufferpointer += DSIZE; /* Count the position */ X } X close(fdin); X return(0); X } X else if(vmsrat != 0) /* must be a text file */ X { /* Write out to standard stream */ X if((filein = fopen(filename,"r")) == NULL) X { X printf("ERROR OPENING %s\n",filename); X return(-1); X } X nbytes = 0; X lseek(temfd,0,0); /* Back to the beginning */ X while((i = fgets(dbuffer,DSIZE,filein)) != NULL) X { X n = strlen(dbuffer); X nbytes += n; X write(temfd,dbuffer,n); X } X fclose(filein); /* All done with the input */ X lseek(temfd,0,0); /* Back to the beginning */ X bytecount = nbytes; /* Use the real count */ X fill_header(pathname); /* Compute the header */ X write_header(outfd); /* Write it */ X while(nbytes > 0) /* Now copy to the output */ X { X n = read(temfd,dbuffer,nbytes>DSIZE? DSIZE:nbytes); X nbytes -= n; X write(fdout,dbuffer,DSIZE); X bufferpointer += DSIZE; /* Count the position */ X } X return(0); X } X /* Other formats e.g. .OBJ are not done */ X bytecount = 0; X return(0); X} X X/* Copy the header to the output file */ Xint write_header(fd) Xint fd; X{ Xint n; X if((n=write(fd,&header,DSIZE))!=DSIZE) X { X printf("Error writing header in output file.\n"); X exit(1); X } X bufferpointer += DSIZE; X return(n); X} X X/* get the file attributes via stat() */ X Xint get_attributes(fname) Xchar fname[]; X{ X if(stat(fname,sblock)) X { X printf("Error getting file status:%s\n",fname); X vmstime = 0; /* Prevent garbage printoout */ X bytecount = 0; /* of inaccessible files */ X return(-1); X } X/* now get the file attributes, we don't use them all */ X bytecount = sblock->st_size; X vmsrat = sblock->st_fab_rat; X vmsmrs = sblock->st_fab_mrs; X vmsrfm = sblock->st_fab_rfm; X vmstime = sblock->st_mtime; X} X X X/* Write the two blank blocks on the output file, and pad the output X* to a full blocksize if needed. */ Xwrite_trailer(fdout) Xint fdout; X{ Xint rem; X header = *empty; X write_header(fdout); X write_header(fdout); X bufferpointer = bufferpointer%BLKSIZE; X while (bufferpointer < BLKSIZE) X write_header(fdout); X return(1); X} X X/* Decode a file name into the directory, and the name, and convert X* to a valid UNIX pathname. Return a value to indicate if this is X* a directory name, or another file. X* We return the extracted directory string in "dire", and the X* filename (if it exists) in "fname". The full title is in "line" X* at input. X*/ X Xint scan_name(line,dire,fname) Xchar line[],dire[],fname[]; X{ Xchar temp[NAMSIZE],*end1,*end2; Xint len,len2,i; X/* The format will be VMS at input, so we have to scan for the X* VMS device separator ':', and also the VMS directory separators X* '[' and ']'. X* If the name ends with '.dir;1' then it is actually a directory name. V* The outputs dire and fname will be a complete file spec, based on the defaul Xt X* directory. X* It may be a rooted directory, in which case there will be a "][" string X* remove it.. V* Strip out colons from the right, in case there is a node name (should not be! X) X*/ X X X strcpy(temp,strrchr(line,':')+1); /* Start with the whole name */ X/* Get rid of default directory part of the name */ X for(end1=temp,end2=strrchr(directory,':')+1;*end2 && (*end1 == *end2); X end1++,end2++); X if(*end2 == 0) X *end1 = 0; /* Perfect match, no directory spec */ X else X { X switch(*end1) X { X case '.': X case '[': /* Legal beginnings or ends */ X break; X case ']': /* We are above the default, use full name */ X end1 = strchr(temp,'['); /* Fixed this from 1.5 */ X break; X default: /* Something strange, back up */ X/******* printf("File located above default directory..\n"); ***/ X while(*end1 != '.' && *end1 != '[' && end1 >= temp) X end1--; X break; X } X end1++; /* Get past the starting . or [ */ X } X strcpy(dire,end1); X if(strlen(dire)) X strcpy(strchr(dire,']'),"/"); /* get rid of the directory marks */ X strcpy(temp,strchr(line,']')+1); /* Now get the file name */ X if((end1=strindex(temp,".dir;1"))!=0) X { X strcpy(end1,"/"); /* Terminate directory name */ X strcat(dire,temp); X strcpy(fname,""); X } X else X { X strcpy(fname,temp); X strcpy(strchr(fname,';'),""); /* no version numbers */ X } X /* Now rewrite the directory name */ X for (i=1;dire[i];i++) /* Change '.' to '/' */ X if(dire[i]=='.') X dire[i]='/'; X if(strlen(fname)==0) X { X return(ISDIRE); X } X else X return(ISFILE); X} X X/* To start looking for file names to satisfy the requested input, X* use the sys$parse routine to create a wild-card name block. When X* it returns, we can then use the resultant FAB and NAM blocks on X* successive calls to sys$search() until there are no more files X* that match X*/ X Xint initsearch(string) Xchar string[]; X{ Xint status; X X if(strindex(string,"::")!=NULL) X { X printf("***** Access across nodes is not supported.\n"); X return(-1); X } X fblock = cc$rms_fab; X nblock = cc$rms_nam; X fblock.fab$l_dna = default_name; X fblock.fab$b_dns = strlen(default_name); X fblock.fab$l_fna = string; X fblock.fab$b_fns = strlen(string); X fblock.fab$l_nam = &nblock; X nblock.nam$l_esa = searchname; X nblock.nam$b_ess = sizeof(searchname); X#ifdef debug X printf("searching on: %s\n",string); X#endif X status = sys$parse(&fblock); X if(status != RMS$_NORMAL) X { X if(status == RMS$_DNF) X printf("Directory not found:%s\n",searchname); X else X printf("Error in sys$parse()\n"); X return (-1); X } X searchname[nblock.nam$b_esl] = 0; /* Terminate the string */ X /* Now reset for searching, pointing to the parsed name block */ X fblock = cc$rms_fab; X fblock.fab$l_nam = &nblock; X return(nblock.nam$b_esl); /* return the length of the string */ X} X X/* Get the next file name that matches the namblock that was set X* up by the sys$search() function. X*/ Xint search(buff,maxlen) Xchar buff[]; Xint maxlen; X{ Xint status; X X nblock.nam$l_rsa = buff; X nblock.nam$b_rss = maxlen; X nblock.nam$b_rsl = 0; /* For next time around */ X while( (status = sys$search(&fblock)) != RMS$_NMF) X { X buff[nblock.nam$b_rsl] = 0; X if(status == RMS$_NORMAL) X { X return(nblock.nam$b_rsl); X } X else X { X if( status == RMS$_PRV) X printf("%s : No privilege for access.\n",buff); X else if (status == RMS$_FNF) X printf("%s : File not found.\n",buff); X else X { X printf(" Error in f$search for :%s\n", buff); X return (0); X } X } X } X return (0); X} X/* Fill the fields of the header; enter with the file name X* if the file name is empty, then this is a trailer, and we should X* fill it with zeroes. */ X Xint fill_header(name) Xchar name[]; X{ Xint i,chksum; Xchar *ptr,tem[15]; X header = *empty; /* Clear the header */ X if(strlen(name)!=0) /* only fill if there is a file */ X { X sprintf(header.title,"%s",name); /* write file name */ X sprintf(header.protection,"%6o ",mode); /* all written with */ X sprintf(header.uid,"%6o ",uid); /* a trailing space */ X sprintf(header.gid,"%6o ",gid); X sprintf(tem,"%11o ",bytecount); /* except the count */ X strncpy(header.count,tem,12); /* and the time, which */ X sprintf(tem,"%11o ",vmstime); /* except the count */ X strncpy(header.time,tem,12); /* have no null */ X strncpy(header.chksum," ",8); /* all blanks for sum*/ X/* I know that the next two are already zero, but do them */ X header.linkmode = 0; /* always zero */ X sprintf(header.linkname,"%s",""); /* always blank */ X for(chksum=0, ptr = &header;ptr < &header.linkmode;ptr++) X chksum += *ptr; /* make the checksum */ X sprintf(header.chksum,"%6o",chksum); /* This is how it looks */ X } /* on UNIX tapes... */ X return(0); X} X X/* Initialize various fields, get some standard values */ X Xinitialize() X{ Xint i; X dbuffer = malloc(DSIZE+1); X sblock = malloc(sizeof(struct stat)); X empty = malloc(DSIZE); X for (i=0;i < DSIZE;i++) X empty->title[i] = 0; /* all zeroes, even if malloc() did it */ X header = *empty; X bufferpointer = 0; X gid = getgid(); /* for now, use the user's uic */ X uid = getuid(); /* and group uic */ X mode = 0644; /* This get changed elsewhere, anyhow */ X strcpy(directory,getenv("PATH")); /* Default directory */ X return; X} X X X/* Search for string2 in string1; return address pointer. */ Xchar *strindex(string1,string2) Xchar *string1,*string2; X{ Xchar *c1, *c2, *cp; X for(c1 = string1; *c1 !=0; c1++) X { X cp = c1; /* save the start address */ X for(c2=string2; *c2 !=0 && *c1 == *c2; c1++,c2++); X if(*c2 == 0) X return(cp); X } X return(NULL); X} X X/* function to change a string to lower case */ Xint chgcase(string) Xchar string[]; X{ Xint i; X for(i=0;string[i]=tolower(string[i]);i++); X return (--i); /* return string length */ X} X X/* Routine to get rid of rooted directory problems, X* and any others that turn up X*/ X Xint cleanup_dire(string) Xchar string[]; X{ Xchar *ptr, temp[NAMSIZE]; X if((ptr=strindex(string,"][")) == NULL) X return(0); X /* Just collapse around the string */ X strcpy(ptr,ptr+2); X return(1); X} $ GoSub Convert_File $ Goto Part2
Dick_Alrutz.WBST147@Xerox.COM, info-vax@kl.sri.COM (03/29/88)
Sid, I have been looking for the updates to tar, and received 1 and not the second in the 5.03 distribution. I also noticed a fix sent along recently. Can you resend parts 1 & 2 with the fix? Thank you, Dick
pjh@mccc.UUCP (Peter J. Holsberg) (04/08/88)
Does anyone have a VMS utility that will read a UNIX TAR-formatted 9-track tape? I'd appreciate a mailing or a posting. Thank you. -- Peter Holsberg UUCP: {rutgers!}princeton!mccc!pjh Technology Division CompuServe: 70240,334 Mercer College GEnie: PJHOLSBERG Trenton, NJ 08690 Voice: 1-609-586-4800