+// This could benefit from madvise()ing
+ rrd->rra_ptr = (rra_ptr_t*)(data + offset);
+ offset += sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt;
+#ifdef USE_MADVISE
+out_done:
+#endif
+ rrd_file->header_len = offset;
+ rrd_file->pos = offset;
+/* we could close(rrd_file->fd); here, the mapping is still valid anyway */
+ return (rrd_file);
+out_nullify_head:
+ rrd->stat_head = NULL;
+out_close:
+ close(rrd_file->fd);
+ return NULL;
+}
+
+/* Close a reference to an rrd_file. */
+int rrd_close(rrd_file_t* rrd_file) {
+ int ret = 0;
+#ifdef HAVE_MMAP
+ ret = munmap(rrd_file->file_start, rrd_file->file_len);
+// if (ret != 0)
+// rrd_set_error("munmap rrd_file");
+#endif
+ free(rrd_file);
+ rrd_file = NULL;
+ return ret;
+}
+
+/* Set position of rrd_file. */
+off_t rrd_seek(rrd_file_t* rrd_file, off_t off, int whence) {
+ off_t ret = 0;
+#ifdef HAVE_MMAP
+ if (whence == SEEK_SET)
+ rrd_file->pos = off;
+ else if (whence == SEEK_CUR)
+ rrd_file->pos += off;
+ else if (whence == SEEK_END)
+ rrd_file->pos = rrd_file->file_len + off;
+#else
+ ret = lseek(rrd_file->fd, off, whence);
+ if (ret < 0)
+ rrd_set_error("lseek: %s", rrd_strerror(errno));
+ rrd_file->pos = ret;
+#endif
+//XXX: mimic fseek, which returns 0 upon success
+ return ret == -1; //XXX: or just ret to mimic lseek
+}
+
+/* Get current position in rrd_file. */
+off_t rrd_tell(rrd_file_t* rrd_file) {
+ return rrd_file->pos;
+}
+
+/* read count bytes into buffer buf, starting at rrd_file->pos.
+ * Returns the number of bytes read. */
+ssize_t rrd_read(rrd_file_t* rrd_file, void*buf, size_t count) {
+#ifdef HAVE_MMAP
+ char* pos = rrd_file->file_start + rrd_file->pos;
+ buf = memmove(buf, pos, count);
+ return count;
+#else
+ ssize_t ret;
+ ret = read(rrd_file->fd, buf, count);
+ //XXX: eventually add generic rrd_set_error(""); here
+ return ret;
+#endif
+}
+
+/* write count bytes from buffer buf to the current position
+ * rrd_file->pos of rrd_file->fd. */
+ssize_t rrd_write(rrd_file_t * rrd_file, const void*buf, size_t count) {
+ ssize_t ret = count;
+#ifdef HAVE_MMAP
+ char *off, *new_pos;
+ off = rrd_file->file_start + rrd_file->pos;
+ new_pos = memmove(rrd_file->file_start + rrd_file->pos, buf, count);
+ ret = new_pos - off;
+#else
+ ret = write(rrd_file->fd, buf, count)
+#endif
+ return ret;
+}
+
+/* flush all data pending to be written to FD. */
+void rrd_flush(rrd_file_t* rrd_file)
+{
+ if (fdatasync(rrd_file->fd) != 0) {
+ rrd_set_error("flushing fd %d: %s", rrd_file->fd,
+ rrd_strerror(errno));
+ }