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