2 * $Id: fork.c,v 1.25 2002-03-13 19:28:22 srittau Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
15 #endif /* HAVE_UNISTD_H */
18 #endif /* HAVE_FCNTL_H */
22 #include <atalk/logger.h>
24 #include <sys/param.h>
26 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netatalk/endian.h>
31 #include <netatalk/at.h>
33 #include <atalk/dsi.h>
34 #include <atalk/atp.h>
35 #include <atalk/asp.h>
36 #include <atalk/afp.h>
37 #include <atalk/adouble.h>
38 #include <atalk/util.h>
40 #include <atalk/cnid.h>
46 #include "directory.h"
50 #define BYTELOCK_MAX 0x7FFFFFFFU
52 struct ofork *writtenfork;
54 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
59 const u_int16_t attrbits;
62 struct stat lst, *lstp;
63 #endif /* !USE_LASTDID */
66 char *data, *nameoff = NULL, *upath;
67 int bit = 0, isad = 1;
71 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
74 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
75 if ( ad_refresh( ofork->of_ad ) < 0 ) {
76 LOG(log_error, logtype_default, "getforkparams: ad_refresh: %s", strerror(errno) );
77 return( AFPERR_PARAM );
79 /* See afp_closefork() for why this is bad */
80 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
83 /* can only get the length of the opened fork */
84 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
85 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
86 return( AFPERR_BITMAP );
89 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
90 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
91 (1 << FILPBIT_BDATE))) {
92 upath = mtoupath(ofork->of_vol, ofork->of_name);
93 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
94 if ( stat( upath, &st ) < 0 )
95 return( AFPERR_NOOBJ );
97 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
98 return( AFPERR_BITMAP );
104 while ( bitmap != 0 ) {
105 while (( bitmap & 1 ) == 0 ) {
113 ad_getattr(ofork->of_ad, &ashort);
118 ashort = htons(ntohs(ashort) | attrbits);
119 memcpy(data, &ashort, sizeof( ashort ));
120 data += sizeof( ashort );
124 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
125 data += sizeof( aint );
130 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
131 aint = AD_DATE_FROM_UNIX(st.st_mtime);
132 memcpy(data, &aint, sizeof( aint ));
133 data += sizeof( aint );
138 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
139 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
140 aint = AD_DATE_FROM_UNIX(st.st_mtime);
141 memcpy(data, &aint, sizeof( aint ));
142 data += sizeof( aint );
147 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
148 aint = AD_DATE_START;
149 memcpy(data, &aint, sizeof( aint ));
150 data += sizeof( aint );
155 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
156 (void *) ufinderi, 32);
158 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
159 ufinderi, 8 ) == 0 ) {
160 memcpy(data, ufinderi, 8 );
161 if (( em = getextmap( ofork->of_name )) != NULL ) {
162 memcpy(data, em->em_type, sizeof( em->em_type ));
163 memcpy(data + 4, em->em_creator,
164 sizeof( em->em_creator ));
172 data += sizeof(u_int16_t);
176 memset(data, 0, sizeof(u_int16_t));
177 data += sizeof(u_int16_t);
182 #if AD_VERSION > AD_VERSION1
183 /* look in AD v2 header */
185 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
186 #endif /* AD_VERSION > AD_VERSION1 */
189 aint = cnid_add(ofork->of_vol->v_db, &st,
190 ofork->of_dir->d_did,
191 upath, strlen(upath), aint);
192 if (aint == CNID_INVALID) {
195 LOG(log_error, logtype_default, "getforkparams: Incorrect parameters passed to cnid_add");
196 return(AFPERR_PARAM);
198 return(AFPERR_PARAM);
208 aint = htonl(( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff ));
209 #else /* USE_LASTDID */
210 lstp = lstat(upath, &lst) < 0 ? &st : &lst;
212 aint = htonl( afpd_st_cnid ( lstp ) );
214 aint = htonl(CNID(lstp, 1));
215 #endif /* DID_MTAB */
216 #endif /* USE_LASTDID */
219 memcpy(data, &aint, sizeof( aint ));
220 data += sizeof( aint );
224 aint = htonl( st.st_size );
225 memcpy(data, &aint, sizeof( aint ));
226 data += sizeof( aint );
231 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
235 memcpy(data, &aint, sizeof( aint ));
236 data += sizeof( aint );
240 return( AFPERR_BITMAP );
247 ashort = htons( data - buf );
248 memcpy(nameoff, &ashort, sizeof( ashort ));
249 aint = strlen( ofork->of_name );
250 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
252 memcpy(data, ofork->of_name, aint );
256 *buflen = data - buf;
260 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
263 int ibuflen, *rbuflen;
267 struct ofork *ofork, *opened;
268 struct adouble *adsame = NULL;
269 int buflen, ret, adflags, eid, lockop;
271 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
272 char fork, *path, *upath;
276 memcpy(&vid, ibuf, sizeof( vid ));
280 if (( vol = getvolbyvid( vid )) == NULL ) {
281 return( AFPERR_PARAM );
284 memcpy(&did, ibuf, sizeof( did ));
285 ibuf += sizeof( int );
287 if (( dir = dirsearch( vol, did )) == NULL ) {
288 return( AFPERR_NOOBJ );
291 memcpy(&bitmap, ibuf, sizeof( bitmap ));
292 bitmap = ntohs( bitmap );
293 ibuf += sizeof( bitmap );
294 memcpy(&access, ibuf, sizeof( access ));
295 access = ntohs( access );
296 ibuf += sizeof( access );
298 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
302 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
303 return( AFPERR_NOOBJ );
306 if ( fork == OPENFORK_DATA ) {
308 adflags = ADFLAGS_DF|ADFLAGS_HF;
311 adflags = ADFLAGS_HF;
314 /* XXX: this probably isn't the best way to do this. the already
315 open bits should really be set if the fork is opened by any
316 program, not just this one. however, that's problematic to do
317 if we can't write lock files somewhere. opened is also passed to
318 ad_open so that we can keep file locks together. */
319 if ((opened = of_findname(vol, curdir, path))) {
320 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
321 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
322 adsame = opened->of_ad;
325 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
327 return( AFPERR_NFILE );
329 if (access & OPENACC_WR) {
330 /* try opening in read-write mode */
331 upath = mtoupath(vol, path);
333 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
345 /* see if client asked for the data fork */
346 if (fork == OPENFORK_DATA) {
347 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
350 adflags = ADFLAGS_DF;
352 } else if (stat(upath, &st) == 0) {
353 /* here's the deal. we only try to create the resource
354 * fork if the user wants to open it for write acess. */
355 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
367 ret = AFPERR_BADTYPE;
371 LOG(log_error, logtype_default, "afp_openfork: ad_open: %s", strerror(errno) );
378 /* try opening in read-only mode */
379 upath = mtoupath(vol, path);
381 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
386 /* check for a read-only data fork */
387 if ((adflags != ADFLAGS_HF) &&
388 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
391 adflags = ADFLAGS_DF;
397 /* see if client asked for the data fork */
398 if (fork == OPENFORK_DATA) {
399 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
402 adflags = ADFLAGS_DF;
404 } else if (stat(upath, &st) != 0) {
415 ret = AFPERR_BADTYPE;
419 LOG(log_error, logtype_default, "afp_openfork: ad_open: %s", strerror(errno) );
426 if ((adflags & ADFLAGS_HF) &&
427 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
428 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
429 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
430 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
431 ad_flush( ofork->of_ad, adflags );
434 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
435 &buflen, attrbits )) != AFP_OK ) {
436 ad_close( ofork->of_ad, adflags );
440 *rbuflen = buflen + 2 * sizeof( u_int16_t );
441 bitmap = htons( bitmap );
442 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
443 rbuf += sizeof( u_int16_t );
446 * synchronization locks:
449 * 1) attempt a read lock to see if we have read or write
451 * 2) if that succeeds, set a write lock to correspond to the
452 * deny mode requested.
453 * 3) whenever a file is read/written, locks get set which
457 /* don't try to lock non-existent rforks. */
458 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
460 /* try to see if we have access. */
462 if (access & OPENACC_WR) {
463 ofork->of_flags |= AFPFORK_ACCWR;
464 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
465 AD_FILELOCK_WR, 1, ofrefnum);
468 if (!ret && (access & OPENACC_RD)) {
469 ofork->of_flags |= AFPFORK_ACCRD;
470 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
471 AD_FILELOCK_RD, 1, ofrefnum);
474 /* can we access the fork? */
476 ad_close( ofork->of_ad, adflags );
479 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
480 return (AFPERR_DENYCONF);
483 /* now try to set the deny lock. if the fork is open for read or
484 * write, a read lock will already have been set. otherwise, we upgrade
485 * our lock to a write lock.
487 * NOTE: we can't write lock a read-only file. on those, we just
488 * make sure that we have a read lock set. that way, we at least prevent
489 * someone else from really setting a deny read/write on the file. */
490 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
491 ADLOCK_WR : ADLOCK_RD;
492 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
493 lockop | ADLOCK_FILELOCK |
494 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
496 if (!ret && (access & OPENACC_DRD))
497 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
498 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
502 ad_close( ofork->of_ad, adflags );
505 case EAGAIN: /* return data anyway */
509 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
510 return( AFPERR_DENYCONF );
514 LOG(log_error, logtype_default, "afp_openfork: ad_lock: %s", strerror(errno) );
515 return( AFPERR_PARAM );
520 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
526 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
530 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
533 int ibuflen, *rbuflen;
537 u_int16_t ofrefnum, bitmap;
541 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
542 ibuf += sizeof( ofrefnum );
543 memcpy(&bitmap, ibuf, sizeof(bitmap));
544 bitmap = ntohs(bitmap);
545 ibuf += sizeof( bitmap );
546 memcpy(&size, ibuf, sizeof( size ));
547 size = ntohl( size );
550 if (( ofork = of_find( ofrefnum )) == NULL ) {
551 LOG(log_error, logtype_default, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum );
552 return( AFPERR_PARAM );
555 if (ofork->of_vol->v_flags & AFPVOL_RO)
558 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
559 return AFPERR_ACCESS;
564 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
565 err = ad_dtruncate( ofork->of_ad, size );
567 goto afp_setfork_err;
568 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
569 (ofork->of_flags & AFPFORK_RSRC)) {
570 ad_refresh( ofork->of_ad );
571 err = ad_rtruncate(ofork->of_ad, size);
573 goto afp_setfork_err;
575 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
576 LOG(log_error, logtype_default, "afp_setforkparams: ad_flush: %s",
578 return( AFPERR_PARAM );
581 return AFPERR_BITMAP;
584 if ( flushfork( ofork ) < 0 ) {
585 LOG(log_error, logtype_default, "afp_setforkparams: flushfork: %s", strerror(errno) );
600 return AFPERR_ACCESS;
611 /* for this to work correctly, we need to check for locks before each
612 * read and write. that's most easily handled by always doing an
613 * appropriate check before each ad_read/ad_write. other things
614 * that can change files like truncate are handled internally to those
617 #define ENDBIT(a) ((a) & 0x80)
618 #define UNLOCKBIT(a) ((a) & 0x01)
619 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
622 int ibuflen, *rbuflen;
625 int32_t offset, length;
632 /* figure out parameters */
634 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
636 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
637 ibuf += sizeof(ofrefnum);
639 if (( ofork = of_find( ofrefnum )) == NULL ) {
640 LOG(log_error, logtype_default, "afp_bytelock: of_find");
641 return( AFPERR_PARAM );
644 if ( ofork->of_flags & AFPFORK_DATA) {
646 } else if (ofork->of_flags & AFPFORK_RSRC) {
651 memcpy(&offset, ibuf, sizeof( offset ));
652 offset = ntohl(offset);
653 ibuf += sizeof(offset);
655 memcpy(&length, ibuf, sizeof( length ));
656 length = ntohl(length);
657 if (length == 0xFFFFFFFF)
658 length = BYTELOCK_MAX;
659 else if (length <= 0) {
661 } else if ((length >= AD_FILELOCK_BASE) &&
662 (ad_hfileno(ofork->of_ad) == -1))
666 offset += ad_size(ofork->of_ad, eid);
668 if (offset < 0) /* error if we have a negative offset */
671 /* if the file is a read-only file, we use read locks instead of
672 * write locks. that way, we can prevent anyone from initiating
674 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
675 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
676 ADLOCK_WR : ADLOCK_RD), offset, length,
677 ofork->of_refnum) < 0) {
681 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
687 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
696 offset = htonl(offset);
697 memcpy(rbuf, &offset, sizeof( offset ));
698 *rbuflen = sizeof( offset );
704 static __inline__ int crlf( of )
709 if ( ad_hfileno( of->of_ad ) == -1 ||
710 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
712 if (( em = getextmap( of->of_name )) == NULL ||
713 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
719 if ( memcmp( ufinderi,
720 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
729 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
730 int offset, u_char nlmask,
731 u_char nlchar, char *rbuf,
732 int *rbuflen, const int xlate)
738 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
740 LOG(log_error, logtype_default, "afp_read: ad_read: %s", strerror(errno) );
742 return( AFPERR_PARAM );
744 if ( cc < *rbuflen ) {
752 for ( p = rbuf, q = p + cc; p < q; ) {
753 if (( *p++ & nlmask ) == nlchar ) {
764 * If this file is of type TEXT, then swap \012 to \015.
767 for ( p = rbuf, q = p + cc; p < q; p++ ) {
768 if ( *p == '\012' ) {
770 } else if ( *p == '\015' ) {
779 return( AFPERR_EOF );
784 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
787 int ibuflen, *rbuflen;
791 int32_t offset, saveoff, reqcount, savereqcount;
792 int cc, err, saveerr, eid, xlate = 0;
794 u_char nlmask, nlchar;
797 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
798 ibuf += sizeof( u_short );
800 if (( ofork = of_find( ofrefnum )) == NULL ) {
801 LOG(log_error, logtype_default, "afp_read: of_find");
806 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
811 memcpy(&offset, ibuf, sizeof( offset ));
812 offset = ntohl( offset );
813 ibuf += sizeof( offset );
814 memcpy(&reqcount, ibuf, sizeof( reqcount ));
815 reqcount = ntohl( reqcount );
816 ibuf += sizeof( reqcount );
821 /* if we wanted to be picky, we could add in the following
822 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
824 if (reqcount < 0 || offset < 0) {
829 if ( ofork->of_flags & AFPFORK_DATA) {
831 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
832 } else if (ofork->of_flags & AFPFORK_RSRC) {
834 } else { /* fork wasn't opened. this should never really happen. */
839 /* zero request count */
845 /* reqcount isn't always truthful. we need to deal with that. */
846 size = ad_size(ofork->of_ad, eid);
848 if (offset >= size) {
853 /* subtract off the offset */
855 savereqcount = reqcount;
856 if (reqcount > size) {
862 /* if EOF lock on the old reqcount, some prg may need it */
863 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount) < 0) {
868 #define min(a,b) ((a)<(b)?(a):(b))
869 *rbuflen = min( reqcount, *rbuflen );
871 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
878 /* dsi can stream requests. we can only do this if we're not checking
879 * for an end-of-line character. oh well. */
880 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
881 DSI *dsi = obj->handle;
883 if (obj->options.flags & OPTION_DEBUG) {
884 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
885 reqcount, dsi->clientID);
886 bprint(rbuf, *rbuflen);
891 /* dsi_readinit() returns size of next read buffer. by this point,
892 * we know that we're sending some data. if we fail, something
893 * horrible happened. */
894 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
897 /* due to the nature of afp packets, we have to exit if we get
898 an error. we can't do this with translation on. */
899 #ifdef HAVE_SENDFILE_READ
900 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
901 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
902 dsi->datasize) < 0) {
906 LOG(log_error, logtype_default, "afp_read: ad_readfile: %s", strerror(errno));
916 #endif /* HAVE_SENDFILE_READ */
918 /* fill up our buffer. */
919 while (*rbuflen > 0) {
920 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
926 if (obj->options.flags & OPTION_DEBUG) {
927 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
928 bprint(rbuf, *rbuflen);
931 /* dsi_read() also returns buffer size of next allocation */
932 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
941 LOG(log_error, logtype_default, "afp_read: %s", strerror(errno));
943 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
948 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
956 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
959 int ibuflen, *rbuflen;
967 memcpy(&vid, ibuf, sizeof(vid));
968 if (( vol = getvolbyvid( vid )) == NULL ) {
969 return( AFPERR_PARAM );
976 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
979 int ibuflen, *rbuflen;
986 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
988 if (( ofork = of_find( ofrefnum )) == NULL ) {
989 LOG(log_error, logtype_default, "afp_flushfork: of_find");
990 return( AFPERR_PARAM );
993 if ( flushfork( ofork ) < 0 ) {
994 LOG(log_error, logtype_default, "afp_flushfork: %s", strerror(errno) );
1000 /* this is very similar to closefork */
1001 int flushfork( ofork )
1002 struct ofork *ofork;
1005 int len, err = 0, doflush = 0;
1007 if ( ad_dfileno( ofork->of_ad ) != -1 &&
1008 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1009 LOG(log_error, logtype_default, "flushfork: dfile(%d) %s",
1010 ad_dfileno(ofork->of_ad), strerror(errno) );
1014 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1016 /* read in the rfork length */
1017 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
1018 ad_refresh(ofork->of_ad);
1020 /* set the date if we're dirty */
1021 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1022 (gettimeofday(&tv, NULL) == 0)) {
1023 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1024 ofork->of_flags &= ~AFPFORK_DIRTY;
1028 /* if we're actually flushing this fork, make sure to set the
1029 * length. otherwise, just use the stored length */
1030 if ((ofork->of_flags & AFPFORK_RSRC) &&
1031 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
1032 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
1037 /* flush the header (if it is a resource fork) */
1038 if (ofork->of_flags & AFPFORK_RSRC)
1039 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
1042 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1046 LOG(log_error, logtype_default, "flushfork: hfile(%d) %s",
1047 ad_hfileno(ofork->of_ad), strerror(errno) );
1053 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1056 int ibuflen, *rbuflen;
1058 struct ofork *ofork;
1060 int adflags, aint, doflush = 0;
1065 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1067 if (( ofork = of_find( ofrefnum )) == NULL ) {
1068 LOG(log_error, logtype_default, "afp_closefork: of_find");
1069 return( AFPERR_PARAM );
1073 if ((ofork->of_flags & AFPFORK_DATA) &&
1074 (ad_dfileno( ofork->of_ad ) != -1)) {
1075 adflags |= ADFLAGS_DF;
1078 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1079 adflags |= ADFLAGS_HF;
1081 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1082 ad_refresh( ofork->of_ad );
1083 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1084 (gettimeofday(&tv, NULL) == 0)) {
1085 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1091 * Only set the rfork's length if we're closing the rfork.
1093 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1094 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1095 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1099 ad_flush( ofork->of_ad, adflags );
1103 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1104 LOG(log_error, logtype_default, "afp_closefork: ad_close: %s", strerror(errno) );
1105 return( AFPERR_PARAM );
1108 of_dealloc( ofork );
1113 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1114 off_t offset, char *rbuf,
1115 size_t rbuflen, const int xlate)
1121 * If this file is of type TEXT, swap \015 to \012.
1124 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1125 if ( *p == '\015' ) {
1127 } else if ( *p == '\012' ) {
1133 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1134 rbuf, rbuflen)) < 0 ) {
1139 return( AFPERR_DFULL );
1141 LOG(log_error, logtype_default, "afp_write: ad_write: %s", strerror(errno) );
1142 return( AFPERR_PARAM );
1149 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1150 * the client may have sent us a bunch of data that's not reflected
1151 * in reqcount et al. */
1152 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1155 int ibuflen, *rbuflen;
1157 struct ofork *ofork;
1158 int32_t offset, saveoff, reqcount;
1159 int endflag, eid, xlate = 0, err = AFP_OK;
1163 /* figure out parameters */
1165 endflag = ENDBIT(*ibuf);
1167 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1168 ibuf += sizeof( ofrefnum );
1169 memcpy(&offset, ibuf, sizeof( offset ));
1170 offset = ntohl( offset );
1171 ibuf += sizeof( offset );
1172 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1173 reqcount = ntohl( reqcount );
1174 ibuf += sizeof( reqcount );
1176 if (( ofork = of_find( ofrefnum )) == NULL ) {
1177 LOG(log_error, logtype_default, "afp_write: of_find");
1182 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1183 err = AFPERR_ACCESS;
1188 writtenfork = ofork;
1191 if ( ofork->of_flags & AFPFORK_DATA) {
1193 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1194 } else if (ofork->of_flags & AFPFORK_RSRC) {
1197 err = AFPERR_ACCESS; /* should never happen */
1202 offset += ad_size(ofork->of_ad, eid);
1204 /* handle bogus parameters */
1205 if (reqcount < 0 || offset < 0) {
1210 /* offset can overflow on 64-bit capable filesystems.
1211 * report disk full if that's going to happen. */
1212 if (offset + reqcount < 0) {
1217 if (!reqcount) { /* handle request counts of 0 */
1219 offset = htonl(offset);
1220 memcpy(rbuf, &offset, sizeof(offset));
1225 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1231 /* this is yucky, but dsi can stream i/o and asp can't */
1232 switch (obj->proto) {
1235 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1237 LOG(log_error, logtype_default, "afp_write: asp_wrtcont: %s", strerror(errno) );
1238 return( AFPERR_PARAM );
1241 if (obj->options.flags & OPTION_DEBUG) {
1242 printf("(write) len: %d\n", *rbuflen);
1243 bprint(rbuf, *rbuflen);
1246 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1249 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1254 #endif /* no afp/asp */
1258 DSI *dsi = obj->handle;
1260 /* find out what we have already and write it out. */
1261 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1263 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1264 dsi_writeflush(dsi);
1266 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1271 #if 0 /*def HAVE_SENDFILE_WRITE*/
1272 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1273 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1274 offset, dsi->datasize)) < 0) {
1282 LOG(log_error, logtype_default, "afp_write: ad_writefile: %s", strerror(errno) );
1283 goto afp_write_loop;
1285 dsi_writeflush(dsi);
1287 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1293 goto afp_write_done;
1295 #endif /* 0, was HAVE_SENDFILE_WRITE */
1297 /* loop until everything gets written. currently
1298 * dsi_write handles the end case by itself. */
1299 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1300 if ( obj->options.flags & OPTION_DEBUG ) {
1301 printf("(write) command cont'd: %d\n", cc);
1305 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1306 dsi_writeflush(dsi);
1308 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1318 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1319 if ( ad_hfileno( ofork->of_ad ) != -1 )
1320 ofork->of_flags |= AFPFORK_DIRTY;
1322 offset = htonl( offset );
1323 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1324 bcopy(&offset, rbuf, sizeof(offset));
1325 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1326 memcpy(rbuf, &offset, sizeof(offset));
1327 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1328 *rbuflen = sizeof(offset);
1332 if (obj->proto == AFPPROTO_DSI) {
1333 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1334 dsi_writeflush(obj->handle);
1337 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1342 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1345 int ibuflen, *rbuflen;
1347 struct ofork *ofork;
1349 u_int16_t ofrefnum, bitmap;
1352 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1353 ibuf += sizeof( ofrefnum );
1354 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1355 bitmap = ntohs( bitmap );
1356 ibuf += sizeof( bitmap );
1359 if (( ofork = of_find( ofrefnum )) == NULL ) {
1360 LOG(log_error, logtype_default, "afp_getforkparams: of_find");
1361 return( AFPERR_PARAM );
1364 if (( ret = getforkparams( ofork, bitmap,
1365 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1369 *rbuflen = buflen + sizeof( u_short );
1370 bitmap = htons( bitmap );
1371 memcpy(rbuf, &bitmap, sizeof( bitmap ));