]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_mmap.c
6a04944b9e3f782eef2b9ed6606fecab47ee79f8
[netatalk.git] / libatalk / adouble / ad_mmap.c
1 /*
2  * $Id: ad_mmap.c,v 1.4 2002-10-05 13:20:14 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 #include <sys/types.h>
17 #include <sys/stat.h>
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif /* HAVE_UNISTD_H */
21 #ifdef HAVE_FCNTL_H
22 #include <fcntl.h>
23 #endif /* HAVE_FCNTL_H */
24 #include <string.h>
25
26 #include <atalk/adouble.h>
27
28 #include "ad_private.h"
29
30 static __inline__ void *ad_mmap(const size_t length, const int prot,
31                                 const int flags, const int fd, 
32                                 const off_t offset)
33 {
34   return mmap(0, length, prot, flags, fd, offset);
35 }
36
37 /* this just sets things up for mmap. as mmap can handle offsets,
38  * we need to reset the file position before handing it off */
39 void *ad_mmapread(struct adouble *ad, const u_int32_t eid, 
40                   const off_t off, const size_t buflen)
41 {
42     /* data fork */
43     if ( eid == ADEID_DFORK ) {
44       if ( lseek( ad->ad_df.adf_fd, 0, SEEK_SET ) < 0 ) {
45         perror( "df lseek" );
46         return (void *) -1;
47       }
48       ad->ad_df.adf_off = 0;
49       return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, 
50                      ad->ad_df.adf_fd, off);
51
52     }
53
54     /* resource fork */
55     if ( lseek( ad->ad_hf.adf_fd, 0, SEEK_SET ) < 0 ) {
56       perror( "hf lseek" );
57       return (void *) -1;
58     }
59     ad->ad_hf.adf_off = 0;
60     return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, 
61                    ad->ad_hf.adf_fd, ad->ad_eid[eid].ade_off + off);
62 }
63
64
65 /* to do writeable mmaps correctly, we actually need to make sure that
66  * the file to be mapped is large enough. that's what all the initial
67  * mess is for. */
68 void *ad_mmapwrite(struct adouble *ad, const u_int32_t eid,
69                    off_t off, const int end, const size_t buflen)
70 {
71     struct stat st;
72
73     /* data fork */
74     if ( eid == ADEID_DFORK ) {
75         if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) {
76             return (void *) -1;
77         }
78
79         if ( end ) {
80             off = st.st_size - off;
81         }
82
83         /* make sure the file is large enough */
84         if (st.st_size < buflen + off) 
85           ftruncate(ad->ad_df.adf_fd, buflen + off);
86
87         if ( lseek( ad->ad_df.adf_fd, 0, SEEK_SET ) < 0 ) {
88           return (void *) -1;
89         }
90         ad->ad_df.adf_off = 0;
91         return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_SHARED,
92                        ad->ad_df.adf_fd, off);
93     }
94
95     
96     if ( fstat( ad->ad_hf.adf_fd, &st ) < 0 ) {
97         return (void *) -1;
98     }
99     
100     if ( end ) {
101         off = ad->ad_eid[ eid ].ade_len - off;
102     }
103     
104     off += ad->ad_eid[eid].ade_off;
105
106     /* make sure the file is large enough */
107     if (st.st_size < buflen + off) 
108       ftruncate(ad->ad_hf.adf_fd, buflen + off);
109
110     if ( lseek( ad->ad_hf.adf_fd, 0, SEEK_SET ) < 0 ) {
111       return (void *) -1;
112     }
113     ad->ad_hf.adf_off = 0;
114     return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_SHARED,
115                    ad->ad_hf.adf_fd, off);
116 }
117
118 #endif