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