Index: src/rrd_dump.c
===================================================================
--- src/rrd_dump.c	(revision 1064)
+++ src/rrd_dump.c	(working copy)
@@ -77,13 +77,14 @@ rrd_dump_r(const char *filename, char *o
     time_t       now;
     char         somestring[255];
     rrd_value_t  my_cdp;
-    long         rra_base, rra_start, rra_next;
-    FILE        *in_file;
+    off_t         rra_base, rra_start, rra_next;
+    rrd_file_t	 *rrd_file;
 		FILE				*out_file;
     rrd_t        rrd;
     rrd_value_t  value;
     struct tm    tm;
-    if(rrd_open(filename, &in_file,&rrd, RRD_READONLY)==-1){
+    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
+    if (rrd_file == NULL) {
 	rrd_free(&rrd);
 	return(-1);
     }
@@ -151,7 +152,7 @@ rrd_dump_r(const char *filename, char *o
 
     fputs("<!-- Round Robin Archives -->", out_file);
 
-    rra_base=ftell(in_file);    
+    rra_base = rrd_file->header_len;
     rra_next = rra_base;
 
     for(i=0;i<rrd.stat_head->rra_cnt;i++){
@@ -314,7 +315,7 @@ rrd_dump_r(const char *filename, char *o
 	fprintf(out_file, "\t\t</cdp_prep>\n");
 
 	fprintf(out_file, "\t\t<database>\n");
-	fseek(in_file,(rra_start
+	rrd_seek(rrd_file,(rra_start
 		       +(rrd.rra_ptr[i].cur_row+1)
 		       * rrd.stat_head->ds_cnt
 		       * sizeof(rrd_value_t)),SEEK_SET);
@@ -323,7 +324,7 @@ rrd_dump_r(const char *filename, char *o
 	for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){	    
 	    ii++;
 	    if (ii>=rrd.rra_def[i].row_cnt) {
-		fseek(in_file,rra_start,SEEK_SET);
+		rrd_seek(rrd_file,rra_start,SEEK_SET);
 		ii=0; /* wrap if max row cnt is reached */
 	    }
 	    now = (rrd.live_head->last_up 
@@ -339,8 +340,8 @@ rrd_dump_r(const char *filename, char *o
 # error "Need strftime"
 #endif
 	    fprintf(out_file, "\t\t\t<!-- %s / %d --> <row>",somestring,(int)now);
-	    for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){			 
-		fread(&my_cdp,sizeof(rrd_value_t),1,in_file);		
+	    for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){
+		rrd_read(rrd_file, &my_cdp,sizeof(rrd_value_t)*1);
 		if (isnan(my_cdp)){
 		  fprintf(out_file, "<v> NaN </v>");
 		} else {
@@ -350,11 +351,11 @@ rrd_dump_r(const char *filename, char *o
 	    fprintf(out_file, "</row>\n");
 	}
 	fprintf(out_file, "\t\t</database>\n\t</rra>\n");
-	
+
     }
     fprintf(out_file, "</rrd>\n");
     rrd_free(&rrd);
-    fclose(in_file);
+    close(rrd_file->fd);
     if (out_file != stdout)
     {
       fclose(out_file);
@@ -362,6 +363,3 @@ rrd_dump_r(const char *filename, char *o
     return(0);
 }
 
-
-
-
Index: src/rrd_fetch.c
===================================================================
--- src/rrd_fetch.c	(revision 1064)
+++ src/rrd_fetch.c	(working copy)
@@ -194,7 +194,6 @@ rrd_fetch_fn(
     rrd_value_t    **data)     /* two dimensional array containing the data */
 {
     long           i,ii;
-    FILE           *in_file;
     time_t         cal_start,cal_end, rra_start_time,rra_end_time;
     long  best_full_rra=0, best_part_rra=0, chosen_rra=0, rra_pointer=0;
     long  best_full_step_diff=0, best_part_step_diff=0, tmp_step_diff=0, tmp_match=0, best_match=0;
@@ -203,9 +202,12 @@ rrd_fetch_fn(
     int            first_full = 1;
     int            first_part = 1;
     rrd_t     rrd;
+    rrd_file_t     *rrd_file;
     rrd_value_t    *data_ptr;
     unsigned long  rows;
+#ifdef HAVE_POSIX_FADVISE
     long  rrd_head_size;
+#endif
 
 #ifdef DEBUG
 fprintf(stderr,"Entered rrd_fetch_fn() searching for the best match\n");
@@ -213,17 +215,19 @@ fprintf(stderr,"Looking for: start %10lu
 						*start,*end,*step);
 #endif
 
-    if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1)
+    rrd_file = rrd_open(filename,&rrd, RRD_READONLY);
+    if (rrd_file == NULL)
 	return(-1);
 
-    rrd_head_size = ftell(in_file);
-    
+#ifdef HAVE_POSIX_FADVISE
+    rrd_head_size = rrd_file->header_len;
+#endif
     /* when was the really last update of this file ? */
 
     if (((*ds_namv) = (char **) malloc(rrd.stat_head->ds_cnt * sizeof(char*)))==NULL){
 	rrd_set_error("malloc fetch ds_namv array");
 	rrd_free(&rrd);
-	fclose(in_file);
+	close(rrd_file->fd);
 	return(-1);
     }
     
@@ -232,7 +236,7 @@ fprintf(stderr,"Looking for: start %10lu
 	    rrd_set_error("malloc fetch ds_namv entry");
 	    rrd_free(&rrd);
 	    free(*ds_namv);
-	    fclose(in_file);
+	    close(rrd_file->fd);
 	    return(-1);
 	}
 	strncpy((*ds_namv)[i],rrd.ds_def[i].ds_nam,DS_NAM_SIZE-1);
@@ -312,7 +316,7 @@ fprintf(stderr,"partial match, not best\
     else {
 	rrd_set_error("the RRD does not contain an RRA matching the chosen CF");
 	rrd_free(&rrd);
-	fclose(in_file);
+	close(rrd_file->fd);
 	return(-1);
     }
 	
@@ -340,14 +344,14 @@ fprintf(stderr,"partial match, not best\
 	      free((*ds_namv)[i]);
 	free(*ds_namv);
 	rrd_free(&rrd);
-	fclose(in_file);
+	close(rrd_file->fd);
 	return(-1);
     }
     
     data_ptr=(*data);
     
     /* find base address of rra */
-    rra_base=ftell(in_file);
+    rra_base = rrd_file->header_len;
     for(i=0;i<chosen_rra;i++)
 	rra_base += ( *ds_cnt
 		      * rrd.rra_def[i].row_cnt
@@ -373,7 +377,7 @@ fprintf(stderr,"partial match, not best\
     else 
 	rra_pointer = rrd.rra_ptr[chosen_rra].cur_row+1+start_offset;
     
-    if(fseek(in_file,(rra_base 
+    if(rrd_seek(rrd_file,(rra_base 
 		   + (rra_pointer
 		      * *ds_cnt
 		      * sizeof(rrd_value_t))),SEEK_SET) != 0){
@@ -384,7 +388,7 @@ fprintf(stderr,"partial match, not best\
 	rrd_free(&rrd);
 	free(*data);
 	*data = NULL;
-	fclose(in_file);
+	close(rrd_file->fd);
 	return(-1);
 
     }
@@ -425,7 +429,7 @@ fprintf(stderr,"partial match, not best\
 	     * be wrapped*/
 	    if (rra_pointer >= (signed)rrd.rra_def[chosen_rra].row_cnt) {
 		rra_pointer -= rrd.rra_def[chosen_rra].row_cnt;
-		if(fseek(in_file,(rra_base+rra_pointer
+		if(rrd_seek(rrd_file,(rra_base+rra_pointer
 			       * *ds_cnt
 			       * sizeof(rrd_value_t)),SEEK_SET) != 0){
 		    rrd_set_error("wrap seek in RRA did fail");
@@ -435,7 +439,7 @@ fprintf(stderr,"partial match, not best\
 		    rrd_free(&rrd);
 		    free(*data);
 		    *data = NULL;
-		    fclose(in_file);
+		    close(rrd_file->fd);
 		    return(-1);
 		}
 #ifdef DEBUG
@@ -443,9 +447,9 @@ fprintf(stderr,"partial match, not best\
 #endif	    
 	    }
 	    
-	    if(fread(data_ptr,
-		     sizeof(rrd_value_t),
-		     *ds_cnt,in_file) != rrd.stat_head->ds_cnt){
+	    if(rrd_read(rrd_file,data_ptr,
+		     sizeof(rrd_value_t)* (*ds_cnt))
+		    != (ssize_t)(sizeof(rrd_value_t)*(*ds_cnt)*rrd.stat_head->ds_cnt)){
 		rrd_set_error("fetching cdp from rra");
 		for (ii=0;(unsigned)ii<*ds_cnt;ii++)
 		    free((*ds_namv)[ii]);
@@ -453,15 +457,15 @@ fprintf(stderr,"partial match, not best\
 		rrd_free(&rrd);
 		free(*data);
 		*data = NULL;
-		fclose(in_file);
+		close(rrd_file->fd);
 		return(-1);
 	    }
 #ifdef HAVE_POSIX_FADVISE
        /* don't pollute the buffer cache with data read from the file. We do this while reading to 
           keep damage minimal */
-       if (0 != posix_fadvise(fileno(in_file), rrd_head_size, ftell(in_file), POSIX_FADV_DONTNEED)) {
+       if (0 != posix_fadvise(rrd_file->fd, rrd_head_size, rrd_file->pos, POSIX_FADV_DONTNEED)) {
            rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno));
-           fclose(in_file);
+           close(rrd_file->fd);
            return(-1);
        } 
 #endif
@@ -482,12 +486,12 @@ fprintf(stderr,"partial match, not best\
     rrd_free(&rrd);
 #ifdef HAVE_POSIX_FADVISE
     /* and just to be sure we drop everything except the header at the end */
-    if (0 != posix_fadvise(fileno(in_file), rrd_head_size, 0, POSIX_FADV_DONTNEED)) {
+    if (0 != posix_fadvise(rrd_file->fd, rrd_head_size, 0, POSIX_FADV_DONTNEED)) {
            rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno));
-           fclose(in_file);
+           close(rrd_file->fd);
            return(-1);
     } 
 #endif	    
-    fclose(in_file);
+    close(rrd_file->fd);
     return(0);
 }
Index: src/rrd_resize.c
===================================================================
--- src/rrd_resize.c	(revision 1064)
+++ src/rrd_resize.c	(working copy)
@@ -12,7 +12,6 @@ int
 rrd_resize(int argc, char **argv)
 {
     char		*infilename,outfilename[11]="resize.rrd";
-    FILE		*infile,*outfile;
     rrd_t		rrdold,rrdnew;
     rrd_value_t		buffer;
     int			version;
@@ -21,6 +20,7 @@ rrd_resize(int argc, char **argv)
     unsigned long	target_rra;
     int			grow=0,shrink=0;
     char		*endptr;
+    rrd_file_t		*rrd_file, *rrd_out_file;
 
     infilename=argv[1];
     if (!strcmp(infilename,"resize.rrd")) {
@@ -51,21 +51,22 @@ rrd_resize(int argc, char **argv)
     if (shrink) modify = -modify;
 
 
-    if (rrd_open(infilename, &infile, &rrdold, RRD_READWRITE)==-1) {
+    rrd_file = rrd_open(infilename, &rrdold, RRD_READWRITE);
+    if (rrd_file == NULL) {
         rrd_set_error("could not open RRD");
         return(-1);
     }
-    if (LockRRD(infile) != 0) {
+    if (LockRRD(rrd_file->fd) != 0) {
         rrd_set_error("could not lock original RRD");
         rrd_free(&rrdold);
-        fclose(infile);
+        close(rrd_file->fd);
         return(-1);
     }
 
     if (target_rra >= rrdold.stat_head->rra_cnt) {
         rrd_set_error("no such RRA in this RRD");
         rrd_free(&rrdold);
-        fclose(infile);
+        close(rrd_file->fd);
         return(-1);
     }
 
@@ -73,10 +74,23 @@ rrd_resize(int argc, char **argv)
 	if ((long)rrdold.rra_def[target_rra].row_cnt <= -modify) {
 	    rrd_set_error("This RRA is not that big");
 	    rrd_free(&rrdold);
-	    fclose(infile);
+	    close(rrd_file->fd);
 	    return(-1);
 	}
 
+    rrd_out_file = rrd_open(outfilename, &rrdnew, RRD_CREAT);
+    if (rrd_out_file == NULL) {
+        rrd_set_error("Can't create '%s': %s",outfilename, rrd_strerror(errno));
+        return(-1);
+    }
+    if (LockRRD(rrd_out_file->fd) != 0) {
+        rrd_set_error("could not lock new RRD");
+        rrd_free(&rrdold);
+        close(rrd_file->fd);
+        close(rrd_out_file->fd);
+        return(-1);
+    }
+/*XXX: do one write for those parts of header that are unchanged */
     rrdnew.stat_head = rrdold.stat_head;
     rrdnew.ds_def    = rrdold.ds_def;
     rrdnew.rra_def   = rrdold.rra_def;
@@ -93,29 +107,20 @@ rrd_resize(int argc, char **argv)
 	default: {
 		rrd_set_error("Do not know how to handle RRD version %s",rrdold.stat_head->version);
 		rrd_free(&rrdold);	
-		fclose(infile);
+		close(rrd_file->fd);
 		return(-1);
 		}
     }
 
-    if ((outfile=fopen(outfilename,"wb"))==NULL) {
-        rrd_set_error("Can't create '%s'",outfilename);
-        return(-1);
-    }
-    if (LockRRD(outfile) != 0) {
-        rrd_set_error("could not lock new RRD");
-        rrd_free(&rrdold);
-        fclose(infile);
-        fclose(outfile);
-        return(-1);
-    }
-    fwrite(rrdnew.stat_head, sizeof(stat_head_t),1,outfile);
-    fwrite(rrdnew.ds_def,sizeof(ds_def_t),rrdnew.stat_head->ds_cnt,outfile);
-    fwrite(rrdnew.rra_def,sizeof(rra_def_t),rrdnew.stat_head->rra_cnt,outfile);
-    fwrite(rrdnew.live_head,sizeof(live_head_t),1,outfile);
-    fwrite(rrdnew.pdp_prep,sizeof(pdp_prep_t),rrdnew.stat_head->ds_cnt,outfile);
-    fwrite(rrdnew.cdp_prep,sizeof(cdp_prep_t),rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,outfile);
-    fwrite(rrdnew.rra_ptr,sizeof(rra_ptr_t),rrdnew.stat_head->rra_cnt,outfile);
+
+/* XXX: Error checking? */
+    rrd_write(rrd_out_file,rrdnew.stat_head, sizeof(stat_head_t)*1);
+    rrd_write(rrd_out_file,rrdnew.ds_def,sizeof(ds_def_t)*rrdnew.stat_head->ds_cnt);
+    rrd_write(rrd_out_file,rrdnew.rra_def,sizeof(rra_def_t)*rrdnew.stat_head->rra_cnt);
+    rrd_write(rrd_out_file,rrdnew.live_head,sizeof(live_head_t)*1);
+    rrd_write(rrd_out_file,rrdnew.pdp_prep,sizeof(pdp_prep_t)*rrdnew.stat_head->ds_cnt);
+    rrd_write(rrd_out_file,rrdnew.cdp_prep,sizeof(cdp_prep_t)*rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt);
+    rrd_write(rrd_out_file,rrdnew.rra_ptr,sizeof(rra_ptr_t)*rrdnew.stat_head->rra_cnt);
 
     /* Move the CDPs from the old to the new database.
     ** This can be made (much) faster but isn't worth the effort. Clarity
@@ -129,8 +134,8 @@ rrd_resize(int argc, char **argv)
         l+=rrdnew.stat_head->ds_cnt * rrdnew.rra_def[rra].row_cnt;
     }
     while (l>0) {
-        fread(&buffer,sizeof(rrd_value_t),1,infile);
-        fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+        rrd_read(rrd_file,&buffer,sizeof(rrd_value_t)*1);
+        rrd_write(rrd_out_file,&buffer,sizeof(rrd_value_t)*1);
         l--;
     }
     /* Move data in this RRA, either removing or adding some rows
@@ -141,14 +146,14 @@ rrd_resize(int argc, char **argv)
         */
         l = rrdnew.stat_head->ds_cnt * (rrdnew.rra_ptr[target_rra].cur_row+1);
         while (l>0) {
-            fread(&buffer,sizeof(rrd_value_t),1,infile);
-            fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+            rrd_read(rrd_file,&buffer,sizeof(rrd_value_t)*1);
+            rrd_write(rrd_out_file,&buffer,sizeof(rrd_value_t)*1);
             l--;
         }
         buffer=DNAN;
         l=rrdnew.stat_head->ds_cnt * modify;
         while (l>0) {
-            fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+            rrd_write(rrd_out_file,&buffer,sizeof(rrd_value_t)*1);
             l--;
         }
     } else {
@@ -161,7 +166,7 @@ rrd_resize(int argc, char **argv)
         remove_end=(rrdnew.rra_ptr[target_rra].cur_row-modify)%rrdnew.rra_def[target_rra].row_cnt;
         if (remove_end <= (signed long int)rrdnew.rra_ptr[target_rra].cur_row) {
             while (remove_end >= 0) {
-                fseek(infile,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
+                rrd_seek(rrd_file,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
                 rrdnew.rra_ptr[target_rra].cur_row--;
                 rrdnew.rra_def[target_rra].row_cnt--;
                 remove_end--;
@@ -172,12 +177,12 @@ rrd_resize(int argc, char **argv)
         for (l=0;l<=rrdnew.rra_ptr[target_rra].cur_row;l++) {
             unsigned int tmp;
             for (tmp=0;tmp<rrdnew.stat_head->ds_cnt;tmp++) {
-                fread(&buffer,sizeof(rrd_value_t),1,infile);
-                fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+                rrd_read(rrd_file,&buffer,sizeof(rrd_value_t)*1);
+                rrd_write(rrd_out_file,&buffer,sizeof(rrd_value_t)*1);
             }
         }
         while (modify<0) {
-            fseek(infile,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
+            rrd_seek(rrd_file,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
             rrdnew.rra_def[target_rra].row_cnt--;
             modify++;
         }
@@ -185,21 +190,20 @@ rrd_resize(int argc, char **argv)
     /* Move the rest of the CDPs
     */
     while (1) {
-	fread(&buffer,sizeof(rrd_value_t),1,infile);
-	if (feof(infile))
+	if (rrd_read(rrd_file,&buffer,sizeof(rrd_value_t)*1) <= 0)
 	    break;
-        fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
+        rrd_write(rrd_out_file,&buffer,sizeof(rrd_value_t)*1);
     }
     rrdnew.rra_def[target_rra].row_cnt += modify;
-    fseek(outfile,sizeof(stat_head_t)+sizeof(ds_def_t)*rrdnew.stat_head->ds_cnt,SEEK_SET);
-    fwrite(rrdnew.rra_def,sizeof(rra_def_t),rrdnew.stat_head->rra_cnt, outfile);
-    fseek(outfile,sizeof(live_head_t),SEEK_CUR);
-    fseek(outfile,sizeof(pdp_prep_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
-    fseek(outfile,sizeof(cdp_prep_t)*rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,SEEK_CUR);
-    fwrite(rrdnew.rra_ptr,sizeof(rra_ptr_t),rrdnew.stat_head->rra_cnt, outfile);
-    
-    fclose(outfile);
+    rrd_seek(rrd_out_file,sizeof(stat_head_t)+sizeof(ds_def_t)*rrdnew.stat_head->ds_cnt,SEEK_SET);
+    rrd_write(rrd_out_file,rrdnew.rra_def,sizeof(rra_def_t)*rrdnew.stat_head->rra_cnt);
+    rrd_seek(rrd_out_file,sizeof(live_head_t),SEEK_CUR);
+    rrd_seek(rrd_out_file,sizeof(pdp_prep_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
+    rrd_seek(rrd_out_file,sizeof(cdp_prep_t)*rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,SEEK_CUR);
+    rrd_write(rrd_out_file,rrdnew.rra_ptr,sizeof(rra_ptr_t)*rrdnew.stat_head->rra_cnt);
+
+    close(rrd_out_file->fd);
     rrd_free(&rrdold);
-    fclose(infile);
+    close(rrd_file->fd);
     return(0);
 }
Index: src/rrd_lastupdate.c
===================================================================
--- src/rrd_lastupdate.c	(revision 1064)
+++ src/rrd_lastupdate.c	(working copy)
@@ -13,8 +13,8 @@ rrd_lastupdate(int argc, char **argv, ti
                  unsigned long *ds_cnt, char ***ds_namv, char ***last_ds) {
     unsigned long i=0;
     char	 *filename;
-    FILE         *in_file;
     rrd_t        rrd;
+    rrd_file_t*	rrd_file;
 
     if(argc < 2){
         rrd_set_error("please specify an rrd");
@@ -22,10 +22,9 @@ rrd_lastupdate(int argc, char **argv, ti
     }
     filename = argv[1];
 
-    if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1){
+    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
+    if (rrd_file == NULL)
 	return(-1);
-    }
-    fclose(in_file);
 
     *last_update=rrd.live_head->last_up;
     *ds_cnt = rrd.stat_head->ds_cnt;
@@ -50,5 +49,6 @@ rrd_lastupdate(int argc, char **argv, ti
     }
 
     rrd_free(&rrd);
+    rrd_close(rrd_file);
     return(0); 
 }
Index: src/rrd_tune.c
===================================================================
--- src/rrd_tune.c	(revision 1064)
+++ src/rrd_tune.c	(working copy)
@@ -51,7 +51,6 @@ int
 rrd_tune(int argc, char **argv)    
 {   
     rrd_t               rrd;
-    FILE               *rrd_file;
     int                 matches;
     int                 optcnt = 0;
     long                ds;
@@ -61,14 +60,15 @@ rrd_tune(int argc, char **argv)    
     double              min;
     double              max;
     char                dst[DST_SIZE];
+    rrd_file_t         *rrd_file;
     optind = 0; opterr = 0;  /* initialize getopt */
 
 
-    if(rrd_open(argv[1],&rrd_file,&rrd, RRD_READWRITE)==-1){
+    rrd_file = rrd_open(argv[1],&rrd,RRD_READWRITE);
+    if (rrd_file == NULL) {
         return -1;
     }
 
-    
     while (1){
 	static struct option long_options[] =
 	{
@@ -102,12 +102,12 @@ rrd_tune(int argc, char **argv)    
 	    if ((matches = sscanf(optarg, DS_NAM_FMT ":%ld",ds_nam,&heartbeat)) != 2){
 		rrd_set_error("invalid arguments for heartbeat");
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((ds=ds_match(&rrd,ds_nam))==-1){
 		rrd_free(&rrd);
-                fclose(rrd_file);
+                close(rrd_file->fd);
 		return -1;
 	    }
 	    rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat;
@@ -117,12 +117,12 @@ rrd_tune(int argc, char **argv)    
 	    if ((matches = sscanf(optarg,DS_NAM_FMT ":%lf",ds_nam,&min)) <1){
 		rrd_set_error("invalid arguments for minimum ds value");
 		rrd_free(&rrd);
-                fclose(rrd_file);
+                close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((ds=ds_match(&rrd,ds_nam))==-1){
 		rrd_free(&rrd);
-                fclose(rrd_file);
+                close(rrd_file->fd);
 		return -1;
 	    }
 
@@ -135,12 +135,12 @@ rrd_tune(int argc, char **argv)    
 	    if ((matches = sscanf(optarg, DS_NAM_FMT ":%lf",ds_nam,&max)) <1){
 		rrd_set_error("invalid arguments for maximum ds value");
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((ds=ds_match(&rrd,ds_nam))==-1){
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if(matches == 1) 
@@ -152,17 +152,17 @@ rrd_tune(int argc, char **argv)    
 	    if ((matches = sscanf(optarg, DS_NAM_FMT ":" DST_FMT ,ds_nam,dst)) != 2){
 		rrd_set_error("invalid arguments for data source type");
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((ds=ds_match(&rrd,ds_nam))==-1){
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((int)dst_conv(dst) == -1){
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    strncpy(rrd.ds_def[ds].dst,dst,DST_SIZE-1);
@@ -180,12 +180,12 @@ rrd_tune(int argc, char **argv)    
 		 sscanf(optarg,DS_NAM_FMT ":" DS_NAM_FMT , ds_nam,ds_new)) != 2){
 		rrd_set_error("invalid arguments for data source type");
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((ds=ds_match(&rrd,ds_nam))==-1){
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    strncpy(rrd.ds_def[ds].ds_nam,ds_new,DS_NAM_SIZE-1);
@@ -243,19 +243,19 @@ rrd_tune(int argc, char **argv)    
 		if (sscanf(optarg,DS_NAM_FMT,ds_nam) != 1){
 		rrd_set_error("invalid argument for aberrant-reset");
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    if ((ds=ds_match(&rrd,ds_nam))==-1){
 	    /* ds_match handles it own errors */	
 		rrd_free(&rrd);
-	        fclose(rrd_file);
+	        close(rrd_file->fd);
 		return -1;
 	    }
 	    reset_aberrant_coefficients(&rrd,rrd_file,(unsigned long) ds);
 		if (rrd_test_error()) {
 		   rrd_free(&rrd);
-		   fclose(rrd_file);
+		   close(rrd_file->fd);
 		   return -1;
 		}
 		break;
@@ -265,20 +265,19 @@ rrd_tune(int argc, char **argv)    
             else
                 rrd_set_error("unknown option '%s'",argv[optind-1]);
 	    rrd_free(&rrd);	    
-            fclose(rrd_file);
+            close(rrd_file->fd);
             return -1;
         }
     }
 	if(optcnt>0){
 	
-	fseek(rrd_file,0,SEEK_SET);
-	fwrite(rrd.stat_head,
-	       sizeof(stat_head_t),1, rrd_file);
-	fwrite(rrd.ds_def,
-	       sizeof(ds_def_t), rrd.stat_head->ds_cnt, rrd_file);
+	rrd_seek(rrd_file,0,SEEK_SET);
+	rrd_write(rrd_file,rrd.stat_head, sizeof(stat_head_t)*1);
+	rrd_write(rrd_file,rrd.ds_def,
+	       sizeof(ds_def_t)* rrd.stat_head->ds_cnt);
 	/* need to write rra_defs for RRA parameter changes */
-	fwrite(rrd.rra_def, sizeof(rra_def_t), rrd.stat_head->rra_cnt,
-		   rrd_file);
+	rrd_write(rrd_file,rrd.rra_def,
+		sizeof(rra_def_t)*rrd.stat_head->rra_cnt);
     } else {
 	int i;
 	for(i=0;i< (int)rrd.stat_head->ds_cnt;i++)
@@ -296,7 +295,7 @@ rrd_tune(int argc, char **argv)    
 	    free(buffer);
 		}
     }
-    fclose(rrd_file);
+    close(rrd_file->fd);
     rrd_free(&rrd);
     return 0;
 }
Index: src/rrd_restore.c
===================================================================
--- src/rrd_restore.c	(revision 1064)
+++ src/rrd_restore.c	(working copy)
@@ -22,7 +22,7 @@ int skipxml(char **);
 int eat_tag(char **, char *);
 int read_tag(char **, char *, char *, void *);
 int xml2rrd(char*, rrd_t*, char);
-int rrd_write(char *, rrd_t *, char);
+int rrd_creat(char *, rrd_t *, char);
 void parse_patch1028_RRA_params(char **buf, rrd_t *rrd, int rra_index);
 void parse_patch1028_CDP_params(char **buf, rrd_t *rrd, int rra_index, int ds_index);
 void parse_FAILURES_history(char **buf, rrd_t *rrd, int rra_index, int ds_index);
@@ -461,7 +461,7 @@ int xml2rrd(char* buf, rrd_t* rrd, char 
 /* create and empty rrd file according to the specs given */
 
 int
-rrd_write(char *file_name, rrd_t *rrd, char force_overwrite)
+rrd_creat(char *file_name, rrd_t *rrd, char force_overwrite)
 {
     unsigned long    i,ii,val_cnt;
     FILE             *rrd_file=NULL;
@@ -584,7 +584,7 @@ rrd_restore(int argc, char **argv) 
 
     free(buf);
 
-    if(rrd_write(argv[optind+1],&rrd,force_overwrite)==-1){
+    if(rrd_creat(argv[optind+1],&rrd,force_overwrite)==-1){
 	rrd_free(&rrd);	
 	return -1;	
     };
Index: src/rrd_first.c
===================================================================
--- src/rrd_first.c	(revision 1064)
+++ src/rrd_first.c	(working copy)
@@ -55,13 +55,14 @@ rrd_first(int argc, char **argv)
 time_t
 rrd_first_r(const char *filename, const int rraindex)
 {
-    long rra_start,
+    off_t rra_start,
          timer;
     time_t then;
-    FILE *in_file;
     rrd_t rrd;
+    rrd_file_t *rrd_file;
 
-    if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1){
+    rrd_file = rrd_open(filename,&rrd, RRD_READONLY);
+    if (rrd_file == NULL) {
         rrd_set_error("could not open RRD");
         return(-1);
     }
@@ -69,12 +70,12 @@ rrd_first_r(const char *filename, const 
     if((rraindex < 0) || (rraindex >= (int)rrd.stat_head->rra_cnt)) {
         rrd_set_error("invalid rraindex number");
         rrd_free(&rrd);
-        fclose(in_file);
+        close(rrd_file->fd);
         return(-1);
     }
 
-    rra_start = ftell(in_file);    
-    fseek(in_file,
+    rra_start = rrd_file->header_len;
+    rrd_seek(rrd_file,
           (rra_start +
            (rrd.rra_ptr[rraindex].cur_row+1) *
            rrd.stat_head->ds_cnt *
@@ -82,7 +83,7 @@ rrd_first_r(const char *filename, const 
           SEEK_SET);
     timer = - (rrd.rra_def[rraindex].row_cnt-1);
     if (rrd.rra_ptr[rraindex].cur_row + 1 > rrd.rra_def[rraindex].row_cnt) {
-      fseek(in_file,rra_start,SEEK_SET);
+      rrd_seek(rrd_file,rra_start,SEEK_SET);
     }
     then = (rrd.live_head->last_up -
             rrd.live_head->last_up %
@@ -91,10 +92,8 @@ rrd_first_r(const char *filename, const 
             rrd.rra_def[rraindex].pdp_cnt*rrd.stat_head->pdp_step);
 
     rrd_free(&rrd);
-    fclose(in_file);
+    close(rrd_file->fd);
+    rrd_close(rrd_file);
     return(then);
 }
 
-
-
-
Index: src/rrd_info.c
===================================================================
--- src/rrd_info.c	(revision 1064)
+++ src/rrd_info.c	(working copy)
@@ -83,17 +83,18 @@ rrd_info(int argc, char **argv) {   
 info_t *
 rrd_info_r(char *filename) {   
     unsigned int i,ii=0;
-    FILE         *in_file;
     rrd_t        rrd;
     info_t       *data,*cd;
     infoval      info;
+    rrd_file_t*  rrd_file;
 	enum cf_en   current_cf;
 	enum dst_en  current_ds;
 
-    if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1){
+    rrd_file = rrd_open(filename,&rrd, RRD_READONLY);
+    if (rrd_file == NULL) {
 	return(NULL);
     }
-    fclose(in_file);
+    close(rrd_file->fd);
 
     info.u_str=filename;
     cd=info_push(NULL,sprintf_alloc("filename"),    RD_I_STR, info);
@@ -233,6 +234,7 @@ rrd_info_r(char *filename) {   
     }
 	}
 	rrd_free(&rrd);
+    rrd_close(rrd_file);
     return(data);
 
 }
Index: src/unused.h
===================================================================
--- src/unused.h	(revision 1064)
+++ src/unused.h	(working copy)
@@ -1,5 +1,8 @@
-/* define a macro to wrap variables in that would
-   otherwhise generate UNUSED variable warnings */
+/* define a macro to wrap variables that would
+   otherwise generate UNUSED variable warnings
+   Note that GCC's attribute unused only supresses the warning, so
+   it is perfectly safe to declare something unused although it is not.
+*/
 
 #ifdef UNUSED
 #elif defined(__GNUC__)
Index: src/rrd_last.c
===================================================================
--- src/rrd_last.c	(revision 1064)
+++ src/rrd_last.c	(working copy)
@@ -23,17 +23,18 @@ rrd_last(int argc, char **argv)
 time_t
 rrd_last_r(const char *filename)
 {
-    FILE	*in_file;
     time_t       lastup;
+    rrd_file_t*	rrd_file;
 
     rrd_t	 rrd;
 
-    if(rrd_open(filename, &in_file, &rrd, RRD_READONLY)==-1){
+    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
+    if (rrd_file == NULL)
         return(-1);
-    }
+
     lastup = rrd.live_head->last_up;
     rrd_free(&rrd);
-    fclose(in_file);
+    rrd_close(rrd_file);
     return(lastup);
 }
 
Index: src/rrd_thread_safe.c
===================================================================
--- src/rrd_thread_safe.c	(revision 1064)
+++ src/rrd_thread_safe.c	(working copy)
@@ -52,7 +52,7 @@ struct rrd_context *rrd_get_context(void
 const char *rrd_strerror(int err) {
     struct rrd_context *ctx = rrd_get_context();
     if (strerror_r(err, ctx->lib_errstr, ctx->errlen)) 
-         return "strerror_r faild. sorry!"; 
+         return "strerror_r failed. sorry!"; 
     else 
          return ctx->lib_errstr; 
 }
Index: src/rrd_hw.c
===================================================================
--- src/rrd_hw.c	(revision 1064)
+++ src/rrd_hw.c	(working copy)
@@ -108,7 +108,7 @@ update_hwpredict(rrd_t *rrd, unsigned lo
 
 int
 lookup_seasonal(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start,
-				FILE *rrd_file, unsigned long offset, rrd_value_t **seasonal_coef)
+				rrd_file_t* rrd_file, unsigned long offset, rrd_value_t **seasonal_coef)
 {
    unsigned long pos_tmp;
    /* rra_ptr[].cur_row points to the rra row to be written; this function
@@ -131,10 +131,10 @@ lookup_seasonal(rrd_t *rrd, unsigned lon
 	  return -1;
    }
 
-   if (!fseek(rrd_file,pos_tmp,SEEK_SET))
+   if (!rrd_seek(rrd_file,pos_tmp,SEEK_SET))
    {
-      if (fread(*seasonal_coef,sizeof(rrd_value_t),rrd->stat_head->ds_cnt,rrd_file)
-		  == rrd -> stat_head -> ds_cnt)
+      if (rrd_read(rrd_file,*seasonal_coef,sizeof(rrd_value_t)*rrd->stat_head->ds_cnt)
+		  == (ssize_t)(sizeof(rrd_value_t)*rrd->stat_head->ds_cnt))
 	  {
 		 /* success! */
          /* we can safely ignore the rule requiring a seek operation between read
@@ -511,7 +511,7 @@ erase_violations(rrd_t *rrd, unsigned lo
  * length = 5% of the period. */
 int
 apply_smoother(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start,
-               FILE *rrd_file)
+               rrd_file_t *rrd_file)
 {
    unsigned long i, j, k;
    unsigned long totalbytes;
@@ -536,21 +536,23 @@ apply_smoother(rrd_t *rrd, unsigned long
    }
 
    /* rra_start is at the beginning of this rra */
-   if (fseek(rrd_file,rra_start,SEEK_SET))
+   if (rrd_seek(rrd_file,rra_start,SEEK_SET))
    {
 	  rrd_set_error("seek to rra %d failed", rra_start);
 	  free(rrd_values);
 	  return -1;
    }
-   fflush(rrd_file);
+   rrd_flush(rrd_file);
    /* could read all data in a single block, but we need to
     * check for NA values */
    for (i = 0; i < row_count; ++i)
    {
 	  for (j = 0; j < row_length; ++j)
 	  {
-		 fread(&(rrd_values[i*row_length + j]),sizeof(rrd_value_t),1,rrd_file);
-		 /* should check fread for errors... */
+		 if (rrd_read(rrd_file, &(rrd_values[i*row_length + j]),sizeof(rrd_value_t)*1)
+			 != (ssize_t)(sizeof(rrd_value_t)*1)) {
+			 rrd_set_error("reading value failed: %s", rrd_strerror(errno));
+		 }
 		 if (isnan(rrd_values[i*row_length + j])) {
 			/* can't apply smoothing, still uninitialized values */
 #ifdef DEBUG
@@ -627,8 +629,8 @@ apply_smoother(rrd_t *rrd, unsigned long
 	 (rrd->cdp_prep[offset]).scratch[CDP_hw_intercept].u_val += baseline[j];
    }
    /* flush cdp to disk */
-   fflush(rrd_file);
-   if (fseek(rrd_file,sizeof(stat_head_t) + 
+   rrd_flush(rrd_file);
+   if (rrd_seek(rrd_file,sizeof(stat_head_t) + 
 	  rrd->stat_head->ds_cnt * sizeof(ds_def_t) +
 	  rrd->stat_head->rra_cnt * sizeof(rra_def_t) + 
 	  sizeof(live_head_t) +
@@ -638,11 +640,11 @@ apply_smoother(rrd_t *rrd, unsigned long
 	  free(rrd_values);
 	  return -1;
    }
-   if (fwrite( rrd -> cdp_prep,
-	  sizeof(cdp_prep_t),
-	  (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt, rrd_file) 
-	  != (rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt) )
-   { 
+   if (rrd_write(rrd_file, rrd -> cdp_prep,
+	  sizeof(cdp_prep_t)*
+		  (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt) 
+	  != (ssize_t)(sizeof(cdp_prep_t)*(rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt)))
+   {
 	  rrd_set_error("apply_smoother: cdp_prep write failed");
 	  free(rrd_values);
 	  return -1;
@@ -650,23 +652,23 @@ apply_smoother(rrd_t *rrd, unsigned long
    } /* endif CF_SEASONAL */ 
 
    /* flush updated values to disk */
-   fflush(rrd_file);
-   if (fseek(rrd_file,rra_start,SEEK_SET))
+   rrd_flush(rrd_file);
+   if (rrd_seek(rrd_file,rra_start,SEEK_SET))
    {
 	  rrd_set_error("apply_smoother: seek to pos %d failed", rra_start);
 	  free(rrd_values);
 	  return -1;
    }
    /* write as a single block */
-   if (fwrite(rrd_values,sizeof(rrd_value_t),row_length*row_count,rrd_file)
-	  != row_length*row_count)
+   if (rrd_write(rrd_file,rrd_values,sizeof(rrd_value_t)*row_length*row_count)
+	  != (ssize_t)(sizeof(rrd_value_t)*row_length*row_count))
    {
 	  rrd_set_error("apply_smoother: write failed to %lu",rra_start);
 	  free(rrd_values);
 	  return -1;
    }
 
-   fflush(rrd_file);
+   rrd_flush(rrd_file);
    free(rrd_values);
    free(baseline);
    return 0;
@@ -675,7 +677,7 @@ apply_smoother(rrd_t *rrd, unsigned long
 /* Reset aberrant behavior model coefficients, including intercept, slope,
  * seasonal, and seasonal deviation for the specified data source. */
 void
-reset_aberrant_coefficients(rrd_t *rrd, FILE *rrd_file, unsigned long ds_idx)
+reset_aberrant_coefficients(rrd_t *rrd, rrd_file_t *rrd_file, unsigned long ds_idx)
 {
    unsigned long cdp_idx, rra_idx, i;
    unsigned long cdp_start, rra_start;
@@ -709,19 +711,19 @@ reset_aberrant_coefficients(rrd_t *rrd, 
 	        rrd->cdp_prep[cdp_idx].scratch[CDP_hw_seasonal].u_val = DNAN;
 	        rrd->cdp_prep[cdp_idx].scratch[CDP_hw_last_seasonal].u_val = DNAN;
 			/* move to first entry of data source for this rra */
-			fseek(rrd_file,rra_start + ds_idx * sizeof(rrd_value_t),SEEK_SET);
+			rrd_seek(rrd_file,rra_start + ds_idx * sizeof(rrd_value_t),SEEK_SET);
 			/* entries for the same data source are not contiguous, 
 			 * temporal entries are contiguous */
 	        for (i = 0; i < rrd->rra_def[rra_idx].row_cnt; ++i)
 			{
-			   if (fwrite(&nan_buffer,sizeof(rrd_value_t),1,rrd_file) != 1)
+			   if (rrd_write(rrd_file,&nan_buffer,sizeof(rrd_value_t)*1) != sizeof(rrd_value_t)*1)
 			   {
                   rrd_set_error(
 				  "reset_aberrant_coefficients: write failed data source %lu rra %s",
 				  ds_idx,rrd->rra_def[rra_idx].cf_nam);
 				  return;
 			   } 
-			   fseek(rrd_file,(rrd->stat_head->ds_cnt - 1) * 
+			   rrd_seek(rrd_file,(rrd->stat_head->ds_cnt - 1) * 
 				  sizeof(rrd_value_t),SEEK_CUR);
 			}
 			break;
@@ -735,14 +737,14 @@ reset_aberrant_coefficients(rrd_t *rrd, 
 	  rra_start += rrd->rra_def[rra_idx].row_cnt * rrd->stat_head->ds_cnt * 
 		 sizeof(rrd_value_t);
    }
-   fseek(rrd_file,cdp_start,SEEK_SET);
-   if (fwrite( rrd -> cdp_prep,
-	  sizeof(cdp_prep_t),
-	  (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt, rrd_file) 
-	  != (rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt) )
+   rrd_seek(rrd_file,cdp_start,SEEK_SET);
+   if (rrd_write(rrd_file,rrd->cdp_prep,
+	  sizeof(cdp_prep_t)*
+	  (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt) 
+	  != (ssize_t)(sizeof(cdp_prep_t)*(rrd->stat_head->rra_cnt) * (rrd->stat_head->ds_cnt)))
    {
 	  rrd_set_error("reset_aberrant_coefficients: cdp_prep write failed");
-	  return;
+	  return;/*XXX: delme */
    }
 }
 
Index: src/rrd_update.c
===================================================================
--- src/rrd_update.c	(revision 1064)
+++ src/rrd_update.c	(working copy)
@@ -70,21 +70,21 @@ static void normalize_time(struct timeva
 }
 
 /* Local prototypes */
-int LockRRD(FILE *rrd_file);
+int LockRRD(int in_file);
 #ifdef HAVE_MMAP
 info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, 
 					unsigned long *rra_current,
 					unsigned short CDP_scratch_idx,
 #ifndef DEBUG
-FILE UNUSED(*rrd_file),
+int UNUSED(in_file),
 #else
-FILE *rrd_file,
+int in_file,
 #endif
 					info_t *pcdp_summary, time_t *rra_time, void *rrd_mmaped_file);
 #else
 info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, 
 					unsigned long *rra_current,
-					unsigned short CDP_scratch_idx, FILE *rrd_file,
+					unsigned short CDP_scratch_idx, int in_file,
 					info_t *pcdp_summary, time_t *rra_time);
 #endif
 int rrd_update_r(const char *filename, const char *tmplt, int argc, const char **argv);
@@ -234,7 +234,6 @@ _rrd_update(const char *filename, const 
 					    transported by the tmplt index */
     unsigned long    tmpl_cnt = 2;       /* time and data */
 
-    FILE             *rrd_file;
     rrd_t            rrd;
     time_t           current_time = 0;
     time_t           rra_time = 0;  	 /* time of update for a RRA */
@@ -261,12 +260,7 @@ _rrd_update(const char *filename, const 
     rpnstack_t       rpnstack; /* used for COMPUTE DS */
     int		     version;  /* rrd version */
     char             *endptr; /* used in the conversion */
-
-#ifdef HAVE_MMAP
-    void	     *rrd_mmaped_file;
-    unsigned long    rrd_filesize;
-#endif
-
+    rrd_file_t*      rrd_file;
 
     rpnstack_init(&rpnstack);
 
@@ -275,10 +269,9 @@ _rrd_update(const char *filename, const 
 	rrd_set_error("Not enough arguments");
 	return -1;
     }
-    
-    
 
-    if(rrd_open(filename,&rrd_file,&rrd, RRD_READWRITE)==-1){
+    rrd_file = rrd_open(filename,&rrd, RRD_READWRITE);
+    if (rrd_file == NULL) {
 	return -1;
     }
 
@@ -294,39 +287,40 @@ _rrd_update(const char *filename, const 
 	current_time_usec = 0;
     }
 
-    rra_current = rra_start = rra_begin = ftell(rrd_file);
+    rra_current = rra_start = rra_begin = rrd_file->header_len;
     /* This is defined in the ANSI C standard, section 7.9.5.3:
 
         When a file is opened with udpate mode ('+' as the second
         or third character in the ... list of mode argument
-        variables), both input and ouptut may be performed on the
+        variables), both input and output may be performed on the
         associated stream.  However, ...  input may not be directly
         followed by output without an intervening call to a file
-        positioning function, unless the input oepration encounters
+        positioning function, unless the input operation encounters
         end-of-file. */
-#ifdef HAVE_MMAP
-    fseek(rrd_file, 0, SEEK_END);
-    rrd_filesize = ftell(rrd_file);
-    fseek(rrd_file, rra_current, SEEK_SET);
+#if 0//def HAVE_MMAP
+rrd_filesize = rrd_file->file_size;
+    fseek(rrd_file->fd, 0, SEEK_END);
+    rrd_filesize = ftell(rrd_file->fd);
+    fseek(rrd_file->fd, rra_current, SEEK_SET);
 #else
-    fseek(rrd_file, 0, SEEK_CUR);
+//    fseek(rrd_file->fd, 0, SEEK_CUR);
 #endif
 
     
     /* get exclusive lock to whole file.
      * lock gets removed when we close the file.
      */
-    if (LockRRD(rrd_file) != 0) {
+    if (LockRRD(rrd_file->fd) != 0) {
       rrd_set_error("could not lock RRD");
       rrd_free(&rrd);
-      fclose(rrd_file);
+      close(rrd_file->fd);
       return(-1);   
     } 
 
     if((updvals = malloc( sizeof(char*) * (rrd.stat_head->ds_cnt+1)))==NULL){
 	rrd_set_error("allocating updvals pointer array");
 	rrd_free(&rrd);
-        fclose(rrd_file);
+        close(rrd_file->fd);
 	return(-1);
     }
 
@@ -335,7 +329,7 @@ _rrd_update(const char *filename, const 
 	rrd_set_error("allocating pdp_temp ...");
 	free(updvals);
 	rrd_free(&rrd);
-        fclose(rrd_file);
+        close(rrd_file->fd);
 	return(-1);
     }
 
@@ -345,7 +339,7 @@ _rrd_update(const char *filename, const 
 	free(pdp_temp);
 	free(updvals);
 	rrd_free(&rrd);
-        fclose(rrd_file);
+        close(rrd_file->fd);
 	return(-1);
     }
     /* initialize tmplt redirector */
@@ -377,14 +371,14 @@ _rrd_update(const char *filename, const 
   		    rrd_set_error("tmplt contains more DS definitions than RRD");
 		    free(updvals); free(pdp_temp);
 		    free(tmpl_idx); rrd_free(&rrd);
-		    fclose(rrd_file); return(-1);
+		    close(rrd_file->fd); return(-1);
 		}
 		if ((tmpl_idx[tmpl_cnt++] = ds_match(&rrd,dsname)) == -1){
   		    rrd_set_error("unknown DS name '%s'",dsname);
 		    free(updvals); free(pdp_temp);
 		    free(tmplt_copy);
 		    free(tmpl_idx); rrd_free(&rrd);
-		    fclose(rrd_file); return(-1);
+		    close(rrd_file->fd); return(-1);
 		} else {
 		  /* the first element is always the time */
 		  tmpl_idx[tmpl_cnt-1]++; 
@@ -407,16 +401,16 @@ _rrd_update(const char *filename, const 
 	free(pdp_temp);
 	free(tmpl_idx);
 	rrd_free(&rrd);
-        fclose(rrd_file);
+        close(rrd_file->fd);
 	return(-1);
     }
 
-#ifdef HAVE_MMAP
+#if 0//def HAVE_MMAP
     rrd_mmaped_file = mmap(0, 
-		    	rrd_filesize, 
+		    	rrd_file->file_len, 
 			PROT_READ | PROT_WRITE, 
 			MAP_SHARED, 
-			fileno(rrd_file), 
+			fileno(in_file), 
 			0);
     if (rrd_mmaped_file == MAP_FAILED) {
         rrd_set_error("error mmapping file %s", filename);
@@ -424,7 +418,7 @@ _rrd_update(const char *filename, const 
 	free(pdp_temp);
 	free(tmpl_idx);
 	rrd_free(&rrd);
-        fclose(rrd_file);
+        close(rrd_file->fd);
 	return(-1);
     }
 #endif
@@ -444,9 +438,9 @@ _rrd_update(const char *filename, const 
                 free(tmpl_idx);
                 rrd_free(&rrd);
 #ifdef HAVE_MMAP
-    		munmap(rrd_mmaped_file, rrd_filesize);
+		rrd_close(rrd_file);
 #endif
-                fclose(rrd_file);
+                close(rrd_file->fd);
                 return(-1);
          }
 	/* initialize all ds input to unknown except the first one
@@ -537,7 +531,7 @@ _rrd_update(const char *filename, const 
 	/* seek to the beginning of the rra's */
 	if (rra_current != rra_begin) {
 #ifndef HAVE_MMAP
-	    if(fseek(rrd_file, rra_begin, SEEK_SET) != 0) {
+	    if(rrd_seek(rrd_file, rra_begin, SEEK_SET) != 0) {
 		rrd_set_error("seek error in rrd");
 		free(step_start);
 		break;
@@ -934,7 +928,7 @@ _rrd_update(const char *filename, const 
 			 }
 		  }
 
-	      rra_current = ftell(rrd_file); 
+	      rra_current = rrd_tell(rrd_file);
 		} /* if cf is DEVSEASONAL or SEASONAL */
 
         if (rrd_test_error()) break;
@@ -1169,7 +1163,7 @@ _rrd_update(const char *filename, const 
 		         lookup_seasonal(&rrd,i,rra_start,rrd_file,
 				    elapsed_pdp_st + (scratch_idx == CDP_primary_val ? 1 : 2),
 			        &seasonal_coef);
-                 rra_current = ftell(rrd_file);
+                 rra_current = rrd_tell(rrd_file);
 			  }
 			  if (rrd_test_error()) break;
 		      /* loop over data soures within each RRA */
@@ -1200,7 +1194,7 @@ _rrd_update(const char *filename, const 
 
 		/* write the first row */
 #ifdef DEBUG
-        fprintf(stderr,"  -- RRA Preseek %ld\n",ftell(rrd_file));
+        fprintf(stderr,"  -- RRA Preseek %ld\n",rrd_file->pos);
 #endif
 	    rrd.rra_ptr[i].cur_row++;
 	    if (rrd.rra_ptr[i].cur_row >= rrd.rra_def[i].row_cnt)
@@ -1210,7 +1204,7 @@ _rrd_update(const char *filename, const 
 		   (rrd.stat_head->ds_cnt)*(rrd.rra_ptr[i].cur_row)*sizeof(rrd_value_t);
 		if(rra_pos_tmp != rra_current) {
 #ifndef HAVE_MMAP
-		   if(fseek(rrd_file, rra_pos_tmp, SEEK_SET) != 0){
+		   if(rrd_seek(rrd_file, rra_pos_tmp, SEEK_SET) != 0){
 		      rrd_set_error("seek error in rrd");
 		      break;
 		   }
@@ -1219,7 +1213,7 @@ _rrd_update(const char *filename, const 
 		}
 
 #ifdef DEBUG
-	    fprintf(stderr,"  -- RRA Postseek %ld\n",ftell(rrd_file));
+	    fprintf(stderr,"  -- RRA Postseek %ld\n",rrd_file->pos);
 #endif
 		scratch_idx = CDP_primary_val;
 		if (pcdp_summary != NULL)
@@ -1229,10 +1223,10 @@ _rrd_update(const char *filename, const 
 		   - ((rra_step_cnt[i]-1)*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step);
 		}
 #ifdef HAVE_MMAP
-		pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, 
-		   pcdp_summary, &rra_time, rrd_mmaped_file);
+		pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd, 
+		   pcdp_summary, &rra_time, rrd_file->file_start);
 #else
-		pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, 
+		pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd, 
 		   pcdp_summary, &rra_time);
 #endif
 		if (rrd_test_error()) break;
@@ -1250,13 +1244,13 @@ _rrd_update(const char *filename, const 
 			  /* wrap */
 			  rrd.rra_ptr[i].cur_row = 0;
 			  /* seek back to beginning of current rra */
-		      if (fseek(rrd_file, rra_start, SEEK_SET) != 0)
+		      if (rrd_seek(rrd_file, rra_start, SEEK_SET) != 0)
 			  {
 		         rrd_set_error("seek error in rrd");
 		         break;
 			  }
 #ifdef DEBUG
-	          fprintf(stderr,"  -- Wraparound Postseek %ld\n",ftell(rrd_file));
+	          fprintf(stderr,"  -- Wraparound Postseek %ld\n",rrd_file->pos);
 #endif
 			  rra_current = rra_start;
 		   }
@@ -1267,10 +1261,10 @@ _rrd_update(const char *filename, const 
 		      - ((rra_step_cnt[i]-2)*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step);
 		   }
 #ifdef HAVE_MMAP
-		   pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file,
-		      pcdp_summary, &rra_time, rrd_mmaped_file);
+		   pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd,
+		      pcdp_summary, &rra_time, rrd_file->file_start);
 #else
-		   pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file,
+		   pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file->fd,
 		      pcdp_summary, &rra_time);
 #endif
 		}
@@ -1297,7 +1291,7 @@ _rrd_update(const char *filename, const 
     rpnstack_free(&rpnstack);
 
 #ifdef HAVE_MMAP
-    if (munmap(rrd_mmaped_file, rrd_filesize) == -1) {
+    if (munmap(rrd_file->file_start, rrd_file->file_len) == -1) {
             rrd_set_error("error writing(unmapping) file: %s", filename);
     }
 #endif    
@@ -1309,14 +1303,14 @@ _rrd_update(const char *filename, const 
 	rrd_free(&rrd);
 	free(pdp_temp);
 	free(pdp_new);
-	fclose(rrd_file);
+	close(rrd_file->fd);
 	return(-1);
     }
 
     /* aargh ... that was tough ... so many loops ... anyway, its done.
      * we just need to write back the live header portion now*/
 
-    if (fseek(rrd_file, (sizeof(stat_head_t)
+    if (rrd_seek(rrd_file, (sizeof(stat_head_t)
 			 + sizeof(ds_def_t)*rrd.stat_head->ds_cnt 
 			 + sizeof(rra_def_t)*rrd.stat_head->rra_cnt),
 	      SEEK_SET) != 0) {
@@ -1326,76 +1320,75 @@ _rrd_update(const char *filename, const 
 	rrd_free(&rrd);
 	free(pdp_temp);
 	free(pdp_new);
-	fclose(rrd_file);
+	close(rrd_file->fd);
 	return(-1);
     }
 
     if(version >= 3) {
-	    if(fwrite( rrd.live_head,
-		       sizeof(live_head_t), 1, rrd_file) != 1){
-		rrd_set_error("fwrite live_head to rrd");
+	    if(rrd_write(rrd_file, rrd.live_head,
+		       sizeof(live_head_t)*1) != sizeof(live_head_t)*1){
+		rrd_set_error("rrd_write live_head to rrd");
 		free(updvals);
 		rrd_free(&rrd);
 		free(tmpl_idx);
 		free(pdp_temp);
 		free(pdp_new);
-		fclose(rrd_file);
+		close(rrd_file->fd);
 		return(-1);
 	    }
     }
     else {
-	    if(fwrite( &rrd.live_head->last_up,
-		       sizeof(time_t), 1, rrd_file) != 1){
-		rrd_set_error("fwrite live_head to rrd");
+	    if(rrd_write(rrd_file, &rrd.live_head->last_up,
+		       sizeof(time_t)*1) != sizeof(time_t)*1){
+		rrd_set_error("rrd_write live_head to rrd");
 		free(updvals);
 		rrd_free(&rrd);
 		free(tmpl_idx);
 		free(pdp_temp);
 		free(pdp_new);
-		fclose(rrd_file);
+		close(rrd_file->fd);
 		return(-1);
 	    }
     }
 	    
 
-    if(fwrite( rrd.pdp_prep,
-	       sizeof(pdp_prep_t),
-	       rrd.stat_head->ds_cnt, rrd_file) != rrd.stat_head->ds_cnt){
-	rrd_set_error("ftwrite pdp_prep to rrd");
+    if(rrd_write(rrd_file, rrd.pdp_prep,
+	       sizeof(pdp_prep_t)*rrd.stat_head->ds_cnt)
+	    != (ssize_t)(sizeof(pdp_prep_t)*rrd.stat_head->ds_cnt)){
+	rrd_set_error("rrd_write pdp_prep to rrd");
 	free(updvals);
 	rrd_free(&rrd);
 	free(tmpl_idx);
 	free(pdp_temp);
 	free(pdp_new);
-	fclose(rrd_file);
+	close(rrd_file->fd);
 	return(-1);
     }
 
-    if(fwrite( rrd.cdp_prep,
-	       sizeof(cdp_prep_t),
-	       rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt, rrd_file) 
-       != rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt){
+    if(rrd_write(rrd_file, rrd.cdp_prep,
+	       sizeof(cdp_prep_t)*rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt)
+       != (ssize_t)(sizeof(cdp_prep_t)*rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt)){
 
-	rrd_set_error("ftwrite cdp_prep to rrd");
+	rrd_set_error("rrd_write cdp_prep to rrd");
 	free(updvals);
 	free(tmpl_idx);
 	rrd_free(&rrd);
 	free(pdp_temp);
 	free(pdp_new);
-	fclose(rrd_file);
+	close(rrd_file->fd);
 	return(-1);
     }
 
-    if(fwrite( rrd.rra_ptr,
-	       sizeof(rra_ptr_t), 
-	       rrd.stat_head->rra_cnt,rrd_file) != rrd.stat_head->rra_cnt){
-	rrd_set_error("fwrite rra_ptr to rrd");
+    if(rrd_write(rrd_file, rrd.rra_ptr,
+	       sizeof(rra_ptr_t)* rrd.stat_head->rra_cnt)
+	    != (ssize_t)(sizeof(rra_ptr_t)*rrd.stat_head->rra_cnt)){
+	rrd_set_error("rrd_write rra_ptr to rrd");
 	free(updvals);
 	free(tmpl_idx);
 	rrd_free(&rrd);
 	free(pdp_temp);
 	free(pdp_new);
-	fclose(rrd_file);
+	close(rrd_file->fd);
 	return(-1);
     }
 #ifdef HAVE_POSIX_FADVISE
@@ -1405,23 +1398,13 @@ _rrd_update(const char *filename, const 
        will let the data off the hook as soon as it is written when if it is from a previous
        update cycle. Calling fdsync to force things is much too hard here. */
 
-    if (0 != posix_fadvise(fileno(rrd_file), rra_begin, 0, POSIX_FADV_DONTNEED)) {
+    if (0 != posix_fadvise(rrd_file->fd, rra_begin, 0, POSIX_FADV_DONTNEED)) {
          rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno));
-         fclose(rrd_file);
+         close(rrd_file->fd);
          return(-1);
     } 
 #endif
-
-    /* OK now close the files and free the memory */
-    if(fclose(rrd_file) != 0){
-	rrd_set_error("closing rrd");
-	free(updvals);
-	free(tmpl_idx);
-	rrd_free(&rrd);
-	free(pdp_temp);
-	free(pdp_new);
-	return(-1);
-    }
+    /*XXX: ? */rrd_flush(rrd_file);
 
     /* calling the smoothing code here guarantees at most
  	 * one smoothing operation per rrd_update call. Unfortunately,
@@ -1430,7 +1413,7 @@ _rrd_update(const char *filename, const 
 	 * critical except during the burning cycles. */
 	if (schedule_smooth)
 	{
-	  rrd_file = fopen(filename,"rb+");
+//	  in_file = fopen(filename,"rb+");
           
 
 	  rra_start = rra_begin;
@@ -1451,14 +1434,26 @@ _rrd_update(const char *filename, const 
 	  }
 #ifdef HAVE_POSIX_FADVISE
           /* same procedure as above ... */
-          if (0 != posix_fadvise(fileno(rrd_file), rra_begin, 0, POSIX_FADV_DONTNEED)) {
+          if (0 != posix_fadvise(rrd_file->fd, rra_begin, 0, POSIX_FADV_DONTNEED)) {
              rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s",filename, rrd_strerror(errno));
-             fclose(rrd_file);
+             close(rrd_file->fd);
              return(-1);
           } 
 #endif
-	  fclose(rrd_file);
+	  close(rrd_file->fd);
 	}
+
+    /* OK now close the files and free the memory */
+    if(close(rrd_file->fd) != 0){
+	rrd_set_error("closing rrd");
+	free(updvals);
+	free(tmpl_idx);
+	rrd_free(&rrd);
+	free(pdp_temp);
+	free(pdp_new);
+	return(-1);
+    }
+
     rrd_free(&rrd);
     free(updvals);
     free(tmpl_idx);
@@ -1474,19 +1469,16 @@ _rrd_update(const char *filename, const 
  * returns 0 on success
  */
 int
-LockRRD(FILE *rrdfile)
+LockRRD(int in_file)
 {
-    int	rrd_fd;		/* File descriptor for RRD */
     int	rcstat;
 
-    rrd_fd = fileno(rrdfile);
-
 	{
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
     struct _stat st;
 
-    if ( _fstat( rrd_fd, &st ) == 0 ) {
-	    rcstat = _locking ( rrd_fd, _LK_NBLCK, st.st_size );
+    if ( _fstat( in_file, &st ) == 0 ) {
+	    rcstat = _locking ( in_file, _LK_NBLCK, st.st_size );
     } else {
 	    rcstat = -1;
     }
@@ -1497,7 +1489,7 @@ LockRRD(FILE *rrdfile)
     lock.l_start = 0;	      /* start of file */
     lock.l_whence = SEEK_SET;   /* end of file */
 
-    rcstat = fcntl(rrd_fd, F_SETLK, &lock);
+    rcstat = fcntl(in_file, F_SETLK, &lock);
 #endif
 	}
 
@@ -1510,15 +1502,15 @@ info_t
 *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current,
 	       unsigned short CDP_scratch_idx, 
 #ifndef DEBUG
-FILE UNUSED(*rrd_file),
+int UNUSED(in_file),
 #else
-FILE *rrd_file,
+int in_file,
 #endif
 		   info_t *pcdp_summary, time_t *rra_time, void *rrd_mmaped_file)
 #else
 info_t
 *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current,
-	       unsigned short CDP_scratch_idx, FILE *rrd_file,
+	       unsigned short CDP_scratch_idx, int in_file,
 		   info_t *pcdp_summary, time_t *rra_time)
 #endif
 {
@@ -1531,7 +1523,7 @@ info_t
       cdp_idx =rra_idx * (rrd -> stat_head->ds_cnt) + ds_idx;
 #ifdef DEBUG
 	  fprintf(stderr,"  -- RRA WRITE VALUE %e, at %ld CF:%s\n",
-	     rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val,ftell(rrd_file),
+	     rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val,rrd_file->pos,
 	     rrd -> rra_def[rra_idx].cf_nam);
 #endif 
       if (pcdp_summary != NULL)
@@ -1549,8 +1541,8 @@ info_t
 			  &(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val),
 			  sizeof(rrd_value_t));
 #else
-	  if(fwrite(&(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val),
-		 sizeof(rrd_value_t),1,rrd_file) != 1)
+	  if(rrd_write(rrd_file,&(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val),
+		 sizeof(rrd_value_t)*1) != sizeof(rrd_value_t)*1)
 	  { 
 	     rrd_set_error("writing rrd");
 	     return 0;
Index: src/rrd_tool.h
===================================================================
--- src/rrd_tool.h	(revision 1064)
+++ src/rrd_tool.h	(working copy)
@@ -171,11 +171,18 @@ void rrd_free(rrd_t *rrd);
 void rrd_freemem(void *mem);
 void rrd_init(rrd_t *rrd);
 
-int rrd_open(const char *file_name, FILE **in_file, rrd_t *rrd, int rdwr);
+rrd_file_t* rrd_open(const char * const file_name, rrd_t *rrd, unsigned rdwr);
+int rrd_close(rrd_file_t* rrd_file);
+ssize_t rrd_read(rrd_file_t* rrd_file, void*buf, size_t count);
+ssize_t rrd_write(rrd_file_t* rrd_file, const void*buf, size_t count);
+void rrd_flush(rrd_file_t* rrd_file);
+off_t rrd_seek(rrd_file_t* rrd_file, off_t off, int whence);
+off_t rrd_tell(rrd_file_t* rrd_file);
 int readfile(const char *file, char **buffer, int skipfirst);
 
 #define RRD_READONLY    0
 #define RRD_READWRITE   1
+#define RRD_CREAT       2
 
 enum cf_en cf_conv(const char *string);
 enum dst_en dst_conv(char *string);
Index: src/rrd_hw.h
===================================================================
--- src/rrd_hw.h	(revision 1064)
+++ src/rrd_hw.h	(working copy)
@@ -11,11 +11,11 @@ int update_aberrant_CF(rrd_t *rrd, rrd_v
 int create_hw_contingent_rras(rrd_t *rrd, unsigned short period, 
    unsigned long hashed_name);
 int lookup_seasonal(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start,
-   FILE *rrd_file, unsigned long offset, rrd_value_t **seasonal_coef);
+   rrd_file_t* rrd_file, unsigned long offset, rrd_value_t **seasonal_coef);
 void erase_violations(rrd_t *rrd, unsigned long cdp_idx, unsigned long rra_idx);
 int apply_smoother(rrd_t *rrd, unsigned long rra_idx, unsigned long rra_start,
-   FILE *rrd_file);
-void reset_aberrant_coefficients(rrd_t *rrd, FILE *rrd_file, unsigned long ds_idx);
+   rrd_file_t *rrd_file);
+void reset_aberrant_coefficients(rrd_t *rrd, rrd_file_t *rrd_file, unsigned long ds_idx);
 void init_hwpredict_cdp(cdp_prep_t *);
 void init_seasonal_cdp(cdp_prep_t *);
 #define BURNIN_CYCLES 3
Index: src/rrd.h
===================================================================
--- src/rrd.h	(revision 1064)
+++ src/rrd.h	(working copy)
@@ -52,6 +52,8 @@ extern "C" {
 #ifndef _RRDLIB_H
 #define _RRDLIB_H
 
+#include <sys/types.h> /* for off_t */
+#include <unistd.h> /* for off_t */
 #include <time.h>
 #include <stdio.h> /* for FILE */
 
@@ -60,6 +62,15 @@ typedef double       rrd_value_t;       
                                            * double */
 /* END rrd_format.h */
 
+/* information about an rrd file */
+typedef struct rrd_file_t {
+	int   fd;         /* file descriptor if this rrd file */
+	char* file_start; /* start address of an open rrd file */
+	off_t header_len; /* length of the header of this rrd file */
+	off_t file_len;   /* total size of the rrd file */
+	off_t pos;        /* current pos in file */
+} rrd_file_t;
+
 /* main function blocks */
 int    rrd_create(int, char **);
 int    rrd_update(int, char **);
@@ -143,7 +154,7 @@ void   rrd_free_context (struct rrd_cont
 /* int    rrd_test_error_r (struct rrd_context *); */
 /* char  *rrd_get_error_r  (struct rrd_context *); */
 
-int  LockRRD(FILE *);
+int  LockRRD(int in_file);
 
 #endif /* _RRDLIB_H */
 
Index: src/rrd_open.c
===================================================================
--- src/rrd_open.c	(revision 1064)
+++ src/rrd_open.c	(working copy)
@@ -63,39 +63,62 @@
  *****************************************************************************/
 
 #include "rrd_tool.h"
+#include "unused.h"
 #define MEMBLK 8192
 
 /* open a database file, return its header and a open filehandle */
 /* positioned to the first cdp in the first rra */
 
-int
-rrd_open(const char *file_name, FILE **in_file, rrd_t *rrd, int rdwr)    
+rrd_file_t*
+rrd_open(const char * const file_name, rrd_t *rrd, unsigned rdwr)
 {
+	int flags = 0;
+	mode_t mode = S_IRUSR;
+	int version, prot = PROT_READ;
+	off_t offset = 0;
+	char *data;
+	struct stat statb;
+	rrd_file_t *rrd_file = malloc(sizeof(rrd_file_t));
+	if (rrd_file == NULL) {
+		rrd_set_error("allocating rrd_file descriptor for '%s'",
+			file_name);
+		return NULL;
+	}
+	memset(rrd_file, 0, sizeof(rrd_file_t));
+	rrd_init(rrd);
+	if (rdwr == RRD_READWRITE) {
+		mode |= S_IWUSR;
+		prot |= PROT_WRITE;
+	} else if (rdwr == RRD_CREAT) {
+		mode |= S_IWUSR;
+		prot |= PROT_WRITE;
+		flags |= (O_CREAT|O_TRUNC);
+	}
+#ifdef O_NONBLOCK
+	flags |= O_NONBLOCK;
+#endif
 
-    
-    char *mode = NULL;
-    int version;
-    
-    rrd_init(rrd);
-    if (rdwr == RRD_READONLY) {
-        mode = "rb";
-    } else {
-        mode = "rb+";
-    }
-    
-    if (((*in_file) = fopen(file_name,mode)) == NULL ){
-        rrd_set_error("opening '%s': %s",file_name, rrd_strerror(errno));
-        return (-1);
-    }
+	if ((rrd_file->fd = open(file_name, flags, mode)) < 0 ){
+		rrd_set_error("opening '%s': %s",file_name, rrd_strerror(errno));
+		return NULL;
+	}
+
+	/* ???: length = lseek(rrd_file->fd, 0, SEEK_END); */
+	/* ??? locking the whole area of the file may overdo it a bit, does it? */
+	if ((fstat(rrd_file->fd, &statb)) < 0) {
+		rrd_set_error("fstat '%s': %s",file_name, rrd_strerror(errno));
+		goto out_close;
+	}
+	rrd_file->file_len = statb.st_size;
 
 #ifdef HAVE_POSIX_FADVISE
     /* In general we need no read-ahead when dealing with rrd_files.
        When we stop reading, it is highly unlikely that we start up again.
        In this manner we actually save time and diskaccess (and buffer cache).
        Thanks to Dave Plonka for the Idea of using POSIX_FADV_RANDOM here. */       
-    if (0 != posix_fadvise(fileno(*in_file), 0, 0, POSIX_FADV_RANDOM)) {
+    if (0 != posix_fadvise(rrd_file->fd, 0, 0, POSIX_FADV_RANDOM)) {
         rrd_set_error("setting POSIX_FADV_RANDOM on '%s': %s",file_name, rrd_strerror(errno));
-        fclose(*in_file);
+        close(fd);
         return(-1);
      }    
 #endif
@@ -103,78 +126,188 @@ rrd_open(const char *file_name, FILE **i
 /*
         if (rdwr == RRD_READWRITE)
         {
-           if (setvbuf((*in_file),NULL,_IONBF,2)) {
+           if (setvbuf((rrd_file->fd),NULL,_IONBF,2)) {
                   rrd_set_error("failed to disable the stream buffer\n");
                   return (-1);
            }
         }
 */
-    
-#define MYFREAD(MYVAR,MYVART,MYCNT) \
-    if ((MYVAR = malloc(sizeof(MYVART) * MYCNT)) == NULL) {\
-        rrd_set_error("" #MYVAR " malloc"); \
-        fclose(*in_file); \
-        return (-1); } \
-    fread(MYVAR,sizeof(MYVART),MYCNT, *in_file); 
+	data = mmap(0, rrd_file->file_len, prot, MAP_SHARED,
+		rrd_file->fd, offset);
 
+	/* lets see if the first read worked */
+	if (data == MAP_FAILED) {
+		rrd_set_error("error mmaping file '%s'",file_name);
+		goto out_close;
+	}
+	rrd_file->file_start = data;
+#ifdef HAVE_MADVISE
+	if (rrd == NULL) { /*XXX: currently not used! */
+		/* We will read everything in a moment (copying) */
+		madvise(data, rrd_file->file_len, MADV_WILLNEED|MADV_SEQUENTIAL);
+		goto out_done;
+	}
+	/* We do not need to read anything in for the moment */
+	madvise(data, rrd_file->file_len, MADV_DONTNEED);
+#endif
 
-    MYFREAD(rrd->stat_head, stat_head_t,  1)
-    /* lets see if the first read worked */
-    if (ferror( *in_file ) || feof(*in_file)) {
-        rrd_set_error("reading the cookie off %s faild",file_name);
-        fclose(*in_file);
-        return(-1);
-    }        
+#ifdef HAVE_MADVISE
+	/* the stat_head will be needed soonish, so hint accordingly */
+	madvise(data+offset, sizeof(stat_head_t), MADV_WILLNEED);
+#endif
+
+	rrd->stat_head = (stat_head_t*)(data + offset);
+	offset += sizeof(stat_head_t);
 
         /* lets do some test if we are on track ... */
-        if (strncmp(rrd->stat_head->cookie,RRD_COOKIE,4) != 0){
-            rrd_set_error("'%s' is not an RRD file",file_name);
-            free(rrd->stat_head);
-            rrd->stat_head = NULL; 
-            fclose(*in_file);
-            return(-1);}
-
-        if (rrd->stat_head->float_cookie != FLOAT_COOKIE){
-            rrd_set_error("This RRD was created on other architecture");
-            free(rrd->stat_head);
-            rrd->stat_head = NULL; 
-            fclose(*in_file);
-            return(-1);}
+	if (memcmp(rrd->stat_head->cookie,RRD_COOKIE,sizeof(RRD_COOKIE)) != 0) {
+		rrd_set_error("'%s' is not an RRD file",file_name);
+		goto out_nullify_head;
+	}
+
+	if (rrd->stat_head->float_cookie != FLOAT_COOKIE){
+		rrd_set_error("This RRD was created on other architecture");
+		goto out_nullify_head;
+	}
 
-    version = atoi(rrd->stat_head->version);
+	version = atoi(rrd->stat_head->version);
 
-        if (version > atoi(RRD_VERSION)){
+	if (version > atoi(RRD_VERSION)) {
             rrd_set_error("can't handle RRD file version %s",
                         rrd->stat_head->version);
-            free(rrd->stat_head);
-            rrd->stat_head = NULL; 
-            fclose(*in_file);
-            return(-1);}
+            goto out_nullify_head;
+	}
 
+#ifdef HAVE_MADVISE
+	/* the ds_def will be needed soonish, so hint accordingly */
+	madvise(data+offset, sizeof(ds_def_t)*rrd->stat_head->ds_cnt, MADV_WILLNEED);
+#endif
+	rrd->ds_def = (ds_def_t*)(data + offset);
+	offset += sizeof(ds_def_t) * rrd->stat_head->ds_cnt;
+
+#ifdef HAVE_MADVISE
+	/* the rra_def will be needed soonish, so hint accordingly */
+	madvise(data+offset, sizeof(rra_def_t)*rrd->stat_head->rra_cnt, MADV_WILLNEED);
+#endif
+	rrd->rra_def = (rra_def_t*)(data + offset);
+	offset += sizeof(rra_def_t) * rrd->stat_head->rra_cnt;
 
-    MYFREAD(rrd->ds_def,    ds_def_t,     rrd->stat_head->ds_cnt)
-    MYFREAD(rrd->rra_def,   rra_def_t,    rrd->stat_head->rra_cnt)
     /* handle different format for the live_head */
-    if(version < 3) {
+	if (version < 3) {
             rrd->live_head = (live_head_t *)malloc(sizeof(live_head_t));
-            if(rrd->live_head == NULL) {
+            if (rrd->live_head == NULL) {
                 rrd_set_error("live_head_t malloc");
-                fclose(*in_file); 
-                return (-1);
+                goto out_close;
             }
-                fread(&rrd->live_head->last_up, sizeof(long), 1, *in_file); 
-                rrd->live_head->last_up_usec = 0;
-    }
-    else {
-            MYFREAD(rrd->live_head, live_head_t, 1)
-    }
-    MYFREAD(rrd->pdp_prep,  pdp_prep_t,   rrd->stat_head->ds_cnt)
-    MYFREAD(rrd->cdp_prep,  cdp_prep_t,   (rrd->stat_head->rra_cnt
-                                             * rrd->stat_head->ds_cnt))
-    MYFREAD(rrd->rra_ptr,   rra_ptr_t,    rrd->stat_head->rra_cnt)
-#undef MYFREAD
+		memmove(&rrd->live_head->last_up, data+offset, sizeof(long));
+		rrd->live_head->last_up_usec = 0;
+	} else {
+#ifdef HAVE_MADVISE
+		/* the live_head will be needed soonish, so hint accordingly */
+		madvise(data+offset, sizeof(live_head_t), MADV_WILLNEED);
+#endif
+		rrd->live_head = (live_head_t*)(data + offset);
+		offset += sizeof(live_head_t);
+	}
+// This doesn't look like it needs madvise
+	rrd->pdp_prep = (pdp_prep_t*)(data + offset);
+	offset += sizeof(pdp_prep_t) * rrd->stat_head->ds_cnt;
+
+// This could benefit from madvise()ing
+	rrd->cdp_prep = (cdp_prep_t*)(data + offset);
+	offset += sizeof(cdp_prep_t) *
+				(rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt);
+
+// This could benefit from madvise()ing
+	rrd->rra_ptr = (rra_ptr_t*)(data + offset);
+	offset += sizeof(rra_ptr_t) * rrd->stat_head->rra_cnt;
+out_done:
+	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
+}
 
-    return(0);
+/* Get position of 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));
+	}
 }
 
 void rrd_init(rrd_t *rrd)
@@ -189,24 +322,26 @@ void rrd_init(rrd_t *rrd)
     rrd->rrd_value = NULL;
 }
 
-void rrd_free(rrd_t *rrd)
+void rrd_free(rrd_t UNUSED(*rrd))
 {
-    if (rrd->stat_head) free(rrd->stat_head);
-    if (rrd->ds_def) free(rrd->ds_def);
-    if (rrd->rra_def) free(rrd->rra_def);
-    if (rrd->live_head) free(rrd->live_head);
-    if (rrd->rra_ptr) free(rrd->rra_ptr);
-    if (rrd->pdp_prep) free(rrd->pdp_prep);
-    if (rrd->cdp_prep) free(rrd->cdp_prep);
-    if (rrd->rrd_value) free(rrd->rrd_value);
+#ifndef HAVE_MMAP
+    if (atoi(rrd->stat_head->version) < 3)
+	    free(rrd->live_head);
+    free(rrd->stat_head);
+    free(rrd->ds_def);
+    free(rrd->rra_def);
+    free(rrd->rra_ptr);
+    free(rrd->pdp_prep);
+    free(rrd->cdp_prep);
+    free(rrd->rrd_value);
+#endif
 }
 
 /* routine used by external libraries to free memory allocated by
  * rrd library */
 void rrd_freemem(void *mem)
 {
-
-    if (mem) free(mem);
+	free(mem);
 }
 
 int readfile(const char *file_name, char **buffer, int skipfirst){
@@ -251,4 +386,3 @@ int readfile(const char *file_name, char
     return writecnt;
 }
 
-
Index: src/rrd_stat.c
===================================================================
--- src/rrd_stat.c	(revision 1064)
+++ src/rrd_stat.c	(working copy)
@@ -6,6 +6,8 @@
 
 #include "rrd_tool.h"
 
+XXX: This file is not compiled. Is this on purpose?
+
 extern char *tzname[2];
 
 stat_node
@@ -16,11 +18,12 @@ rrd_stat(int argc, char **argv)    
     char         somestring[255];
     rrd_value_t  my_cdp;
     long         rra_base, rra_start, rra_next;
-    FILE                  *in_file;
     rrd_t             rrd;
+    rrd_file_t  *rrd_file;
 
 
-    if(rrd_open(argv[1],&in_file,&rrd, RRD_READONLY)==-1){
+    rrd_file = rrd_open(argv[1],&rrd, RRD_READONLY);
+    if (rrd_file == NULL) {
 	return(-1);
     }
     puts("<!-- Round Robin Database Dump -->");
@@ -66,7 +69,7 @@ rrd_stat(int argc, char **argv)    
 
     puts("<!-- Round Robin Archives -->");
 
-    rra_base=ftell(in_file);    
+    rra_base = rrd_file->header_len;
     rra_next = rra_base;
 
     for(i=0;i<rrd.stat_head->rra_cnt;i++){
@@ -97,7 +100,7 @@ rrd_stat(int argc, char **argv)    
 	printf("\t\t</cdp_prep>\n");
 
 	printf("\t\t<database>\n");
-	fseek(in_file,(rra_start
+	rrd_seek(rrd_file,(rra_start
 		       +(rrd.rra_ptr[i].cur_row+1)
 		       * rrd.stat_head->ds_cnt
 		       * sizeof(rrd_value_t)),SEEK_SET);
@@ -106,7 +109,7 @@ rrd_stat(int argc, char **argv)    
 	for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){	    
 	    ii++;
 	    if (ii>=rrd.rra_def[i].row_cnt) {
-		fseek(in_file,rra_start,SEEK_SET);
+		rrd_seek(rrd_file,rra_start,SEEK_SET);
 		ii=0; /* wrap if max row cnt is reached */
 	    }
 	    now = (rrd.live_head->last_up 
@@ -122,7 +125,7 @@ rrd_stat(int argc, char **argv)    
 #endif
 	    printf("\t\t\t<!-- %s --> <row>",somestring);
 	    for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){			 
-		fread(&my_cdp,sizeof(rrd_value_t),1,in_file);		
+		rrd_read(rrd_file,&my_cdp,sizeof(rrd_value_t)*1);
 		if (isnan(my_cdp)){
 		  printf("<v> NaN </v>");
 		} else {
@@ -136,7 +139,7 @@ rrd_stat(int argc, char **argv)    
     }
     printf("</rrd>\n");
     rrd_free(&rrd);
-    fclose(in_file);
+    close(rrd_file->fd);
     return(0);
 }
 
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 1064)
+++ src/Makefile.am	(working copy)
@@ -30,22 +30,22 @@ RRD_C_FILES =		\
 	hash_32.c	\
 	pngsize.c	\
 	rrd_create.c	\
-	rrd_dump.c	\
-	rrd_fetch.c	\
 	rrd_graph.c	\
 	rrd_graph_helper.c	\
+	rrd_version.c	\
 	rrd_last.c	\
 	rrd_lastupdate.c	\
 	rrd_first.c	\
-	rrd_resize.c	\
 	rrd_restore.c	\
-	rrd_tune.c	\
-	rrd_version.c	\
 	rrd_xport.c	\
         art_rgba_svp.c \
 	rrd_gfx.c \
 	rrd_afm.c rrd_afm_data.c \
-	rrd_tool.c
+	rrd_dump.c	\
+	rrd_fetch.c	\
+	rrd_tool.c	\
+	rrd_resize.c \
+	rrd_tune.c
 
 noinst_HEADERS = \
         art_rgba_svp.h \
Index: configure.ac
===================================================================
--- configure.ac	(revision 1064)
+++ configure.ac	(working copy)
@@ -70,10 +70,21 @@ char *strchr (), *strrchr ();
 # endif
 #endif
 
+#if defined(HAVE_OPEN)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
+#if defined(HAVE_MADVISE)
+#include <sys/mman.h>
+#endif
+
 /* enable posix_fadvise on linux */
 #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_FCNTL_H)
-#include <fcntl.h>
+#error no need for fadvise here..
 #define __USE_XOPEN2K 1
+#include <fcntl.h>
 #endif
 
 #ifdef NO_NULL_REALLOC
@@ -248,7 +259,7 @@ AC_C_BIGENDIAN
 dnl for each function found we get a definition in config.h 
 dnl of the form HAVE_FUNCTION
 
-AC_CHECK_FUNCS(tzset mbstowcs opendir readdir chdir chroot getuid setlocale strerror strerror_r snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday posix_fadvise)
+AC_CHECK_FUNCS(tzset mbstowcs opendir readdir chdir chroot getuid setlocale strerror strerror_r snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday open close madvise)
 
 
 if test "x$enable_mmap" = xyes; then
