• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/libatalk/adouble/
1/*
2 * $Id: ad_read.c,v 1.10 2010-02-10 14:05:37 franklahm 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
38ssize_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. */
62ssize_t ad_read( struct adouble *ad, const u_int32_t eid, off_t off, char *buf, const size_t buflen)
63{
64    ssize_t     cc;
65
66    /* We're either reading the data fork (and thus the data file)
67     * or we're reading anything else (and thus the header file). */
68    if ( eid == ADEID_DFORK ) {
69        if (ad->ad_data_fork.adf_syml !=0 ) {
70            /* It's a symlink, we already have the target in adf_syml */
71            cc = strlen(ad->ad_data_fork.adf_syml);
72            if (buflen < cc)
73                /* Request buffersize is too small, force AFPERR_PARAM */
74                return -1;
75            memcpy(buf, ad->ad_data_fork.adf_syml, cc);
76        } else {
77            cc = adf_pread(&ad->ad_data_fork, buf, buflen, off);
78        }
79    } else {
80        off_t r_off;
81
82        if ( ad_reso_fileno( ad ) == -1 ) {
83            /* resource fork is not open ( cf etc/afp/fork.c) */
84            return 0;
85        }
86        r_off = ad_getentryoff(ad, eid) + off;
87
88        if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 ) {
89            return( -1 );
90        }
91        /*
92         * We've just read in bytes from the disk that we read earlier
93         * into ad_data. If we're going to write this buffer out later,
94         * we need to update ad_data.
95         * FIXME : always false?
96         */
97        if (r_off < ad_getentryoff(ad, ADEID_RFORK)) {
98            if ( ad->ad_resource_fork.adf_flags & O_RDWR ) {
99                memcpy(buf, ad->ad_data + r_off,
100                       MIN(sizeof( ad->ad_data ) - r_off, cc));
101            } else {
102                memcpy(ad->ad_data + r_off, buf,
103                       MIN(sizeof( ad->ad_data ) - r_off, cc));
104            }
105        }
106    }
107
108    return( cc );
109}
110