* 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
+#endif /* HAVE_CONFIG_H */
#include <string.h>
-#include <sys/types.h>
#include <sys/param.h>
+#include <errno.h>
+#include <stdlib.h>
+
#include <atalk/adouble.h>
-#include <unistd.h>
+#include <atalk/ea.h>
+#include <atalk/logger.h>
+#include <atalk/util.h>
-#ifndef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
+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 uint32_t eid, off_t off, char *buf, const size_t buflen)
{
- ssize_t cc;
+ ssize_t cc;
+ off_t r_off = 0;
/* 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;
+ if (! AD_RSRC_OPEN(ad))
+ /* resource fork is not open ( cf etc/afp/fork.c) */
+ return 0;
-#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;
+ if (ad->ad_vers == AD_VERSION_EA) {
+#ifdef HAVE_EAFD
+ r_off = off;
#else
-ad_read_done:
+ r_off = off + ADEDOFF_RFORK_OSX;
#endif
+ } else {
+ r_off = ad_getentryoff(ad, eid) + off;
+ }
+
+ if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 )
+ return( -1 );
}
return( cc );