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

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

unix.superglobalmegacorp.com

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