⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileio.c

📁 PGP—Pretty Good Privacy
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (path == NULL || *path == '\0') {
        tmpdir[0] = '\0';
        return;
    }
    strcpy(tmpdir, path);
    p = tmpdir + strlen(tmpdir) - 1;
    if (*p != '/' && *p != '\\' && *p != ']' && *p != ':') {
        /* append path separator, either / or \ */
        if ((p = strchr(tmpdir, '/')) == NULL &&
            (p = strchr(tmpdir, '\\')) == NULL)
            p = "/"; /* path did not contain / or \, use / */
        strncat(tmpdir, p, 1);
    }
}

/*
 * set output directory to avoid a file copy when temp file is renamed to
 * output file.  the argument filename must be a valid path for a file, not
 * a directory.
 */
void setOutDir( struct pgpfileBones *filebPtr, char *filename )
{
    char *p;

    if (filename == NULL) {
        strcpy(outdir, tmpdir);
        return;
    }
    strcpy(outdir, filename);
    p = fileTail(outdir);
    strcpy(tmpbasename, p);
    *p = '\0';
    dropExtension( filebPtr, tmpbasename );
#if !defined(BSD42) && !defined(BSD43) && !defined(sun)
    /*
     *  we don't depend on pathconf here, if it returns an incorrect value
     * for NAME_MAX (like Linux 0.97 with minix FS) finding a unique name
     * for temp files can fail.
     */
    tmpbasename[10] = '\0'; /* 14 char limit */
#endif
}

PGPError touchFile( char *filename, int mode )
{
    int fd;
#ifndef PGP_UNIX
    FILE *fp;
#endif

#if defined(PGP_UNIX) || defined(VMS)
    if ((fd = open(filename, O_RDWR | O_CREAT, mode)) != -1)
        close(fd);
#else
    if ((fp = fopen(filename, "w")) != NULL)
        fclose(fp);
    fd = (fp == NULL ? -1 : 0);
#endif
    return fd;
}

/*
 * return a unique temporary file name
 */
char *tempFile( struct pgpfileBones *filebPtr, int flags, int *perrorLvl)
{
    int i, j;
    int num;
    int fd;
#ifndef PGP_UNIX
    FILE *fp;
#endif
    struct pgpenvBones *envbPtr = filebPtr->envbPtr;
    PGPEnv *env = envbPtr->m_env;
    PGPInt32 pri;
    PGPError err;

    for (i = 0; i < MAXTMPF; ++i)
        if (tmpf[i].flags == 0)
            break;

    if (i == MAXTMPF) {
        /* message only for debugging, no need for LANG */
        fprintf(stderr, LANG("\n\007Out of temporary files\n"));
        return NULL;
    }
  again:
    num = 0;
    do {
        for (j = 0; j < MAXTMPF; ++j)
            if (tmpf[j].flags && tmpf[j].num == num)
                break;
        if (j < MAXTMPF)
            continue; /* sequence number already in use */
        sprintf(tmpf[i].path, "%s%s.%c%02d",
                ((flags & TMP_TMPDIR) && *tmpdir ? tmpdir : outdir),
                tmpbasename, TMP_EXT, num);
        if (!fileExists(tmpf[i].path))
            break;
    }
    while (++num < 100);

    if (num == 100) {
        fprintf(filebPtr->pgpout,
                LANG("\n\007tempfile: cannot find unique name\n"));
        return NULL;
    }
#if defined(PGP_UNIX) || defined(VMS)
    if ((fd = open(tmpf[i].path, O_EXCL | O_RDWR | O_CREAT, 0600)) != -1)
        close(fd);
#else
    if ((fp = fopen(tmpf[i].path, "w")) != NULL)
        fclose(fp);
    fd = (fp == NULL ? -1 : 0);
#endif

    if (fd == -1) {
        if (!(flags & TMP_TMPDIR)) {
            flags |= TMP_TMPDIR;
            goto again;
        }
#ifdef PGP_UNIX
        else if (tmpdir[0] == '\0') {
            strcpy(tmpdir, "/tmp/");
            goto again;
        }
#endif
    }
    if (fd == -1) {
        fprintf(filebPtr->pgpout,
                LANG("\n\007Cannot create temporary file '%s'\n"),
                tmpf[i].path);
        userError(filebPtr, perrorLvl);
        return NULL;
    }
#ifdef VMS
    remove(tmpf[i].path);
#endif

    tmpf[i].num = num;
    tmpf[i].flags = flags | TMP_INUSE;
    if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
        fprintf(filebPtr->pgpout, LANG("tempfile: created '%s'\n"),
                tmpf[i].path);
    return tmpf[i].path;
} /* tempfile */

/*
 * remove temporary file, wipe if necessary.
 */
void rmTemp( struct pgpfileBones *filebPtr, char *name )
{
    int i;
    struct pgpenvBones *envbPtr = filebPtr->envbPtr;
    PGPEnv *env = envbPtr->m_env;
    PGPInt32 pri;
    PGPError err;

    for (i = 0; i < MAXTMPF; ++i)
        if (tmpf[i].flags && strcmp(tmpf[i].path, name) == 0)
            break;

    if (i < MAXTMPF) {
        if (strlen(name) > 3 && name[strlen(name) - 3] == TMP_EXT) {
            /* only remove file if name hasn't changed */
            if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
                fprintf(filebPtr->pgpout, LANG("rmtemp: removing '%s'\n"),
                        name);
            if (tmpf[i].flags & TMP_WIPE)
                wipefile(filebPtr, name);
            if (!remove(name)) {
                tmpf[i].flags = 0;
            } else if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err )) {
                fprintf(stderr, LANG("\nrmtemp: Failed to remove %s"),
                        name);
                perror(LANG("\nError"));
            }
        } else if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
            fprintf(filebPtr->pgpout, LANG("rmtemp: not removing '%s'\n"),
                    name);
    }
} /* rmtemp */

/*
 * make temporary file permanent, returns the new name.
 */
char *saveTemp( struct pgpfileBones *filebPtr, char *name, char *newname )
{
    int i, overwrite;
    static char buf[MAX_PATH];
    struct pgpenvBones *envbPtr = filebPtr->envbPtr;
    PGPEnv *env = envbPtr->m_env;
    PGPInt32 pri;
    PGPError err;

    if (strcmp(name, newname) == 0)
        return name;

    for (i = 0; i < MAXTMPF; ++i)
        if (tmpf[i].flags && strcmp(tmpf[i].path, name) == 0)
            break;

    if (i < MAXTMPF) {
        if (strlen(name) < 4 || name[strlen(name) - 3] != TMP_EXT) {
            if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
                fprintf(filebPtr->pgpout,
                        LANG("savetemp: not renaming '%s' to '%s'\n"),
                        name, newname);
            return name; /* return original file name */
        }
    }
    while (fileExists(newname)) {
        if (pgpenvGetInt( env, PGPENV_BATCHMODE, &pri, &err ) &&
                !pgpenvGetInt( env, PGPENV_FORCE, &pri, &err )) {
            fprintf(filebPtr->pgpout,
                    LANG("\n\007Output file '%s' already exists.\n"),
                    newname);
            return NULL;
        }
        if (isRegularFile(newname)) {
            if (pgpenvGetInt( env, PGPENV_FORCE, &pri, &err )) {
                /* remove without asking */
                remove(newname);
                break;
            }
            fprintf(filebPtr->pgpout, LANG(
"\n\007Output file '%s' already exists.  Overwrite (y/N)? "),
                    newname);
            overwrite = getyesno(filebPtr,'n', (PGPBoolean)pgpenvGetInt( env,
                    PGPENV_BATCHMODE, &pri, &err ));

        } else {
            fprintf(filebPtr->pgpout, LANG(
"\n\007Output file '%s' already exists.\n"), newname);

            if (pgpenvGetInt( env, PGPENV_FORCE, &pri, &err ))
                /* never remove special file */
                return NULL;
            overwrite = FALSE;
        }

        if (!overwrite) {
            fprintf(filebPtr->pgpout, LANG("\nEnter new file name: "));
            pgpTtyGetString(buf, MAX_PATH - 1, filebPtr->pgpout);
            if (buf[0] == '\0')
                return NULL;
            newname = buf;
        } else {
            remove(newname);
        }
    }
    if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
        fprintf(filebPtr->pgpout, LANG("savetemp: renaming '%s' to '%s'\n"),
                name, newname);
    if (rename2( filebPtr, name, newname ) < 0) {
        /* errorLvl = UNKNOWN_FILE_ERROR; */
        fprintf(filebPtr->pgpout, LANG("Can't create output file '%s'\n"),
                newname);

        return NULL;
    }
    if (i < MAXTMPF)
        tmpf[i].flags = 0;
    return newname;
}/* savetemp */

/*
 * like saveTemp(), only make backup of destname if it exists
 */
int saveTempBak( struct pgpfileBones *filebPtr, char *tmpname, char
        *destname )

{
    char bakpath[MAX_PATH];
#ifdef PGP_UNIX
    int mode = -1;
#endif

    if (isTempFile(filebPtr, destname)) {
        remove(destname);
    } else {
        if (fileExists(destname)) {
#ifdef PGP_UNIX
            struct stat st;
            if (stat(destname, &st) != -1)
                mode = st.st_mode & 07777;
#endif
            strcpy(bakpath, destname);
            forceExtension( filebPtr, bakpath, filebPtr->BAK_EXTENSION );
            remove(bakpath);
#ifdef VMS
            if (rename(destname, bakpath) != 0)
#else
            if (rename(destname, bakpath) == -1)
#endif
                return -1;
        }
    }
    if (saveTemp( filebPtr, tmpname, destname ) == NULL)
        return -1;
#ifdef PGP_UNIX
    if (mode != -1)
        chmod(destname, mode);
#endif
    return 0;
}

/*
 * remove all temporary files and wipe them if necessary
 */
void cleanupTempFiles(struct pgpfileBones *filebPtr)
{
    int i;

    for (i = 0; i < MAXTMPF; ++i)
        if (tmpf[i].flags)
            rmTemp( filebPtr, tmpf[i].path );
} /* cleanup_tmpf */

#if 0
/* search for manuals is disabled at the request of Jon Callas */
/*
 * Routines to search for the manuals.
 *
 * Why all this code?
 *
 * Some people may object to PGP insisting on finding the manual somewhere
 * in the neighborhood to generate a key.  They bristle against this
 * seemingly authoritarian attitude.  Some people have even modified PGP
 * to defeat this feature, and redistributed their hotwired version to
 * others.  That creates problems for me (PRZ).
 *
 * Here is the problem.  Before I added this feature, there were maimed
 * versions of the PGP distribution package floating around that lacked
 * the manual.  One of them was uploaded to Compuserve, and was
 * distributed to countless users who called me on the phone to ask me why
 * such a complicated program had no manual.  It spread out to BBS systems
 * around the country.  And a freeware distributor got hold of the package
 * from Compuserve and enshrined it on CD-ROM, distributing thousands of
 * copies without the manual.  What a mess.
 *
 * Please don't make my life harder by modifying PGP to disable this
 * feature so that others may redistribute PGP without the manual.  If you
 * run PGP on a palmtop with no memory for the manual, is it too much to
 * ask that you type one little extra word on the command line to do a key
 * generation, a command that is seldom used by people who already know
 * how to use PGP?  If you can't stand even this trivial inconvenience,
 * can you suggest a better method of reducing PGP's distribution without
 * the manual?
 */

static unsigned extMissing(char *prefix)
{
    static char const *const extensions[] =
#ifdef VMS
        { ".doc", ".txt", ".man", ".tex", ".", 0 };
#else
        { ".doc", ".txt", ".man", ".tex", "", 0 };
#endif
    char const *const *p;
    char *end = prefix + strlen(prefix);

    for (p = extensions; *p; p++) {
        strcpy(end, *p);
#if 0 /* Debugging code */
        fprintf(filebPtr->pgpout, LANG("Looking for \"%s\"\n"), prefix);
#endif
        if (fileExists(prefix))
            return 0;
    }
    return 1;
}

/*
 * Returns mask of files missing
 */
static unsigned filesMissing(char *prefix)
{
    static char const *const names[] =
    {"pgpdoc1", "pgpdoc2", 0};
    char const *const *p;
    unsigned bit, mask = 3;
    int len = strlen(prefix);

#ifndef VMS
    /*
     * Optimization: if directory doesn't exist, stop.  But access()
     * (used internally by fileExists()) doesn't work on dirs under VMS.
     */
    if (prefix[0] && !fileExists(prefix)) /* Directory doesn't exist? */
        return mask;
#endif /* VMS */
    if (len && strchr(DIRSEPS, prefix[len - 1]) == 0)
        prefix[len++] = DIRSEPS[0];
    for (p = names, bit = 1; *p; p++, bit <<= 1) {
        strcpy(prefix + len, *p);
        if (!extMissing(prefix))
            mask &= ~bit;
    }

    return mask; /* Bitmask of which files exist */
}

/*
 * Search prefix directory and doc subdirectory.
 */
static unsigned docMissing(char *prefix)
{
    unsigned mask;
    int len = strlen(prefix);

    mask = filesMissing(prefix);
    if (!mask)
        return 0;
#ifdef VMS
    if (len && prefix[len - 1] == ']') {
        strcpy(prefix + len - 1, ".doc]");
    } else {
        assert(!len || prefix[len - 1] == ':');
        strcpy(prefix + len, "[doc]");
    }
#else
    if (len && prefix[len - 1] != DIRSEPS[0])
        prefix[len++] = DIRSEPS[0];
    strcpy(prefix + len, "doc");
#endif

    mask &= filesMissing(prefix);

    prefix[len] = '\0';
    return mask;
}

/*
 * Expands a leading environment variable.  Returns 0 on success;
 * <0 if there is an error.
 */
static int expandEnv(char const *src, char *dest)
{
    char const *var, *suffix;
    unsigned len;

    if (*src != '$') {
        strcpy(dest, src);
        return 0;
    }
    /* Find end of variable */
    if (src[1] == '{') { /* ${FOO} form */
        var = src + 2;
        len = strchr(var, '}') - var;
        suffix = src + 2 + len + 1;
    } else { /* $FOO form - allow $ for VMS */
        var = src + 1;
        len = strspn(var, "ABCDEFGHIJKLMNOPQRSTUVWXYZ$_");
        suffix = src + 1 + len;
    }

    memcpy(dest, var, len); /* Copy name */
    dest[len] = '\0'; /* Null-terminate */

    var = getenv(dest);
    if (!var || !*var)
        return -1; /* No env variable */

    /* Copy expanded form to destination */
    strcpy(dest, var);

    /* Add tail */
    strcat(dest, suffix);

    return 0;
}

unsigned manualsMissing(void)
{
    char buf[256];
    unsigned mask = ~((unsigned)0);
    char const *const *p;

    for (p = manual_dirs; *p; p++) {
        if (expandEnv(*p, buf) < 0)
            continue; /* Ignore */
        mask &= docMissing(buf);
        if (!mask)
            break;
    }

    return mask;
}

/*
 * Why all this code?
 *
 * See block of comments above.
 */
#endif



/* Reads the first count bytes from infile into header. */
int getHeaderInfoFromFile(char *infile,  PGPByte *header, int count)
{
        FILE *f;
        fill0(header,count);
        /* open file f for read, in binary (not text) mode...*/
        if ((f = fopen(infile,FOPRBIN)) == NULL)
                return -1;
        /* read Cipher Type Byte, and maybe more */
        count = fread(header,1,count,f);
        fclose(f);
        return count; /* normal return */
} /* get_header_info_from_file */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -