2 * $Id: fork.c,v 1.11.2.5 2002-03-11 17:54:01 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 */
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 syslog( LOG_ERR, "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);
194 if (aint == CNID_INVALID) {
197 syslog(LOG_ERR, "getforkparams: Incorrect parameters passed to cnid_add");
198 return(AFPERR_PARAM);
200 return(AFPERR_PARAM);
210 aint = htonl(( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff ));
211 #else /* USE_LASTDID */
212 lstp = lstat(upath, &lst) < 0 ? &st : &lst;
214 aint = htonl( afpd_st_cnid ( lstp ) );
216 aint = htonl(CNID(lstp, 1));
217 #endif /* DID_MTAB */
218 #endif /* USE_LASTDID */
221 memcpy(data, &aint, sizeof( aint ));
222 data += sizeof( aint );
226 aint = htonl( st.st_size );
227 memcpy(data, &aint, sizeof( aint ));
228 data += sizeof( aint );
233 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
237 memcpy(data, &aint, sizeof( aint ));
238 data += sizeof( aint );
242 return( AFPERR_BITMAP );
249 ashort = htons( data - buf );
250 memcpy(nameoff, &ashort, sizeof( ashort ));
251 aint = strlen( ofork->of_name );
252 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
254 memcpy(data, ofork->of_name, aint );
258 *buflen = data - buf;
262 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
265 int ibuflen, *rbuflen;
269 struct ofork *ofork, *opened;
270 struct adouble *adsame = NULL;
271 int buflen, ret, adflags, eid, lockop;
273 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
274 char fork, *path, *upath;
278 memcpy(&vid, ibuf, sizeof( vid ));
282 if (( vol = getvolbyvid( vid )) == NULL ) {
283 return( AFPERR_PARAM );
286 memcpy(&did, ibuf, sizeof( did ));
287 ibuf += sizeof( int );
289 if (( dir = dirsearch( vol, did )) == NULL ) {
290 return( AFPERR_NOOBJ );
293 memcpy(&bitmap, ibuf, sizeof( bitmap ));
294 bitmap = ntohs( bitmap );
295 ibuf += sizeof( bitmap );
296 memcpy(&access, ibuf, sizeof( access ));
297 access = ntohs( access );
298 ibuf += sizeof( access );
300 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
304 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
305 return( AFPERR_NOOBJ );
308 if ( fork == OPENFORK_DATA ) {
310 adflags = ADFLAGS_DF|ADFLAGS_HF;
313 adflags = ADFLAGS_HF;
316 /* XXX: this probably isn't the best way to do this. the already
317 open bits should really be set if the fork is opened by any
318 program, not just this one. however, that's problematic to do
319 if we can't write lock files somewhere. opened is also passed to
320 ad_open so that we can keep file locks together. */
321 if ((opened = of_findname(vol, curdir, path))) {
322 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
323 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
324 adsame = opened->of_ad;
327 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
329 return( AFPERR_NFILE );
331 if (access & OPENACC_WR) {
332 /* try opening in read-write mode */
333 upath = mtoupath(vol, path);
335 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
347 /* see if client asked for the data fork */
348 if (fork == OPENFORK_DATA) {
349 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
352 adflags = ADFLAGS_DF;
354 } else if (stat(upath, &st) == 0) {
355 /* here's the deal. we only try to create the resource
356 * fork if the user wants to open it for write acess. */
357 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
369 ret = AFPERR_BADTYPE;
373 syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
380 /* try opening in read-only mode */
381 upath = mtoupath(vol, path);
383 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
388 /* check for a read-only data fork */
389 if ((adflags != ADFLAGS_HF) &&
390 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
393 adflags = ADFLAGS_DF;
399 /* see if client asked for the data fork */
400 if (fork == OPENFORK_DATA) {
401 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
404 adflags = ADFLAGS_DF;
406 } else if (stat(upath, &st) != 0) {
417 ret = AFPERR_BADTYPE;
421 syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
428 if ((adflags & ADFLAGS_HF) &&
429 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
430 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
431 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
432 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
433 ad_flush( ofork->of_ad, adflags );
436 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
437 &buflen, attrbits )) != AFP_OK ) {
438 ad_close( ofork->of_ad, adflags );
442 *rbuflen = buflen + 2 * sizeof( u_int16_t );
443 bitmap = htons( bitmap );
444 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
445 rbuf += sizeof( u_int16_t );
448 * synchronization locks:
451 * 1) attempt a read lock to see if we have read or write
453 * 2) if that succeeds, set a write lock to correspond to the
454 * deny mode requested.
455 * 3) whenever a file is read/written, locks get set which
459 /* don't try to lock non-existent rforks. */
460 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
462 /* try to see if we have access. */
464 if (access & OPENACC_WR) {
465 ofork->of_flags |= AFPFORK_ACCWR;
466 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
467 AD_FILELOCK_WR, 1, ofrefnum);
470 if (!ret && (access & OPENACC_RD)) {
471 ofork->of_flags |= AFPFORK_ACCRD;
472 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
473 AD_FILELOCK_RD, 1, ofrefnum);
476 /* can we access the fork? */
478 ad_close( ofork->of_ad, adflags );
481 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
482 return (AFPERR_DENYCONF);
485 /* now try to set the deny lock. if the fork is open for read or
486 * write, a read lock will already have been set. otherwise, we upgrade
487 * our lock to a write lock.
489 * NOTE: we can't write lock a read-only file. on those, we just
490 * make sure that we have a read lock set. that way, we at least prevent
491 * someone else from really setting a deny read/write on the file. */
492 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
493 ADLOCK_WR : ADLOCK_RD;
494 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
495 lockop | ADLOCK_FILELOCK |
496 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
498 if (!ret && (access & OPENACC_DRD))
499 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
500 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
504 ad_close( ofork->of_ad, adflags );
507 case EAGAIN: /* return data anyway */
511 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
512 return( AFPERR_DENYCONF );
516 syslog( LOG_ERR, "afp_openfork: ad_lock: %s", strerror(errno) );
517 return( AFPERR_PARAM );
522 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
528 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
532 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
535 int ibuflen, *rbuflen;
539 u_int16_t ofrefnum, bitmap;
543 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
544 ibuf += sizeof( ofrefnum );
545 memcpy(&bitmap, ibuf, sizeof(bitmap));
546 bitmap = ntohs(bitmap);
547 ibuf += sizeof( bitmap );
548 memcpy(&size, ibuf, sizeof( size ));
549 size = ntohl( size );
552 if (( ofork = of_find( ofrefnum )) == NULL ) {
553 syslog( LOG_ERR, "afp_setforkparams: of_find: %s", strerror(errno) );
554 return( AFPERR_PARAM );
557 if (ofork->of_vol->v_flags & AFPVOL_RO)
560 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
561 return AFPERR_ACCESS;
566 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
567 err = ad_dtruncate( ofork->of_ad, size );
569 goto afp_setfork_err;
570 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
571 (ofork->of_flags & AFPFORK_RSRC)) {
572 ad_refresh( ofork->of_ad );
573 err = ad_rtruncate(ofork->of_ad, size);
575 goto afp_setfork_err;
577 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
578 syslog( LOG_ERR, "afp_setforkparams: ad_flush: %s",
580 return( AFPERR_PARAM );
583 return AFPERR_BITMAP;
586 if ( flushfork( ofork ) < 0 ) {
587 syslog( LOG_ERR, "afp_setforkparams: flushfork: %s", strerror(errno) );
602 return AFPERR_ACCESS;
613 /* for this to work correctly, we need to check for locks before each
614 * read and write. that's most easily handled by always doing an
615 * appropriate check before each ad_read/ad_write. other things
616 * that can change files like truncate are handled internally to those
619 #define ENDBIT(a) ((a) & 0x80)
620 #define UNLOCKBIT(a) ((a) & 0x01)
621 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
624 int ibuflen, *rbuflen;
627 int32_t offset, length;
634 /* figure out parameters */
636 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
638 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
639 ibuf += sizeof(ofrefnum);
641 if (( ofork = of_find( ofrefnum )) == NULL ) {
642 syslog( LOG_ERR, "afp_bytelock: of_find: %s", strerror(errno) );
643 return( AFPERR_PARAM );
646 if ( ofork->of_flags & AFPFORK_DATA) {
648 } else if (ofork->of_flags & AFPFORK_RSRC) {
653 memcpy(&offset, ibuf, sizeof( offset ));
654 offset = ntohl(offset);
655 ibuf += sizeof(offset);
657 memcpy(&length, ibuf, sizeof( length ));
658 length = ntohl(length);
659 if (length == 0xFFFFFFFF)
660 length = BYTELOCK_MAX;
661 else if (length <= 0) {
663 } else if ((length >= AD_FILELOCK_BASE) &&
664 (ad_hfileno(ofork->of_ad) == -1))
668 offset += ad_size(ofork->of_ad, eid);
670 if (offset < 0) /* error if we have a negative offset */
673 /* if the file is a read-only file, we use read locks instead of
674 * write locks. that way, we can prevent anyone from initiating
676 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
677 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
678 ADLOCK_WR : ADLOCK_RD), offset, length,
679 ofork->of_refnum) < 0) {
683 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
689 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
698 offset = htonl(offset);
699 memcpy(rbuf, &offset, sizeof( offset ));
700 *rbuflen = sizeof( offset );
706 static __inline__ int crlf( of )
711 if ( ad_hfileno( of->of_ad ) == -1 ||
712 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
714 if (( em = getextmap( of->of_name )) == NULL ||
715 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
721 if ( memcmp( ufinderi,
722 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
731 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
732 int offset, u_char nlmask,
733 u_char nlchar, char *rbuf,
734 int *rbuflen, const int xlate)
740 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
742 syslog( LOG_ERR, "afp_read: ad_read: %s", strerror(errno) );
744 return( AFPERR_PARAM );
746 if ( cc < *rbuflen ) {
754 for ( p = rbuf, q = p + cc; p < q; ) {
755 if (( *p++ & nlmask ) == nlchar ) {
766 * If this file is of type TEXT, then swap \012 to \015.
769 for ( p = rbuf, q = p + cc; p < q; p++ ) {
770 if ( *p == '\012' ) {
772 } else if ( *p == '\015' ) {
781 return( AFPERR_EOF );
786 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
789 int ibuflen, *rbuflen;
793 int32_t offset, saveoff, reqcount, savereqcount;
794 int cc, err, saveerr, eid, xlate = 0;
796 u_char nlmask, nlchar;
799 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
800 ibuf += sizeof( u_short );
802 if (( ofork = of_find( ofrefnum )) == NULL ) {
803 syslog( LOG_ERR, "afp_read: of_find: %s", strerror(errno) );
808 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
813 memcpy(&offset, ibuf, sizeof( offset ));
814 offset = ntohl( offset );
815 ibuf += sizeof( offset );
816 memcpy(&reqcount, ibuf, sizeof( reqcount ));
817 reqcount = ntohl( reqcount );
818 ibuf += sizeof( reqcount );
823 /* if we wanted to be picky, we could add in the following
824 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
826 if (reqcount < 0 || offset < 0) {
831 if ( ofork->of_flags & AFPFORK_DATA) {
833 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
834 } else if (ofork->of_flags & AFPFORK_RSRC) {
836 } else { /* fork wasn't opened. this should never really happen. */
841 /* zero request count */
847 /* reqcount isn't always truthful. we need to deal with that. */
848 size = ad_size(ofork->of_ad, eid);
850 if (offset >= size) {
855 /* subtract off the offset */
857 savereqcount = reqcount;
858 if (reqcount > size) {
864 /* if EOF lock on the old reqcount, some prg may need it */
865 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount) < 0) {
870 #define min(a,b) ((a)<(b)?(a):(b))
871 *rbuflen = min( reqcount, *rbuflen );
873 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
880 /* dsi can stream requests. we can only do this if we're not checking
881 * for an end-of-line character. oh well. */
882 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
883 DSI *dsi = obj->handle;
885 if (obj->options.flags & OPTION_DEBUG) {
886 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
887 reqcount, dsi->clientID);
888 bprint(rbuf, *rbuflen);
893 /* dsi_readinit() returns size of next read buffer. by this point,
894 * we know that we're sending some data. if we fail, something
895 * horrible happened. */
896 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
899 /* due to the nature of afp packets, we have to exit if we get
900 an error. we can't do this with translation on. */
901 #ifdef HAVE_SENDFILE_READ
902 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
903 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
904 dsi->datasize) < 0) {
908 syslog(LOG_ERR, "afp_read: ad_readfile: %s", strerror(errno));
918 #endif /* HAVE_SENDFILE_READ */
920 /* fill up our buffer. */
921 while (*rbuflen > 0) {
922 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
928 if (obj->options.flags & OPTION_DEBUG) {
929 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
930 bprint(rbuf, *rbuflen);
933 /* dsi_read() also returns buffer size of next allocation */
934 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
943 syslog(LOG_ERR, "afp_read: %s", strerror(errno));
945 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
950 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
958 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
961 int ibuflen, *rbuflen;
969 memcpy(&vid, ibuf, sizeof(vid));
970 if (( vol = getvolbyvid( vid )) == NULL ) {
971 return( AFPERR_PARAM );
978 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
981 int ibuflen, *rbuflen;
988 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
990 if (( ofork = of_find( ofrefnum )) == NULL ) {
991 syslog( LOG_ERR, "afp_flushfork: of_find: %s", strerror(errno) );
992 return( AFPERR_PARAM );
995 if ( flushfork( ofork ) < 0 ) {
996 syslog( LOG_ERR, "afp_flushfork: %s", strerror(errno) );
1002 /* this is very similar to closefork */
1003 int flushfork( ofork )
1004 struct ofork *ofork;
1007 int len, err = 0, doflush = 0;
1009 if ( ad_dfileno( ofork->of_ad ) != -1 &&
1010 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1011 syslog( LOG_ERR, "flushfork: dfile(%d) %s",
1012 ad_dfileno(ofork->of_ad), strerror(errno) );
1016 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1018 /* read in the rfork length */
1019 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
1020 ad_refresh(ofork->of_ad);
1022 /* set the date if we're dirty */
1023 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1024 (gettimeofday(&tv, NULL) == 0)) {
1025 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1026 ofork->of_flags &= ~AFPFORK_DIRTY;
1030 /* if we're actually flushing this fork, make sure to set the
1031 * length. otherwise, just use the stored length */
1032 if ((ofork->of_flags & AFPFORK_RSRC) &&
1033 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
1034 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
1039 /* flush the header (if it is a resource fork) */
1040 if (ofork->of_flags & AFPFORK_RSRC)
1041 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
1044 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1048 syslog( LOG_ERR, "flushfork: hfile(%d) %s",
1049 ad_hfileno(ofork->of_ad), strerror(errno) );
1055 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1058 int ibuflen, *rbuflen;
1060 struct ofork *ofork;
1062 int adflags, aint, doflush = 0;
1067 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1069 if (( ofork = of_find( ofrefnum )) == NULL ) {
1070 syslog( LOG_ERR, "afp_closefork: of_find: %s", strerror(errno) );
1071 return( AFPERR_PARAM );
1075 if ((ofork->of_flags & AFPFORK_DATA) &&
1076 (ad_dfileno( ofork->of_ad ) != -1)) {
1077 adflags |= ADFLAGS_DF;
1080 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1081 adflags |= ADFLAGS_HF;
1083 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1084 ad_refresh( ofork->of_ad );
1085 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1086 (gettimeofday(&tv, NULL) == 0)) {
1087 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1093 * Only set the rfork's length if we're closing the rfork.
1095 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1096 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1097 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1101 ad_flush( ofork->of_ad, adflags );
1105 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1106 syslog( LOG_ERR, "afp_closefork: ad_close: %s", strerror(errno) );
1107 return( AFPERR_PARAM );
1110 of_dealloc( ofork );
1115 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1116 off_t offset, char *rbuf,
1117 size_t rbuflen, const int xlate)
1123 * If this file is of type TEXT, swap \015 to \012.
1126 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1127 if ( *p == '\015' ) {
1129 } else if ( *p == '\012' ) {
1135 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1136 rbuf, rbuflen)) < 0 ) {
1141 return( AFPERR_DFULL );
1143 syslog( LOG_ERR, "afp_write: ad_write: %s", strerror(errno) );
1144 return( AFPERR_PARAM );
1151 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1152 * the client may have sent us a bunch of data that's not reflected
1153 * in reqcount et al. */
1154 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1157 int ibuflen, *rbuflen;
1159 struct ofork *ofork;
1160 int32_t offset, saveoff, reqcount;
1161 int endflag, eid, xlate = 0, err = AFP_OK;
1165 /* figure out parameters */
1167 endflag = ENDBIT(*ibuf);
1169 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1170 ibuf += sizeof( ofrefnum );
1171 memcpy(&offset, ibuf, sizeof( offset ));
1172 offset = ntohl( offset );
1173 ibuf += sizeof( offset );
1174 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1175 reqcount = ntohl( reqcount );
1176 ibuf += sizeof( reqcount );
1178 if (( ofork = of_find( ofrefnum )) == NULL ) {
1179 syslog( LOG_ERR, "afp_write: of_find: %s", strerror(errno) );
1184 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1185 err = AFPERR_ACCESS;
1190 writtenfork = ofork;
1193 if ( ofork->of_flags & AFPFORK_DATA) {
1195 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1196 } else if (ofork->of_flags & AFPFORK_RSRC) {
1199 err = AFPERR_ACCESS; /* should never happen */
1204 offset += ad_size(ofork->of_ad, eid);
1206 /* handle bogus parameters */
1207 if (reqcount < 0 || offset < 0) {
1212 /* offset can overflow on 64-bit capable filesystems.
1213 * report disk full if that's going to happen. */
1214 if (offset + reqcount < 0) {
1219 if (!reqcount) { /* handle request counts of 0 */
1221 offset = htonl(offset);
1222 memcpy(rbuf, &offset, sizeof(offset));
1227 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1233 /* this is yucky, but dsi can stream i/o and asp can't */
1234 switch (obj->proto) {
1237 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1239 syslog( LOG_ERR, "afp_write: asp_wrtcont: %s", strerror(errno) );
1240 return( AFPERR_PARAM );
1243 if (obj->options.flags & OPTION_DEBUG) {
1244 printf("(write) len: %d\n", *rbuflen);
1245 bprint(rbuf, *rbuflen);
1248 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1251 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1256 #endif /* no afp/asp */
1260 DSI *dsi = obj->handle;
1262 /* find out what we have already and write it out. */
1263 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1265 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1266 dsi_writeflush(dsi);
1268 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1273 #if 0 /*def HAVE_SENDFILE_WRITE*/
1274 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1275 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1276 offset, dsi->datasize)) < 0) {
1284 syslog( LOG_ERR, "afp_write: ad_writefile: %s", strerror(errno) );
1285 goto afp_write_loop;
1287 dsi_writeflush(dsi);
1289 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1295 goto afp_write_done;
1297 #endif /* 0, was HAVE_SENDFILE_WRITE */
1299 /* loop until everything gets written. currently
1300 * dsi_write handles the end case by itself. */
1302 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1303 if ( obj->options.flags & OPTION_DEBUG ) {
1304 printf("(write) command cont'd: %d\n", cc);
1308 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1309 dsi_writeflush(dsi);
1311 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1322 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1323 if ( ad_hfileno( ofork->of_ad ) != -1 )
1324 ofork->of_flags |= AFPFORK_DIRTY;
1326 offset = htonl( offset );
1327 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1328 bcopy(&offset, rbuf, sizeof(offset));
1329 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1330 memcpy(rbuf, &offset, sizeof(offset));
1331 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1332 *rbuflen = sizeof(offset);
1336 if (obj->proto == AFPPROTO_DSI) {
1337 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1338 dsi_writeflush(obj->handle);
1341 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1346 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1349 int ibuflen, *rbuflen;
1351 struct ofork *ofork;
1353 u_int16_t ofrefnum, bitmap;
1356 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1357 ibuf += sizeof( ofrefnum );
1358 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1359 bitmap = ntohs( bitmap );
1360 ibuf += sizeof( bitmap );
1363 if (( ofork = of_find( ofrefnum )) == NULL ) {
1364 syslog( LOG_ERR, "afp_getforkparams: of_find: %s", strerror(errno) );
1365 return( AFPERR_PARAM );
1368 if (( ret = getforkparams( ofork, bitmap,
1369 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1373 *rbuflen = buflen + sizeof( u_short );
1374 bitmap = htons( bitmap );
1375 memcpy(rbuf, &bitmap, sizeof( bitmap ));