Track and clean up temp files master
authorRobert Pengelly <robertapengelly@hotmail.com>
Tue, 9 Jun 2026 06:39:40 +0000 (07:39 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Tue, 9 Jun 2026 06:39:40 +0000 (07:39 +0100)
Makefile.unix
Makefile.w32
Makefile.wat
ar.c
delete.c
hashtab.c [new file with mode: 0755]
hashtab.h [new file with mode: 0755]
lib.c
lib.h
ranlib.c
replace.c

index 14d855d53551bfec7bfd5c800cbc98a4f1c1e1a7..46f6d6734509dda3556bd6c578f7dc40d68cdbf0 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 CC                  :=  gcc
 CFLAGS              :=  -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
 
-CSRC                :=  append.c ar.c conv.c delete.c display.c extract.c lib.c ranlib.c replace.c report.c
+CSRC                :=  append.c ar.c conv.c delete.c display.c extract.c hashtab.c lib.c ranlib.c replace.c report.c
 
 ifeq ($(OS), Windows_NT)
 all: sar.exe
index 26d499a2b956e3a744bb474ba853d8f8b2809b7d..73b11b1aba5039c9317ea2e6c8db04d818b229fd 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 CC                  :=  gcc
 CFLAGS              :=  -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra
 
-CSRC                :=  append.c ar.c conv.c delete.c display.c extract.c lib.c ranlib.c replace.c report.c
+CSRC                :=  append.c ar.c conv.c delete.c display.c extract.c hashtab.c lib.c ranlib.c replace.c report.c
 
 all: sar.exe
 
index dfc128620c0460004134f59c7642b562cdfa5e30..09236020a5951e0488fc447c98072effbf0522e5 100644 (file)
@@ -4,7 +4,7 @@
 SRCDIR              ?=  $(CURDIR)
 VPATH               :=  $(SRCDIR)
 
-SRC                 :=  append.c ar.c conv.c delete.c display.c extract.c lib.c ranlib.c replace.c report.c
+SRC                 :=  append.c ar.c conv.c delete.c display.c extract.c hashtab.c lib.c ranlib.c replace.c report.c
 
 all: sar.exe
 
diff --git a/ar.c b/ar.c
index 868abda931491ddd748a0d9b3638abe447dcf177..ad5e1a1e38fa5bc3ccf5df97cc6fdb5bc2047832 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -25,6 +25,8 @@ static void cleanup (void) {
         }
     
     }
+    
+    cleanup_tempfiles ();
 
 }
 
index 3649ff2a2575c650468eae5673bbc523ab5ce3fa..acbaab3487e2eb4b2f0acfbb27f0ed1414f20b91 100644 (file)
--- a/delete.c
+++ b/delete.c
 
 void delete (FILE *arfp, const char *fname) {
 
-    FILE *tfp = get_temp_file ();
     long bytes, len, read;
     
     const char *name;
     char temp[17], *p, *contents;
     
+    FILE *tfp;
+    
+    if (!(tfp = sar_tmpfile ())) {
+    
+        report_at (program_name, 0, REPORT_ERROR, "failed to create temp file");
+        return;
+    
+    }
+    
     if (fwrite ("!<arch>\n", 8, 1, tfp) != 1) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed whilst writing ar header");
+        
+        sar_close (tfp);
         return;
     
     }
@@ -78,7 +86,7 @@ void delete (FILE *arfp, const char *fname) {
         
         if (fwrite (&hdr, sizeof (hdr), 1, tfp) != 1) {
         
-            fclose (tfp);
+            sar_close (tfp);
             
             report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header");
             exit (EXIT_FAILURE);
@@ -99,10 +107,11 @@ void delete (FILE *arfp, const char *fname) {
             
             if (fread (contents, read, 1, arfp) != 1) {
             
+                report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile);
+                
+                sar_close (tfp);
                 free (contents);
-                fclose (tfp);
                 
-                report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile);
                 exit (EXIT_FAILURE);
             
             }
@@ -111,10 +120,11 @@ void delete (FILE *arfp, const char *fname) {
             
             if (fwrite (contents, read, 1, tfp) != 1) {
             
+                report_at (program_name, 0, REPORT_ERROR, "failed to write temp file");
+                
+                sar_close (tfp);
                 free (contents);
-                fclose (tfp);
                 
-                report_at (program_name, 0, REPORT_ERROR, "failed to write temp file");
                 exit (EXIT_FAILURE);
             
             }
@@ -130,9 +140,9 @@ void delete (FILE *arfp, const char *fname) {
     
     if ((arfp = fopen (state->outfile, "w+b")) == NULL) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed to open %s for writing", state->outfile);
+        
+        sar_close (tfp);
         exit (EXIT_FAILURE);
     
     }
@@ -155,10 +165,11 @@ void delete (FILE *arfp, const char *fname) {
         
         if (fread (contents, read, 1, tfp) != 1) {
             
+            report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file");
+            
+            sar_close (tfp);
             free (contents);
-            fclose (tfp);
             
-            report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file");
             return;
         
         }
@@ -167,17 +178,18 @@ void delete (FILE *arfp, const char *fname) {
         
         if (fwrite (contents, read, 1, arfp) != 1) {
         
+            report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s", state->outfile);
+            
+            sar_close (tfp);
             free (contents);
-            fclose (tfp);
             
-            report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s", state->outfile);
             exit (EXIT_FAILURE);
         
         }
     
     }
     
+    sar_close (tfp);
     free (contents);
-    fclose (tfp);
 
 }
diff --git a/hashtab.c b/hashtab.c
new file mode 100755 (executable)
index 0000000..78b3d6c
--- /dev/null
+++ b/hashtab.c
@@ -0,0 +1,222 @@
+/******************************************************************************
+ * @file            hashtab.c
+ *****************************************************************************/
+#include    <stddef.h>
+#include    <stdlib.h>
+#include    <string.h>
+
+#include    "hashtab.h"
+
+static struct hashtab_entry *find_entry (struct hashtab_entry *entries, unsigned long capacity, struct hashtab_name *key);
+
+static int adjust_capacity (struct hashtab *table, unsigned long new_capacity) {
+
+    struct hashtab_entry *new_entries, *old_entries;
+    unsigned long i, new_count, old_capacity;
+    
+    if ((new_entries = malloc (sizeof (*new_entries) * new_capacity)) == NULL) {
+        return -2;
+    }
+    
+    for (i = 0; i < new_capacity; i++) {
+    
+        struct hashtab_entry *entry = &new_entries[i];
+        
+        entry->key = NULL;
+        entry->value = NULL;
+    
+    }
+    
+    old_entries = table->entries;
+    old_capacity = table->capacity;
+    
+    new_count = 0;
+    
+    for (i = 0; i < old_capacity; i++) {
+    
+        struct hashtab_entry *entry = &old_entries[i], *dest;
+        
+        if (entry->key == NULL) {
+            continue;
+        }
+        
+        dest = find_entry (new_entries, new_capacity, entry->key);
+        
+        dest->key = entry->key;
+        dest->value = entry->value;
+        
+        new_count++;
+    
+    }
+    
+    free (old_entries);
+    
+    table->capacity = new_capacity;
+    table->count = new_count;
+    table->entries = new_entries;
+    table->used = new_count;
+    
+    return 0;
+
+}
+
+static struct hashtab_entry *find_entry (struct hashtab_entry *entries, unsigned long capacity, struct hashtab_name *key) {
+
+    struct hashtab_entry *tombstone = NULL;
+    unsigned long index;
+    
+    for (index = key->hash % capacity; ; index = (index + 1) % capacity) {
+    
+        struct hashtab_entry *entry = &entries[index];
+        
+        if (entry->key == NULL) {
+        
+            if (entry->value == NULL) {
+            
+                if (tombstone == NULL) {
+                    return entry;
+                }
+                
+                return tombstone;
+            
+            } else if (tombstone == NULL) {
+                tombstone = entry;
+            }
+        
+        } else if (entry->key->bytes == key->bytes) {
+        
+            if (memcmp (entry->key->chars, key->chars, key->bytes) == 0 && entry->key->hash == key->hash) {
+                return entry;
+            }
+        
+        }
+    
+    }
+
+}
+
+static unsigned long hash_string (const void *p, unsigned long length) {
+
+    unsigned char *str = (unsigned char *) p;
+    unsigned long i;
+    
+    unsigned long result = 0;
+    
+    for (i = 0; i < length; i++) {
+        result = (((unsigned short) str[i]) << 4) + (result >> 9) + result + (result >> 3) + (((unsigned short) str[i]) << 2) - (result << 12);
+    }
+    
+    return result;
+
+}
+
+struct hashtab_name *hashtab_alloc_name (const char *str) {
+
+    unsigned long bytes = strlen (str), hash = hash_string (str, bytes);
+    struct hashtab_name *name;
+    
+    if (!(name = malloc (sizeof (*name)))) {
+        return 0;
+    }
+    
+    name->bytes = bytes;
+    name->chars = str;
+    name->hash = hash;
+    
+    return name;
+
+}
+
+struct hashtab_name *hashtab_get_key (struct hashtab *table, const char *name) {
+
+    struct hashtab_name *key;
+    struct hashtab_entry *entry;
+    
+    if (!table || table->count == 0 || !(key = hashtab_alloc_name (name))) {
+        return 0;
+    }
+    
+    entry = find_entry (table->entries, table->capacity, key);
+    free (key);
+    
+    return entry->key;
+
+}
+
+void *hashtab_get (struct hashtab *table, struct hashtab_name *key) {
+
+    struct hashtab_entry *entry;
+    
+    if (!table || table->count == 0) {
+        return 0;
+    }
+    
+    entry = find_entry (table->entries, table->capacity, key);
+    
+    if (!entry->key) {
+        return 0;
+    }
+    
+    return entry->value;
+
+}
+
+int hashtab_put (struct hashtab *table, struct hashtab_name *key, void *value) {
+
+    const int MIN_CAPACITY = 15;
+    
+    struct hashtab_entry *entry;
+    int ret = 0;
+    
+    if (table->used >= table->capacity / 2) {
+    
+        long capacity = table->capacity * 2 - 1;
+        
+        if (capacity < MIN_CAPACITY) {
+            capacity = MIN_CAPACITY;
+        }
+        
+        if ((ret = adjust_capacity (table, capacity))) {
+            return ret;
+        }
+    
+    }
+    
+    entry = find_entry (table->entries, table->capacity, key);
+    
+    if (!entry->key) {
+    
+        table->count++;
+        
+        if (!entry->value) {
+            table->used++;
+        }
+    
+    }
+    
+    entry->key = key;
+    entry->value = value;
+    
+    return 0;
+
+}
+
+void hashtab_remove (struct hashtab *table, struct hashtab_name *key) {
+
+    struct hashtab_entry *entry;
+
+    if (!table || table->count == 0) {
+        return;
+    }
+
+    entry = find_entry (table->entries, table->capacity, key);
+
+    if (!entry->key) {
+        return;
+    }
+
+    entry->value = HASHTAB_TOMBSTONE;
+    entry->key = 0;
+
+    --table->count;
+}
diff --git a/hashtab.h b/hashtab.h
new file mode 100755 (executable)
index 0000000..1959593
--- /dev/null
+++ b/hashtab.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * @file            hashtab.h
+ *****************************************************************************/
+#ifndef     _HASHTAB_H
+#define     _HASHTAB_H
+
+struct hashtab_name {
+
+    const char *chars;
+    unsigned long bytes, hash;
+
+};
+
+struct hashtab_entry {
+
+    struct hashtab_name *key;
+    void *value;
+
+};
+
+struct hashtab {
+
+    struct hashtab_entry *entries;
+    int capacity, count, used;
+
+};
+
+#define     HASHTAB_TOMBSTONE           ((void *) -1)
+struct hashtab_name *hashtab_alloc_name (const char *str);
+
+struct hashtab_name *hashtab_get_key (struct hashtab *table, const char *name);
+void *hashtab_get (struct hashtab *table, struct hashtab_name *key);
+
+int hashtab_put (struct hashtab *table, struct hashtab_name *key, void *value);
+void hashtab_remove (struct hashtab *table, struct hashtab_name *key);
+
+#endif      /* _HASHTAB_H */
diff --git a/lib.c b/lib.c
index af41105291fadc584435bbb3c354f6eb9dbb5b95..2eea95d0874426be44da23ae06bb0f438adfbaf1 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -271,9 +271,26 @@ void *xrealloc (void *__ptr, unsigned long __size) {
 
 
 #if     defined (unix) || defined (__unix) || defined (__unix__) || defined (__APPLE__)
-FILE *get_temp_file (void) {
+# include       <unistd.h>
+# include       "hashtab.h"
 
-    char *temp_path, *template;
+struct temp_file {
+
+    char *name, *path;
+    FILE *fp;
+
+};
+
+static struct hashtab hashtab_tmpfiles = { 0 };
+
+FILE *sar_tmpfile (void) {
+
+    char *temp_path, *template, *name, *p;
+    
+    struct hashtab_name *key;
+    struct temp_file *tmp;
+    
+    FILE *fp;
     int fd;
     
     if (!(temp_path = getenv ("TMPDIR"))) {
@@ -281,40 +298,434 @@ FILE *get_temp_file (void) {
     }
     
     template = xmalloc (strlen (temp_path) + 1 + 10 + 1);
+    
+again:
+    
     sprintf (template, "%s/sarXXXXXX", temp_path);
     
-    if (!(fd = mkstemp (template))) {
+    if ((fd = mkstemp (template)) < 0) {
         return 0;
     }
     
-    return fdopen (fd, "w+b");
+    if ((p = strrchr (template, '/'))) {
+        name = xstrdup (p + 1);
+    } else {
+        name = xstrdup (template);
+    }
+    
+    if ((key = hashtab_get_key (&hashtab_tmpfiles, name))) {
+    
+        close (fd);
+        
+        remove (template);
+        free (name);
+        
+        goto again;
+    
+    }
+    
+    if (!((key = hashtab_alloc_name (name)))) {
+    
+        report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for key");
+        exit (EXIT_FAILURE);
+    
+    }
+    
+    if ((fp = fdopen (fd, "w+b"))) {
+    
+        tmp = xmalloc (sizeof (*tmp));
+        tmp->fp = fp;
+        
+        tmp->path = xstrdup (template);
+        tmp->name = name;
+        
+        hashtab_put (&hashtab_tmpfiles, key, tmp);
+        
+        free (template);
+        return fp;
+    
+    }
+    
+    free (name);
+    free (key);
+    
+    close (fd);
+    
+    remove (template);
+    free (template);
+    
+    return 0;
+
+}
+
+int sar_close (FILE *fp) {
+
+    struct hashtab_entry *entry;
+    struct temp_file *tmp;
+    
+    int ret, i;
+    
+    for (i = 0; i < hashtab_tmpfiles.capacity; i++) {
+    
+        if (!(entry = &hashtab_tmpfiles.entries[i])) {
+            continue;
+        }
+        
+        if (!entry->key || !entry->value || entry->value == HASHTAB_TOMBSTONE) {
+            continue;
+        }
+        
+        tmp = (struct temp_file *) entry->value;
+        
+        if (tmp->fp == fp) {
+        
+            if ((ret = fclose (fp))) {
+                return ret;
+            }
+            
+            hashtab_remove (&hashtab_tmpfiles, entry->key);
+            remove (tmp->path);
+            
+            free (tmp->path);
+            free (tmp->name);
+            
+            free (tmp);
+            return 0;
+        
+        }
+    
+    }
+    
+    return 0;
+
+}
+
+void cleanup_tempfiles (void) {
+
+    struct hashtab_entry *entry;
+    struct temp_file *tmp;
+    
+    int ret, i;
+    
+    for (i = 0; i < hashtab_tmpfiles.capacity; i++) {
+    
+        if (!(entry = &hashtab_tmpfiles.entries[i])) {
+            continue;
+        }
+        
+        if (!entry->key || !entry->value || entry->value == HASHTAB_TOMBSTONE) {
+            continue;
+        }
+        
+        tmp = (struct temp_file *) entry->value;
+        
+        if ((ret = fclose (tmp->fp))) {
+            continue;
+        }
+        
+        remove (tmp->path);
+    
+    }
 
 }
-#elif   defined (_WIN32)
-# include   <windows.h>
+#elif       defined (_WIN32)
+# include       <windows.h>
 
 # ifndef    MAX_PATH
 #  define       MAX_PATH                206
 # endif
 
-FILE *get_temp_file (void) {
+# include       "hashtab.h"
+
+struct temp_file {
+
+    char *name, *path;
+    FILE *fp;
+
+};
+
+static struct hashtab hashtab_tmpfiles = { 0 };
+
+FILE *sar_tmpfile (void) {
 
     char temp_path[MAX_PATH + 1] = { 0 };
     char full_path[MAX_PATH + 1] = { 0 };
     
+    struct hashtab_name *key;
+    struct temp_file *tmp;
+    
+    char *name, *p;
+    FILE *fp;
+    
     if (!GetTempPath (MAX_PATH + 1, temp_path)) {
         return 0;
     }
     
+again:
+    
     if (!GetTempFileName (temp_path, "sar", 0, full_path)) {
         return 0;
     }
     
-    return fopen (full_path, "w+b");
+    if ((p = strrchr (full_path, '\\'))) {
+        name = xstrdup (p + 1);
+    } else {
+        name = xstrdup (full_path);
+    }
+    
+    if ((key = hashtab_get_key (&hashtab_tmpfiles, name))) {
+    
+        free (name);
+        goto again;
+    
+    }
+    
+    if (!((key = hashtab_alloc_name (name)))) {
+    
+        report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for key");
+        exit (EXIT_FAILURE);
+    
+    }
+    
+    if ((fp = fopen (full_path, "w+b"))) {
+    
+        tmp = xmalloc (sizeof (*tmp));
+        tmp->fp = fp;
+        
+        tmp->path = xstrdup (full_path);
+        tmp->name = name;
+        
+        hashtab_put (&hashtab_tmpfiles, key, tmp);
+        return fp;
+    
+    }
+    
+    free (name);
+    free (key);
+    
+    return 0;
+
+}
+
+int sar_close (FILE *fp) {
+
+    struct hashtab_entry *entry;
+    struct temp_file *tmp;
+    
+    int ret, i;
+    
+    for (i = 0; i < hashtab_tmpfiles.capacity; i++) {
+    
+        if (!(entry = &hashtab_tmpfiles.entries[i])) {
+            continue;
+        }
+        
+        if (!entry->key || !entry->value || entry->value == HASHTAB_TOMBSTONE) {
+            continue;
+        }
+        
+        tmp = (struct temp_file *) entry->value;
+        
+        if (tmp->fp == fp) {
+        
+            if ((ret = fclose (fp))) {
+                return ret;
+            }
+            
+            hashtab_remove (&hashtab_tmpfiles, entry->key);
+            remove (tmp->path);
+            
+            free (tmp->path);
+            free (tmp->name);
+            
+            free (tmp);
+            return 0;
+        
+        }
+    
+    }
+    
+    return 0;
+
+}
+
+void cleanup_tempfiles (void) {
+
+    struct hashtab_entry *entry;
+    struct temp_file *tmp;
+    
+    int ret, i;
+    
+    for (i = 0; i < hashtab_tmpfiles.capacity; i++) {
+    
+        if (!(entry = &hashtab_tmpfiles.entries[i])) {
+            continue;
+        }
+        
+        if (!entry->key || !entry->value || entry->value == HASHTAB_TOMBSTONE) {
+            continue;
+        }
+        
+        tmp = (struct temp_file *) entry->value;
+        
+        if ((ret = fclose (tmp->fp))) {
+            continue;
+        }
+        
+        remove (tmp->path);
+    
+    }
 
 }
 #else
-FILE *get_temp_file (void) {
-    return tmpfile ();
+# include       "hashtab.h"
+
+struct temp_file {
+
+    char *name;
+    FILE *fp;
+
+};
+
+FILE *sar_tmpfile (void) {
+
+    static char name[64] = { 0 };
+    
+    char *temp;
+    unsigned long index, i, j;
+    
+    struct hashtab_name *key;
+    struct temp_file *tmp;
+    
+    FILE *fp;
+    
+    for (i = 0; i < 456976; i++) {
+    
+        sprintf (name, "sar_AAAA.tmp");
+        
+        index = 7;
+        j = i;
+        
+        do {
+        
+            name[index] = (j % 26) + 'A';
+            index--;
+        
+        } while ((j /= 26) > 0);
+        
+        temp = xstrdup (name);
+        
+        if ((key = hashtab_get_key (&hashtab_tmpfiles, temp))) {
+        
+            free (temp);
+            continue;
+        
+        }
+        
+        if ((fp = fopen (temp, "rb"))) {
+        
+            fclose (fp);
+            
+            free (temp);
+            continue;
+        
+        }
+        
+        if (!((key = hashtab_alloc_name (temp)))) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for key");
+            exit (EXIT_FAILURE);
+        
+        }
+        
+        if ((fp = fopen (temp, "w+b"))) {
+            
+            tmp = xmalloc (sizeof (*tmp));
+            
+            tmp->name = temp;
+            tmp->fp = fp;
+        
+            hashtab_put (&hashtab_tmpfiles, key, tmp);
+            return fp;
+        
+        }
+        
+        free (temp);
+        free (key);
+    
+    }
+    
+    return 0;
+
+}
+
+int sar_close (FILE *fp) {
+
+    struct hashtab_entry *entry;
+    struct temp_file *tmp;
+    
+    int ret, i;
+    
+    for (i = 0; i < hashtab_tmpfiles.capacity; i++) {
+    
+        if (!(entry = &hashtab_tmpfiles.entries[i])) {
+            continue;
+        }
+        
+        if (!entry->key || !entry->value || entry->value == HASHTAB_TOMBSTONE) {
+            continue;
+        }
+        
+        tmp = (struct temp_file *) entry->value;
+        
+        if (tmp->fp == fp) {
+        
+            if ((ret = fclose (fp))) {
+                return ret;
+            }
+            
+            hashtab_remove (&hashtab_tmpfiles, entry->key);
+            remove (tmp->name);
+            
+            free (tmp->name);
+            free (tmp);
+            
+            return 0;
+        
+        }
+    
+    }
+    
+    return 0;
+
+}
+
+void cleanup_tempfiles (void) {
+
+    struct hashtab_entry *entry;
+    struct temp_file *tmp;
+    
+    int ret, i;
+    
+    for (i = 0; i < hashtab_tmpfiles.capacity; i++) {
+    
+        if (!(entry = &hashtab_tmpfiles.entries[i])) {
+            continue;
+        }
+        
+        if (!entry->key || !entry->value || entry->value == HASHTAB_TOMBSTONE) {
+            continue;
+        }
+        
+        tmp = (struct temp_file *) entry->value;
+        
+        if ((ret = fclose (tmp->fp))) {
+            continue;
+        }
+        
+        remove (tmp->name);
+    
+    }
+
 }
 #endif
diff --git a/lib.h b/lib.h
index 52f1f4833a5762537fb5cb154810b3095a110b43..d9f51cad8247575048ef2ad5acde6bbfccd22834 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -16,6 +16,10 @@ void *xmalloc (unsigned long __size);
 void *xrealloc (void *__ptr, unsigned long __size);
 
 #include    <stdio.h>
-FILE *get_temp_file (void);
+
+FILE *sar_tmpfile (void);
+int sar_close (FILE *fp);
+
+void cleanup_tempfiles (void);
 
 #endif      /* _LIB_H */
index 7b26ca527207c5c60ea3ab47e4d199d176b8c4a9..9cd53f8a62efb71a312cdc673e93b28f9d33bf02 100644 (file)
--- a/ranlib.c
+++ b/ranlib.c
@@ -715,8 +715,6 @@ static void omf_get_symbols (void *object, char *filename, uint64_t bytes, int64
 
 void ranlib (FILE *arfp) {
 
-    FILE *tfp = get_temp_file ();
-    
     struct ar_header header;
     long i, j, len, read, val;
     
@@ -726,12 +724,21 @@ void ranlib (FILE *arfp) {
     char temp[16];
     long offset = 0;
     
+    FILE *tfp;
+    
 #if     UINT_MAX == 65535
     long bytes;
 #else
     int bytes;
 #endif
     
+    if (!(tfp = sar_tmpfile ())) {
+    
+        report_at (program_name, 0, REPORT_ERROR, "failed to create temp file");
+        return;
+    
+    }
+    
     for (;;) {
     
         struct ar_header hdr;
@@ -765,9 +772,9 @@ void ranlib (FILE *arfp) {
         
         if (fread (object, bytes, 1, arfp) != 1) {
         
-            free (object);
-            
             report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile);
+            
+            free (object);
             exit (EXIT_FAILURE);
             
         
@@ -836,9 +843,9 @@ void ranlib (FILE *arfp) {
     
     if (fwrite ("!<arch>\n", 8, 1, tfp) != 1) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed whilst writing ar header");
+        
+        sar_close (tfp);
         return;
     
     }
@@ -872,9 +879,9 @@ void ranlib (FILE *arfp) {
     
     if (fwrite (&header, sizeof (header), 1, tfp) != 1) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header");
+        
+        sar_close (tfp);
         return;
     
     }
@@ -960,9 +967,9 @@ void ranlib (FILE *arfp) {
         
         if (fwrite (&hdr, sizeof (hdr), 1, tfp) != 1) {
         
-            fclose (tfp);
-            
             report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header");
+            
+            sar_close (tfp);
             exit (EXIT_FAILURE);
         
         }
@@ -981,10 +988,11 @@ void ranlib (FILE *arfp) {
             
             if (fread (contents, read, 1, arfp) != 1) {
             
+                report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile);
+                
+                sar_close (tfp);
                 free (contents);
-                fclose (tfp);
                 
-                report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile);
                 exit (EXIT_FAILURE);
             
             }
@@ -993,10 +1001,11 @@ void ranlib (FILE *arfp) {
             
             if (fwrite (contents, read, 1, tfp) != 1) {
             
+                report_at (program_name, 0, REPORT_ERROR, "failed to write temp file");
+                
+                sar_close (tfp);
                 free (contents);
-                fclose (tfp);
                 
-                report_at (program_name, 0, REPORT_ERROR, "failed to write temp file");
                 exit (EXIT_FAILURE);
             
             }
@@ -1012,9 +1021,9 @@ void ranlib (FILE *arfp) {
     
     if ((arfp = fopen (state->outfile, "w+b")) == NULL) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed to open %s for writing", state->outfile);
+        
+        sar_close (tfp);
         exit (EXIT_FAILURE);
     
     }
@@ -1037,10 +1046,11 @@ void ranlib (FILE *arfp) {
         
         if (fread (contents, read, 1, tfp) != 1) {
             
+            report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file");
+            
+            sar_close (tfp);
             free (contents);
-            fclose (tfp);
             
-            report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file");
             return;
         
         }
@@ -1049,17 +1059,18 @@ void ranlib (FILE *arfp) {
         
         if (fwrite (contents, read, 1, arfp) != 1) {
         
+            report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s", state->outfile);
+            
+            sar_close (tfp);
             free (contents);
-            fclose (tfp);
             
-            report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s", state->outfile);
             exit (EXIT_FAILURE);
         
         }
     
     }
     
+    sar_close (tfp);
     free (contents);
-    fclose (tfp);
 
 }
index 876df8a2f6387e82480d7a30dee2cc824b8b9f4e..d0e9ad702cc385de6fb7aa3e083a48012c6d03b5 100644 (file)
--- a/replace.c
+++ b/replace.c
 
 void replace (FILE *arfp, const char *fname) {
 
-    FILE *tfp = get_temp_file ();
     long bytes, len, read;
     
     const char *name;
     char temp[17], *p, *contents;
     
+    FILE *tfp;
+    
+    if (!(tfp = sar_tmpfile ())) {
+    
+        report_at (program_name, 0, REPORT_ERROR, "failed to create temp file");
+        return;
+    
+    }
+    
     if (fwrite ("!<arch>\n", 8, 1, tfp) != 1) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed whilst writing ar header");
+        
+        sar_close (tfp);
         return;
     
     }
@@ -83,9 +91,9 @@ void replace (FILE *arfp, const char *fname) {
         
         if (fwrite (&hdr, sizeof (hdr), 1, tfp) != 1) {
         
-            fclose (tfp);
-            
             report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header");
+            
+            sar_close (tfp);
             exit (EXIT_FAILURE);
         
         }
@@ -104,9 +112,9 @@ void replace (FILE *arfp, const char *fname) {
             
             if (fread (contents, read, 1, arfp) != 1) {
             
-                free (contents);
-                
                 report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile);
+                
+                free (contents);
                 exit (EXIT_FAILURE);
             
             }
@@ -114,10 +122,10 @@ void replace (FILE *arfp, const char *fname) {
             bytes -= read;
             
             if (fwrite (contents, read, 1, tfp) != 1) {
-            
-                free (contents);
                 
                 report_at (program_name, 0, REPORT_ERROR, "failed to write temp file");
+                
+                free (contents);
                 exit (EXIT_FAILURE);
             
             }
@@ -140,9 +148,9 @@ void replace (FILE *arfp, const char *fname) {
     
     if ((arfp = fopen (state->outfile, "w+b")) == NULL) {
     
-        fclose (tfp);
-        
         report_at (program_name, 0, REPORT_ERROR, "failed to open %s", state->outfile);
+        
+        sar_close (tfp);
         exit (EXIT_FAILURE);
     
     }
@@ -165,10 +173,11 @@ void replace (FILE *arfp, const char *fname) {
         
         if (fread (contents, read, 1, tfp) != 1) {
             
+            report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file");
+            
+            sar_close (tfp);
             free (contents);
-            fclose (tfp);
             
-            report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file");
             return;
         
         }
@@ -177,17 +186,18 @@ void replace (FILE *arfp, const char *fname) {
         
         if (fwrite (contents, read, 1, arfp) != 1) {
         
+            report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s", state->outfile);
+            
+            sar_close (tfp);
             free (contents);
-            fclose (tfp);
             
-            report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s", state->outfile);
             exit (EXIT_FAILURE);
         
         }
     
     }
     
+    sar_close (tfp);
     free (contents);
-    fclose (tfp);
 
 }