📄 fileio.c
字号:
*/
static void addslash(char *name)
{
int i = strlen(name);
if (i != 0 && !strchr(DIRSEPS, name[i - 1])) {
name[i] = DIRSEPS[0];
name[i + 1] = '\0';
}
}
/*
* Builds a filename with a complete path specifier from the environmental
* variable PGPPATH.
*/
char *buildFileName(char *result, const char *fname)
{
char const *s = getenv(PGPPATH);
result[0] = '\0';
if (s && strlen(s) <= 50) {
strcpy(result, s);
}
#ifdef PGP_UNIX
/* On Unix, default to $HOME/.pgp, otherwise, current directory. */
else {
s = getenv("HOME");
if (s && strlen(s) <= 50) {
strcpy(result, s);
addslash(result);
strcat(result, ".pgp");
}
}
#else if PGP_WIN32
/* on Win32 (NT), try %USERPROFILE\Application Data\pgp,
otherwise, %SYSTEMROOT\pgp directory. */
else if ((s = getenv("USERPROFILE")) != NULL)
{
if (strlen(s) <= 50) {
strcpy(result, s);
strcat(result, "\\Application Data\\pgp");
}
}
else
{
s = getenv("SYSTEMROOT");
if(s && strlen(s) <= 50) {
strcpy(result, s);
strcat(result, "\\pgp");
}
}
#endif /* PGP_UNIX */
addslash(result);
strcat(result, fname);
return result;
} /* buildFileName */
char *buildSysFileName(char *result, char *fname)
{
buildFileName(result, fname);
#ifdef PGP_SYSTEM_DIR
if (fileExists(result))
return result;
strcpy(result, PGP_SYSTEM_DIR);
strcat(result, fname);
if (fileExists(result))
return result;
buildFileName(result, fname); /* Put name back for error */
#endif
return result;
}
/* Convert filename to canonical form, with slashes as separators */
void fileToCanon(char *filename)
{
#ifdef BSLASH
while (*filename) {
if (*filename == '\\')
*filename = '/';
++filename;
}
#endif
}
int writeError( struct pgpfileBones *filebPtr, FILE * f )
{
fflush(f);
if (ferror(f)) {
#ifdef ENOSPC
if (errno == ENOSPC)
fprintf(filebPtr->pgpout, LANG("\nDisk full.\n"));
else
#endif
fprintf(filebPtr->pgpout, LANG("\nFile write error.\n"));
return -1;
}
return 0;
}
/* copy file f to file g, for longcount bytes */
int copyFile(FILE * f, FILE * g, PGPUInt32 longcount)
{
int count, status = 0;
do { /* read and write the whole file... */
if (longcount < (PGPUInt32) DISKBUFSIZE)
count = (int) longcount;
else
count = DISKBUFSIZE;
count = fread(textbuf, 1, count, f);
if (count > 0) {
if (get_CONVERSION() != NO_CONV) {
int i;
for (i = 0; i < count; i++)
textbuf[i] = (get_CONVERSION() == EXT_CONV) ?
EXT_C(textbuf[i]) :
INT_C(textbuf[i]);
}
if (fwrite(textbuf, 1, count, g) != (size_t)count) {
/* Problem: return error value */
status = -1;
break;
}
longcount -= count;
}
/* if text block was short, exit loop */
} while (count == DISKBUFSIZE);
burn(textbuf); /* burn sensitive data on stack */
return status;
} /* copyFile */
/*
* Like copyFile, but takes a position for file f. Returns with
* f and g pointing just past the copied data.
*/
int copyFilePos(FILE * f, FILE * g, PGPUInt32 longcount, PGPUInt32 fpos)
{
fseek(f, fpos, SEEK_SET);
return copyFile(f, g, longcount);
}
/* copy file f to file g, for longcount bytes. Convert to
* canonical form as we go. f is open in text mode. Canonical
* form uses crlf's as line separators.
*/
int copyFileToCanon(FILE * f, FILE * g, PGPUInt32 longcount, PGPBoolean
strip_spaces)
{
int count, status = 0;
PGPByte c, *tb1, *tb2;
int i, nbytes;
int nspaces = 0;
do { /* read and write the whole file... */
if (longcount < (PGPUInt32) DISKBUFSIZE)
count = (int) longcount;
else
count = DISKBUFSIZE;
count = fread(textbuf, 1, count, f);
if (count > 0) {
/* Convert by adding CR before LF */
tb1 = textbuf;
tb2 = (PGPByte *) textbuf2;
for (i = 0; i < count; ++i) {
switch (get_CONVERSION()) {
case EXT_CONV:
c = EXT_C(*tb1++);
break;
case INT_CONV:
c = INT_C(*tb1++);
break;
default:
c = *tb1++;
}
if (strip_spaces) {
if (c == ' ') {
/* Don't output spaces yet */
nspaces += 1;
} else {
if (c == '\n') {
*tb2++ = '\r';
nspaces = 0; /* Delete trailing spaces */
}
if (nspaces) {
/* Put out spaces now */
do
*tb2++ = ' ';
while (--nspaces);
}
*tb2++ = c;
}
} else {
if (c == '\n')
*tb2++ = '\r';
*tb2++ = c;
}
}
nbytes = tb2 - (PGPByte *) textbuf2;
if (fwrite(textbuf2, 1, nbytes, g) != (size_t)nbytes) {
/* Problem: return error value */
status = -1;
break;
}
longcount -= count;
}
/* if text block was short, exit loop */
} while (count == DISKBUFSIZE);
burn(textbuf); /* burn sensitive data on stack */
burn(textbuf2);
return status;
} /* copyFileToCanon */
/* copy file f to file g, for longcount bytes. Convert from
* canonical to local form as we go. g is open in text mode. Canonical
* form uses crlf's as line separators.
*/
int copyFileFromCanon(FILE * f, FILE * g, PGPUInt32 longcount)
{
int count, status = 0;
PGPByte c, *tb1, *tb2;
int i, nbytes;
do { /* read and write the whole file... */
if (longcount < (PGPUInt32) DISKBUFSIZE)
count = (int) longcount;
else
count = DISKBUFSIZE;
count = fread(textbuf, 1, count, f);
if (count > 0) {
/* Convert by removing CR's */
tb1 = textbuf;
tb2 = (PGPByte *) textbuf2;
for (i = 0; i < count; ++i) {
switch (get_CONVERSION()) {
case EXT_CONV:
c = EXT_C(*tb1++);
break;
case INT_CONV:
c = INT_C(*tb1++);
break;
default:
c = *tb1++;
}
if (c != '\r')
*tb2++ = c;
}
nbytes = tb2 - (PGPByte *) textbuf2;
if (fwrite(textbuf2, 1, nbytes, g) != (size_t)nbytes) {
/* Problem: return error value */
status = -1;
break;
}
longcount -= count;
}
/* if text block was short, exit loop */
} while (count == DISKBUFSIZE);
burn(textbuf); /* burn sensitive data on stack */
burn(textbuf2);
return status;
} /* copyFileFromCanon */
/* Copy srcFile to destFile */
int copyFilesByName( struct pgpfileBones *filebPtr, char *srcFile,
char *destFile )
{
FILE *f, *g;
int status = 0;
long fileLength;
f = fopen(srcFile, FOPRBIN);
if (f == NULL)
return -1;
g = fopen(destFile, FOPWBIN);
if (g == NULL) {
fclose(f);
return -1;
}
/* Get file length and copy it */
fseek(f, 0L, SEEK_END);
fileLength = ftell(f);
rewind(f);
status = copyFile(f, g, fileLength);
fclose(f);
if (writeError( filebPtr, g ))
status = -1;
fclose(g);
return status;
} /* copyFilesByName */
/* Copy srcFile to destFile, converting to canonical text form */
int makeCanonical( struct pgpfileBones *filebPtr, char *srcFile, char
*destFile )
{
FILE *f, *g;
int status = 0;
long fileLength;
if (((f = fopen(srcFile, FOPRTXT)) == NULL) ||
((g = fopen(destFile, FOPWBIN)) == NULL))
/* Can't open files */
return -1;
/* Get file length and copy it */
fseek(f, 0L, SEEK_END);
fileLength = ftell(f);
rewind(f);
set_CONVERSION(INT_CONV);
status = copyFileToCanon(f, g, fileLength, filebPtr->stripSpaces);
set_CONVERSION(NO_CONV);
fclose(f);
if (writeError( filebPtr, g ))
status = -1;
fclose(g);
return status;
} /* make_canonical */
/*
* Like rename() but will try to copy the file if the rename fails.
* This is because under OS's with multiple physical volumes if the
* source and destination are on different volumes the rename will fail
*/
int rename2( struct pgpfileBones *filebPtr, char *srcFile, char *destFile )
{
FILE *f, *g;
int status = 0;
long fileLength;
#ifdef VMS
if (rename(srcFile, destFile) != 0)
#else
if (rename(srcFile, destFile) == -1)
#endif
{
/* Rename failed, try a copy */
if (((f = fopen(srcFile, FOPRBIN)) == NULL) ||
((g = fopen(destFile, FOPWBIN)) == NULL))
/* Can't open files */
return -1;
/* Get file length and copy it */
fseek(f, 0L, SEEK_END);
fileLength = ftell(f);
rewind(f);
status = copyFile(f, g, fileLength);
if (writeError( filebPtr, g ))
status = -1;
/* Zap source file if the copy went OK, otherwise zap the (possibly
incomplete) destination file */
if (status >= 0) {
wipeout(filebPtr, f); /* Zap source file */
fclose(f);
remove(srcFile);
fclose(g);
} else {
if (isRegularFile(destFile)) {
wipeout(filebPtr, g); /* Zap destination file */
fclose(g);
remove(destFile);
} else {
fclose(g);
}
fclose(f);
}
}
return status;
}
/* read the data from stdin to the phantom input file */
int readPhantomInput( struct pgpfileBones *filebPtr, char *filename )
{
FILE *outFilePtr;
PGPByte buffer[512];
int bytesRead, status = 0;
struct pgpenvBones *envbPtr = filebPtr->envbPtr;
PGPEnv *env = envbPtr->m_env;
PGPInt32 pri;
PGPError err;
if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
fprintf(filebPtr->pgpout, LANG("writing stdin to file %s\n"),
filename);
if ((outFilePtr = fopen(filename, FOPWBIN)) == NULL)
return -1;
#if defined(MSDOS) || defined(OS2)
/* Under DOS must set input stream to binary mode to avoid data
mangling */
setmode(fileno(stdin), O_BINARY);
#endif /* MSDOS || OS2 */
while ((bytesRead = fread(buffer, 1, 512, stdin)) > 0)
if (fwrite(buffer, 1, bytesRead, outFilePtr) != (size_t)bytesRead) {
status = -1;
break;
}
if (writeError( filebPtr, outFilePtr ))
status = -1;
fclose(outFilePtr);
#if defined(MSDOS) || defined(OS2)
setmode(fileno(stdin), O_TEXT); /* Reset stream */
#endif /* MSDOS || OS2 */
return status;
}
/* write the data from the phantom output file to stdout */
int writePhantomOutput( struct pgpfileBones *filebPtr, char *filename )
{
FILE *outFilePtr;
PGPByte buffer[512];
int bytesRead, status = 0;
struct pgpenvBones *envbPtr = filebPtr->envbPtr;
PGPEnv *env = envbPtr->m_env;
PGPInt32 pri;
PGPError err;
if (pgpenvGetInt( env, PGPENV_VERBOSE, &pri, &err ))
fprintf(filebPtr->pgpout, LANG("writing file %s to stdout\n"),
filename);
/* this can't fail since we just created the file */
outFilePtr = fopen(filename, FOPRBIN);
#if defined(MSDOS) || defined(OS2)
setmode(fileno(stdout), O_BINARY);
#endif /* MSDOS || OS2 */
while ((bytesRead = fread(buffer, 1, 512, outFilePtr)) > 0)
if (fwrite(buffer, 1, bytesRead, stdout) != (size_t)bytesRead) {
status = -1;
break;
}
fclose(outFilePtr);
fflush(stdout);
if (ferror(stdout)) {
status = -1;
fprintf(filebPtr->pgpout, LANG("\007Write error on stdout.\n"));
}
#if defined(MSDOS) || defined(OS2)
setmode(fileno(stdout), O_TEXT);
#endif /* MSDOS || OS2 */
return status;
}
/* Return the size from the current position of file f to the end */
PGPUInt32 fsize(FILE * f)
{
long fpos = ftell(f);
long fpos2;
fseek(f, 0L, SEEK_END);
fpos2 = ftell(f);
fseek(f, fpos, SEEK_SET);
return (PGPUInt32) (fpos2 - fpos);
}
/* Return TRUE if file filename looks like a pure text file */
int isTextFile( struct pgpfileBones *filebPtr, char *filename )
{
FILE *f = fopen(filename, "r"); /* FOPRBIN gives problem with VMS */
int i, n, bit8 = 0;
unsigned char buf[512];
unsigned char *bufptr = buf;
unsigned char c;
struct pgpenvBones *envbPtr = filebPtr->envbPtr;
PGPEnv *env = envbPtr->m_env;
PGPInt32 pri;
if (!f)
return FALSE; /* error opening it, so not a text file */
i = n = fread(buf, 1, sizeof(buf), f);
fclose(f);
if (n <= 0)
return FALSE; /* empty file or error, not a text file */
if (compressSignature(buf,NULL,NULL) >= 0)
return FALSE;
while (i--) {
c = *bufptr++;
if (c & 0x80)
++bit8;
else /* allow BEL BS HT LF VT FF CR EOF control characters */
if (c < '\007' || (c > '\r' && c < ' ' && c != '\032'))
return FALSE; /* not a text file */
}
if (strcmp( pgpenvGetCString( env, PGPENV_LANGUAGE, &pri ), "ru") == 0)
return TRUE;
/* assume binary if more than 1/4 bytes have 8th bit set */
return bit8 < n / 4;
} /* is_text_file */
/*
temporary file routines
*/
#define MAXTMPF 8
#define TMP_INUSE 2
static struct {
char path[MAX_PATH];
int flags;
int num;
} tmpf[MAXTMPF];
static char tmpdir[256]; /* temporary file directory */
static char outdir[256]; /* output directory */
static char tmpbasename[64] = "pgptemp"; /* basename for temporary files */
/*
* set directory for temporary files. path will be stored in
* tmpdir[] with an appropriate trailing path separator.
*/
void setTempDir( struct pgpfileBones *filebPtr, char *path )
{
char *p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -