Ultrix-3.1/src/cmd/ltf/xtractf.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
#ifndef lint
static char *sccsid = "@(#)xtractf.c 3.0 (ULTRIX) 4/21/86";
#endif lint
/**/
/*
*
* File name:
*
* xtractf.c
*
* Source file description:
*
* Contains the functions that read data from the
* input volume and places it in the resultant
* output disk file.
*
* Functions:
*
* checkdir() Check to see if a directory exists
* & create missing directories
*
* fufcnv() Converts a Fortran Unformatted File
* (from input volume) to correct Ultrix
* disk file format
*
* getlen() Get the length of the next variable-
* length record from the input volume
*
* xtractf() Top level logic to extract files
* from the input volume
*
* Usage:
*
* n/a
*
* Compile:
*
* cc -O -c xtractf.c <- For Ultrix-32/32m
*
* cc CFLAGS=-DU11-O xtractf.c <- For Ultrix-11
*
*
* Modification history:
* ~~~~~~~~~~~~~~~~~~~~
*
* revision comments
* -------- -----------------------------------------------
* 01.0 25-April-85 Ray Glaser
* Create original version
*
* 01.1 4-Sep-85 Suzanne Logcher
* Correct use of Noheader3 in xtractf()
*
* 01.2 4-Oct-85 Suzanne Logcher
* Add logic to extract a segmented file
*/
/*
* +--> Include File(s)
*/
#include "ltfdefs.h"
/**/
/*
*
* Function:
*
* checkdir
*
* Function Description:
*
* This function checks to see if a directory exists.
* It creates those directories that are not found to exist.
*
* Arguments:
*
* char *path Pointer to the string containing the
* directory path structure to be checked.
*
* Return values:
*
* TRUE if the directory existed
* FALSE if the directory had to be created
*
* Side Effects:
*
* This functions "forks" a child process to create a
* needed directory.
*
* If the function fails to create the required directory,
* an error message is output to stderr and the function
* exits to system control.
*
*/
checkdir(path)
char *path;
{
/*
* +--> Local variables
*/
char dummy[MAXPATHLEN+1];
char dummy2[MAXPATHLEN+1];
int k;
/*------*\
Code
\*------*/
/* Remove any trailing slash from directory name, else
* the mkdir call will fail. dummy is used to preserve the
* orginal form of path given to us.
*/
strcpy(dummy2,path);
j = 0;
for (cp = dummy2; *cp; cp++)
if (*cp == '/')
j++;
i = strlen(dummy2);
if (dummy2[i-1] == '/')
dummy2[i-1] = 0;
for (i = 1; i <= j; i++) {
strcpy(dummy, dummy2);
cp = dummy;
for (k = 1; *cp && k <= i; cp++)
if (*cp == '/')
k++;
if (*(--cp) == '/')
*cp = 0;
if (stat(dummy, &Inode) < 0) {
register int pid, rp;
if (!(pid = fork())) {
execl("/bin/mkdir", "mkdir", dummy, 0);
execl("/usr/bin/mkdir", "mkdir", dummy, 0);
/* If the execl's ever return to here, ERROR */
PERROR "\n%s: %s %s %c\n", Progname, CANTMKD, dummy,BELL);
perror(Progname);
exit(FAIL);
}/*E if pid = fork ..*/
while ((rp = wait(&i)) >= 0 && rp != pid)
;
return(TRUE);
}/*E if stat dummy &Inode ..*/
}/*E for */
return(FALSE);
}/*E checkdir() */
/**/
/*
*
* Function:
*
* fufcnv
*
* Function Description:
*
* Converts a Fortran Unformatted File (from input volume)
* to the correct form for an Ultrix disk file.
*
* Arguments:
*
* int count;
* FILE *fp;
* char *p;
*
*
* Return values:
*
*
* Side Effects:
*
*
*/
fufcnv(name, p, count, fp)
char *name; /* filename used for error */
char *p;
int count;
FILE *fp;
{
/*
* +--> Local Variables
*/
int bincnt = 0;
/*------*\
Code
\*------*/
i = *p++;
j = *p++;
if (j != 0)
PERROR "\n%s: %s %d%c\n", Progname, SCNDCB, j, BELL);
count -= 2;
switch(i) {
case ALL:
bincnt = count;
if (write(fileno(fp), &bincnt, sizeof(bincnt)) != sizeof(bincnt)) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
if (write(fileno(fp), p, bincnt) != bincnt) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
if (write(fileno(fp), &bincnt, sizeof(bincnt)) != sizeof(bincnt)) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
break;
case FIRST:
bincnt = 0;
if (write(fileno(fp), Spaces, sizeof(bincnt)) != sizeof(bincnt)) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
if (write(fileno(fp), p, count) != count) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
bincnt += count;
break;
case MIDDLE:
if (write(fileno(fp), p, count) != count) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
bincnt += count;
break;
case LAST:
if (write(fileno(fp), p, count) != count) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
bincnt += count;
fseek(fp, (long)(-1 * (bincnt+sizeof(bincnt))), 1);
if (write(fileno(fp), &bincnt, sizeof(bincnt)) != sizeof(bincnt)) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
fseek(fp, (long)bincnt, 1);
if (write(fileno(fp), &bincnt, sizeof(bincnt)) != sizeof(bincnt)) {
PERROR "\n:%s %s %s\n", Progname, ERRWRF, name);
exit(FAIL);
}
break;
default:
PERROR "\n%s: %s %d%c\n", Progname, FSTCB, i, BELL);
break;
}
return(1);
}/*E fufcnv() */
/**/
/*
*
* Function:
*
* getlen
*
* Function Description:
*
* Get and return the length of the next variable-length
* record from the input volume.
*
* Arguments:
*
* char *s Pointer to the string containing ?_?
*
* Return values:
*
* The integer length of the record is returned.
*
* A zero length is a valid return value. It indicates
* an empty record.
*
* If *s points to the padding character (^),
* -1 is returned to signify the end of available data
* in the current block.
*
*
* Side Effects:
*
* none
*/
getlen(s)
char *s;
{
/*------*\
Code
\*------*/
if (*s == PAD)
return(-1); /* Record padding character seen, signal
* end of data to the caller.
*/
/* Increment pointer if record is segmented
*/
if (L_recformat == SEGMENT)
s++;
/* Default is an empty record
*/
j = 0;
for (i=0; i < 4; i++)
j = 10 * j + (*s++ - '0');
/* If VARIABLE, -4. If SEGMENT, -5
*/
if (L_recformat == VARIABLE)
return(j-4);
return(j-5);
}/*E getlen() */
/**/
/*
*
* Function:
*
* xtractf
*
* Function Description:
*
* Extract a given file from the input Volume.
*
* Arguments:
*
* char *path; Pathname_+_filename from input vol
* char *s; User entered path/file name
* long charcnt; Character count (if applicable)
* char *name; Alternate name given to disk file if
* different from that on the input
* volume (user driven). Used when -W
* switch is given and the input volume
* file is found to exist on disk.
*
* Return values:
*
* 1. The character count of the extracted file.
* 2. -or- -1 if an error was encountered that can
* be recovered from without undue hardship.
*
* (xtractf must return -1 upon error because a
* zero-length file can have a valid returned
* length of 0 bytes)
*
* Side Effects:
*
* If the function cannot write the file on the output
* disk for whatever ... An error message is output to
* stderr and the function exits to system control.
*
* If the user has requested that warnings be issued when
* a file being extracted is already on disk (-W qualifier)
* the logic will pause and give the user the option(s) of:
*
* 1. Cancel the extraction of the file from
* the input volume.
*
* 2. Extract the file and overwrite the existing
* copy on the output medium.
*
* 3. Extract the file, but give it a new name as
* supplied by the user.
*/
long xtractf(path, s, charcnt, name)
char *path; /* pathname_+_filename from input vol */
char *s; /* user entered path/file name */
long charcnt; /* character count (if applicable) */
char *name; /* alternate extracted filename
* (if different from user entered
* name) */
{
/*
* +--> Local Variables
*/
int count;
int done = FALSE; /* Boolean to make sure new file names
* get "stat" -ed too */
char dummy2[MAXPATHLEN+1]; /* Temporary variable */
char Inbuf[MAXBLKSIZE+1]; /* File writing buffer */
int nbytes;
long num = 0L;
char *p;
char *q;
FILE *xfp;
/*------*\
Code
\*------*/
/* If user didn't specify path/file names, use the
* name from the input volume as default.
*/
if (!*s) {
strcpy(dummy2,path);
#if 0
sprintf(dummy2, "%s%s", path, L_filename);
term_string(dummy2,DELNL,TRUNCATE);
#endif
}
else
strcpy(dummy2, s);
if (Wildc) {
/*
* User entered a wild card name string that matched
* the current file on the input volume.
* Use the actual name found on the
* input volume.
*/
#if 0
term_string(path,DELNL,TRUNCATE);
#endif
strcpy(name,path);
strcpy(dummy2,path);
}
if (!strcmp(Tftypes,"dir")) {
Dircre = checkdir(dummy2);
fsf(1);
return((long)(0));
}/*T if (!strcmp(Tftypes,"dir")) */
while (stat(dummy2, &Inode) >= 0 && !done) {
if (Warning) {
PROMPT "\n%s: %s %s\n", Progname, EXISTS, dummy2);
PROMPT "%s: %s %c", Progname, OVRWRT, BELL);
gets(Labelbuf);
PROMPT "\n");
Labelbuf[0] = Labelbuf[0] == 'Y' ? 'y' : Labelbuf[0];
if (Labelbuf[0] != 'y') {
/*
* User does not want to overwrite existing file.
*/
char dummy[MAXPATHLEN+1];
PROMPT "%s: %s ", Progname, ALTERN);
gets(dummy);
PERROR "\n");
if (!dummy[0]) {
/*
* User wants to skip extract of this file.
*/
fsf(2);
return((long)(-1));
}/*T if !dummy[0] */
else {
if (strlen(dummy) > MAXPATHLEN) {
PERROR "\n%s: %s %s%c", Progname,
FNTL, dummy, BELL);
fsf(2);
return((long)(-1));
}/*T if strlen dummy > MAXPATHLEN */
else {
#if 0
term_string(dummy,DELNL,TRUNCATE);
#endif
strcpy(dummy2, dummy);
strcpy(name, dummy2);
Wildc = FALSE;
}/*F if strlen dummy > MAXPATHLEN */
}/*F if !dummy[0] */
}/*T if Labelbuf[0] != 'y') */
else
done = TRUE;
}/*E if Warning */
else
done = TRUE;
}/*while stat dummy2 ..*/
/* File being extracted ...
*/
if (!(xfp = fopen(dummy2, "w")))
if ((Dircre = checkdir(dummy2)) == FALSE) {
PERROR "\n%s: %s %s %c\n", Progname,
CANTCRE, dummy2, BELL);
perror(Progname);
fsf(2);
return((long)(-1));
}
else {
if (!(xfp = fopen(dummy2, "w"))) {
PERROR "\n%s: %s %s %c\n", Progname, CANTCRE, dummy2, BELL);
perror(Progname);
fsf(2);
return((long)(-1));
}/*if !xfp */
}
while ((nbytes = read(fileno(Magtfp), p=Inbuf, L_blklen)) > 0 ) {
if (!Tape) {
if (tape_mark(Inbuf))
goto eofdata;
}/*E if !Tape */
if (L_recformat == FIXED || L_recformat == UFORMAT || (L_recformat != VARIABLE && L_recformat != SEGMENT)) {
/*
* Test if charcnt == 0L
* foreign tapes won't have a character count !
*/
if (charcnt == 0L) {
cp = p;
cp += nbytes;
while (*--cp == PAD)
;
cp++;
num += (long)(cp - p);
if (write(fileno(xfp), p, cp - p) != (cp - p)) {
PERROR "\n%s: %s %s\n", Progname, ERRWRF, dummy2);
exit(FAIL);
}/*E if write < 0 */
}/*T if charcnt == 0L */
else if (charcnt >= (long)nbytes) {
if (write(fileno(xfp), Inbuf, nbytes) != nbytes) {
PERROR "\n%s: %s %s\n", Progname, ERRWRF, dummy2);
exit(FAIL);
}/* if write < 0 */
charcnt -= (long)nbytes;
num += (long)nbytes;
}/*T if charcnt >= nbytes */
else if (charcnt > 0L) {
if (write(fileno(xfp), Inbuf,(int)charcnt) != (int)charcnt){
PERROR "\n%s: %s %s\n", Progname, ERRWRF, dummy2);
exit(FAIL);
}/* if write < 0 */
num += charcnt;
/* Set charcnt equal to -1 */
charcnt = (long)(-1);
}/* if charcnt > 0L */
}/*T if (L_recformat == FIXED) */
/**/
/*
* Volume file was not FIXED LENGTH record format.
*/
else {
j = 0;
while (p < &Inbuf[nbytes] && (count = getlen(p)) >= 0) {
if (L_recformat == VARIABLE) {
p += 4;
if (!count) {
putc('\n', xfp);
fflush(xfp);
num++;
continue;
}/*E if !count */
}/*T if L_recformat == VARIABLE */
else if (L_recformat == FUF) {
p += 4;
if (! fufcnv(dummy2, p, count, xfp)) {
PERROR "\n%s: %s\n", Progname, FUFTL);
PERROR "%s: %s -> %s%c\n", Progname,
NOTEX, dummy2, BELL);
fsf(2);
return((long)(-1));
}/*E if ! fufcnv ..*/
p += count;
continue;
}/*T if L_recformat == FUF */
else
if (L_recformat == SEGMENT) {
q = p;
p += 5;
if (write(fileno(xfp), p, count) != count) {
PERROR "\n%s: %s %s\n", Progname, ERRWRF, dummy2);
exit(FAIL);
}/*E if write < 0 */
if (*q == '0' || *q == '3') {
putc('\n', xfp);
fflush(xfp);
num++;
}/*T if (*q == '0' || *q == '3') */
p += count;
num += (long)count;
continue;
}/*T if L_recformat == SEGMENT */
else /* L_recformat == DD */
count += 4;
if (write(fileno(xfp), p, count) != count) {
PERROR "\n%s: %s %s\n", Progname, ERRWRF, dummy2);
exit(FAIL);
}/*E if write < 0 */
p += count;
num += (long)count;
/* ?_?
* ?_? Checking for VARIABLE type AGAIN ??? ?_?
*/
if (L_recformat == VARIABLE) {
putc('\n', xfp);
fflush(xfp);
num++;
}/*E if L_recformat == VARIABLE */
}/*E while p < &Inbuf[nbytes] .. */
}/*F if (L_recformat == FIXED) */
}/*E while ((nbytes = read(fileno(Magtfp), p=Inbuf, L_blklen))) */
if (nbytes < 0) {
PERROR "\n%s: %s %s\n", Progname, CANTRD, Magtdev);
ceot();
}
/*
*/
eofdata:
fclose(xfp);
return(num);
}/*E xtractf() */
/**\\**\\**\\**\\**\\** EOM xtractf.c **\\**\\**\\**\\**\\*/
/**\\**\\**\\**\\**\\** EOM xtractf.c **\\**\\**\\**\\**\\*/