2 * $Id: fork.c,v 1.51.2.2.2.10.2.1 2004-10-30 22:42:06 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
18 #include <atalk/adouble.h>
19 #include <atalk/logger.h>
21 #include <sys/param.h>
22 #include <sys/socket.h>
24 #include <netatalk/at.h>
26 #include <atalk/dsi.h>
27 #include <atalk/atp.h>
28 #include <atalk/asp.h>
29 #include <atalk/afp.h>
31 #include <atalk/util.h>
32 #include <atalk/cnid.h>
37 #include "directory.h"
42 #define Debug(a) ((a)->options.flags & OPTION_DEBUG)
47 struct ofork *writtenfork;
48 extern int getmetadata(struct vol *vol,
50 struct path *path, struct dir *dir, char *buf,
51 int *buflen, struct adouble *adp, int attrbits );
53 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
58 const u_int16_t attrbits;
68 /* can only get the length of the opened fork */
69 if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
70 && (ofork->of_flags & AFPFORK_RSRC))
72 ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
73 && (ofork->of_flags & AFPFORK_DATA))) {
74 return( AFPERR_BITMAP );
77 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
86 if (NULL == (path.u_name = mtoupath(vol, ofork->of_name, dir->d_did, utf8_encoding()))) {
87 return( AFPERR_MISC );
89 path.m_name = ofork->of_name;
91 if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
92 (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
93 (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
94 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
95 if (movecwd(vol, dir) < 0)
96 return( AFPERR_NOOBJ );
97 if ( stat( path.u_name, st ) < 0 )
98 return( AFPERR_NOOBJ );
100 if ( fstat( ad_dfileno( ofork->of_ad ), st ) < 0 ) {
101 return( AFPERR_BITMAP );
105 return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp, attrbits );
108 /* ---------------------------- */
109 static off_t get_off_t(ibuf, is64)
117 memcpy(&temp, *ibuf, sizeof( temp ));
118 ret = ntohl(temp); /* ntohl is unsigned */
119 *ibuf += sizeof(temp);
122 memcpy(&temp, *ibuf, sizeof( temp ));
123 *ibuf += sizeof(temp);
124 ret = ntohl(temp)| (ret << 32);
127 ret = (int)ret; /* sign extend */
132 /* ---------------------- */
133 static int set_off_t(offset, rbuf, is64)
143 temp = htonl(offset >> 32);
144 memcpy(rbuf, &temp, sizeof( temp ));
145 rbuf += sizeof(temp);
146 ret = sizeof( temp );
147 offset &= 0xffffffff;
149 temp = htonl(offset);
150 memcpy(rbuf, &temp, sizeof( temp ));
151 ret += sizeof( temp );
156 /* ------------------------
158 static int is_neg(int is64, off_t val)
160 if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
165 static __inline__ int sum_neg(int is64, off_t offset, off_t reqcount)
167 if (is_neg(is64, offset +reqcount) )
172 /* -------------------------
174 static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
176 return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
179 /* -------------------------
181 static int getforkmode(struct adouble *adp, int eid, int what)
183 return ad_testlock(adp, eid, what);
186 static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
194 if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
195 return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
198 if ((access & (OPENACC_RD | OPENACC_DRD))) {
199 if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
201 if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
204 if ((access & OPENACC_RD) && denyreadset) {
208 if ((access & OPENACC_DRD) && readset) {
212 /* boolean logic is not enough, because getforkmode is not always telling the
215 if ((access & OPENACC_RD)) {
216 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
220 if ((access & OPENACC_DRD)) {
221 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
226 /* ------------same for writing -------------- */
227 if ((access & (OPENACC_WR | OPENACC_DWR))) {
228 if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
230 if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
233 if ((access & OPENACC_WR) && denywriteset) {
237 if ((access & OPENACC_DWR) && writeset) {
241 if ((access & OPENACC_WR)) {
242 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
246 if ((access & OPENACC_DWR)) {
247 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
252 if ( access == (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD)) {
253 return ad_excl_lock(adp, eid);
258 /* ----------------------- */
259 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
262 int ibuflen, *rbuflen;
266 struct ofork *ofork, *opened;
267 struct adouble *adsame = NULL;
268 int buflen, ret, adflags, eid;
270 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
271 char fork, *path, *upath;
278 memcpy(&vid, ibuf, sizeof( vid ));
282 if (NULL == ( vol = getvolbyvid( vid ))) {
283 return( AFPERR_PARAM );
286 memcpy(&did, ibuf, sizeof( did ));
287 ibuf += sizeof( int );
289 if (NULL == ( dir = dirlookup( vol, did ))) {
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 (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
305 return get_afp_errno(AFPERR_PARAM);
308 if (*s_path->m_name == '\0') {
310 return AFPERR_BADTYPE;
313 /* stat() data fork st is set because it's not a dir */
314 switch ( s_path->st_errno ) {
320 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
322 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
325 /* FIXME should we check it first ? */
326 upath = s_path->u_name;
327 if (!vol_unix_priv(vol)) {
328 if (check_access(upath, access ) < 0) {
329 return AFPERR_ACCESS;
333 if (file_access(s_path, access ) < 0) {
334 return AFPERR_ACCESS;
339 /* XXX: this probably isn't the best way to do this. the already
340 open bits should really be set if the fork is opened by any
341 program, not just this one. however, that's problematic to do
342 if we can't write lock files somewhere. opened is also passed to
343 ad_open so that we can keep file locks together.
344 FIXME: add the fork we are opening?
346 if ((opened = of_findname(s_path))) {
347 attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
348 attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
350 adsame = opened->of_ad;
353 if ( fork == OPENFORK_DATA ) {
355 adflags = ADFLAGS_DF|ADFLAGS_HF;
358 adflags = ADFLAGS_HF;
361 path = s_path->m_name;
362 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
363 adsame, st)) == NULL ) {
364 return( AFPERR_NFILE );
368 if (access & OPENACC_WR) {
369 /* try opening in read-write mode */
370 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
378 if (fork == OPENFORK_DATA) {
379 /* try to open only the data fork */
380 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
383 adflags = ADFLAGS_DF;
386 /* here's the deal. we only try to create the resource
387 * fork if the user wants to open it for write acess. */
388 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
390 ofork->of_flags |= AFPFORK_OPEN;
399 ret = AFPERR_BADTYPE;
403 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
410 /* the ressource fork is open too */
411 ofork->of_flags |= AFPFORK_OPEN;
414 /* try opening in read-only mode */
416 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
424 /* see if client asked for a read only data fork */
425 if (fork == OPENFORK_DATA) {
426 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
429 adflags = ADFLAGS_DF;
431 /* else we don't set AFPFORK_OPEN because there's no ressource fork file
432 * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
433 * then create in open read-write.
434 * FIXME , it doesn't play well with byte locking example:
435 * ressource fork open read only
436 * locking set on it (no effect, there's no file!)
437 * ressource fork open read write now
446 ret = AFPERR_BADTYPE;
450 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
456 /* the ressource fork is open too */
457 ofork->of_flags |= AFPFORK_OPEN;
461 if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
462 if (ad_setname(ofork->of_ad, path)) {
463 ad_flush( ofork->of_ad, adflags );
467 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
468 &buflen, attrbits )) != AFP_OK ) {
469 ad_close( ofork->of_ad, adflags );
473 *rbuflen = buflen + 2 * sizeof( u_int16_t );
474 bitmap = htons( bitmap );
475 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
476 rbuf += sizeof( u_int16_t );
478 /* check WriteInhibit bit if we have a ressource fork
479 * the test is done here, after some Mac trafic capture
481 if (ad_hfileno(ofork->of_ad) != -1) {
482 ad_getattr(ofork->of_ad, &bshort);
483 if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
484 ad_close( ofork->of_ad, adflags );
487 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
488 return(AFPERR_OLOCK);
493 * synchronization locks:
496 /* don't try to lock non-existent rforks. */
497 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
499 ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
500 /* can we access the fork? */
503 ad_close( ofork->of_ad, adflags );
506 case EAGAIN: /* return data anyway */
510 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
511 return( AFPERR_DENYCONF );
515 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) );
516 return( AFPERR_PARAM );
519 if ((access & OPENACC_WR))
520 ofork->of_flags |= AFPFORK_ACCWR;
522 /* the file may be open read only without ressource fork */
523 if ((access & OPENACC_RD))
524 ofork->of_flags |= AFPFORK_ACCRD;
526 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
532 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
536 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
539 int ibuflen, *rbuflen;
543 u_int16_t ofrefnum, bitmap;
551 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
552 ibuf += sizeof( ofrefnum );
554 memcpy(&bitmap, ibuf, sizeof(bitmap));
555 bitmap = ntohs(bitmap);
556 ibuf += sizeof( bitmap );
559 if (NULL == ( ofork = of_find( ofrefnum )) ) {
560 LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum );
561 return( AFPERR_PARAM );
564 if (ofork->of_vol->v_flags & AFPVOL_RO)
567 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
568 return AFPERR_ACCESS;
570 if ( ofork->of_flags & AFPFORK_DATA) {
572 } else if (ofork->of_flags & AFPFORK_RSRC) {
577 if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
578 && eid == ADEID_RFORK
580 ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
581 && eid == ADEID_DFORK)) {
582 return AFPERR_BITMAP;
586 if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
587 if (afp_version >= 30) {
591 return AFPERR_BITMAP;
594 if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
595 return AFPERR_PARAM ;
597 size = get_off_t(&ibuf, is64);
600 return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
603 if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
604 st_size = ad_size(ofork->of_ad, eid);
606 if (st_size > size &&
607 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
608 goto afp_setfork_err;
610 err = ad_dtruncate( ofork->of_ad, size );
612 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
614 goto afp_setfork_err;
615 } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
616 ad_refresh( ofork->of_ad );
618 st_size = ad_size(ofork->of_ad, eid);
620 if (st_size > size &&
621 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
622 goto afp_setfork_err;
624 err = ad_rtruncate(ofork->of_ad, size);
626 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
628 goto afp_setfork_err;
630 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
631 LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", ofork->of_name, strerror(errno) );
635 return AFPERR_BITMAP;
638 if ( flushfork( ofork ) < 0 ) {
639 LOG(log_error, logtype_afpd, "afp_setforkparams(%s): flushfork: %s", ofork->of_name, strerror(errno) );
654 return AFPERR_ACCESS;
665 /* for this to work correctly, we need to check for locks before each
666 * read and write. that's most easily handled by always doing an
667 * appropriate check before each ad_read/ad_write. other things
668 * that can change files like truncate are handled internally to those
671 #define ENDBIT(a) ((a) & 0x80)
672 #define UNLOCKBIT(a) ((a) & 0x01)
675 /* ---------------------- */
676 static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
679 int ibuflen, *rbuflen;
683 off_t offset, length;
691 /* figure out parameters */
693 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
695 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
696 ibuf += sizeof(ofrefnum);
698 if (NULL == ( ofork = of_find( ofrefnum )) ) {
699 LOG(log_error, logtype_afpd, "afp_bytelock: of_find(%d) could not locate fork", ofrefnum );
700 return( AFPERR_PARAM );
703 if ( ofork->of_flags & AFPFORK_DATA) {
705 } else if (ofork->of_flags & AFPFORK_RSRC) {
710 offset = get_off_t(&ibuf, is64);
711 length = get_off_t(&ibuf, is64);
713 /* FIXME AD_FILELOCK test is surely wrong */
715 length = BYTELOCK_MAX;
716 else if (!length || is_neg(is64, length)) {
718 } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_hfileno(ofork->of_ad))) {
723 offset += ad_size(ofork->of_ad, eid);
724 /* FIXME what do we do if file size > 2 GB and
725 it's not byte_lock_ext?
728 if (offset < 0) /* error if we have a negative offset */
731 /* if the file is a read-only file, we use read locks instead of
732 * write locks. that way, we can prevent anyone from initiating
734 lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
735 if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
736 ofork->of_refnum) < 0) {
740 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
746 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
754 *rbuflen = set_off_t (offset, rbuf, is64);
758 /* --------------------------- */
759 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
762 int ibuflen, *rbuflen;
764 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
767 /* --------------------------- */
768 int afp_bytelock_ext(obj, ibuf, ibuflen, rbuf, rbuflen )
771 int ibuflen, *rbuflen;
773 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
778 /* --------------------------- */
779 static __inline__ int crlf( of )
784 if ( ad_hfileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) {
785 /* no resource fork or no finderinfo, use our files extension mapping */
786 if (!( em = getextmap( of->of_name )) || memcmp( "TEXT", em->em_type, sizeof( em->em_type ))) {
789 /* file type is TEXT */
792 } else if ( !memcmp( "TEXT", ad_entry( of->of_ad, ADEID_FINDERI ), 4 )) {
799 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
800 off_t offset, u_char nlmask,
801 u_char nlchar, char *rbuf,
802 int *rbuflen, const int xlate)
808 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
810 LOG(log_error, logtype_afpd, "afp_read(%s): ad_read: %s", ofork->of_name, strerror(errno) );
812 return( AFPERR_PARAM );
814 if ( cc < *rbuflen ) {
822 for ( p = rbuf, q = p + cc; p < q; ) {
823 if (( *p++ & nlmask ) == nlchar ) {
834 * If this file is of type TEXT, then swap \012 to \015.
837 for ( p = rbuf, q = p + cc; p < q; p++ ) {
838 if ( *p == '\012' ) {
840 } else if ( *p == '\015' ) {
849 return( AFPERR_EOF );
854 /* -----------------------------
855 * with ddp, afp_read can return fewer bytes than in reqcount
856 * so return EOF only if read actually past end of file not
857 * if offset +reqcount > size of file
859 * getfork size ==> 10430
860 * read fork offset 0 size 10752 ???? ==> 4264 bytes (without EOF)
861 * read fork offset 4264 size 6128 ==> 4264 (without EOF)
862 * read fork offset 9248 size 1508 ==> 1182 (EOF)
863 * 10752 is a bug in Mac 7.5.x finder
865 * with dsi, should we check that reqcount < server quantum?
867 static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
870 int ibuflen, *rbuflen;
874 off_t offset, saveoff, reqcount, savereqcount;
875 int cc, err, eid, xlate = 0;
877 u_char nlmask, nlchar;
880 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
881 ibuf += sizeof( u_short );
883 if (NULL == ( ofork = of_find( ofrefnum )) ) {
884 LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum );
889 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
893 offset = get_off_t(&ibuf, is64);
894 reqcount = get_off_t(&ibuf, is64);
903 /* if we wanted to be picky, we could add in the following
904 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
906 if (reqcount < 0 || offset < 0) {
911 if ( ofork->of_flags & AFPFORK_DATA) {
913 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
914 } else if (ofork->of_flags & AFPFORK_RSRC) {
916 } else { /* fork wasn't opened. this should never really happen. */
921 /* zero request count */
927 savereqcount = reqcount;
929 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
934 #define min(a,b) ((a)<(b)?(a):(b))
935 *rbuflen = min( reqcount, *rbuflen );
936 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
940 /* dsi can stream requests. we can only do this if we're not checking
941 * for an end-of-line character. oh well. */
942 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
943 DSI *dsi = obj->handle;
945 int non_blocking = 0;
948 if (obj->options.flags & OPTION_DEBUG) {
949 printf( "(read) reply: %d/%d, %d\n", *rbuflen,(int) reqcount, dsi->clientID);
950 bprint(rbuf, *rbuflen);
953 /* reqcount isn't always truthful. we need to deal with that. */
954 size = ad_size(ofork->of_ad, eid);
956 /* subtract off the offset */
958 if (reqcount > size) {
965 /* dsi_readinit() returns size of next read buffer. by this point,
966 * we know that we're sending some data. if we fail, something
967 * horrible happened. */
968 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
971 /* due to the nature of afp packets, we have to exit if we get
972 an error. we can't do this with translation on. */
973 #if 0 /* ifdef WITH_SENDFILE */
974 /* FIXME with OS X deadlock partial workaround we can't use sendfile */
975 if (!(xlate || Debug(obj) )) {
976 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize) < 0) {
977 if (errno == EINVAL || errno == ENOSYS)
980 LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", ofork->of_name, strerror(errno));
992 /* fill up our buffer. */
994 /* set to non blocking mode */
998 /* fill up our buffer. */
999 while (*rbuflen > 0) {
1000 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen, xlate);
1006 if (obj->options.flags & OPTION_DEBUG) {
1007 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
1008 bprint(rbuf, *rbuflen);
1011 /* dsi_read() also returns buffer size of next allocation */
1012 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
1018 /* set back to blocking mode */
1025 LOG(log_error, logtype_afpd, "afp_read(%s): %s", ofork->of_name, strerror(errno));
1027 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
1028 obj->exit(EXITERR_CLNT);
1032 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
1040 /* ---------------------- */
1041 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
1044 int ibuflen, *rbuflen;
1046 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
1049 /* ---------------------- */
1050 int afp_read_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
1053 int ibuflen, *rbuflen;
1055 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
1058 /* ---------------------- */
1059 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
1062 int ibuflen, *rbuflen;
1070 memcpy(&vid, ibuf, sizeof(vid));
1071 if (NULL == ( vol = getvolbyvid( vid )) ) {
1072 return( AFPERR_PARAM );
1079 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
1082 int ibuflen, *rbuflen;
1084 struct ofork *ofork;
1089 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1091 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1092 LOG(log_error, logtype_afpd, "afp_flushfork: of_find(%d) could not locate fork", ofrefnum );
1093 return( AFPERR_PARAM );
1096 if ( flushfork( ofork ) < 0 ) {
1097 LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", ofork->of_name, strerror(errno) );
1103 /* this is very similar to closefork */
1104 int flushfork( ofork )
1105 struct ofork *ofork;
1109 int err = 0, doflush = 0;
1111 if ( ad_dfileno( ofork->of_ad ) != -1 &&
1112 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1113 LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
1114 ofork->of_name, ad_dfileno(ofork->of_ad), strerror(errno) );
1118 if ( ad_hfileno( ofork->of_ad ) != -1 &&
1119 (ofork->of_flags & AFPFORK_RSRC)) {
1121 /* read in the rfork length */
1122 ad_refresh(ofork->of_ad);
1124 /* set the date if we're dirty */
1125 if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
1126 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1127 ofork->of_flags &= ~AFPFORK_DIRTY;
1131 /* flush the header */
1132 if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)
1135 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1139 LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s",
1140 ofork->of_name, ad_hfileno(ofork->of_ad), strerror(errno) );
1146 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1149 int ibuflen, *rbuflen;
1151 struct ofork *ofork;
1153 int adflags, doflush = 0;
1158 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1160 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1161 LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum );
1162 return( AFPERR_PARAM );
1166 if ((ofork->of_flags & AFPFORK_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) {
1167 adflags |= ADFLAGS_DF;
1169 if ( (ofork->of_flags & AFPFORK_OPEN) && ad_hfileno( ofork->of_ad ) != -1 ) {
1170 adflags |= ADFLAGS_HF;
1172 * Only set the rfork's length if we're closing the rfork.
1174 if ((ofork->of_flags & AFPFORK_RSRC)) {
1175 ad_refresh( ofork->of_ad );
1176 if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
1177 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec);
1181 ad_flush( ofork->of_ad, adflags );
1186 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1187 LOG(log_error, logtype_afpd, "afp_closefork(%s): ad_close: %s", ofork->of_name, strerror(errno) );
1188 return( AFPERR_PARAM );
1191 of_dealloc( ofork );
1196 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1197 off_t offset, char *rbuf,
1198 size_t rbuflen, const int xlate)
1204 * If this file is of type TEXT, swap \015 to \012.
1207 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1208 if ( *p == '\015' ) {
1210 } else if ( *p == '\012' ) {
1216 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1217 rbuf, rbuflen)) < 0 ) {
1222 return( AFPERR_DFULL );
1224 LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", ofork->of_name, strerror(errno) );
1225 return( AFPERR_PARAM );
1233 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1234 * the client may have sent us a bunch of data that's not reflected
1235 * in reqcount et al. */
1236 static int write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
1239 int ibuflen, *rbuflen;
1242 struct ofork *ofork;
1243 off_t offset, saveoff, reqcount;
1244 int endflag, eid, xlate = 0, err = AFP_OK;
1248 /* figure out parameters */
1250 endflag = ENDBIT(*ibuf);
1252 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1253 ibuf += sizeof( ofrefnum );
1255 offset = get_off_t(&ibuf, is64);
1256 reqcount = get_off_t(&ibuf, is64);
1258 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1259 LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum );
1264 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1265 err = AFPERR_ACCESS;
1270 writtenfork = ofork;
1273 if ( ofork->of_flags & AFPFORK_DATA) {
1275 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1276 } else if (ofork->of_flags & AFPFORK_RSRC) {
1279 err = AFPERR_ACCESS; /* should never happen */
1284 offset += ad_size(ofork->of_ad, eid);
1286 /* handle bogus parameters */
1287 if (reqcount < 0 || offset < 0) {
1292 /* offset can overflow on 64-bit capable filesystems.
1293 * report disk full if that's going to happen. */
1294 if (sum_neg(is64, offset, reqcount)) {
1299 if (!reqcount) { /* handle request counts of 0 */
1301 *rbuflen = set_off_t (offset, rbuf, is64);
1306 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1307 reqcount, ofork->of_refnum) < 0) {
1312 /* this is yucky, but dsi can stream i/o and asp can't */
1313 switch (obj->proto) {
1316 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1318 LOG(log_error, logtype_afpd, "afp_write: asp_wrtcont: %s", strerror(errno) );
1319 return( AFPERR_PARAM );
1323 if (obj->options.flags & OPTION_DEBUG) {
1324 printf("(write) len: %d\n", *rbuflen);
1325 bprint(rbuf, *rbuflen);
1328 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1331 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1336 #endif /* no afp/asp */
1340 DSI *dsi = obj->handle;
1342 /* find out what we have already and write it out. */
1343 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1344 if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1345 dsi_writeflush(dsi);
1347 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1352 #if 0 /*def HAVE_SENDFILE_WRITE*/
1353 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1354 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1355 offset, dsi->datasize)) < 0) {
1363 LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
1364 goto afp_write_loop;
1366 dsi_writeflush(dsi);
1368 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1369 reqcount, ofork->of_refnum);
1374 goto afp_write_done;
1376 #endif /* 0, was HAVE_SENDFILE_WRITE */
1378 /* loop until everything gets written. currently
1379 * dsi_write handles the end case by itself. */
1380 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1382 if ( obj->options.flags & OPTION_DEBUG ) {
1383 printf("(write) command cont'd: %d\n", cc);
1387 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1388 dsi_writeflush(dsi);
1390 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1391 reqcount, ofork->of_refnum);
1400 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1401 if ( ad_hfileno( ofork->of_ad ) != -1 )
1402 ofork->of_flags |= AFPFORK_DIRTY;
1404 *rbuflen = set_off_t (offset, rbuf, is64);
1408 if (obj->proto == AFPPROTO_DSI) {
1409 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1410 dsi_writeflush(obj->handle);
1412 if (err != AFP_OK) {
1418 /* ---------------------------- */
1419 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1422 int ibuflen, *rbuflen;
1424 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
1427 /* ----------------------------
1428 * FIXME need to deal with SIGXFSZ signal
1430 int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
1433 int ibuflen, *rbuflen;
1435 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
1438 /* ---------------------------- */
1439 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1442 int ibuflen, *rbuflen;
1444 struct ofork *ofork;
1446 u_int16_t ofrefnum, bitmap;
1447 u_int16_t attrbits = 0;
1450 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1451 ibuf += sizeof( ofrefnum );
1452 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1453 bitmap = ntohs( bitmap );
1454 ibuf += sizeof( bitmap );
1457 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1458 LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum );
1459 return( AFPERR_PARAM );
1461 attrbits = ((ofork->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
1462 attrbits |= ((ofork->of_ad->ad_hf.adf_refcount > ofork->of_ad->ad_df.adf_refcount) ? ATTRBIT_ROPEN : 0);
1464 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1465 if ( ad_refresh( ofork->of_ad ) < 0 ) {
1466 LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", ofork->of_name, strerror(errno) );
1467 return( AFPERR_PARAM );
1471 if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
1472 rbuf + sizeof( u_short ), &buflen, attrbits ))) {
1476 *rbuflen = buflen + sizeof( u_short );
1477 bitmap = htons( bitmap );
1478 memcpy(rbuf, &bitmap, sizeof( bitmap ));