Make read_tempfile() much faster, and make it close the file also on error.
[cubemap] / util.cpp
1 #include <errno.h>
2 #include <stddef.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6
7 #include "util.h"
8
9 using namespace std;
10
11 int make_tempfile(const std::string &contents)
12 {
13         char filename[] = "/tmp/cubemap.XXXXXX";
14         int fd = mkstemp(filename);
15         if (fd == -1) {
16                 perror("mkstemp");
17                 return -1;
18         }
19
20         if (unlink(filename) == -1) {
21                 perror("unlink");
22                 // Can still continue;
23         }
24
25         const char *ptr = contents.data();
26         size_t to_write = contents.size();
27         while (to_write > 0) {
28                 ssize_t ret = write(fd, ptr, to_write);
29                 if (ret == -1) {
30                         perror("write");
31                         close(fd);
32                         return -1;
33                 }
34
35                 ptr += ret;
36                 to_write -= ret;
37         }
38
39         return fd;
40 }
41
42 bool read_tempfile(int fd, std::string *contents)
43 {
44         bool ok = true;
45         ssize_t ret, has_read;
46
47         off_t len = lseek(fd, 0, SEEK_END);
48         if (len == -1) {
49                 perror("lseek");
50                 ok = false;
51                 goto done;
52         }
53
54         contents->resize(len);
55
56         if (lseek(fd, 0, SEEK_SET) == -1) {
57                 perror("lseek");
58                 ok = false;
59                 goto done;
60         }
61
62         has_read = 0;
63         while (has_read < len) {
64                 ret = read(fd, &((*contents)[has_read]), len - has_read);
65                 if (ret == -1) {
66                         perror("read");
67                         ok = false;
68                         goto done;
69                 }
70                 if (ret == 0) {
71                         fprintf(stderr, "Unexpected EOF!\n");
72                         ok = false;
73                         goto done;
74                 }
75                 has_read += ret;
76         }
77
78 done:
79         do {
80                 ret = close(fd);  // Implicitly deletes the files.
81         } while (ret == -1 && errno == EINTR);
82         
83         if (ret == -1) {
84                 perror("close");
85                 // Can still continue.
86         }
87
88         return ok;
89 }