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