2 * $Id: fork.c,v 1.7 2001-08-15 01:37:34 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 */
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;
63 char *data, *nameoff = NULL, *upath;
64 int bit = 0, isad = 1;
68 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
71 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
72 if ( ad_refresh( ofork->of_ad ) < 0 ) {
73 syslog( LOG_ERR, "getforkparams: ad_refresh: %s", strerror(errno) );
74 return( AFPERR_PARAM );
76 /* See afp_closefork() for why this is bad */
77 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
80 /* can only get the length of the opened fork */
81 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
82 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
83 return( AFPERR_BITMAP );
86 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
87 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
88 (1 << FILPBIT_BDATE))) {
89 upath = mtoupath(ofork->of_vol, ofork->of_name);
90 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
91 if ( stat( upath, &st ) < 0 )
92 return( AFPERR_NOOBJ );
94 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
95 return( AFPERR_BITMAP );
101 while ( bitmap != 0 ) {
102 while (( bitmap & 1 ) == 0 ) {
110 ad_getattr(ofork->of_ad, &ashort);
115 ashort = htons(ntohs(ashort) | attrbits);
116 memcpy(data, &ashort, sizeof( ashort ));
117 data += sizeof( ashort );
121 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
122 data += sizeof( aint );
127 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
128 aint = AD_DATE_FROM_UNIX(st.st_mtime);
129 memcpy(data, &aint, sizeof( aint ));
130 data += sizeof( aint );
135 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
136 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
137 aint = AD_DATE_FROM_UNIX(st.st_mtime);
138 memcpy(data, &aint, sizeof( aint ));
139 data += sizeof( aint );
144 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
145 aint = AD_DATE_START;
146 memcpy(data, &aint, sizeof( aint ));
147 data += sizeof( aint );
152 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
153 (void *) ufinderi, 32);
155 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
156 ufinderi, 8 ) == 0 ) {
157 memcpy(data, ufinderi, 8 );
158 if (( em = getextmap( ofork->of_name )) != NULL ) {
159 memcpy(data, em->em_type, sizeof( em->em_type ));
160 memcpy(data + 4, em->em_creator,
161 sizeof( em->em_creator ));
169 data += sizeof(u_int16_t);
173 memset(data, 0, sizeof(u_int16_t));
174 data += sizeof(u_int16_t);
180 /* find out if we have a fixed did already */
181 aint = cnid_lookup(ofork->of_vol->v_db, &st,
182 ofork->of_dir->d_did,
183 upath, strlen(upath));
186 /* look in AD v2 header */
189 #if AD_VERSION > AD_VERSION1
191 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
192 #endif /* AD_VERSION > AD_VERSION1 */
195 aint = cnid_add(ofork->of_vol->v_db, &st,
196 ofork->of_dir->d_did,
197 upath, strlen(upath), aint);
205 aint = ( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff );
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 );
320 /* try opening in read-write mode with a fallback to read-only
321 * if we don't need write access. */
322 upath = mtoupath(vol, path);
324 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
329 if (access & OPENACC_WR)
332 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
333 /* check for a read-only data fork */
334 if ((adflags != ADFLAGS_HF) &&
335 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
338 adflags = ADFLAGS_DF;
345 /* see if client asked for the data fork */
346 if (fork == OPENFORK_DATA) {
347 if (((access & OPENACC_WR) &&
348 (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0))
349 || (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0,
350 ofork->of_ad) < 0)) {
353 adflags = ADFLAGS_DF;
355 } else if (stat(upath, &st) == 0) {
356 /* here's the deal. we only try to create the resource
357 * fork if the user wants to open it for write access. */
358 if ((access & OPENACC_WR) &&
359 (ad_open(upath, adflags, O_RDWR | O_CREAT,
360 0666, ofork->of_ad) < 0))
372 ret = AFPERR_BADTYPE;
376 syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
383 if ((adflags & ADFLAGS_HF) &&
384 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
385 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
386 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
387 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
388 ad_flush( ofork->of_ad, adflags );
391 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
392 &buflen, attrbits )) != AFP_OK ) {
393 ad_close( ofork->of_ad, adflags );
397 *rbuflen = buflen + 2 * sizeof( u_int16_t );
398 bitmap = htons( bitmap );
399 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
400 rbuf += sizeof( u_int16_t );
403 * synchronization locks:
406 * 1) attempt a read lock to see if we have read or write
408 * 2) if that succeeds, set a write lock to correspond to the
409 * deny mode requested.
410 * 3) whenever a file is read/written, locks get set which
414 /* don't try to lock non-existent rforks. */
415 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
417 /* try to see if we have access. */
419 if (access & OPENACC_WR) {
420 ofork->of_flags |= AFPFORK_ACCWR;
421 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
422 AD_FILELOCK_WR, 1, ofrefnum);
425 if (!ret && (access & OPENACC_RD)) {
426 ofork->of_flags |= AFPFORK_ACCRD;
427 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
428 AD_FILELOCK_RD, 1, ofrefnum);
431 /* can we access the fork? */
433 ad_close( ofork->of_ad, adflags );
436 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
437 return (AFPERR_DENYCONF);
440 /* now try to set the deny lock. if the fork is open for read or
441 * write, a read lock will already have been set. otherwise, we upgrade
442 * our lock to a write lock.
444 * NOTE: we can't write lock a read-only file. on those, we just
445 * make sure that we have a read lock set. that way, we at least prevent
446 * someone else from really setting a deny read/write on the file. */
447 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
448 ADLOCK_WR : ADLOCK_RD;
449 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
450 lockop | ADLOCK_FILELOCK |
451 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
453 if (!ret && (access & OPENACC_DRD))
454 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
455 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
459 ad_close( ofork->of_ad, adflags );
462 case EAGAIN: /* return data anyway */
466 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
467 return( AFPERR_DENYCONF );
471 syslog( LOG_ERR, "afp_openfork: ad_lock: %s", strerror(errno) );
472 return( AFPERR_PARAM );
477 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
483 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
487 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
490 int ibuflen, *rbuflen;
494 u_int16_t ofrefnum, bitmap;
498 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
499 ibuf += sizeof( ofrefnum );
500 memcpy(&bitmap, ibuf, sizeof(bitmap));
501 bitmap = ntohs(bitmap);
502 ibuf += sizeof( bitmap );
503 memcpy(&size, ibuf, sizeof( size ));
504 size = ntohl( size );
507 if (( ofork = of_find( ofrefnum )) == NULL ) {
508 syslog( LOG_ERR, "afp_setforkparams: of_find: %s", strerror(errno) );
509 return( AFPERR_PARAM );
512 if (ofork->of_vol->v_flags & AFPVOL_RO)
515 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
516 return AFPERR_ACCESS;
521 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
522 err = ad_dtruncate( ofork->of_ad, size );
524 goto afp_setfork_err;
525 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
526 (ofork->of_flags & AFPFORK_RSRC)) {
527 ad_refresh( ofork->of_ad );
528 err = ad_rtruncate(ofork->of_ad, size);
530 goto afp_setfork_err;
532 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
533 syslog( LOG_ERR, "afp_setforkparams: ad_flush: %s",
535 return( AFPERR_PARAM );
538 return AFPERR_BITMAP;
541 if ( flushfork( ofork ) < 0 ) {
542 syslog( LOG_ERR, "afp_setforkparams: flushfork: %m" );
557 return AFPERR_ACCESS;
568 /* for this to work correctly, we need to check for locks before each
569 * read and write. that's most easily handled by always doing an
570 * appropriate check before each ad_read/ad_write. other things
571 * that can change files like truncate are handled internally to those
574 #define ENDBIT(a) ((a) & 0x80)
575 #define UNLOCKBIT(a) ((a) & 0x01)
576 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
579 int ibuflen, *rbuflen;
582 int32_t offset, length;
589 /* figure out parameters */
591 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
593 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
594 ibuf += sizeof(ofrefnum);
596 if (( ofork = of_find( ofrefnum )) == NULL ) {
597 syslog( LOG_ERR, "afp_bytelock: of_find: %s", strerror(errno) );
598 return( AFPERR_PARAM );
601 if ( ofork->of_flags & AFPFORK_DATA) {
603 } else if (ofork->of_flags & AFPFORK_RSRC) {
608 memcpy(&offset, ibuf, sizeof( offset ));
609 offset = ntohl(offset);
610 ibuf += sizeof(offset);
612 memcpy(&length, ibuf, sizeof( length ));
613 length = ntohl(length);
614 if (length == 0xFFFFFFFF)
615 length = BYTELOCK_MAX;
616 else if (length <= 0) {
618 } else if ((length >= AD_FILELOCK_BASE) &&
619 (ad_hfileno(ofork->of_ad) == -1))
623 offset += ad_size(ofork->of_ad, eid);
625 if (offset < 0) /* error if we have a negative offset */
628 /* if the file is a read-only file, we use read locks instead of
629 * write locks. that way, we can prevent anyone from initiating
631 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
632 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
633 ADLOCK_WR : ADLOCK_RD), offset, length,
634 ofork->of_refnum) < 0) {
638 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
644 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
653 offset = htonl(offset);
654 memcpy(rbuf, &offset, sizeof( offset ));
655 *rbuflen = sizeof( offset );
661 static __inline__ int crlf( of )
666 if ( ad_hfileno( of->of_ad ) == -1 ||
667 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
669 if (( em = getextmap( of->of_name )) == NULL ||
670 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
676 if ( memcmp( ufinderi,
677 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
686 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
687 int offset, u_char nlmask,
688 u_char nlchar, char *rbuf,
689 int *rbuflen, const int xlate)
695 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
697 syslog( LOG_ERR, "afp_read: ad_read: %s", strerror(errno) );
699 return( AFPERR_PARAM );
701 if ( cc < *rbuflen ) {
709 for ( p = rbuf, q = p + cc; p < q; ) {
710 if (( *p++ & nlmask ) == nlchar ) {
721 * If this file is of type TEXT, then swap \012 to \015.
724 for ( p = rbuf, q = p + cc; p < q; p++ ) {
725 if ( *p == '\012' ) {
727 } else if ( *p == '\015' ) {
736 return( AFPERR_EOF );
741 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
744 int ibuflen, *rbuflen;
748 int32_t offset, saveoff, reqcount;
749 int cc, err, eid, xlate = 0;
751 u_char nlmask, nlchar;
754 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
755 ibuf += sizeof( u_short );
757 if (( ofork = of_find( ofrefnum )) == NULL ) {
758 syslog( LOG_ERR, "afp_read: of_find: %s", strerror(errno) );
763 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
768 memcpy(&offset, ibuf, sizeof( offset ));
769 offset = ntohl( offset );
770 ibuf += sizeof( offset );
771 memcpy(&reqcount, ibuf, sizeof( reqcount ));
772 reqcount = ntohl( reqcount );
773 ibuf += sizeof( reqcount );
778 /* if we wanted to be picky, we could add in the following
779 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
781 if (reqcount < 0 || offset < 0) {
786 if ( ofork->of_flags & AFPFORK_DATA) {
788 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
789 } else if (ofork->of_flags & AFPFORK_RSRC) {
791 } else { /* fork wasn't opened. this should never really happen. */
796 /* zero request count */
802 /* reqcount isn't always truthful. we need to deal with that. */
803 if ((size = ad_size(ofork->of_ad, eid)) == 0) {
809 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, reqcount) < 0) {
814 #define min(a,b) ((a)<(b)?(a):(b))
815 *rbuflen = min( reqcount, *rbuflen );
816 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
821 /* dsi can stream requests. we can only do this if we're not checking
822 * for an end-of-line character. oh well. */
823 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
824 DSI *dsi = obj->handle;
826 /* subtract off the offset */
828 if (reqcount > size) {
833 if (obj->options.flags & OPTION_DEBUG) {
834 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
835 reqcount, dsi->clientID);
836 bprint(rbuf, *rbuflen);
841 /* dsi_readinit() returns size of next read buffer. by this point,
842 * we know that we're sending some data. if we fail, something
843 * horrible happened. */
844 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
847 /* due to the nature of afp packets, we have to exit if we get
848 an error. we can't do this with translation on. */
849 #ifdef HAVE_SENDFILE_READ
850 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
851 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
852 dsi->datasize) < 0) {
856 syslog(LOG_ERR, "afp_read: ad_readfile: %s", strerror(errno));
866 #endif /* HAVE_SENDFILE_READ */
868 /* fill up our buffer. */
869 while (*rbuflen > 0) {
870 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
876 if (obj->options.flags & OPTION_DEBUG) {
877 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
878 bprint(rbuf, *rbuflen);
881 /* dsi_read() also returns buffer size of next allocation */
882 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
891 syslog(LOG_ERR, "afp_read: %s", strerror(errno));
893 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
898 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
906 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
909 int ibuflen, *rbuflen;
917 memcpy(&vid, ibuf, sizeof(vid));
918 if (( vol = getvolbyvid( vid )) == NULL ) {
919 return( AFPERR_PARAM );
926 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
929 int ibuflen, *rbuflen;
936 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
938 if (( ofork = of_find( ofrefnum )) == NULL ) {
939 syslog( LOG_ERR, "afp_flushfork: of_find: %s", strerror(errno) );
940 return( AFPERR_PARAM );
943 if ( flushfork( ofork ) < 0 ) {
944 syslog( LOG_ERR, "afp_flushfork: %s", strerror(errno) );
950 /* this is very similar to closefork */
951 int flushfork( ofork )
955 int len, err = 0, doflush = 0;
957 if ( ad_dfileno( ofork->of_ad ) != -1 &&
958 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
959 syslog( LOG_ERR, "flushfork: dfile(%d) %s",
960 ad_dfileno(ofork->of_ad), strerror(errno) );
964 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
966 /* read in the rfork length */
967 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
968 ad_refresh(ofork->of_ad);
970 /* set the date if we're dirty */
971 if ((ofork->of_flags & AFPFORK_DIRTY) &&
972 (gettimeofday(&tv, NULL) == 0)) {
973 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
974 ofork->of_flags &= ~AFPFORK_DIRTY;
978 /* if we're actually flushing this fork, make sure to set the
979 * length. otherwise, just use the stored length */
980 if ((ofork->of_flags & AFPFORK_RSRC) &&
981 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
982 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
987 /* flush the header (if it is a resource fork) */
988 if (ofork->of_flags & AFPFORK_RSRC)
989 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
992 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
996 syslog( LOG_ERR, "flushfork: hfile(%d) %m",
997 ad_hfileno(ofork->of_ad) );
1003 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1006 int ibuflen, *rbuflen;
1008 struct ofork *ofork;
1010 int adflags, aint, doflush = 0;
1015 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1017 if (( ofork = of_find( ofrefnum )) == NULL ) {
1018 syslog( LOG_ERR, "afp_closefork: of_find: %m" );
1019 return( AFPERR_PARAM );
1023 if ((ofork->of_flags & AFPFORK_DATA) &&
1024 (ad_dfileno( ofork->of_ad ) != -1)) {
1025 adflags |= ADFLAGS_DF;
1028 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1029 adflags |= ADFLAGS_HF;
1031 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1032 ad_refresh( ofork->of_ad );
1033 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1034 (gettimeofday(&tv, NULL) == 0)) {
1035 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1041 * Only set the rfork's length if we're closing the rfork.
1043 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1044 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1045 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1049 ad_flush( ofork->of_ad, adflags );
1053 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1054 syslog( LOG_ERR, "afp_closefork: ad_close: %m" );
1055 return( AFPERR_PARAM );
1058 of_dealloc( ofork );
1063 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1064 off_t offset, char *rbuf,
1065 size_t rbuflen, const int xlate)
1071 * If this file is of type TEXT, swap \015 to \012.
1074 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1075 if ( *p == '\015' ) {
1077 } else if ( *p == '\012' ) {
1083 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1084 rbuf, rbuflen)) < 0 ) {
1089 return( AFPERR_DFULL );
1091 syslog( LOG_ERR, "afp_write: ad_write: %m" );
1092 return( AFPERR_PARAM );
1099 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1100 * the client may have sent us a bunch of data that's not reflected
1101 * in reqcount et al. */
1102 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1105 int ibuflen, *rbuflen;
1107 struct ofork *ofork;
1108 int32_t offset, saveoff, reqcount;
1109 int endflag, eid, xlate = 0, err = AFP_OK;
1113 /* figure out parameters */
1115 endflag = ENDBIT(*ibuf);
1117 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1118 ibuf += sizeof( ofrefnum );
1119 memcpy(&offset, ibuf, sizeof( offset ));
1120 offset = ntohl( offset );
1121 ibuf += sizeof( offset );
1122 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1123 reqcount = ntohl( reqcount );
1124 ibuf += sizeof( reqcount );
1126 if (( ofork = of_find( ofrefnum )) == NULL ) {
1127 syslog( LOG_ERR, "afp_write: of_find: %m" );
1132 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1133 err = AFPERR_ACCESS;
1138 writtenfork = ofork;
1141 if ( ofork->of_flags & AFPFORK_DATA) {
1143 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1144 } else if (ofork->of_flags & AFPFORK_RSRC) {
1147 err = AFPERR_ACCESS; /* should never happen */
1152 offset += ad_size(ofork->of_ad, eid);
1154 /* handle bogus parameters */
1155 if (reqcount < 0 || offset < 0) {
1160 /* offset can overflow on 64-bit capable filesystems.
1161 * report disk full if that's going to happen. */
1162 if (offset + reqcount < 0) {
1167 if (!reqcount) { /* handle request counts of 0 */
1169 offset = htonl(offset);
1170 memcpy(rbuf, &offset, sizeof(offset));
1175 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1181 /* this is yucky, but dsi can stream i/o and asp can't */
1182 switch (obj->proto) {
1185 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1187 syslog( LOG_ERR, "afp_write: asp_wrtcont: %m" );
1188 return( AFPERR_PARAM );
1191 if (obj->options.flags & OPTION_DEBUG) {
1192 printf("(write) len: %d\n", *rbuflen);
1193 bprint(rbuf, *rbuflen);
1196 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1199 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1204 #endif /* no afp/asp */
1208 DSI *dsi = obj->handle;
1210 /* find out what we have already and write it out. */
1211 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1213 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1214 dsi_writeflush(dsi);
1216 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1221 #if 0 /*def HAVE_SENDFILE_WRITE*/
1222 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1223 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1224 offset, dsi->datasize)) < 0) {
1232 syslog( LOG_ERR, "afp_write: ad_writefile: %m" );
1233 goto afp_write_loop;
1235 dsi_writeflush(dsi);
1237 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1243 goto afp_write_done;
1245 #endif /* 0, was HAVE_SENDFILE_WRITE */
1247 /* loop until everything gets written. currently
1248 * dsi_write handles the end case by itself. */
1250 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1251 if ( obj->options.flags & OPTION_DEBUG ) {
1252 printf("(write) command cont'd: %d\n", cc);
1256 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1257 dsi_writeflush(dsi);
1259 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1270 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1271 if ( ad_hfileno( ofork->of_ad ) != -1 )
1272 ofork->of_flags |= AFPFORK_DIRTY;
1274 offset = htonl( offset );
1275 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1276 bcopy(&offset, rbuf, sizeof(offset));
1277 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1278 memcpy(rbuf, &offset, sizeof(offset));
1279 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1280 *rbuflen = sizeof(offset);
1284 if (obj->proto == AFPPROTO_DSI) {
1285 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1286 dsi_writeflush(obj->handle);
1289 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1294 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1297 int ibuflen, *rbuflen;
1299 struct ofork *ofork;
1301 u_int16_t ofrefnum, bitmap;
1304 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1305 ibuf += sizeof( ofrefnum );
1306 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1307 bitmap = ntohs( bitmap );
1308 ibuf += sizeof( bitmap );
1311 if (( ofork = of_find( ofrefnum )) == NULL ) {
1312 syslog( LOG_ERR, "afp_getforkparams: of_find: %m" );
1313 return( AFPERR_PARAM );
1316 if (( ret = getforkparams( ofork, bitmap,
1317 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1321 *rbuflen = buflen + sizeof( u_short );
1322 bitmap = htons( bitmap );
1323 memcpy(rbuf, &bitmap, sizeof( bitmap ));