📄 fileio.c
字号:
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 + -