]> git.sesse.net Git - cubemap/blob - util.cpp
Fix a crash when a HTTP input connected to an UDP output goes unavailable.
[cubemap] / util.cpp
1 #include <errno.h>
2 #include <stddef.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <fcntl.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8
9 #include "log.h"
10 #include "util.h"
11
12 #ifndef O_TMPFILE
13 #define __O_TMPFILE 020000000
14 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
15 #endif
16
17 using namespace std;
18
19 int make_tempfile(const string &contents)
20 {
21         int fd = open("/tmp", O_RDWR | O_TMPFILE | O_CLOEXEC, 0600);
22         if (fd == -1) {
23                 char filename[] = "/tmp/cubemap.XXXXXX";
24                 mode_t old_umask = umask(077);
25                 fd = mkstemp(filename);
26                 if (fd == -1) {
27                         log_perror("mkstemp");
28                         return -1;
29                 }
30                 umask(old_umask);
31
32                 if (unlink(filename) == -1) {
33                         log_perror("unlink");
34                         // Can still continue.
35                 }
36         }
37
38         const char *ptr = contents.data();
39         size_t to_write = contents.size();
40         while (to_write > 0) {
41                 ssize_t ret = write(fd, ptr, to_write);
42                 if (ret == -1) {
43                         log_perror("write");
44                         safe_close(fd);
45                         return -1;
46                 }
47
48                 ptr += ret;
49                 to_write -= ret;
50         }
51
52         return fd;
53 }
54
55 bool read_tempfile_and_close(int fd, string *contents)
56 {
57         bool ok = read_tempfile(fd, contents);
58         safe_close(fd);  // Implicitly deletes the file.
59         return ok;
60 }
61
62 bool read_tempfile(int fd, string *contents)
63 {
64         ssize_t ret, has_read;
65
66         off_t len = lseek(fd, 0, SEEK_END);
67         if (len == -1) {
68                 log_perror("lseek");
69                 return false;
70         }
71
72         contents->resize(len);
73
74         if (lseek(fd, 0, SEEK_SET) == -1) {
75                 log_perror("lseek");
76                 return false;
77         }
78
79         has_read = 0;
80         while (has_read < len) {
81                 ret = read(fd, &((*contents)[has_read]), len - has_read);
82                 if (ret == -1) {
83                         log_perror("read");
84                         return false;
85                 }
86                 if (ret == 0) {
87                         log(ERROR, "Unexpected EOF!");
88                         return false;
89                 }
90                 has_read += ret;
91         }
92
93         return true;
94 }
95
96 int safe_close(int fd)
97 {
98         int ret;
99         do {
100                 ret = close(fd);
101         } while (ret == -1 && errno == EINTR);
102
103         if (ret == -1) {
104                 log_perror("close()");
105         }
106
107         return ret;
108 }