2 * $Id: fork.c,v 1.21 2002-02-03 04:57:38 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);
194 if (aint == CNID_INVALID) {
197 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "afp_setforkparams: ad_flush: %s",
580 return( AFPERR_PARAM );
583 return AFPERR_BITMAP;
586 if ( flushfork( ofork ) < 0 ) {
587 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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 LOG(log_error, logtype_default, "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,
881 /* dsi can stream requests. we can only do this if we're not checking
882 * for an end-of-line character. oh well. */
883 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
884 DSI *dsi = obj->handle;
886 if (obj->options.flags & OPTION_DEBUG) {
887 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
888 reqcount, dsi->clientID);
889 bprint(rbuf, *rbuflen);
894 /* dsi_readinit() returns size of next read buffer. by this point,
895 * we know that we're sending some data. if we fail, something
896 * horrible happened. */
897 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
900 /* due to the nature of afp packets, we have to exit if we get
901 an error. we can't do this with translation on. */
902 #ifdef HAVE_SENDFILE_READ
903 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
904 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
905 dsi->datasize) < 0) {
909 LOG(log_error, logtype_default, "afp_read: ad_readfile: %s", strerror(errno));
919 #endif /* HAVE_SENDFILE_READ */
921 /* fill up our buffer. */
922 while (*rbuflen > 0) {
923 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
929 if (obj->options.flags & OPTION_DEBUG) {
930 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
931 bprint(rbuf, *rbuflen);
934 /* dsi_read() also returns buffer size of next allocation */
935 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
944 LOG(log_error, logtype_default, "afp_read: %s", strerror(errno));
946 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
951 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
959 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
962 int ibuflen, *rbuflen;
970 memcpy(&vid, ibuf, sizeof(vid));
971 if (( vol = getvolbyvid( vid )) == NULL ) {
972 return( AFPERR_PARAM );
979 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
982 int ibuflen, *rbuflen;
989 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
991 if (( ofork = of_find( ofrefnum )) == NULL ) {
992 LOG(log_error, logtype_default, "afp_flushfork: of_find: %s", strerror(errno) );
993 return( AFPERR_PARAM );
996 if ( flushfork( ofork ) < 0 ) {
997 LOG(log_error, logtype_default, "afp_flushfork: %s", strerror(errno) );
1003 /* this is very similar to closefork */
1004 int flushfork( ofork )
1005 struct ofork *ofork;
1008 int len, err = 0, doflush = 0;
1010 if ( ad_dfileno( ofork->of_ad ) != -1 &&
1011 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1012 LOG(log_error, logtype_default, "flushfork: dfile(%d) %s",
1013 ad_dfileno(ofork->of_ad), strerror(errno) );
1017 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1019 /* read in the rfork length */
1020 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
1021 ad_refresh(ofork->of_ad);
1023 /* set the date if we're dirty */
1024 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1025 (gettimeofday(&tv, NULL) == 0)) {
1026 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1027 ofork->of_flags &= ~AFPFORK_DIRTY;
1031 /* if we're actually flushing this fork, make sure to set the
1032 * length. otherwise, just use the stored length */
1033 if ((ofork->of_flags & AFPFORK_RSRC) &&
1034 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
1035 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
1040 /* flush the header (if it is a resource fork) */
1041 if (ofork->of_flags & AFPFORK_RSRC)
1042 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
1045 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1049 LOG(log_error, logtype_default, "flushfork: hfile(%d) %s",
1050 ad_hfileno(ofork->of_ad), strerror(errno) );
1056 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1059 int ibuflen, *rbuflen;
1061 struct ofork *ofork;
1063 int adflags, aint, doflush = 0;
1068 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1070 if (( ofork = of_find( ofrefnum )) == NULL ) {
1071 LOG(log_error, logtype_default, "afp_closefork: of_find: %s", strerror(errno) );
1072 return( AFPERR_PARAM );
1076 if ((ofork->of_flags & AFPFORK_DATA) &&
1077 (ad_dfileno( ofork->of_ad ) != -1)) {
1078 adflags |= ADFLAGS_DF;
1081 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1082 adflags |= ADFLAGS_HF;
1084 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1085 ad_refresh( ofork->of_ad );
1086 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1087 (gettimeofday(&tv, NULL) == 0)) {
1088 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1094 * Only set the rfork's length if we're closing the rfork.
1096 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1097 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1098 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1102 ad_flush( ofork->of_ad, adflags );
1106 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1107 LOG(log_error, logtype_default, "afp_closefork: ad_close: %s", strerror(errno) );
1108 return( AFPERR_PARAM );
1111 of_dealloc( ofork );
1116 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1117 off_t offset, char *rbuf,
1118 size_t rbuflen, const int xlate)
1124 * If this file is of type TEXT, swap \015 to \012.
1127 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1128 if ( *p == '\015' ) {
1130 } else if ( *p == '\012' ) {
1136 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1137 rbuf, rbuflen)) < 0 ) {
1142 return( AFPERR_DFULL );
1144 LOG(log_error, logtype_default, "afp_write: ad_write: %s", strerror(errno) );
1145 return( AFPERR_PARAM );
1152 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1153 * the client may have sent us a bunch of data that's not reflected
1154 * in reqcount et al. */
1155 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1158 int ibuflen, *rbuflen;
1160 struct ofork *ofork;
1161 int32_t offset, saveoff, reqcount;
1162 int endflag, eid, xlate = 0, err = AFP_OK;
1166 /* figure out parameters */
1168 endflag = ENDBIT(*ibuf);
1170 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1171 ibuf += sizeof( ofrefnum );
1172 memcpy(&offset, ibuf, sizeof( offset ));
1173 offset = ntohl( offset );
1174 ibuf += sizeof( offset );
1175 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1176 reqcount = ntohl( reqcount );
1177 ibuf += sizeof( reqcount );
1179 if (( ofork = of_find( ofrefnum )) == NULL ) {
1180 LOG(log_error, logtype_default, "afp_write: of_find: %s", strerror(errno) );
1185 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1186 err = AFPERR_ACCESS;
1191 writtenfork = ofork;
1194 if ( ofork->of_flags & AFPFORK_DATA) {
1196 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1197 } else if (ofork->of_flags & AFPFORK_RSRC) {
1200 err = AFPERR_ACCESS; /* should never happen */
1205 offset += ad_size(ofork->of_ad, eid);
1207 /* handle bogus parameters */
1208 if (reqcount < 0 || offset < 0) {
1213 /* offset can overflow on 64-bit capable filesystems.
1214 * report disk full if that's going to happen. */
1215 if (offset + reqcount < 0) {
1220 if (!reqcount) { /* handle request counts of 0 */
1222 offset = htonl(offset);
1223 memcpy(rbuf, &offset, sizeof(offset));
1228 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1234 /* this is yucky, but dsi can stream i/o and asp can't */
1235 switch (obj->proto) {
1238 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1240 LOG(log_error, logtype_default, "afp_write: asp_wrtcont: %s", strerror(errno) );
1241 return( AFPERR_PARAM );
1244 if (obj->options.flags & OPTION_DEBUG) {
1245 printf("(write) len: %d\n", *rbuflen);
1246 bprint(rbuf, *rbuflen);
1249 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1252 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1257 #endif /* no afp/asp */
1261 DSI *dsi = obj->handle;
1263 /* find out what we have already and write it out. */
1264 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1266 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1267 dsi_writeflush(dsi);
1269 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1274 #if 0 /*def HAVE_SENDFILE_WRITE*/
1275 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1276 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1277 offset, dsi->datasize)) < 0) {
1285 LOG(log_error, logtype_default, "afp_write: ad_writefile: %s", strerror(errno) );
1286 goto afp_write_loop;
1288 dsi_writeflush(dsi);
1290 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1296 goto afp_write_done;
1298 #endif /* 0, was HAVE_SENDFILE_WRITE */
1300 /* loop until everything gets written. currently
1301 * dsi_write handles the end case by itself. */
1303 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1304 if ( obj->options.flags & OPTION_DEBUG ) {
1305 printf("(write) command cont'd: %d\n", cc);
1309 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1310 dsi_writeflush(dsi);
1312 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1323 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1324 if ( ad_hfileno( ofork->of_ad ) != -1 )
1325 ofork->of_flags |= AFPFORK_DIRTY;
1327 offset = htonl( offset );
1328 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1329 bcopy(&offset, rbuf, sizeof(offset));
1330 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1331 memcpy(rbuf, &offset, sizeof(offset));
1332 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1333 *rbuflen = sizeof(offset);
1337 if (obj->proto == AFPPROTO_DSI) {
1338 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1339 dsi_writeflush(obj->handle);
1342 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1347 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1350 int ibuflen, *rbuflen;
1352 struct ofork *ofork;
1354 u_int16_t ofrefnum, bitmap;
1357 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1358 ibuf += sizeof( ofrefnum );
1359 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1360 bitmap = ntohs( bitmap );
1361 ibuf += sizeof( bitmap );
1364 if (( ofork = of_find( ofrefnum )) == NULL ) {
1365 LOG(log_error, logtype_default, "afp_getforkparams: of_find: %s", strerror(errno) );
1366 return( AFPERR_PARAM );
1369 if (( ret = getforkparams( ofork, bitmap,
1370 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1374 *rbuflen = buflen + sizeof( u_short );
1375 bitmap = htons( bitmap );
1376 memcpy(rbuf, &bitmap, sizeof( bitmap ));