diff options
Diffstat (limited to 'lib/pmfileio.c')
-rw-r--r-- | lib/pmfileio.c | 184 |
1 files changed, 145 insertions, 39 deletions
diff --git a/lib/pmfileio.c b/lib/pmfileio.c index 4048e74d..65d61dff 100644 --- a/lib/pmfileio.c +++ b/lib/pmfileio.c @@ -452,27 +452,16 @@ pm_tmpfile_fd(void) { } - -FILE * -pm_openr_seekable(const char name[]) { +static bool +isSeekable(FILE * const fP) { /*---------------------------------------------------------------------------- - Open the file named by name[] such that it is seekable (i.e. it can be - rewound and read in multiple passes with fseek()). + The file is seekable -- we can set its read/write position to anything we + want. - If the file is actually seekable, this reduces to the same as - pm_openr(). If not, we copy the named file to a temporary file - and return that file's stream descriptor. - - We use a file that the operating system recognizes as temporary, so - it picks the filename and deletes the file when Caller closes it. + If we can't tell if it is seekable, we return false. -----------------------------------------------------------------------------*/ - int stat_rc; - int seekable; /* logical: file is seekable */ + int statRc; struct stat statbuf; - FILE * original_file; - FILE * seekable_file; - - original_file = pm_openr((char *) name); /* I would use fseek() to determine if the file is seekable and be a little more general than checking the type of file, but I @@ -486,41 +475,62 @@ pm_openr_seekable(const char name[]) { some other file is, it doesn't hurt much to assume it isn't. */ - stat_rc = fstat(fileno(original_file), &statbuf); - if (stat_rc == 0 && S_ISREG(statbuf.st_mode)) - seekable = TRUE; - else - seekable = FALSE; + statRc = fstat(fileno(fP), &statbuf); + + return statRc == 0 && S_ISREG(statbuf.st_mode); +} + - if (seekable) { - seekable_file = original_file; + +FILE * +pm_openr_seekable(const char name[]) { +/*---------------------------------------------------------------------------- + Open the file named by name[] such that it is seekable (i.e. it can be + rewound and read in multiple passes with fseek()). + + If the file is actually seekable, this reduces to the same as + pm_openr(). If not, we copy the named file to a temporary file + and return that file's stream descriptor. + + We use a file that the operating system recognizes as temporary, so + it picks the filename and deletes the file when Caller closes it. +-----------------------------------------------------------------------------*/ + FILE * originalFileP; + FILE * seekableFileP; + + originalFileP = pm_openr((char *) name); + + if (isSeekable(originalFileP)) { + seekableFileP = originalFileP; } else { - seekable_file = pm_tmpfile(); + seekableFileP = pm_tmpfile(); /* Copy the input into the temporary seekable file */ - while (!feof(original_file) && !ferror(original_file) - && !ferror(seekable_file)) { + while (!feof(originalFileP) && !ferror(originalFileP) + && !ferror(seekableFileP)) { char buffer[4096]; - int bytes_read; - bytes_read = fread(buffer, 1, sizeof(buffer), original_file); - fwrite(buffer, 1, bytes_read, seekable_file); + size_t nBytesRead; + + nBytesRead = fread(buffer, 1, sizeof(buffer), originalFileP); + fwrite(buffer, 1, nBytesRead, seekableFileP); } - if (ferror(original_file)) + if (ferror(originalFileP)) pm_error("Error reading input file into temporary file. " "Errno = %s (%d)", strerror(errno), errno); - if (ferror(seekable_file)) + if (ferror(seekableFileP)) pm_error("Error writing input into temporary file. " "Errno = %s (%d)", strerror(errno), errno); - pm_close(original_file); + pm_close(originalFileP); { - int seek_rc; - seek_rc = fseek(seekable_file, 0, SEEK_SET); - if (seek_rc != 0) + int seekRc; + + seekRc = fseek(seekableFileP, 0, SEEK_SET); + if (seekRc != 0) pm_error("fseek() failed to rewind temporary file. " "Errno = %s (%d)", strerror(errno), errno); } } - return seekable_file; + return seekableFileP; } @@ -929,6 +939,72 @@ pm_getline(FILE * const ifP, +void +pm_readfile(FILE * const fileP, + const unsigned char ** const bytesP, + size_t * const szP) { + + unsigned char * buf; + size_t allocatedSz; + size_t szSoFar; + size_t chunkSz; + bool eof; + + for (szSoFar = 0, buf = NULL, allocatedSz = 0, chunkSz = 4096, + eof = false; + !eof; ) { + + size_t bytesReadCt; + + if (szSoFar + chunkSz > allocatedSz) { + allocatedSz = szSoFar + chunkSz; + REALLOCARRAY(buf, allocatedSz); + + if (!buf) { + pm_error("Failed to get memory for %lu byte input buffer", + allocatedSz); + } + } + bytesReadCt = fread(buf + szSoFar, 1, chunkSz, fileP); + + if (ferror(fileP)) + pm_error("Failed to read input from file"); + + szSoFar += bytesReadCt; + + if (bytesReadCt < chunkSz) + eof = true; + else { + /* Double buffer and read size up to 1 MiB */ + if (szSoFar <= 1024*1024) + chunkSz = szSoFar; + } + } + + *bytesP = buf; + *szP = szSoFar; +} + + + +void +pm_writefile(FILE * const fileP, + const unsigned char * const bytes, + size_t const sz) { + + size_t bytesWrittenCt; + + bytesWrittenCt = fwrite(bytes, 1, sz, fileP); + + if (bytesWrittenCt != sz) { + pm_error("Failed to write %lu bytes to Standard Output. " + "%lu bytes successfully written", + sz, bytesWrittenCt); + } +} + + + union cheat { uint32_t l; short s; @@ -968,6 +1044,20 @@ pm_bs_long(long const l) { +int +pm_is_seekable(FILE * const fP) { + + return isSeekable(fP) ? 1 : 0; +} + + + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wduplicated-cond" + + + void pm_tell2(FILE * const fileP, void * const fileposP, @@ -1008,6 +1098,10 @@ pm_tell2(FILE * const fileP, +#pragma GCC diagnostic pop + + + unsigned int pm_tell(FILE * const fileP) { @@ -1020,6 +1114,12 @@ pm_tell(FILE * const fileP) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wduplicated-cond" + + + void pm_seek2(FILE * const fileP, const pm_filepos * const fileposP, @@ -1047,8 +1147,13 @@ pm_seek2(FILE * const fileP, +#pragma GCC diagnostic pop + + + void -pm_seek(FILE * const fileP, unsigned long filepos) { +pm_seek(FILE * const fileP, + unsigned long const filepos) { /*---------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ @@ -1062,7 +1167,8 @@ pm_seek(FILE * const fileP, unsigned long filepos) { void -pm_nextimage(FILE * const file, int * const eofP) { +pm_nextimage(FILE * const file, + int * const eofP) { /*---------------------------------------------------------------------------- Position the file 'file' to the next image in the stream, assuming it is now positioned just after the current image. I.e. read off any white |