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