about summary refs log tree commit diff
path: root/lib/pmfileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pmfileio.c')
-rw-r--r--lib/pmfileio.c184
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