]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_read.c
b286f5561bd97a100d71d9733c473fcc24209364
[netatalk.git] / libatalk / adouble / ad_read.c
1 /*
2  * Copyright (c) 1990,1991 Regents of The University of Michigan.
3  * All Rights Reserved.
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both that copyright notice and this permission notice appear
9  * in supporting documentation, and that the name of The University
10  * of Michigan not be used in advertising or publicity pertaining to
11  * distribution of the software without specific, written prior
12  * permission. This software is supplied as is without expressed or
13  * implied warranties of any kind.
14  *
15  *      Research Systems Unix Group
16  *      The University of Michigan
17  *      c/o Mike Clark
18  *      535 W. William Street
19  *      Ann Arbor, Michigan
20  *      +1-313-763-0525
21  *      netatalk@itd.umich.edu
22  */
23
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <atalk/adouble.h>
28 #include <unistd.h>
29
30 #ifndef MIN
31 #define MIN(a,b)        ((a)<(b)?(a):(b))
32 #endif
33
34 /* XXX: this would probably benefit from pread. 
35  *      locks have to be checked before each stream of consecutive 
36  *      ad_reads to prevent a denial in the middle from causing
37  *      problems. */
38 ssize_t ad_read( ad, eid, off, buf, buflen)
39     struct adouble      *ad;
40     const u_int32_t     eid;
41     off_t               off;
42     char                *buf;
43     const size_t        buflen;
44 {
45     ssize_t             cc;
46
47     /* We're either reading the data fork (and thus the data file)
48      * or we're reading anything else (and thus the header file). */
49     if ( eid == ADEID_DFORK ) {
50         if ( ad->ad_df.adf_off != off ) {
51             if ( lseek( ad->ad_df.adf_fd, (off_t) off, SEEK_SET ) < 0 ) {
52                 return( -1 );
53             }
54             ad->ad_df.adf_off = off;
55         }
56         if (( cc = read( ad->ad_df.adf_fd, buf, buflen )) < 0 ) {
57             return( -1 );
58         }
59         ad->ad_df.adf_off += cc;
60     } else {
61         cc = ad->ad_eid[eid].ade_off + off;
62
63 #ifdef USE_MMAPPED_HEADERS
64         if (eid != ADEID_RFORK) {
65           memcpy(buf, ad->ad_data + cc, buflen);
66           cc = buflen;
67           goto ad_read_done;
68         }
69 #endif  
70         if ( ad->ad_hf.adf_off != cc ) {
71           if ( lseek( ad->ad_hf.adf_fd, (off_t) cc, SEEK_SET ) < 0 ) {
72               return( -1 );
73           }
74           ad->ad_hf.adf_off = cc;
75         }
76           
77         if (( cc = read( ad->ad_hf.adf_fd, buf, buflen )) < 0 ) {
78           return( -1 );
79         }
80           
81 #ifndef USE_MMAPPED_HEADERS
82         /*
83          * We've just read in bytes from the disk that we read earlier
84          * into ad_data. If we're going to write this buffer out later,
85          * we need to update ad_data.
86          */
87         if (ad->ad_hf.adf_off < ad_getentryoff(ad, ADEID_RFORK)) {
88             if ( ad->ad_hf.adf_flags & O_RDWR ) {
89               memcpy(buf, ad->ad_data + ad->ad_hf.adf_off,
90                      MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc));
91             } else {
92               memcpy(ad->ad_data + ad->ad_hf.adf_off, buf,
93                      MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc));
94             }
95         }
96         ad->ad_hf.adf_off += cc;
97 #else
98 ad_read_done:
99 #endif
100     }
101
102     return( cc );
103 }