+// Serialize the given state to a file descriptor, and return the (still open)
+// descriptor.
+int make_tempfile(const CubemapStateProto &state)
+{
+ char tmpl[] = "/tmp/cubemapstate.XXXXXX";
+ int state_fd = mkstemp(tmpl);
+ if (state_fd == -1) {
+ perror("mkstemp");
+ exit(1);
+ }
+
+ string serialized;
+ state.SerializeToString(&serialized);
+
+ const char *ptr = serialized.data();
+ size_t to_write = serialized.size();
+ while (to_write > 0) {
+ ssize_t ret = write(state_fd, ptr, to_write);
+ if (ret == -1) {
+ perror("write");
+ exit(1);
+ }
+
+ ptr += ret;
+ to_write -= ret;
+ }
+
+ return state_fd;
+}
+
+// Read the state back from the file descriptor made by make_tempfile,
+// and close it.
+CubemapStateProto read_tempfile(int state_fd)
+{
+ if (lseek(state_fd, 0, SEEK_SET) == -1) {
+ perror("lseek");
+ exit(1);
+ }
+
+ string serialized;
+ char buf[4096];
+ for ( ;; ) {
+ ssize_t ret = read(state_fd, buf, sizeof(buf));
+ if (ret == -1) {
+ perror("read");
+ exit(1);
+ }
+ if (ret == 0) {
+ // EOF.
+ break;
+ }
+
+ serialized.append(string(buf, buf + ret));
+ }
+
+ close(state_fd); // Implicitly deletes the file.
+
+ CubemapStateProto state;
+ if (!state.ParseFromString(serialized)) {
+ fprintf(stderr, "PANIC: Failed deserialization of state.\n");
+ exit(1);
+ }
+
+ return state;
+}
+