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