1/* 2 * $Id: ad_mmap.c,v 1.6 2008-12-03 18:35:44 didg Exp $ 3 * 4 * ad_mmap provides interfaces to memory mapped files. as this is the 5 * case, we don't have to deal w/ temporary buffers such as 6 * ad_data. the ad_mmap routines are designed to not interact w/ the 7 * ad_read/ad_write routines to avoid confusion. 8 */ 9 10#ifdef HAVE_CONFIG_H 11#include "config.h" 12#endif /* HAVE_CONFIG_H */ 13 14#ifdef USE_MMAPPED_HEADERS 15#include <stdio.h> 16 17#include <atalk/adouble.h> 18#include <string.h> 19 20#include "ad_private.h" 21 22static void *ad_mmap(const size_t length, const int prot, 23 const int flags, const int fd, 24 const off_t offset) 25{ 26 return mmap(0, length, prot, flags, fd, offset); 27} 28 29/* this just sets things up for mmap. as mmap can handle offsets, 30 * we need to reset the file position before handing it off */ 31void *ad_mmapread(struct adouble *ad, const u_int32_t eid, 32 const off_t off, const size_t buflen) 33{ 34 /* data fork */ 35 if ( eid == ADEID_DFORK ) { 36 if ( lseek( ad->ad_df.adf_fd, 0, SEEK_SET ) < 0 ) { 37 perror( "df lseek" ); 38 return (void *) -1; 39 } 40 ad->ad_df.adf_off = 0; 41 return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, 42 ad->ad_df.adf_fd, off); 43 44 } 45 46 /* resource fork */ 47 if ( lseek( ad->ad_hf.adf_fd, 0, SEEK_SET ) < 0 ) { 48 perror( "hf lseek" ); 49 return (void *) -1; 50 } 51 ad->ad_hf.adf_off = 0; 52 return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, 53 ad->ad_hf.adf_fd, ad->ad_eid[eid].ade_off + off); 54} 55 56 57/* to do writeable mmaps correctly, we actually need to make sure that 58 * the file to be mapped is large enough. that's what all the initial 59 * mess is for. */ 60void *ad_mmapwrite(struct adouble *ad, const u_int32_t eid, 61 off_t off, const int end, const size_t buflen) 62{ 63 struct stat st; 64 65 /* data fork */ 66 if ( eid == ADEID_DFORK ) { 67 if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) { 68 return (void *) -1; 69 } 70 71 if ( end ) { 72 off = st.st_size - off; 73 } 74 75 /* make sure the file is large enough */ 76 if (st.st_size < buflen + off) 77 ftruncate(ad->ad_df.adf_fd, buflen + off); 78 79 if ( lseek( ad->ad_df.adf_fd, 0, SEEK_SET ) < 0 ) { 80 return (void *) -1; 81 } 82 ad->ad_df.adf_off = 0; 83 return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_SHARED, 84 ad->ad_df.adf_fd, off); 85 } 86 87 88 if ( fstat( ad->ad_hf.adf_fd, &st ) < 0 ) { 89 return (void *) -1; 90 } 91 92 if ( end ) { 93 off = ad->ad_eid[ eid ].ade_len - off; 94 } 95 96 off += ad->ad_eid[eid].ade_off; 97 98 /* make sure the file is large enough */ 99 if (st.st_size < buflen + off) 100 ftruncate(ad->ad_hf.adf_fd, buflen + off); 101 102 if ( lseek( ad->ad_hf.adf_fd, 0, SEEK_SET ) < 0 ) { 103 return (void *) -1; 104 } 105 ad->ad_hf.adf_off = 0; 106 return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_SHARED, 107 ad->ad_hf.adf_fd, off); 108} 109 110#endif 111