xtractf.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 687 行
C
687 行
#ifndef lintstatic char *sccsid = "@(#)xtractf.c 4.2 ULTRIX 9/7/90";#endif lint/**************************************************************** * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * 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 Digital Equipment Corporation. * * * * Digital assumes no responsibility for the use or * * reliability of its software on equipment which is not * * supplied by Digital. * * * ****************************************************************//**//* * * 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 * * 01.3 3-Jul-90 Allen Carito * In xtractf, PAD check section was causing files * to be partially copied. That section was removed. * The end result is the full block read is fully copied. * *//* * +--> 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;union wait *status;/*------*\ 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. */status = '\0';strcpy(dummy2,path);j = 0;for (cp = dummy2; *cp; cp++) if (*cp == '/') j++;if (j == 0) return(FALSE);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(status)) >= 0 && rp != pid) ; Dircre = TRUE; }/*E if stat dummy &Inode ..*/}/*E for */return(TRUE);}/*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), (char *)&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), (char *)&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), (char *)&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), (char *)&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")) { (void) 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 ((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 + nbytes; 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 **\\**\\**\\**\\**\\*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?