Import Upstream version 20180207
[hcoop/debian/mlton.git] / runtime / platform / diskBack.unix.c
CommitLineData
7f918cf1
CE
1static 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
30typedef struct {
31 FILE *f;
32} *WriteToDiskData;
33
34void 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
54void GC_diskBack_close (void *data) {
55 FILE *f;
56
57 f = ((WriteToDiskData)data)->f;
58 fclose_safe (f);
59 free (data);
60}
61
62void *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}