From:	ADVAX::"mcnc!CUNYVM.CUNY.EDU!MAILSERV%FRSIM51.BITNET" 22-FEB-1991 11:55:46.81
To:	ARISIA::EVERHART
CC:	
Subj:	MAEVA:[MAILSERV.PUB.VMSTAR]VMSTAR.SHARE_3;1

Received: by ADVAX.DECnet (utk-mail11 v1.5) ; Fri, 22 Feb 91 11:54:51 EST
Received:  from mcnc by ge-dab.GE.COM (5.61/GE-DAB 1.15) with UUCP
	id AA26080 for ; Fri, 22 Feb 91 11:47:50 -0500
Received: from CUNYVM.CUNY.EDU by mcnc.mcnc.org (5.59/MCNC/6-11-90)
	id AA17488; Fri, 22 Feb 91 10:14:52 -0500
	for ARISIA.DNET.ge.com!EVERHART
Message-Id: <9102221514.AA17488@mcnc.mcnc.org>
Received: from FRSIM51.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.2.2MX) with BSMTP id 5161; Fri, 22 Feb 91 10:15:17 EST
Date: 22 FEB 91 16:10:07.15-WET
From: mcnc!CUNYVM.CUNY.EDU!MAILSERV%FRSIM51.BITNET
Subject: MAEVA:[MAILSERV.PUB.VMSTAR]VMSTAR.SHARE_3;1
To: ARISIA::EVERHART
 
-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+
Xchar *dotp;
X
X    created = 1;
X    status = mkdir(want, 0);   /* mkdir in VAX C creates all missing levels
V */
X    if (status != 0)
X    `7B
X        if (errno == EEXIST)
X            return (0);
X        if (errno != EINVAL)
X            return (-1);          /* unknown error, simply return */
X        else                      /* maybe too many levels of directories */
X        `7B                         /* change "`5B...FOO.BAR`5D" to "`5B...F
VOO$BAR`5D" */
X        for (dotp = &want`5Bstrlen(want) - 1`5D;dotp > want && status != 0;)
X            if (*--dotp == '.')`20
X            `7B
X                *dotp = '$';
X                status = mkdir(want, 0);
X                if (status != 0 && errno == EEXIST)
X                `7B
X                    status = created = 0;
X                    break;
X                `7D
X            `7D
X        `7D
X    `7D
X    if (status != 0)
X        return (-1);
X    if(verbose && created)
X        printf("                              %s\n",want);
X    return(0);
X`7D
X
X /* Function to open and get data from the blocked input file */
XFILE *opentar()
X`7B
XFILE *fp;
X    fp = fopen(tarfile, "rb");
X    if(fp == NULL)
X        `7B
X        printf("tar: can't open tarfile.\n");
X        return(0);
X        `7D
X    return(fp);
X`7D
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`7B
Xint stat;
X    stat = fread(buffer,1,DSIZE,tarfp);    /* read the header */
X    return(stat);                       /* catch them next read ? */
X`7D
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`7B
Xint i=0;
X    while(bytes > 0)
X        `7B
X        if((i=fread(buffer,1,DSIZE,tarfp)) == 0)
X            `7B
X            printf("tar: EOF hit while skipping.\n");
X            return(-1);
X            `7D
X        bytes -= i;
X        `7D
X    return(0);
X`7D
X
X/* Decode the fields of the header */
X
Xint decode_header()
X`7B
Xint idate, *bintim, chksum, value;
Xchar ll, *ptr;
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`5B24`5D=0;
X    sscanf(header.count,"%o",&bytecount);
X    sscanf(header.protection,"%o",&mode);
X    sscanf(header.uid,"%o",&uic1);
X    sscanf(header.gid,"%o",&uic2);
X    sscanf(header.chksum,"%o",&chksum);
X
X/* Verify checksum */
X
X    for(value = 0, ptr = &header; ptr < &header.chksum; ptr++)
X             value += *ptr;                /* make the checksum */
X    for(ptr = &header.linkcount; ptr <= &header.dummy`5B255`5D; ptr++)
X             value += *ptr;
X    value += (8 * ' ');`09               /* checksum considered as all space
Vs */
X
X    if (chksum != value)
X    `7B                                       /* abort if incorrect */
X        printf("tar: directory checksum error for %s\n",pathname);
X        exit(1);
X    `7D
X
X
X/* We may have the link written as binary or as character:  */
X
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`7D
X
X
X/* vms_cleanup -- removes illegal characters from directory and file names
X * Replaces hyphens and commas with underscores. Returns number of translati
Vons
X * that were made.
X */
X
Xvms_cleanup(string)
Xchar string`5B`5D;
X`7B
X    int i,flag=0;
X    char c;
X
X    for(i=0; c=string`5Bi`5D; ++i)
X    `7B
X        if (strchr(badchars, c) != NULL)
X        `7B                    /* Replace illegal characters by underscores
V */
X            string`5Bi`5D= '_';
X            flag++;          /* Record if any changes were made */
X        `7D
X        else
X            string`5Bi`5D = toupper(c); /* Map to uppercase */
X    `7D
X    return(flag);
X`7D
X
X/* vms2tar -- handles create function */
X
Xvms2tar(argc,argv)
Xint argc;
Xchar **argv;
X`7B
X    int argi, process, file_type, absolute;
X    char string`5BNAMSIZE`5D, *cp, *dp, *wp;
X
X    if (argc < 3 `7C`7C (foption && argc < 4)) usage();
X
X    bufferpointer = 0;
X    gid = getgid();
X    uid = getuid();
X    mode = 0644;
X
X/* Open the output file */
X
X    outfd = creat(tarfile,0600,"rfm=fix","mrs=512");
X    if (outfd < 0)
X    `7B
X        printf("tar: error opening output tarfile %s\n", tarfile);
X        exit(SS$_NORMAL);
X    `7D `20
X
X    for (argi = foption ? 3 : 2; argi < argc; ++argi)
X    `7B
X        strcpy(string, argv`5Bargi`5D);
X        absolute = 0;
X        cp = strchr(string, ':');   /* device name in argument ? */
X        if (cp != NULL)            /* yes, force absolute mode */
X            absolute = 1;
X        else
X        `7B
X            cp = strchr(string, '`5B');  /* test argument for absolute... */
X            if (cp != NULL)            /* ...or relative filespec */
X            `7B
X                ++cp;
X                if (*cp != '.' && *cp != '-')
X                    absolute = 1;
X            `7D
X        `7D
X        if(initsearch(string) <= 0)
X            printf("tar: no files matching %s\n",string);
X        else
X          while(search(newfile,NAMSIZE)!=0)
X          `7B
X            strcpy(linkname, newfile);
X            cleanup_dire(newfile);
X            file_type = scan_name(newfile,new_directory,outfile,absolute);
X            strcpy(pathname,new_directory);
X            strcat(pathname,outfile);
X            get_attributes(newfile);
X            process = 1;
X            if(wait)
X            `7B
X                *temp = '\0';
X                while (*temp != 'y' && *temp != 'n')
X                `7B
X                    printf("%s   (y/n) ? ", linkname);
X                    scanf("%s", temp);
X                    *temp = tolower(*temp);
X                `7D
X                process = (*temp == 'y');
X            `7D
X            if (process)
X            `7B
X                if(file_type == ISDIRE)
X                `7B
X                    bytecount =  0;
X                    mode = 0755;
X                    fill_header(pathname);
X                    write_header(outfd);
X                `7D
X                if(file_type == ISFILE)
X                `7B
X                    mode = 0644;
X                    if(addfile(newfile, pathname) < 0)
X                    `7B
X                        printf("tar:error copying %s\n",linkname);
X                        exit(SS$_NORMAL);
X                    `7D
X                `7D
X                if (bytecount == 0 && file_type == ISFILE)
X                    printf("*** skipped  %s\n", linkname);
X                if (verbose && (bytecount `7C`7C file_type == ISDIRE))
X                `7B
X                     strcpy(creation,ctime(&vmstime)); /* work on this */
X                     creation`5B24`5D=0;
X                     printf("%s %8d %s\n",creation + 4,bytecount,pathname);
X                `7D
X            `7D
X          `7D
X    `7D
X    write_trailer(outfd);
X    close(outfd);
X`7D
X
X/* addfile - copy the vms file to the output file */
X
Xint addfile(vmsname,unixname)
Xchar vmsname`5B`5D,unixname`5B`5D;
X`7B
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`7D
X
X
X/* out_file - 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* read the file twice in case of a text file
X* so that we get the correct byte count.
X* We set the bytecount=0 if this is funny file.
X*/
X
Xint out_file(filename,nbytes,fdout)
Xchar filename`5B`5D;
Xint fdout, nbytes;
X`7B
Xint i, n, pos, fdin;
Xchar *bufp, *linep;
XFILE *filein;
X
X    if(vmsrfm == FIXED)
X    `7B
X        if((fdin=open(filename,0)) <=0)
X        `7B
X            printf("tar: error opening input file %s\n",filename);
X            return(-1);
X        `7D
X        fill_header(pathname);          /* We have all of the information */
X        write_header(outfd);            /* So write to the output */
X        while(nbytes > 0)
X        `7B
X            n = read(fdin,buffer,nbytes>DSIZE? DSIZE:nbytes);
X            if(n<0)
X            `7B
X                close(fdin);
X                printf("tar: error reading input file %s\n",filename);
X                return(-1);
X            `7D
X            nbytes -= n;
X            flushout(fdout);
X        `7D
X        close(fdin);
X        return(0);
X    `7D
X    else
X        if(vmsrat != 0)                 /* must be a text file  */
X        `7B                               /* compute "Unix" file size */
X            if((filein = fopen(filename,"r")) == NULL)
X            `7B
X                printf("tar: error opening input file %s\n",filename);
X                return(-1);
X            `7D
X            nbytes = 0;
X            while(fgets(dbuffer,DSIZE,filein) !=  NULL)
X                nbytes += strlen(dbuffer);
X            rewind(filein);                 /* 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            bufp = buffer;
X
X            while(fgets(dbuffer,DSIZE,filein) !=  NULL)
X            `7B                               /* Now copy to the output */
X                linep = dbuffer;
X                while (*linep != '\0')      /* read source file line by line
V */
X                `7B
X                    *bufp++ = *linep++;  /* copy in fixed size output buffer
V */
X                    if (bufp >= &buffer`5BDSIZE`5D)
X                    `7B
X                        bufp = buffer;
X                        flushout(fdout);         /* if buffer full, flush it
V */
X                    `7D
X                `7D
X            `7D
X            flushout(fdout);
X            fclose(filein);
X            return(0);
X        `7D
X                        /* Other formats e.g. .OBJ are not done  */
X        bytecount = 0;
X        return(0);
X`7D
X
X/* flushout - write a fixed size block in output tarfile */
X
Xflushout(fdout)
Xint fdout;
X`7B
X    if (write(fdout,buffer,DSIZE) != DSIZE)
X    `7B
X        printf("tar: error writing tarfile.\n");
X        exit(SS$_NORMAL);
X    `7D
X    bufferpointer += DSIZE;
X`7D
X
X/* write_header - copy the header to the output file  */
X
Xint write_header(fd)
Xint fd;
X`7B
Xint n;
X    if((n=write(fd,&header,DSIZE))!=DSIZE)
X    `7B
X        printf("tar: error writing header in tarfile.\n");
X        exit(SS$_NORMAL);
X    `7D
X    bufferpointer += DSIZE;
X    return(n);
X`7D
X
X/*  get_attributes - get the file attributes via stat()  */
X
Xint get_attributes(fname)
Xchar fname`5B`5D;
X`7B
X    if(stat(fname,&sblock))
X    `7B
X        printf("tar: can't get file status on %s\n",fname);
X        vmstime = 0;                    /* Prevent garbage printoout */
X        bytecount = 0;                  /* of inaccessible files  */
X        return(-1);
X    `7D
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`7D
X
X
X/* write_trailer - write the two blank blocks on the output file */
X/* pad the output to a full blocksize if needed. */
X
Xwrite_trailer(fdout)
Xint fdout;
X`7B
Xint i;
X    for (i=0; i < NAMSIZE; ++i)
X        header.title`5Bi`5D = '\0';
X    write_header(fdout);
X    write_header(fdout);
X    bufferpointer = bufferpointer%BLKSIZE;
X    while (bufferpointer < BLKSIZE)
X        write_header(fdout);
X    return(1);
X`7D
X
X/* scan_name - decode a file name */
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,absolute)
Xchar line`5B`5D,dire`5B`5D,fname`5B`5D;
Xint absolute;
X`7B
Xchar *cp1,*cp2;
Xint len,len2,i;
Xchar *strindex();
X
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* '`5B' and '`5D'.
X* If the name ends with '.dir;1' then it is actually a directory name.
X* The outputs dire and  fname will be a complete file spec, based on the def
Vault
X* directory.
X* It may be a rooted directory, in which case there will be a "`5D`5B" strin
Vg,
X* remove it.
X* Strip out colons from the right, in case there is a node name (should not
V be!)
X* If the filename ends in a trailing '.', suppress it , unless the "d" optio
Vn
X* is set.
X*/
X
X
X    strcpy(temp,strrchr(line,':')+1);           /* Start with the whole name
V */
X
X/* If relative path, get rid of default directory part of the name  */
X
X    if (absolute == 0)
X    `7B
X        strcpy(dire,"./");
X        for(cp1 = temp ,cp2 = curdir; *cp2 && (*cp1 == *cp2);
X            cp1++, cp2++);
X        if(*cp2 == 0)
X            *cp1 = 0;              /* Perfect match, no directory spec  */
X        else
X        `7B
X            switch(*cp1)
X            `7B
X            case '.':
X            case '`5B':               /* Legal beginnings or ends  */
X                break;
X            default:            /* We are above the default, use full name *
V/
X                cp1 = strchr(temp,'`5B');    /* Fixed this from 1.5  */
X                *dire = '\0';
X                break;
X            `7D
X            cp1++;                 /* Get past the starting . or `5B */
X        `7D
X        strcat(dire, cp1);
X    `7D
X    else
X        strcpy(dire, temp + 1);
+-+-+-+-+-+-+-+-  END  OF PART 3 +-+-+-+-+-+-+-+-
