]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_read.c
1fcda8a11dba36c1e9b823ac04773fc040ac9990
[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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <atalk/adouble.h>
32 #include <unistd.h>
33
34 #ifndef MIN
35 #define MIN(a,b)        ((a)<(b)?(a):(b))
36 #endif
37
38 /* XXX: this would probably benefit from pread. 
39  *      locks have to be checked before each stream of consecutive 
40  *      ad_reads to prevent a denial in the middle from causing
41  *      problems. */
42 ssize_t ad_read( ad, eid, off, buf, buflen)
43     struct adouble      *ad;
44     const u_int32_t     eid;
45     off_t               off;
46     char                *buf;
47     const size_t        buflen;
48 {
49     ssize_t             cc;
50
51     /* We're either reading the data fork (and thus the data file)
52      * or we're reading anything else (and thus the header file). */
53     if ( eid == ADEID_DFORK ) {
54         if ( ad->ad_df.adf_off != off ) {
55             if ( lseek( ad->ad_df.adf_fd, (off_t) off, SEEK_SET ) < 0 ) {
56                 return( -1 );
57             }
58             ad->ad_df.adf_off = off;
59         }
60         if (( cc = read( ad->ad_df.adf_fd, buf, buflen )) < 0 ) {
61             return( -1 );
62         }
63         ad->ad_df.adf_off += cc;
64     } else {
65         cc = ad->ad_eid[eid].ade_off + off;
66
67 #ifdef USE_MMAPPED_HEADERS
68         if (eid != ADEID_RFORK) {
69           memcpy(buf, ad->ad_data + cc, buflen);
70           cc = buflen;
71           goto ad_read_done;
72         }
73 #endif  
74         if ( ad->ad_hf.adf_off != cc ) {
75           if ( lseek( ad->ad_hf.adf_fd, (off_t) cc, SEEK_SET ) < 0 ) {
76               return( -1 );
77           }
78           ad->ad_hf.adf_off = cc;
79         }
80           
81         if (( cc = read( ad->ad_hf.adf_fd, buf, buflen )) < 0 ) {
82           return( -1 );
83         }
84           
85 #ifndef USE_MMAPPED_HEADERS
86         /*
87          * We've just read in bytes from the disk that we read earlier
88          * into ad_data. If we're going to write this buffer out later,
89          * we need to update ad_data.
90          */
91         if (ad->ad_hf.adf_off < ad_getentryoff(ad, ADEID_RFORK)) {
92             if ( ad->ad_hf.adf_flags & O_RDWR ) {
93               memcpy(buf, ad->ad_data + ad->ad_hf.adf_off,
94                      MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc));
95             } else {
96               memcpy(ad->ad_data + ad->ad_hf.adf_off, buf,
97                      MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc));
98             }
99         }
100         ad->ad_hf.adf_off += cc;
101 #else
102 ad_read_done:
103 #endif
104     }
105
106     return( cc );
107 }