| 1 | static FILE *tempFileDes (void) { |
| 2 | int fd; |
| 3 | FILE *f; |
| 4 | char *template; |
| 5 | const char *tmpDir; |
| 6 | const char *tag = "/TempFileXXXXXXXXXX"; |
| 7 | size_t tmpDirLen, tagLen; |
| 8 | mode_t m; |
| 9 | |
| 10 | tmpDir = getenv ("TMP"); |
| 11 | if (NULL == tmpDir) { |
| 12 | tmpDir = getenv ("TMPDIR"); |
| 13 | if (NULL == tmpDir) |
| 14 | tmpDir = "/var/tmp"; |
| 15 | } |
| 16 | tmpDirLen = strlen(tmpDir); |
| 17 | tagLen = strlen(tag); |
| 18 | template = malloc_safe (tmpDirLen + tagLen + 1); |
| 19 | strncpy (template, tmpDir, tmpDirLen + 1); |
| 20 | strncpy (template + tmpDirLen, tag, tagLen + 1); |
| 21 | m = umask(077); |
| 22 | fd = mkstemp_safe (template); |
| 23 | f = fdopen_safe (fd, "w+"); |
| 24 | (void)umask(m); |
| 25 | unlink_safe (template); |
| 26 | free (template); |
| 27 | return f; |
| 28 | } |
| 29 | |
| 30 | typedef struct { |
| 31 | FILE *f; |
| 32 | } *WriteToDiskData; |
| 33 | |
| 34 | void GC_diskBack_read (void *data, pointer buf, size_t size) { |
| 35 | FILE *f; |
| 36 | |
| 37 | const size_t READ_CHUNK_SIZE = 0x2000000; /* 32M */ |
| 38 | |
| 39 | f = ((WriteToDiskData)data)->f; |
| 40 | fseek_safe (f, 0, SEEK_SET); |
| 41 | /* fread (_, 1, size, _) succeeds |
| 42 | * with size >= 2^31 |
| 43 | * for a 32-bit executable on 64-bit linux. |
| 44 | * Nonetheless, match GC_diskBack_write. |
| 45 | */ |
| 46 | while (size > 0) { |
| 47 | size_t s = min (READ_CHUNK_SIZE, size); |
| 48 | fread_safe (buf, 1, s, f); |
| 49 | buf += s; |
| 50 | size -= s; |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | void GC_diskBack_close (void *data) { |
| 55 | FILE *f; |
| 56 | |
| 57 | f = ((WriteToDiskData)data)->f; |
| 58 | fclose_safe (f); |
| 59 | free (data); |
| 60 | } |
| 61 | |
| 62 | void *GC_diskBack_write (pointer buf, size_t size) { |
| 63 | FILE *f; |
| 64 | WriteToDiskData d; |
| 65 | |
| 66 | const size_t WRITE_CHUNK_SIZE = 0x2000000; /* 32M */ |
| 67 | |
| 68 | f = tempFileDes (); |
| 69 | /* fwrite (_, 1, size, _) fails |
| 70 | * (with no helpful error conditions!) |
| 71 | * with size >= 2^31 |
| 72 | * on x86-linux. |
| 73 | */ |
| 74 | while (size > 0) { |
| 75 | size_t s = min (WRITE_CHUNK_SIZE, size); |
| 76 | fwrite_safe (buf, 1, s, f); |
| 77 | buf += s; |
| 78 | size -= s; |
| 79 | } |
| 80 | d = (WriteToDiskData)(malloc_safe (sizeof(*d))); |
| 81 | d->f = f; |
| 82 | return d; |
| 83 | } |