Annotation of pgp/src/fileio.c, revision 1.1.1.1

1.1       root        1: /*     fileio.c  - I/O routines for PGP.
                      2:        PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
                      3: 
                      4:        (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
                      5:        The author assumes no liability for damages resulting from the use
                      6:        of this software, even if the damage results from defects in this
                      7:        software.  No warranty is expressed or implied.
                      8: 
                      9:        All the source code Philip Zimmermann wrote for PGP is available for
                     10:        free under the "Copyleft" General Public License from the Free
                     11:        Software Foundation.  A copy of that license agreement is included in
                     12:        the source release package of PGP.  Code developed by others for PGP
                     13:        is also freely available.  Other code that has been incorporated into
                     14:        PGP from other sources was either originally published in the public
                     15:        domain or was used with permission from the various authors.  See the
                     16:        PGP User's Guide for more complete information about licensing,
                     17:        patent restrictions on certain algorithms, trademarks, copyrights,
                     18:        and export controls.  
                     19: 
                     20:        Modified 16 Apr 92 - HAJK
                     21:        Mods for support of VAX/VMS file system
                     22: */
                     23: 
                     24: #include <ctype.h>
                     25: #include <stdio.h>
                     26: #include <stdlib.h>
                     27: #include <string.h>
                     28: #if defined(UNIX)
                     29: #include <sys/stat.h>
                     30: #if !defined(NeXT)
                     31: #include <unistd.h>
                     32: #endif
                     33: #endif
                     34: #include "random.h"
                     35: #include "mpilib.h"
                     36: #include "mpiio.h"
                     37: #include "fileio.h"
                     38: #include "language.h"
                     39: #include "pgp.h"
                     40: #ifdef MSDOS
                     41: #include <io.h>
                     42: #include <fcntl.h>
                     43: #endif
                     44: 
                     45: /* 1st character of temporary file extension */
                     46: #define        TMP_EXT '$'             /* extensions are '.$##' */
                     47: 
                     48: /* The PGPPATH environment variable */
                     49: 
                     50: char PGPPATH[] = "PGPPATH";
                     51: 
                     52: /* Disk buffers, used here and in crypto.c */
                     53: byte textbuf[DISKBUFSIZE];
                     54: static byte textbuf2[2*DISKBUFSIZE];
                     55: 
                     56: boolean file_exists(char *filename)
                     57: /*     Returns TRUE iff file exists. */
                     58: {
                     59: #ifdef UNIX
                     60: #ifndef F_OK
                     61: #define F_OK   0
                     62: #endif
                     63:        return(access(filename, F_OK) == 0);
                     64: #else
                     65:        FILE *f;
                     66:        /* open file f for read, in binary (not text) mode...*/
                     67:        if ((f = fopen(filename,"rb")) == NULL)
                     68:                return(FALSE);
                     69:        fclose(f);
                     70:        return(TRUE);
                     71: #endif
                     72: }      /* file_exists */
                     73: 
                     74: 
                     75: boolean file_ok_write(char *filename)
                     76: /*     Returns TRUE iff file can be opened for writing.
                     77:        Does not harm file!
                     78: */
                     79: {      FILE *f;
                     80:        if (file_exists (filename))
                     81:                return(TRUE);
                     82:        if ((f = fopen(filename,"wb")) == NULL)
                     83:                return(FALSE);
                     84:        fclose(f);
                     85:        remove(filename);
                     86:        return(TRUE);
                     87: }      /* file_ok_write */
                     88: 
                     89: boolean is_regular_file(char *filename)
                     90: {
                     91: #ifdef S_ISREG
                     92:        struct stat st;
                     93:        return(stat(filename, &st) != -1 && S_ISREG(st.st_mode));
                     94: #else
                     95:        return TRUE;
                     96: #endif
                     97: }
                     98: 
                     99: int wipeout(FILE *f)
                    100: {      /*      Completely overwrite and erase file, so that no sensitive
                    101:                information is left on the disk.
                    102:                NOTE:  File MUST be open for read/write.
                    103:        */
                    104: 
                    105:        long flength;
                    106:        int count = 0;
                    107: 
                    108:        fseek(f, 0L, SEEK_END);
                    109:        flength = ftell(f);
                    110:        rewind(f);
                    111: 
                    112:        fill0(textbuf, sizeof(textbuf));
                    113:        while (flength > 0L)
                    114:        {       /* write zeros to the whole file... */
                    115:                if (flength < (word32) DISKBUFSIZE)
                    116:                        count = (int)flength;
                    117:                else
                    118:                        count = DISKBUFSIZE;
                    119:                fwrite(textbuf,1,count,f);
                    120:                flength -= count;
                    121:        }
                    122:        rewind(f);      /* maybe this isn't necessary */
                    123:        return(0);      /* normal return */
                    124: }      /* wipeout */
                    125: 
                    126: 
                    127: int wipefile(char *filename)
                    128: {      /*      Completely overwrite and erase file, so that no sensitive
                    129:                information is left on the disk.
                    130:        */
                    131:        FILE *f;
                    132:        /* open file f for read/write, in binary (not text) mode...*/
                    133: #ifdef VMS
                    134:        if ((f = fopen(filename,"rb+","ctx=stm")) == NULL)
                    135: #else
                    136:        if ((f = fopen(filename,"rb+")) == NULL)
                    137: #endif
                    138:                return(-1);     /* error - file can't be opened */
                    139:        wipeout(f);
                    140:        fclose(f);
                    141:        return(0);      /* normal return */
                    142: }      /* wipefile */
                    143: 
                    144: char   *file_tail (char *filename)
                    145: /*     Returns the after-slash part of filename.  Also skips backslashes,
                    146:  *  colons, and right brackets.        */
                    147: {
                    148:        char *bslashPos = strrchr(filename, '\\');/* Find last bslash in filename */
                    149:        char *slashPos = strrchr(filename, '/');/* Find last slash in filename */
                    150:        char *colonPos = strrchr(filename, ':');
                    151:        char *rbrakPos = strrchr(filename, ']');
                    152: 
                    153:        if (!slashPos  ||  bslashPos > slashPos)
                    154:                slashPos = bslashPos;
                    155:        if (!slashPos  ||  colonPos > slashPos)
                    156:                slashPos = colonPos;
                    157:        if (!slashPos  ||  rbrakPos > slashPos)
                    158:                slashPos = rbrakPos;
                    159:        return( slashPos?(slashPos+1):filename );
                    160: }
                    161: /* Define BSLASH for machines that use backslash, FSLASH for machines
                    162:  * that use forward slash as separators.
                    163:  */
                    164: 
                    165: #ifdef MSDOS
                    166: #define        BSLASH
                    167: #endif
                    168: #ifdef ATARI
                    169: #define BSLASH
                    170: #endif
                    171: #ifdef UNIX
                    172: #define FSLASH
                    173: #define MULTIPLE_DOTS
                    174: #endif
                    175: #ifdef AMIGA
                    176: #define FSLASH
                    177: #define MULTIPLE_DOTS
                    178: #endif
                    179: 
                    180: boolean has_extension(char *filename, char *extension)
                    181: {      /* return TRUE if extension matches the end of filename */
                    182:        int lf = strlen(filename);
                    183:        int lx = strlen(extension);
                    184: 
                    185:        if (lf <= lx)
                    186:                return(FALSE);
                    187:        return(!strcmp(filename + lf - lx, extension));
                    188: }
                    189: 
                    190: boolean is_tempfile(char *path)
                    191: {      /* return TRUE if path is a filename created by tempfile() */
                    192:        char *p;
                    193:        
                    194:        return((p = strrchr(path, '.')) != NULL &&
                    195:                        p[1] == TMP_EXT && strlen(p) == 4);
                    196: }
                    197: 
                    198: boolean no_extension(char *filename)
                    199: /*     Returns TRUE if user left off file extension, allowing default. */
                    200: {
                    201: #ifdef MULTIPLE_DOTS   /* filename can have more than one dot */
                    202:        if (has_extension(filename, CTX_EXTENSION) ||
                    203:                has_extension(filename, ASC_EXTENSION) ||
                    204:                has_extension(filename, PGP_EXTENSION) ||
                    205:                has_extension(filename, SIG_EXTENSION) ||
                    206:                is_tempfile(filename))
                    207:                return(FALSE);
                    208:        else
                    209:                return(TRUE);
                    210: #else
                    211: #ifdef BSLASH
                    212:        char *slashPos = strrchr(filename, '\\');       /* Find last slash in filename */
                    213: 
                    214:        /* Look for the filename after the last slash if there is one */
                    215:        return(strchr((slashPos != NULL ) ? slashPos : filename, '.') == NULL);
                    216: #else
                    217: #ifdef FSLASH
                    218:        char *slashPos = strrchr(filename, '/');        /* Find last slash in filename */
                    219: 
                    220:        /* Look for the filename after the last slash if there is one */
                    221:        return(strchr((slashPos != NULL ) ? slashPos : filename, '.') == NULL);
                    222: #else
                    223: #ifdef VMS
                    224:        char *slashPos = strrchr(filename,']');         /* Locate end of directory spec */
                    225: 
                    226:        /* Look for last period in filename */
                    227:        return(strrchr((slashPos != NULL) ? slashPos : filename, '.') == NULL );
                    228: #else
                    229:        return( (strrchr(filename,'.')==NULL) ? TRUE : FALSE );
                    230: #endif /* VMS */
                    231: #endif /* FSLASH */
                    232: #endif /* BSLASH */
                    233: #endif /* MULTIPLE_DOTS */
                    234: }      /* no_extension */
                    235: 
                    236: 
                    237: void drop_extension(char *filename)
                    238: {      /* deletes trailing ".xxx" file extension after the period. */
                    239:        if (!no_extension(filename))
                    240:                *strrchr(filename,'.') = '\0';
                    241: }      /* drop_extension */
                    242: 
                    243: 
                    244: void default_extension(char *filename, char *extension)
                    245: {      /* append filename extension if there isn't one already. */
                    246:        if (no_extension(filename))
                    247:                strcat(filename,extension);
                    248: }      /* default_extension */
                    249: 
                    250: #ifndef MAX_NAMELEN
                    251: #if defined(AMIGA) || defined(NeXT)
                    252: #define        MAX_NAMELEN     255
                    253: #endif
                    254: #endif
                    255: 
                    256: void truncate_name(char *path, int ext_len)
                    257: {      /* truncate the filename so that an extension can be tacked on. */
                    258: #ifdef UNIX            /* for other systems this is a no-op */
                    259:        char dir[MAX_PATH], *p;
                    260:        int namemax;
                    261: 
                    262: #ifdef MAX_NAMELEN     /* overrides the use of pathconf() */
                    263:        namemax = MAX_NAMELEN
                    264: #else
                    265: #ifdef _PC_NAME_MAX
                    266:        strcpy(dir, path);
                    267:        if ((p = strrchr(dir, '/')) == NULL)
                    268:                strcpy(dir, ".");
                    269:        else
                    270:        {       if (p == dir)
                    271:                        ++p;
                    272:                *p = '\0';
                    273:        }
                    274:        if ((namemax = pathconf(dir, _PC_NAME_MAX)) <= ext_len)
                    275:                return;
                    276: #else
                    277:        namemax = 14;
                    278: #endif
                    279: #endif /* MAX_NAMELEN */
                    280: 
                    281:        if ((p = strrchr(path, '/')) == NULL)
                    282:                p = path;
                    283:        else
                    284:                ++p;
                    285:        if (strlen(p) > namemax - ext_len)
                    286:        {
                    287:                if (verbose)
                    288:                        fprintf(pgpout, "Truncating filename '%s' ", path);
                    289:                p[namemax - ext_len] = '\0';
                    290:                if (verbose)
                    291:                        fprintf(pgpout, "to '%s'\n", path);
                    292:        }
                    293: #endif /* UNIX */
                    294: }
                    295: 
                    296: void force_extension(char *filename, char *extension)
                    297: {      /* change the filename extension. */
                    298:        drop_extension(filename);       /* out with the old */
                    299:        truncate_name(filename, strlen(extension));
                    300:        strcat(filename,extension);     /* in with the new */
                    301: }      /* force_extension */
                    302: 
                    303: 
                    304: boolean getyesno(char default_answer)
                    305: /*     Get yes/no answer from user, returns TRUE for yes, FALSE for no. 
                    306:        First the translations are checked, if they don't match 'y' and 'n'
                    307:        are tried.
                    308: */
                    309: {      char buf[8];
                    310:        static char yes[8], no[8];
                    311: 
                    312:        if (yes[0] == '\0')
                    313:        {       strncpy(yes, PSTR("y"), 7);
                    314:                strncpy(no, PSTR("n"), 7);
                    315:        }
                    316:        flush_input();
                    317:        getstring(buf,6,TRUE);  /* echo keyboard input */
                    318:        strlwr(buf);
                    319:        if (!strncmp(buf, no, strlen(no)))
                    320:                return(FALSE);
                    321:        if (!strncmp(buf, yes, strlen(yes)))
                    322:                return(TRUE);
                    323:        if (buf[0] == 'n')
                    324:                return(FALSE);
                    325:        if (buf[0] == 'y')
                    326:                return(TRUE);
                    327:        return(default_answer == 'y' ? TRUE : FALSE);
                    328: }      /* getyesno */
                    329: 
                    330: 
                    331: 
                    332: void maybe_force_extension(char *filename, char *extension)
                    333: {      /* if user consents to it, change the filename extension. */
                    334:        char newname[MAX_PATH];
                    335:        if (!has_extension(filename,extension))
                    336:        {       strcpy(newname,filename);
                    337:                force_extension(newname,extension);
                    338:                if (!file_exists(newname))
                    339:                {       fprintf(pgpout,PSTR("\nShould '%s' be renamed to '%s' [Y/n]? "),
                    340:                                filename,newname);
                    341:                        if (getyesno('y'))
                    342:                                rename(filename,newname);
                    343:                }
                    344:        }
                    345: }      /* maybe_force_extension */
                    346: 
                    347: char *buildfilename(char *result, char *fname)
                    348: /*     Builds a filename with a complete path specifier from the environmental
                    349:        variable PGPPATH.
                    350: */
                    351: {      char *s = getenv(PGPPATH);
                    352: 
                    353:        if ( s==NULL || strlen(s) > 50) /* undefined, or too long to use */
                    354:                s="";
                    355:        strcpy(result,s);
                    356:        if (strlen(result) != 0)
                    357: #ifdef BSLASH
                    358:                if (result[strlen(result)-1] != '\\')
                    359:                        strcat(result,"\\");
                    360: #else
                    361: #ifdef FSLASH
                    362:                if (result[strlen(result)-1] != '/')
                    363:                        strcat(result,"/");
                    364: #else
                    365: #ifdef VMS
                    366:                if (result[strlen(result)-1] != ']')
                    367:                        strcat(result,"]");
                    368: #endif
                    369: #endif
                    370: #endif /* Various OS-specific defines */
                    371:        strcat(result,fname);
                    372:        return(result);
                    373: }      /* buildfilename */
                    374: 
                    375: int build_path(char *path, char *fileName, char *origPath)
                    376: /* Build a path for fileName based on origPath */
                    377: {      int i, lastSlash = 0;
                    378: 
                    379: #ifdef BSLASH
                    380:        for (i=0; origPath[i]; i++)
                    381:                if (origPath[i] == ':' || origPath[i] == '\\')
                    382:                        lastSlash = i + 1;
                    383: #else
                    384: #ifdef VMS
                    385:        for (i=0; origPath[i]; i++)
                    386:                if (origPath[i] == ']')
                    387:                        lastSlash = i + 1;
                    388: #else
                    389:        for (i=0; origPath[i]; i++)
                    390:                if (origPath[i] == '/')
                    391:                        lastSlash = i + 1;
                    392: #endif
                    393: #endif
                    394: 
                    395:        /* Sanity check: Make sure the path is of legal length */
                    396:        if (i>=MAX_PATH)
                    397:        {       fprintf(pgpout,PSTR("Path '%s' too long\n"), origPath);
                    398:                return(-1);     /* error return */
                    399:        }
                    400: 
                    401:        strncpy(path,origPath,lastSlash);       /* Add path component */
                    402:        strcpy(path+lastSlash,fileName);        /* Append filename */
                    403:        return(0);      /* normal return */
                    404: }      /* build_path */
                    405: 
                    406: 
                    407: void file_to_canon(char *filename)
                    408: {      /* Convert filename to canonical form, with slashes as separators */
                    409: #ifdef BSLASH
                    410:        while (*filename) {
                    411:                if (*filename == '\\')
                    412:                        *filename = '/';
                    413:                ++filename;
                    414:        }
                    415: #endif
                    416: }
                    417: 
                    418: 
                    419: void file_from_canon(char *filename)
                    420: {      /* Convert filename from canonical to local form */
                    421:        /* I think everyone can handle slashes */
                    422:        filename = filename;            /* Suppress warning */
                    423: }
                    424: 
                    425: 
                    426: FILE *fopenbin(char *name, char *mode)
                    427: {
                    428: #if !defined(UNIX)
                    429:        char mode_b[8];
                    430: 
                    431:        strcpy(mode_b, mode);
                    432:        strcat(mode_b, "b");
                    433:        mode = mode_b;
                    434: #endif
                    435: 
                    436: #ifdef VMS
                    437:        if (*mode == 'r')
                    438:                return(fopen(name, mode, "ctx=stm"));
                    439:        else
                    440:                return(fopen(name, mode));
                    441: #else
                    442:        return(fopen(name, mode));
                    443: #endif
                    444: }
                    445: 
                    446: FILE *fopentxt(char *name, char *mode)
                    447: {
                    448: #ifdef VMS
                    449:        if (*mode == 'r')
                    450:                return(fopen(name, mode, "ctx=stm"));
                    451:        else
                    452:                return(fopen(name, mode));
                    453: #else
                    454:        return(fopen(name, mode));
                    455: #endif
                    456: }
                    457: 
                    458: 
                    459: int copyfile(FILE *f, FILE *g, word32 longcount)
                    460: {      /* copy file f to file g, for longcount bytes */
                    461:        int count, status = 0;
                    462:        do      /* read and write the whole file... */
                    463:        {
                    464:                if (longcount < (word32) DISKBUFSIZE)
                    465:                        count = (int)longcount;
                    466:                else
                    467:                        count = DISKBUFSIZE;
                    468:                count = fread(textbuf,1,count,f);
                    469:                if (count>0)
                    470:                {
                    471:                        if (CONVERSION != NO_CONV)
                    472:                        {       int i;
                    473:                                for (i = 0; i < count; i++)
                    474:                                        textbuf[i] = (CONVERSION == EXT_CONV) ?
                    475:                                                     EXT_C(textbuf[i]) :
                    476:                                                     INT_C(textbuf[i]);
                    477:                        }
                    478:                        if (fwrite(textbuf,1,count,g) != count )
                    479:                        {   /* Problem: return error value */
                    480:                                status = -1;
                    481:                                break;
                    482:                        }
                    483:                        longcount -= count;
                    484:                }
                    485:                /* if text block was short, exit loop */
                    486:        } while (count==DISKBUFSIZE);
                    487:        burn(textbuf);  /* burn sensitive data on stack */
                    488:        return(status);
                    489: }      /* copyfile */
                    490: 
                    491: int copyfilepos (FILE *f, FILE *g, word32 longcount, word32 fpos)
                    492: /* Like copyfile, but takes a position for file f.  Returns with
                    493:  * f and g pointing just past the copied data.
                    494:  */
                    495: {
                    496:        fseek (f, fpos, SEEK_SET);
                    497:        return copyfile (f, g, longcount);
                    498: }
                    499: 
                    500: 
                    501: #ifndef CANONICAL_TEXT
                    502: int copyfile_to_canon (FILE *f, FILE *g, word32 longcount)
                    503: {      /* copy file f to file g, for longcount bytes.  Convert to
                    504:           canonical form as we go.  f is open in text mode.  Canonical
                    505:           form uses crlf's as line separators. */
                    506:        int count, status = 0;
                    507:        byte c, *tb1, *tb2;
                    508:        int i, nbytes;
                    509:        do      /* read and write the whole file... */
                    510:        {
                    511:                if (longcount < (word32) DISKBUFSIZE)
                    512:                        count = (int)longcount;
                    513:                else
                    514:                        count = DISKBUFSIZE;
                    515:                count = fread(textbuf,1,count,f);
                    516:                if (count>0)
                    517:                {       /* Convert by adding CR before LF */
                    518:                        tb1 = textbuf;
                    519:                        tb2 = textbuf2;
                    520:                        for (i=0; i<count; ++i)
                    521:                        {       switch (CONVERSION) {
                    522:                                case EXT_CONV:
                    523:                                    c = EXT_C(*tb1++);
                    524:                                    break;
                    525:                                case INT_CONV:
                    526:                                    c = INT_C(*tb1++);
                    527:                                    break;
                    528:                                default:
                    529:                                    c = *tb1++;
                    530:                                }
                    531:                                if (c == '\n')
                    532:                                        *tb2++ = '\r';
                    533:                                *tb2++ = c;
                    534:                        }
                    535:                        nbytes = tb2 - textbuf2;
                    536:                        if (fwrite(textbuf2,1,nbytes,g) != nbytes )
                    537:                        {   /* Problem: return error value */
                    538:                                status = -1;
                    539:                                break;
                    540:                        }
                    541:                        longcount -= count;
                    542:                }
                    543:                /* if text block was short, exit loop */
                    544:        } while (count==DISKBUFSIZE);
                    545:        burn(textbuf);  /* burn sensitive data on stack */
                    546:        burn(textbuf2);
                    547:        return(status);
                    548: }      /* copyfile_to_canon */
                    549: #endif
                    550: 
                    551: 
                    552: #ifndef CANONICAL_TEXT
                    553: int copyfile_from_canon (FILE *f, FILE *g, word32 longcount)
                    554: {      /* copy file f to file g, for longcount bytes.  Convert from
                    555:           canonical to local form as we go.  g is open in text mode.  Canonical
                    556:           form uses crlf's as line separators. */
                    557:        int count, status = 0;
                    558:        byte c, *tb1, *tb2;
                    559:        int i, nbytes;
                    560:        do      /* read and write the whole file... */
                    561:        {
                    562:                if (longcount < (word32) DISKBUFSIZE)
                    563:                        count = (int)longcount;
                    564:                else
                    565:                        count = DISKBUFSIZE;
                    566:                count = fread(textbuf,1,count,f);
                    567:                if (count>0)
                    568:                {       /* Convert by removing CR's */
                    569:                        tb1 = textbuf;
                    570:                        tb2 = textbuf2;
                    571:                        for (i=0; i<count; ++i)
                    572:                        {       switch (CONVERSION) {
                    573:                                case EXT_CONV:
                    574:                                    c = EXT_C(*tb1++);
                    575:                                    break;
                    576:                                case INT_CONV:
                    577:                                    c = INT_C(*tb1++);
                    578:                                    break;
                    579:                                default:
                    580:                                    c = *tb1++;
                    581:                                }
                    582:                                if (c != '\r')
                    583:                                        *tb2++ = c;
                    584:                        }
                    585:                        nbytes = tb2 - textbuf2;
                    586:                        if (fwrite(textbuf2,1,nbytes,g) != nbytes )
                    587:                        {   /* Problem: return error value */
                    588:                                status = -1;
                    589:                                break;
                    590:                        }
                    591:                        longcount -= count;
                    592:                }
                    593:                /* if text block was short, exit loop */
                    594:        } while (count==DISKBUFSIZE);
                    595:        burn(textbuf);  /* burn sensitive data on stack */
                    596:        burn(textbuf2);
                    597:        return(status);
                    598: }      /* copyfile_from_canon */
                    599: #endif
                    600: 
                    601: 
                    602: int copyfiles_by_name(char *srcFile, char *destFile)
                    603: /*     Copy srcFile to destFile  */
                    604: {
                    605:        FILE *f, *g;
                    606:        int status = 0;
                    607:        long fileLength;
                    608: 
                    609: #ifdef VMS
                    610:        if (((f=fopen(srcFile,"rb","ctx=stm")) == NULL) ||
                    611: #else
                    612:        if (((f=fopen(srcFile,"rb")) == NULL) ||
                    613: #endif
                    614:                ((g=fopen(destFile,"wb")) == NULL))
                    615:                /* Can't open files */
                    616:                return(-1);
                    617: 
                    618:        /* Get file length and copy it */
                    619:        fseek(f,0L,SEEK_END);
                    620:        fileLength = ftell(f);
                    621:        rewind(f);
                    622:        status = copyfile(f,g,fileLength);
                    623:        fclose(f);
                    624:        fclose(g);
                    625:        return(status);
                    626: }      /* copyfiles_by_name */
                    627: 
                    628: 
                    629: int make_canonical(char *srcFile, char *destFile)
                    630: /*     Copy srcFile to destFile, converting to canonical text form  */
                    631: {
                    632:        FILE *f, *g;
                    633:        int status = 0;
                    634:        long fileLength;
                    635: 
                    636: #ifdef CANONICAL_TEXT
                    637:        if (((f=fopen(srcFile,"rb")) == NULL) ||
                    638: #else
                    639:        if (((f=fopen(srcFile,"r")) == NULL) ||
                    640: #endif
                    641:                ((g=fopen(destFile,"wb")) == NULL))
                    642:                /* Can't open files */
                    643:                return(-1);
                    644: 
                    645:        /* Get file length and copy it */
                    646:        fseek(f,0L,SEEK_END);
                    647:        fileLength = ftell(f);
                    648:        rewind(f);
                    649:        CONVERSION = INT_CONV;
                    650: #ifdef CANONICAL_TEXT
                    651:        status = copyfile(f,g,fileLength);
                    652: #else
                    653:        status = copyfile_to_canon(f,g,fileLength);
                    654: #endif
                    655:        CONVERSION = NO_CONV;
                    656:        fclose(f);
                    657:        fclose(g);
                    658:        return(status);
                    659: }      /* make_canonical */
                    660: 
                    661: 
                    662: int rename2(char *srcFile, char *destFile)
                    663: /*     Like rename() but will try to copy the file if the rename fails.
                    664:        This is because under OS's with multiple physical volumes if the
                    665:        source and destination are on different volumes the rename will fail */
                    666: {
                    667:        FILE *f, *g;
                    668:        int status = 0;
                    669:        long fileLength;
                    670: 
                    671:        if (rename(srcFile,destFile) == -1)
                    672:        {       /* Rename failed, try a copy */
                    673: #ifdef VMS
                    674:                if (((f=fopen(srcFile,"rb","ctx=stm")) == NULL) ||
                    675: #else
                    676:                if (((f=fopen(srcFile,"rb")) == NULL) ||
                    677: #endif
                    678:                        ((g=fopen(destFile,"wb")) == NULL))
                    679:                        /* Can't open files */
                    680:                        return(-1);
                    681: 
                    682:                /* Get file length and copy it */
                    683:                fseek(f,0L,SEEK_END);
                    684:                fileLength = ftell(f);
                    685:                rewind(f);
                    686:                status = copyfile(f,g,fileLength);
                    687: 
                    688:                /* Zap source file if the copy went OK, otherwise zap the (possibly
                    689:                   incomplete) destination file */
                    690:                if (status >= 0)
                    691:                {       wipeout(f);             /* Zap source file */
                    692:                        fclose(f);
                    693:                        remove(srcFile);
                    694:                        fclose(g);
                    695:                }
                    696:                else
                    697:                {       if (is_regular_file(destFile))
                    698:                        {       wipeout(g);             /* Zap destination file */
                    699:                                fclose(g);
                    700:                                remove(destFile);
                    701:                        } else
                    702:                                fclose(g);
                    703:                        fclose(f);
                    704:                }
                    705:        }
                    706:        return(status);
                    707: }
                    708: 
                    709: 
                    710: int readPhantomInput(char *filename)
                    711: /* read the data from stdin to the phantom input file */
                    712: {      FILE *outFilePtr;
                    713:        byte buffer[ 512 ];
                    714:        int bytesRead;
                    715: 
                    716:        if ((outFilePtr = fopen(filename,"wb")) == NULL)
                    717:                return(-1);
                    718: 
                    719: #ifdef MSDOS
                    720:        /* Under DOS must set input stream to binary mode to avoid data mangling */
                    721:        setmode(fileno(stdin), O_BINARY);
                    722: #endif /* MSDOS */
                    723:        while ((bytesRead = fread (buffer, 1, 512, stdin)) > 0)
                    724:                fwrite (buffer, 1, bytesRead, outFilePtr);
                    725:        fclose (outFilePtr);
                    726: #ifdef MSDOS
                    727:        setmode(fileno(stdin), O_TEXT); /* Reset stream */
                    728: #endif /* MSDOS */
                    729:        return(0);
                    730: }
                    731: 
                    732: 
                    733: void writePhantomOutput(char *filename)
                    734: /* write the data from the phantom output file to stdout */
                    735: {      FILE *outFilePtr;
                    736:        byte buffer[ 512 ];
                    737:        int bytesRead;
                    738: 
                    739:        /* this can't fail since we just created the file */
                    740:        outFilePtr = fopen(filename,"rb");
                    741: 
                    742: #ifdef MSDOS
                    743:        setmode(fileno(stdout), O_BINARY);
                    744: #endif
                    745:        while ((bytesRead = fread (buffer, 1, 512, outFilePtr)) > 0)
                    746:                fwrite (buffer, 1, bytesRead, stdout);
                    747:        fclose (outFilePtr);
                    748:        fflush(stdout);
                    749: #ifdef MSDOS
                    750:        setmode(fileno(stdout), O_TEXT);
                    751: #endif
                    752: 
                    753:        /* finally, delete the phantom file */
                    754:        wipefile(filename);
                    755:        remove(filename);
                    756: }
                    757: 
                    758: /* Return the size from the current position of file f to the end */
                    759: word32 fsize (FILE *f)
                    760: {
                    761:        long fpos = ftell (f);
                    762:        long fpos2;
                    763: 
                    764:        fseek (f, 0L, SEEK_END);
                    765:        fpos2 = ftell (f);
                    766:        fseek (f, fpos, SEEK_SET);
                    767:        return (word32)(fpos2 - fpos);
                    768: }
                    769: 
                    770: /* Return TRUE if file filename looks like a pure text file */
                    771: int is_text_file (char *filename)
                    772: {
                    773:        FILE    *f = fopen(filename,"rb");
                    774:        int             i, n, bit8 = 0;
                    775:        unsigned char buf[512];
                    776:        unsigned char *bufptr = buf;
                    777:        unsigned char c;
                    778: 
                    779:        if (!f)
                    780:                return(FALSE);  /* error opening it, so not a text file */
                    781:        i = n = fread (buf, 1, sizeof(buf), f);
                    782:        fclose(f);
                    783:        if (n <= 0)
                    784:                return(FALSE);  /* empty file or error, not a text file */
                    785:        if (compressSignature(buf) >= 0)
                    786:                return(FALSE);
                    787:        while (i--)
                    788:        {       c = *bufptr++;
                    789:                if (c & 0x80)
                    790:                        ++bit8;
                    791:                else /* allow BEL BS HT LF VT FF CR EOF control characters */
                    792:                        if (c < '\007' || (c > '\r' && c < ' ' && c != '\032'))
                    793:                                return(FALSE);  /* not a text file */
                    794:        }
                    795:        if (strcmp(language, "ru"))
                    796:                return(TRUE);
                    797:        /* assume binary if more than 1/4 bytes have 8th bit set */
                    798:        return(bit8 < n / 4);
                    799: } /* is_text_file */
                    800: 
                    801: void *xmalloc(unsigned size)
                    802: {      void *p;
                    803:        if (size == 0)
                    804:                ++size;
                    805:        if ((p = malloc(size)) == NULL)
                    806:        {       fprintf(stderr, PSTR("\n\007Out of memory.\n"));
                    807:                exitPGP(1);
                    808:        }
                    809:        return(p);
                    810: }
                    811: 
                    812: /*----------------------------------------------------------------------
                    813:  *     temporary file routines
                    814:  */
                    815: 
                    816: 
                    817: #define MAXTMPF 8
                    818: 
                    819: #define        TMP_INUSE       2
                    820: 
                    821: static struct
                    822: {      char path[MAX_PATH];
                    823:        int flags;
                    824: } tmpf[MAXTMPF];
                    825: 
                    826: extern char outdir[];
                    827: extern char basename[];
                    828: 
                    829: /*
                    830:  * return a unique temporary file name
                    831:  */
                    832: char *tempfile(int flags)
                    833: {
                    834:        int i;
                    835:        int num = 0;
                    836: 
                    837:        for (i = 0; i < MAXTMPF; ++i)
                    838:                if (tmpf[i].flags == 0)
                    839:                        break;
                    840:        
                    841:        if (i == MAXTMPF)
                    842:        {       /* message only for debugging, no need for PSTR */
                    843:                fprintf(stderr, "\n\007Out of temporary files\n");
                    844:                return(NULL);
                    845:        }
                    846: 
                    847:        do
                    848:                sprintf(tmpf[i].path, "%s%s.%c%02d",
                    849:                        (flags & TMP_TMPDIR ? tmpdir : outdir), basename, TMP_EXT, num);
                    850:        while (file_exists(tmpf[i].path) && ++num < 100);
                    851: 
                    852:        if (!file_ok_write(tmpf[i].path))
                    853:        {       fprintf(pgpout, PSTR("\n\007Cannot create temporary file '%s'\n"), tmpf[i].path);
                    854:                user_error();
                    855:        }
                    856: 
                    857:        if (num == 100)
                    858:        {       fprintf(stderr, "\n\007tempfile: cannot find unique name\n");
                    859:                return(NULL);
                    860:        }
                    861: 
                    862:        tmpf[i].flags = flags | TMP_INUSE;
                    863:        if (verbose)
                    864:                fprintf(stderr, "tempfile: created '%s'\n", tmpf[i].path);
                    865:        return(tmpf[i].path);
                    866: }      /* tempfile */
                    867: 
                    868: /*
                    869:  * remove temporary file, wipe if necessary.
                    870:  */
                    871: void rmtemp(char *name)
                    872: {
                    873:        int i;
                    874: 
                    875:        for (i = 0; i < MAXTMPF; ++i)
                    876:                if (tmpf[i].flags && strcmp(tmpf[i].path, name) == 0)
                    877:                        break;
                    878: 
                    879:        if (i < MAXTMPF)
                    880:        {       if (strlen(name) > 3 && name[strlen(name)-3] == TMP_EXT)
                    881:                {       /* only remove file if name hasn't changed */
                    882:                        if (verbose)
                    883:                                fprintf(stderr, "rmtemp: removing '%s'\n", name);
                    884:                        if (tmpf[i].flags & TMP_WIPE)
                    885:                                wipefile(name);
                    886:                        remove(name);
                    887:                        tmpf[i].flags = 0;
                    888:                } else if (verbose)
                    889:                        fprintf(stderr, "rmtemp: not removing '%s'\n", name);
                    890:        }
                    891: }      /* rmtemp */
                    892: 
                    893: /*
                    894:  * make temporary file permanent, returns the new name.
                    895:  */
                    896: char *savetemp(char *name, char *newname)
                    897: {
                    898:        int i, overwrite;
                    899:        static char buf[MAX_PATH];
                    900: 
                    901:        if (strcmp(name, newname) == 0)
                    902:                return(name);
                    903: 
                    904:        for (i = 0; i < MAXTMPF; ++i)
                    905:                if (tmpf[i].flags && strcmp(tmpf[i].path, name) == 0)
                    906:                        break;
                    907: 
                    908:        if (i < MAXTMPF)
                    909:        {       if (strlen(name) < 4 || name[strlen(name)-3] != TMP_EXT)
                    910:                {       if (verbose)
                    911:                                fprintf(stderr, "savetemp: not renaming '%s' to '%s'\n",
                    912:                                                name, newname);
                    913:                        return(name);   /* return original file name */
                    914:                }
                    915:        }
                    916: 
                    917:        while (file_exists(newname))
                    918:        {
                    919:                if (is_regular_file(newname))
                    920:                {       fprintf(pgpout,PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "),newname);
                    921:                        overwrite = getyesno('n');
                    922:                }
                    923:                else
                    924:                {       fprintf(pgpout,PSTR("\n\007Output file '%s' already exists.\n"),newname);
                    925:                        overwrite = FALSE;
                    926:                }
                    927: 
                    928:                if (!overwrite)
                    929:                {       fprintf(pgpout, PSTR("\nEnter new file name: "));
                    930:                        getstring(buf, MAX_PATH - 1, TRUE);
                    931:                        if (buf[0] == '\0')
                    932:                                return(NULL);
                    933:                        newname = buf;
                    934:                }
                    935:                else
                    936:                        remove(newname);
                    937:        }
                    938:        if (verbose)
                    939:                fprintf(stderr, "savetemp: renaming '%s' to '%s'\n", name, newname);
                    940:        if (rename2(name, newname) < 0)
                    941:        {       /* errorLvl = UNKNOWN_FILE_ERROR; */
                    942:                return(NULL);
                    943:        }
                    944:        if (i < MAXTMPF)
                    945:                tmpf[i].flags = 0;
                    946:        return(newname);
                    947: }      /* savetemp */
                    948: 
                    949: /*
                    950:  * like savetemp(), only make backup of destname if it exists
                    951:  */
                    952: int savetempbak(char *tmpname, char *destname)
                    953: {
                    954:        char bakpath[MAX_PATH];
                    955: 
                    956:        if (strcmp(destname, SCRATCH_KEYRING_PATH) == 0 ||
                    957:                        is_tempfile(destname))
                    958:                remove(destname);
                    959:        else
                    960:        {       if (file_exists(destname))
                    961:                {
                    962:                        strcpy(bakpath, destname);
                    963:                        force_extension(bakpath, BAK_EXTENSION);
                    964:                        remove(bakpath);
                    965:                        if (rename(destname, bakpath) == -1)
                    966:                                return(-1);
                    967:                }
                    968:        }
                    969:        if (savetemp(tmpname, destname) == NULL)
                    970:                return(-1);
                    971:        return(0);
                    972: }
                    973: 
                    974: /*
                    975:  * remove all temporary files and wipe them if necessary
                    976:  */
                    977: void cleanup_tmpf(void)
                    978: {
                    979:        int i;
                    980: 
                    981:        for (i = 0; i < MAXTMPF; ++i)
                    982:                if (tmpf[i].flags)
                    983:                        rmtemp(tmpf[i].path);
                    984: }      /* cleanup_tmpf */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.