X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=libatalk%2Fadouble%2Fad_read.c;h=17c2361faa99a775fef26c000bfb1ff82a8b2675;hp=b286f5561bd97a100d71d9733c473fcc24209364;hb=2bf71d3ccf20c072bc67a9d075b6ac8b0798021e;hpb=31843674b7bd32eabcce3a1ad6159b4f94921f79 diff --git a/libatalk/adouble/ad_read.c b/libatalk/adouble/ad_read.c index b286f556..17c2361f 100644 --- a/libatalk/adouble/ad_read.c +++ b/libatalk/adouble/ad_read.c @@ -1,4 +1,6 @@ /* + * $Id: ad_read.c,v 1.10 2010-02-10 14:05:37 franklahm Exp $ + * * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. * @@ -12,91 +14,95 @@ * permission. This software is supplied as is without expressed or * implied warranties of any kind. * - * Research Systems Unix Group - * The University of Michigan - * c/o Mike Clark - * 535 W. William Street - * Ann Arbor, Michigan - * +1-313-763-0525 - * netatalk@itd.umich.edu + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include #include -#include #include -#include -#include #ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif /* ! MIN */ + +ssize_t adf_pread(struct ad_fd *ad_fd, void *buf, size_t count, off_t offset) +{ + ssize_t cc; + +#ifndef HAVE_PREAD + if ( ad_fd->adf_off != offset ) { + if ( lseek( ad_fd->adf_fd, offset, SEEK_SET ) < 0 ) { + return -1; + } + ad_fd->adf_off = offset; + } + if (( cc = read( ad_fd->adf_fd, buf, count )) < 0 ) { + return -1; + } + ad_fd->adf_off += cc; +#else + cc = pread(ad_fd->adf_fd, buf, count, offset ); #endif + return cc; +} -/* XXX: this would probably benefit from pread. - * locks have to be checked before each stream of consecutive +/* XXX: locks have to be checked before each stream of consecutive * ad_reads to prevent a denial in the middle from causing * problems. */ -ssize_t ad_read( ad, eid, off, buf, buflen) - struct adouble *ad; - const u_int32_t eid; - off_t off; - char *buf; - const size_t buflen; +ssize_t ad_read( struct adouble *ad, const u_int32_t eid, off_t off, char *buf, const size_t buflen) { - ssize_t cc; + ssize_t cc; /* We're either reading the data fork (and thus the data file) * or we're reading anything else (and thus the header file). */ if ( eid == ADEID_DFORK ) { - if ( ad->ad_df.adf_off != off ) { - if ( lseek( ad->ad_df.adf_fd, (off_t) off, SEEK_SET ) < 0 ) { - return( -1 ); - } - ad->ad_df.adf_off = off; - } - if (( cc = read( ad->ad_df.adf_fd, buf, buflen )) < 0 ) { - return( -1 ); - } - ad->ad_df.adf_off += cc; + if (ad->ad_data_fork.adf_syml !=0 ) { + /* It's a symlink, we already have the target in adf_syml */ + cc = strlen(ad->ad_data_fork.adf_syml); + if (buflen < cc) + /* Request buffersize is too small, force AFPERR_PARAM */ + return -1; + memcpy(buf, ad->ad_data_fork.adf_syml, cc); + } else { + cc = adf_pread(&ad->ad_data_fork, buf, buflen, off); + } } else { - cc = ad->ad_eid[eid].ade_off + off; + off_t r_off; -#ifdef USE_MMAPPED_HEADERS - if (eid != ADEID_RFORK) { - memcpy(buf, ad->ad_data + cc, buflen); - cc = buflen; - goto ad_read_done; - } -#endif - if ( ad->ad_hf.adf_off != cc ) { - if ( lseek( ad->ad_hf.adf_fd, (off_t) cc, SEEK_SET ) < 0 ) { - return( -1 ); - } - ad->ad_hf.adf_off = cc; - } - - if (( cc = read( ad->ad_hf.adf_fd, buf, buflen )) < 0 ) { - return( -1 ); - } - -#ifndef USE_MMAPPED_HEADERS - /* - * We've just read in bytes from the disk that we read earlier - * into ad_data. If we're going to write this buffer out later, - * we need to update ad_data. - */ - if (ad->ad_hf.adf_off < ad_getentryoff(ad, ADEID_RFORK)) { - if ( ad->ad_hf.adf_flags & O_RDWR ) { - memcpy(buf, ad->ad_data + ad->ad_hf.adf_off, - MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc)); - } else { - memcpy(ad->ad_data + ad->ad_hf.adf_off, buf, - MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc)); - } - } - ad->ad_hf.adf_off += cc; -#else -ad_read_done: -#endif + if ( ad_reso_fileno( ad ) == -1 ) { + /* resource fork is not open ( cf etc/afp/fork.c) */ + return 0; + } + r_off = ad_getentryoff(ad, eid) + off; + + if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 ) { + return( -1 ); + } + /* + * We've just read in bytes from the disk that we read earlier + * into ad_data. If we're going to write this buffer out later, + * we need to update ad_data. + * FIXME : always false? + */ + if (r_off < ad_getentryoff(ad, ADEID_RFORK)) { + if ( ad->ad_resource_fork.adf_flags & O_RDWR ) { + memcpy(buf, ad->ad_data + r_off, + MIN(sizeof( ad->ad_data ) - r_off, cc)); + } else { + memcpy(ad->ad_data + r_off, buf, + MIN(sizeof( ad->ad_data ) - r_off, cc)); + } + } } return( cc );