2 * $Id: fork.c,v 1.15 2002-01-16 19:55:15 jmarcus 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 hst, lst, *lstp;
63 #else /* USE_LASTDID */
68 char *data, *nameoff = NULL, *upath;
69 int bit = 0, isad = 1;
73 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
76 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
77 if ( ad_refresh( ofork->of_ad ) < 0 ) {
78 LOG(log_error, logtype_default, "getforkparams: ad_refresh: %s", strerror(errno) );
79 return( AFPERR_PARAM );
81 /* See afp_closefork() for why this is bad */
82 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
85 /* can only get the length of the opened fork */
86 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
87 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
88 return( AFPERR_BITMAP );
91 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
92 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
93 (1 << FILPBIT_BDATE))) {
94 upath = mtoupath(ofork->of_vol, ofork->of_name);
95 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
96 if ( stat( upath, &st ) < 0 )
97 return( AFPERR_NOOBJ );
99 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
100 return( AFPERR_BITMAP );
106 while ( bitmap != 0 ) {
107 while (( bitmap & 1 ) == 0 ) {
115 ad_getattr(ofork->of_ad, &ashort);
120 ashort = htons(ntohs(ashort) | attrbits);
121 memcpy(data, &ashort, sizeof( ashort ));
122 data += sizeof( ashort );
126 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
127 data += sizeof( aint );
132 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
133 aint = AD_DATE_FROM_UNIX(st.st_mtime);
134 memcpy(data, &aint, sizeof( aint ));
135 data += sizeof( aint );
140 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
141 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
142 aint = AD_DATE_FROM_UNIX(st.st_mtime);
143 memcpy(data, &aint, sizeof( aint ));
144 data += sizeof( aint );
149 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
150 aint = AD_DATE_START;
151 memcpy(data, &aint, sizeof( aint ));
152 data += sizeof( aint );
157 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
158 (void *) ufinderi, 32);
160 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
161 ufinderi, 8 ) == 0 ) {
162 memcpy(data, ufinderi, 8 );
163 if (( em = getextmap( ofork->of_name )) != NULL ) {
164 memcpy(data, em->em_type, sizeof( em->em_type ));
165 memcpy(data + 4, em->em_creator,
166 sizeof( em->em_creator ));
174 data += sizeof(u_int16_t);
178 memset(data, 0, sizeof(u_int16_t));
179 data += sizeof(u_int16_t);
184 #if AD_VERSION > AD_VERSION1
185 /* look in AD v2 header */
187 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
188 #endif /* AD_VERSION > AD_VERSION1 */
191 aint = cnid_add(ofork->of_vol->v_db, &st,
192 ofork->of_dir->d_did,
193 upath, strlen(upath), aint);
198 aint = htonl(( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff ));
199 #else /* USE_LASTDID */
200 lstp = lstat(upath, &lst) < 0 ? st : &lst;
202 aint = htonl( afpd_st_cnid ( lstp ) );
204 aint = htonl(CNID(lstp, 1));
205 #endif /* DID_MTAB */
206 #endif /* USE_LASTDID */
209 memcpy(data, &aint, sizeof( aint ));
210 data += sizeof( aint );
214 aint = htonl( st.st_size );
215 memcpy(data, &aint, sizeof( aint ));
216 data += sizeof( aint );
221 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
225 memcpy(data, &aint, sizeof( aint ));
226 data += sizeof( aint );
230 return( AFPERR_BITMAP );
237 ashort = htons( data - buf );
238 memcpy(nameoff, &ashort, sizeof( ashort ));
239 aint = strlen( ofork->of_name );
240 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
242 memcpy(data, ofork->of_name, aint );
246 *buflen = data - buf;
250 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
253 int ibuflen, *rbuflen;
257 struct ofork *ofork, *opened;
258 struct adouble *adsame = NULL;
259 int buflen, ret, adflags, eid, lockop;
261 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
262 char fork, *path, *upath;
266 memcpy(&vid, ibuf, sizeof( vid ));
270 if (( vol = getvolbyvid( vid )) == NULL ) {
271 return( AFPERR_PARAM );
274 memcpy(&did, ibuf, sizeof( did ));
275 ibuf += sizeof( int );
277 if (( dir = dirsearch( vol, did )) == NULL ) {
278 return( AFPERR_NOOBJ );
281 memcpy(&bitmap, ibuf, sizeof( bitmap ));
282 bitmap = ntohs( bitmap );
283 ibuf += sizeof( bitmap );
284 memcpy(&access, ibuf, sizeof( access ));
285 access = ntohs( access );
286 ibuf += sizeof( access );
288 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
292 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
293 return( AFPERR_NOOBJ );
296 if ( fork == OPENFORK_DATA ) {
298 adflags = ADFLAGS_DF|ADFLAGS_HF;
301 adflags = ADFLAGS_HF;
304 /* XXX: this probably isn't the best way to do this. the already
305 open bits should really be set if the fork is opened by any
306 program, not just this one. however, that's problematic to do
307 if we can't write lock files somewhere. opened is also passed to
308 ad_open so that we can keep file locks together. */
309 if ((opened = of_findname(vol, curdir, path))) {
310 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
311 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
312 adsame = opened->of_ad;
315 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
317 return( AFPERR_NFILE );
319 if (access & OPENACC_WR) {
320 /* try opening in read-write mode */
321 upath = mtoupath(vol, path);
323 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
335 /* see if client asked for the data fork */
336 if (fork == OPENFORK_DATA) {
337 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
340 adflags = ADFLAGS_DF;
342 } else if (stat(upath, &st) == 0) {
343 /* here's the deal. we only try to create the resource
344 * fork if the user wants to open it for write acess. */
345 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
357 ret = AFPERR_BADTYPE;
361 LOG(log_error, logtype_default, "afp_openfork: ad_open: %s", strerror(errno) );
368 /* try opening in read-only mode */
369 upath = mtoupath(vol, path);
371 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
376 /* check for a read-only data fork */
377 if ((adflags != ADFLAGS_HF) &&
378 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
381 adflags = ADFLAGS_DF;
387 /* see if client asked for the data fork */
388 if (fork == OPENFORK_DATA) {
389 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
392 adflags = ADFLAGS_DF;
394 } else if (stat(upath, &st) != 0) {
405 ret = AFPERR_BADTYPE;
409 LOG(log_error, logtype_default, "afp_openfork: ad_open: %s", strerror(errno) );
416 if ((adflags & ADFLAGS_HF) &&
417 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
418 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
419 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
420 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
421 ad_flush( ofork->of_ad, adflags );
424 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
425 &buflen, attrbits )) != AFP_OK ) {
426 ad_close( ofork->of_ad, adflags );
430 *rbuflen = buflen + 2 * sizeof( u_int16_t );
431 bitmap = htons( bitmap );
432 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
433 rbuf += sizeof( u_int16_t );
436 * synchronization locks:
439 * 1) attempt a read lock to see if we have read or write
441 * 2) if that succeeds, set a write lock to correspond to the
442 * deny mode requested.
443 * 3) whenever a file is read/written, locks get set which
447 /* don't try to lock non-existent rforks. */
448 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
450 /* try to see if we have access. */
452 if (access & OPENACC_WR) {
453 ofork->of_flags |= AFPFORK_ACCWR;
454 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
455 AD_FILELOCK_WR, 1, ofrefnum);
458 if (!ret && (access & OPENACC_RD)) {
459 ofork->of_flags |= AFPFORK_ACCRD;
460 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
461 AD_FILELOCK_RD, 1, ofrefnum);
464 /* can we access the fork? */
466 ad_close( ofork->of_ad, adflags );
469 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
470 return (AFPERR_DENYCONF);
473 /* now try to set the deny lock. if the fork is open for read or
474 * write, a read lock will already have been set. otherwise, we upgrade
475 * our lock to a write lock.
477 * NOTE: we can't write lock a read-only file. on those, we just
478 * make sure that we have a read lock set. that way, we at least prevent
479 * someone else from really setting a deny read/write on the file. */
480 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
481 ADLOCK_WR : ADLOCK_RD;
482 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
483 lockop | ADLOCK_FILELOCK |
484 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
486 if (!ret && (access & OPENACC_DRD))
487 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
488 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
492 ad_close( ofork->of_ad, adflags );
495 case EAGAIN: /* return data anyway */
499 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
500 return( AFPERR_DENYCONF );
504 LOG(log_error, logtype_default, "afp_openfork: ad_lock: %s", strerror(errno) );
505 return( AFPERR_PARAM );
510 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
516 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
520 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
523 int ibuflen, *rbuflen;
527 u_int16_t ofrefnum, bitmap;
531 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
532 ibuf += sizeof( ofrefnum );
533 memcpy(&bitmap, ibuf, sizeof(bitmap));
534 bitmap = ntohs(bitmap);
535 ibuf += sizeof( bitmap );
536 memcpy(&size, ibuf, sizeof( size ));
537 size = ntohl( size );
540 if (( ofork = of_find( ofrefnum )) == NULL ) {
541 LOG(log_error, logtype_default, "afp_setforkparams: of_find: %s", strerror(errno) );
542 return( AFPERR_PARAM );
545 if (ofork->of_vol->v_flags & AFPVOL_RO)
548 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
549 return AFPERR_ACCESS;
554 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
555 err = ad_dtruncate( ofork->of_ad, size );
557 goto afp_setfork_err;
558 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
559 (ofork->of_flags & AFPFORK_RSRC)) {
560 ad_refresh( ofork->of_ad );
561 err = ad_rtruncate(ofork->of_ad, size);
563 goto afp_setfork_err;
565 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
566 LOG(log_error, logtype_default, "afp_setforkparams: ad_flush: %s",
568 return( AFPERR_PARAM );
571 return AFPERR_BITMAP;
574 if ( flushfork( ofork ) < 0 ) {
575 LOG(log_error, logtype_default, "afp_setforkparams: flushfork: %s", strerror(errno) );
590 return AFPERR_ACCESS;
601 /* for this to work correctly, we need to check for locks before each
602 * read and write. that's most easily handled by always doing an
603 * appropriate check before each ad_read/ad_write. other things
604 * that can change files like truncate are handled internally to those
607 #define ENDBIT(a) ((a) & 0x80)
608 #define UNLOCKBIT(a) ((a) & 0x01)
609 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
612 int ibuflen, *rbuflen;
615 int32_t offset, length;
622 /* figure out parameters */
624 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
626 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
627 ibuf += sizeof(ofrefnum);
629 if (( ofork = of_find( ofrefnum )) == NULL ) {
630 LOG(log_error, logtype_default, "afp_bytelock: of_find: %s", strerror(errno) );
631 return( AFPERR_PARAM );
634 if ( ofork->of_flags & AFPFORK_DATA) {
636 } else if (ofork->of_flags & AFPFORK_RSRC) {
641 memcpy(&offset, ibuf, sizeof( offset ));
642 offset = ntohl(offset);
643 ibuf += sizeof(offset);
645 memcpy(&length, ibuf, sizeof( length ));
646 length = ntohl(length);
647 if (length == 0xFFFFFFFF)
648 length = BYTELOCK_MAX;
649 else if (length <= 0) {
651 } else if ((length >= AD_FILELOCK_BASE) &&
652 (ad_hfileno(ofork->of_ad) == -1))
656 offset += ad_size(ofork->of_ad, eid);
658 if (offset < 0) /* error if we have a negative offset */
661 /* if the file is a read-only file, we use read locks instead of
662 * write locks. that way, we can prevent anyone from initiating
664 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
665 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
666 ADLOCK_WR : ADLOCK_RD), offset, length,
667 ofork->of_refnum) < 0) {
671 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
677 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
686 offset = htonl(offset);
687 memcpy(rbuf, &offset, sizeof( offset ));
688 *rbuflen = sizeof( offset );
694 static __inline__ int crlf( of )
699 if ( ad_hfileno( of->of_ad ) == -1 ||
700 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
702 if (( em = getextmap( of->of_name )) == NULL ||
703 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
709 if ( memcmp( ufinderi,
710 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
719 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
720 int offset, u_char nlmask,
721 u_char nlchar, char *rbuf,
722 int *rbuflen, const int xlate)
728 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
730 LOG(log_error, logtype_default, "afp_read: ad_read: %s", strerror(errno) );
732 return( AFPERR_PARAM );
734 if ( cc < *rbuflen ) {
742 for ( p = rbuf, q = p + cc; p < q; ) {
743 if (( *p++ & nlmask ) == nlchar ) {
754 * If this file is of type TEXT, then swap \012 to \015.
757 for ( p = rbuf, q = p + cc; p < q; p++ ) {
758 if ( *p == '\012' ) {
760 } else if ( *p == '\015' ) {
769 return( AFPERR_EOF );
774 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
777 int ibuflen, *rbuflen;
781 int32_t offset, saveoff, reqcount;
782 int cc, err, eid, xlate = 0;
784 u_char nlmask, nlchar;
787 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
788 ibuf += sizeof( u_short );
790 if (( ofork = of_find( ofrefnum )) == NULL ) {
791 LOG(log_error, logtype_default, "afp_read: of_find: %s", strerror(errno) );
796 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
801 memcpy(&offset, ibuf, sizeof( offset ));
802 offset = ntohl( offset );
803 ibuf += sizeof( offset );
804 memcpy(&reqcount, ibuf, sizeof( reqcount ));
805 reqcount = ntohl( reqcount );
806 ibuf += sizeof( reqcount );
811 /* if we wanted to be picky, we could add in the following
812 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
814 if (reqcount < 0 || offset < 0) {
819 if ( ofork->of_flags & AFPFORK_DATA) {
821 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
822 } else if (ofork->of_flags & AFPFORK_RSRC) {
824 } else { /* fork wasn't opened. this should never really happen. */
829 /* zero request count */
835 /* reqcount isn't always truthful. we need to deal with that. */
836 if ((size = ad_size(ofork->of_ad, eid)) == 0) {
842 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, reqcount) < 0) {
847 #define min(a,b) ((a)<(b)?(a):(b))
848 *rbuflen = min( reqcount, *rbuflen );
849 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
854 /* dsi can stream requests. we can only do this if we're not checking
855 * for an end-of-line character. oh well. */
856 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
857 DSI *dsi = obj->handle;
859 /* subtract off the offset */
861 if (reqcount > size) {
866 if (obj->options.flags & OPTION_DEBUG) {
867 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
868 reqcount, dsi->clientID);
869 bprint(rbuf, *rbuflen);
874 /* dsi_readinit() returns size of next read buffer. by this point,
875 * we know that we're sending some data. if we fail, something
876 * horrible happened. */
877 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
880 /* due to the nature of afp packets, we have to exit if we get
881 an error. we can't do this with translation on. */
882 #ifdef HAVE_SENDFILE_READ
883 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
884 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
885 dsi->datasize) < 0) {
889 LOG(log_error, logtype_default, "afp_read: ad_readfile: %s", strerror(errno));
899 #endif /* HAVE_SENDFILE_READ */
901 /* fill up our buffer. */
902 while (*rbuflen > 0) {
903 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
909 if (obj->options.flags & OPTION_DEBUG) {
910 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
911 bprint(rbuf, *rbuflen);
914 /* dsi_read() also returns buffer size of next allocation */
915 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
924 LOG(log_error, logtype_default, "afp_read: %s", strerror(errno));
926 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
931 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
939 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
942 int ibuflen, *rbuflen;
950 memcpy(&vid, ibuf, sizeof(vid));
951 if (( vol = getvolbyvid( vid )) == NULL ) {
952 return( AFPERR_PARAM );
959 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
962 int ibuflen, *rbuflen;
969 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
971 if (( ofork = of_find( ofrefnum )) == NULL ) {
972 LOG(log_error, logtype_default, "afp_flushfork: of_find: %s", strerror(errno) );
973 return( AFPERR_PARAM );
976 if ( flushfork( ofork ) < 0 ) {
977 LOG(log_error, logtype_default, "afp_flushfork: %s", strerror(errno) );
983 /* this is very similar to closefork */
984 int flushfork( ofork )
988 int len, err = 0, doflush = 0;
990 if ( ad_dfileno( ofork->of_ad ) != -1 &&
991 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
992 LOG(log_error, logtype_default, "flushfork: dfile(%d) %s",
993 ad_dfileno(ofork->of_ad), strerror(errno) );
997 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
999 /* read in the rfork length */
1000 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
1001 ad_refresh(ofork->of_ad);
1003 /* set the date if we're dirty */
1004 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1005 (gettimeofday(&tv, NULL) == 0)) {
1006 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1007 ofork->of_flags &= ~AFPFORK_DIRTY;
1011 /* if we're actually flushing this fork, make sure to set the
1012 * length. otherwise, just use the stored length */
1013 if ((ofork->of_flags & AFPFORK_RSRC) &&
1014 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
1015 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
1020 /* flush the header (if it is a resource fork) */
1021 if (ofork->of_flags & AFPFORK_RSRC)
1022 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
1025 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1029 LOG(log_error, logtype_default, "flushfork: hfile(%d) %s",
1030 ad_hfileno(ofork->of_ad), strerror(errno) );
1036 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1039 int ibuflen, *rbuflen;
1041 struct ofork *ofork;
1043 int adflags, aint, doflush = 0;
1048 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1050 if (( ofork = of_find( ofrefnum )) == NULL ) {
1051 LOG(log_error, logtype_default, "afp_closefork: of_find: %s", strerror(errno) );
1052 return( AFPERR_PARAM );
1056 if ((ofork->of_flags & AFPFORK_DATA) &&
1057 (ad_dfileno( ofork->of_ad ) != -1)) {
1058 adflags |= ADFLAGS_DF;
1061 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1062 adflags |= ADFLAGS_HF;
1064 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1065 ad_refresh( ofork->of_ad );
1066 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1067 (gettimeofday(&tv, NULL) == 0)) {
1068 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1074 * Only set the rfork's length if we're closing the rfork.
1076 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1077 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1078 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1082 ad_flush( ofork->of_ad, adflags );
1086 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1087 LOG(log_error, logtype_default, "afp_closefork: ad_close: %s", strerror(errno) );
1088 return( AFPERR_PARAM );
1091 of_dealloc( ofork );
1096 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1097 off_t offset, char *rbuf,
1098 size_t rbuflen, const int xlate)
1104 * If this file is of type TEXT, swap \015 to \012.
1107 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1108 if ( *p == '\015' ) {
1110 } else if ( *p == '\012' ) {
1116 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1117 rbuf, rbuflen)) < 0 ) {
1122 return( AFPERR_DFULL );
1124 LOG(log_error, logtype_default, "afp_write: ad_write: %s", strerror(errno) );
1125 return( AFPERR_PARAM );
1132 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1133 * the client may have sent us a bunch of data that's not reflected
1134 * in reqcount et al. */
1135 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1138 int ibuflen, *rbuflen;
1140 struct ofork *ofork;
1141 int32_t offset, saveoff, reqcount;
1142 int endflag, eid, xlate = 0, err = AFP_OK;
1146 /* figure out parameters */
1148 endflag = ENDBIT(*ibuf);
1150 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1151 ibuf += sizeof( ofrefnum );
1152 memcpy(&offset, ibuf, sizeof( offset ));
1153 offset = ntohl( offset );
1154 ibuf += sizeof( offset );
1155 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1156 reqcount = ntohl( reqcount );
1157 ibuf += sizeof( reqcount );
1159 if (( ofork = of_find( ofrefnum )) == NULL ) {
1160 LOG(log_error, logtype_default, "afp_write: of_find: %s", strerror(errno) );
1165 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1166 err = AFPERR_ACCESS;
1171 writtenfork = ofork;
1174 if ( ofork->of_flags & AFPFORK_DATA) {
1176 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1177 } else if (ofork->of_flags & AFPFORK_RSRC) {
1180 err = AFPERR_ACCESS; /* should never happen */
1185 offset += ad_size(ofork->of_ad, eid);
1187 /* handle bogus parameters */
1188 if (reqcount < 0 || offset < 0) {
1193 /* offset can overflow on 64-bit capable filesystems.
1194 * report disk full if that's going to happen. */
1195 if (offset + reqcount < 0) {
1200 if (!reqcount) { /* handle request counts of 0 */
1202 offset = htonl(offset);
1203 memcpy(rbuf, &offset, sizeof(offset));
1208 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1214 /* this is yucky, but dsi can stream i/o and asp can't */
1215 switch (obj->proto) {
1218 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1220 LOG(log_error, logtype_default, "afp_write: asp_wrtcont: %s", strerror(errno) );
1221 return( AFPERR_PARAM );
1224 if (obj->options.flags & OPTION_DEBUG) {
1225 printf("(write) len: %d\n", *rbuflen);
1226 bprint(rbuf, *rbuflen);
1229 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1232 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1237 #endif /* no afp/asp */
1241 DSI *dsi = obj->handle;
1243 /* find out what we have already and write it out. */
1244 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1246 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1247 dsi_writeflush(dsi);
1249 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1254 #if 0 /*def HAVE_SENDFILE_WRITE*/
1255 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1256 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1257 offset, dsi->datasize)) < 0) {
1265 LOG(log_error, logtype_default, "afp_write: ad_writefile: %s", strerror(errno) );
1266 goto afp_write_loop;
1268 dsi_writeflush(dsi);
1270 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1276 goto afp_write_done;
1278 #endif /* 0, was HAVE_SENDFILE_WRITE */
1280 /* loop until everything gets written. currently
1281 * dsi_write handles the end case by itself. */
1283 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1284 if ( obj->options.flags & OPTION_DEBUG ) {
1285 printf("(write) command cont'd: %d\n", cc);
1289 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1290 dsi_writeflush(dsi);
1292 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1303 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1304 if ( ad_hfileno( ofork->of_ad ) != -1 )
1305 ofork->of_flags |= AFPFORK_DIRTY;
1307 offset = htonl( offset );
1308 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1309 bcopy(&offset, rbuf, sizeof(offset));
1310 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1311 memcpy(rbuf, &offset, sizeof(offset));
1312 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1313 *rbuflen = sizeof(offset);
1317 if (obj->proto == AFPPROTO_DSI) {
1318 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1319 dsi_writeflush(obj->handle);
1322 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1327 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1330 int ibuflen, *rbuflen;
1332 struct ofork *ofork;
1334 u_int16_t ofrefnum, bitmap;
1337 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1338 ibuf += sizeof( ofrefnum );
1339 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1340 bitmap = ntohs( bitmap );
1341 ibuf += sizeof( bitmap );
1344 if (( ofork = of_find( ofrefnum )) == NULL ) {
1345 LOG(log_error, logtype_default, "afp_getforkparams: of_find: %s", strerror(errno) );
1346 return( AFPERR_PARAM );
1349 if (( ret = getforkparams( ofork, bitmap,
1350 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1354 *rbuflen = buflen + sizeof( u_short );
1355 bitmap = htons( bitmap );
1356 memcpy(rbuf, &bitmap, sizeof( bitmap ));