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 /* HAVE_CONFIG_H */ 27 28#include <string.h> 29#include <sys/param.h> 30#include <errno.h> 31#include <stdlib.h> 32 33#include <atalk/adouble.h> 34#include <atalk/ea.h> 35#include <atalk/logger.h> 36#include <atalk/util.h> 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 uint32_t eid, off_t off, char *buf, const size_t buflen) 63{ 64 ssize_t cc; 65 off_t r_off = 0; 66 67 /* We're either reading the data fork (and thus the data file) 68 * or we're reading anything else (and thus the header file). */ 69 if ( eid == ADEID_DFORK ) { 70 if (ad->ad_data_fork.adf_syml !=0 ) { 71 /* It's a symlink, we already have the target in adf_syml */ 72 cc = strlen(ad->ad_data_fork.adf_syml); 73 if (buflen < cc) 74 /* Request buffersize is too small, force AFPERR_PARAM */ 75 return -1; 76 memcpy(buf, ad->ad_data_fork.adf_syml, cc); 77 } else { 78 cc = adf_pread(&ad->ad_data_fork, buf, buflen, off); 79 } 80 } else { 81 if (! AD_RSRC_OPEN(ad)) 82 /* resource fork is not open ( cf etc/afp/fork.c) */ 83 return 0; 84 85 if (ad->ad_vers == AD_VERSION_EA) { 86#ifdef HAVE_EAFD 87 r_off = off; 88#else 89 r_off = off + ADEDOFF_RFORK_OSX; 90#endif 91 } else { 92 r_off = ad_getentryoff(ad, eid) + off; 93 } 94 95 if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 ) 96 return( -1 ); 97 } 98 99 return( cc ); 100} 101