2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * Copyright (c) 2010 Frank Lahm
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
15 #include <sys/param.h>
16 #include <sys/socket.h>
19 #include <atalk/dsi.h>
20 #include <atalk/afp.h>
21 #include <atalk/adouble.h>
22 #include <atalk/logger.h>
23 #include <atalk/util.h>
24 #include <atalk/cnid.h>
25 #include <atalk/bstradd.h>
26 #include <atalk/globals.h>
27 #include <atalk/netatalk_conf.h>
31 #include "directory.h"
36 struct ofork *writtenfork;
39 static int getforkparams(const AFPObj *obj, struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen)
49 /* can only get the length of the opened fork */
50 if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
51 && (ofork->of_flags & AFPFORK_RSRC))
53 ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
54 && (ofork->of_flags & AFPFORK_DATA))) {
55 return( AFPERR_BITMAP );
58 if (! AD_META_OPEN(ofork->of_ad)) {
65 dir = dirlookup(vol, ofork->of_did);
67 if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) {
68 return( AFPERR_MISC );
70 path.m_name = of_name(ofork);
73 if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
74 (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
75 (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
76 if ( ad_data_fileno( ofork->of_ad ) <= 0 ) {
77 /* 0 is for symlink */
78 if (movecwd(vol, dir) < 0)
79 return( AFPERR_NOOBJ );
80 if ( lstat( path.u_name, st ) < 0 )
81 return( AFPERR_NOOBJ );
83 if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) {
84 return( AFPERR_BITMAP );
88 return getmetadata(obj, vol, bitmap, &path, dir, buf, buflen, adp );
91 static off_t get_off_t(char **ibuf, int is64)
97 memcpy(&temp, *ibuf, sizeof( temp ));
98 ret = ntohl(temp); /* ntohl is unsigned */
99 *ibuf += sizeof(temp);
102 memcpy(&temp, *ibuf, sizeof( temp ));
103 *ibuf += sizeof(temp);
104 ret = ntohl(temp)| (ret << 32);
107 ret = (int)ret; /* sign extend */
112 static int set_off_t(off_t offset, char *rbuf, int is64)
119 temp = htonl(offset >> 32);
120 memcpy(rbuf, &temp, sizeof( temp ));
121 rbuf += sizeof(temp);
122 ret = sizeof( temp );
123 offset &= 0xffffffff;
125 temp = htonl(offset);
126 memcpy(rbuf, &temp, sizeof( temp ));
127 ret += sizeof( temp );
132 static int is_neg(int is64, off_t val)
134 if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
139 static int sum_neg(int is64, off_t offset, off_t reqcount)
141 if (is_neg(is64, offset +reqcount) )
146 static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
154 if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
155 return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
158 if ((access & (OPENACC_RD | OPENACC_DRD))) {
159 if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
161 if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
164 if ((access & OPENACC_RD) && denyreadset) {
168 if ((access & OPENACC_DRD) && readset) {
172 /* boolean logic is not enough, because getforkmode is not always telling the
175 if ((access & OPENACC_RD)) {
176 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
180 if ((access & OPENACC_DRD)) {
181 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
186 /* ------------same for writing -------------- */
187 if ((access & (OPENACC_WR | OPENACC_DWR))) {
188 if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
190 if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
193 if ((access & OPENACC_WR) && denywriteset) {
197 if ((access & OPENACC_DWR) && writeset) {
201 if ((access & OPENACC_WR)) {
202 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
206 if ((access & OPENACC_DWR)) {
207 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
216 /* ----------------------- */
217 int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
221 struct ofork *ofork, *opened;
222 struct adouble *adsame = NULL;
224 int ret, adflags, eid;
226 uint16_t vid, bitmap, access, ofrefnum;
227 char fork, *path, *upath;
235 memcpy(&vid, ibuf, sizeof( vid ));
239 if (NULL == ( vol = getvolbyvid( vid ))) {
240 return( AFPERR_PARAM );
243 memcpy(&did, ibuf, sizeof( did ));
244 ibuf += sizeof( int );
246 if (NULL == ( dir = dirlookup( vol, did ))) {
250 memcpy(&bitmap, ibuf, sizeof( bitmap ));
251 bitmap = ntohs( bitmap );
252 ibuf += sizeof( bitmap );
253 memcpy(&access, ibuf, sizeof( access ));
254 access = ntohs( access );
255 ibuf += sizeof( access );
257 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
261 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
262 return get_afp_errno(AFPERR_PARAM);
265 if (*s_path->m_name == '\0') {
267 return AFPERR_BADTYPE;
270 /* stat() data fork st is set because it's not a dir */
271 switch ( s_path->st_errno ) {
277 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
279 LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno));
282 /* FIXME should we check it first ? */
283 upath = s_path->u_name;
284 if (!vol_unix_priv(vol)) {
285 if (check_access(obj, vol, upath, access ) < 0) {
286 return AFPERR_ACCESS;
289 if (file_access(obj, vol, s_path, access ) < 0) {
290 return AFPERR_ACCESS;
295 /* XXX: this probably isn't the best way to do this. the already
296 open bits should really be set if the fork is opened by any
297 program, not just this one. however, that's problematic to do
298 if we can't write lock files somewhere. opened is also passed to
299 ad_open so that we can keep file locks together.
300 FIXME: add the fork we are opening?
302 if ((opened = of_findname(s_path))) {
303 adsame = opened->of_ad;
306 if ( fork == OPENFORK_DATA ) {
308 adflags = ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF;
311 adflags = ADFLAGS_RF | ADFLAGS_HF | ADFLAGS_NOHF;
312 if (!(access & OPENACC_WR))
313 adflags |= ADFLAGS_NORF;
316 path = s_path->m_name;
317 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
318 adsame, st)) == NULL ) {
319 return( AFPERR_NFILE );
322 LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\", %s, %s)",
323 fullpathname(s_path->u_name),
324 (fork == OPENFORK_DATA) ? "data" : "reso",
325 !(access & OPENACC_WR) ? "O_RDONLY" : "O_RDWR");
328 if (access & OPENACC_WR) {
329 /* try opening in read-write mode */
330 if (ad_open(ofork->of_ad, upath,
331 adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD) < 0) {
338 if (fork == OPENFORK_DATA) {
339 /* try to open only the data fork */
340 if (ad_open(ofork->of_ad, upath,
341 ADFLAGS_DF | ADFLAGS_RDWR | ADFLAGS_SETSHRMD) < 0) {
344 adflags = ADFLAGS_DF;
346 /* here's the deal. we only try to create the resource
347 * fork if the user wants to open it for write acess. */
348 if (ad_open(ofork->of_ad, upath,
349 adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD | ADFLAGS_CREATE, 0666) < 0)
351 ofork->of_flags |= AFPFORK_META;
359 ret = AFPERR_BADTYPE;
362 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
368 /* the ressource fork is open too */
369 ofork->of_flags |= AFPFORK_META;
372 /* try opening in read-only mode */
374 if (ad_open(ofork->of_ad, upath, adflags | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
382 /* see if client asked for a read only data fork */
383 if (fork == OPENFORK_DATA) {
384 if (ad_open(ofork->of_ad, upath, ADFLAGS_DF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
387 adflags = ADFLAGS_DF;
389 /* else we don't set AFPFORK_META because there's no ressource fork file
390 * We need to check AFPFORK_META in afp_closefork(). eg fork open read-only
391 * then create in open read-write.
392 * FIXME , it doesn't play well with byte locking example:
393 * ressource fork open read only
394 * locking set on it (no effect, there's no file!)
395 * ressource fork open read write now
403 ret = AFPERR_BADTYPE;
406 LOG(log_error, logtype_afpd, "afp_openfork(\"%s\"): %s",
407 fullpathname(s_path->m_name), strerror(errno) );
411 ofork->of_flags |= AFPFORK_META;
415 if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) {
416 if (ad_setname(ofork->of_ad, path)) {
417 ad_flush( ofork->of_ad );
421 if ((ret = getforkparams(obj, ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
422 ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
426 *rbuflen = buflen + 2 * sizeof( uint16_t );
427 bitmap = htons( bitmap );
428 memcpy(rbuf, &bitmap, sizeof( uint16_t ));
429 rbuf += sizeof( uint16_t );
431 /* check WriteInhibit bit if we have a ressource fork
432 * the test is done here, after some Mac trafic capture
434 if (ad_meta_fileno(ofork->of_ad) != -1) { /* META */
435 ad_getattr(ofork->of_ad, &bshort);
436 if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
437 ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
440 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
441 return(AFPERR_OLOCK);
446 * synchronization locks:
449 /* don't try to lock non-existent rforks. */
450 if ((eid == ADEID_DFORK)
451 || (ad_reso_fileno(ofork->of_ad) != -1)
452 || (ofork->of_ad->ad_vers == AD_VERSION_EA)) {
453 ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
454 /* can we access the fork? */
456 ofork->of_flags |= AFPFORK_ERROR;
458 ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
461 case EAGAIN: /* return data anyway */
465 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
466 return( AFPERR_DENYCONF );
470 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) );
471 return( AFPERR_PARAM );
474 if ((access & OPENACC_WR))
475 ofork->of_flags |= AFPFORK_ACCWR;
477 /* the file may be open read only without ressource fork */
478 if ((access & OPENACC_RD))
479 ofork->of_flags |= AFPFORK_ACCRD;
481 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
487 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
491 int afp_setforkparams(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen)
495 uint16_t ofrefnum, bitmap;
503 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
504 ibuf += sizeof( ofrefnum );
506 memcpy(&bitmap, ibuf, sizeof(bitmap));
507 bitmap = ntohs(bitmap);
508 ibuf += sizeof( bitmap );
511 if (NULL == ( ofork = of_find( ofrefnum )) ) {
512 LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum );
513 return( AFPERR_PARAM );
516 if (ofork->of_vol->v_flags & AFPVOL_RO)
519 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
520 return AFPERR_ACCESS;
522 if ( ofork->of_flags & AFPFORK_DATA) {
524 } else if (ofork->of_flags & AFPFORK_RSRC) {
529 if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
530 && eid == ADEID_RFORK
532 ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
533 && eid == ADEID_DFORK)) {
534 return AFPERR_BITMAP;
538 if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
539 if (obj->afp_version >= 30) {
543 return AFPERR_BITMAP;
546 if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
547 return AFPERR_PARAM ;
549 size = get_off_t(&ibuf, is64);
552 return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
555 if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
556 st_size = ad_size(ofork->of_ad, eid);
558 if (st_size > size &&
559 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
560 goto afp_setfork_err;
562 err = ad_dtruncate( ofork->of_ad, size );
564 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
566 goto afp_setfork_err;
567 } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
568 ad_refresh(NULL, ofork->of_ad );
570 st_size = ad_size(ofork->of_ad, eid);
572 if (st_size > size &&
573 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
574 goto afp_setfork_err;
576 err = ad_rtruncate(ofork->of_ad, size);
578 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
580 goto afp_setfork_err;
582 if (ad_flush( ofork->of_ad ) < 0) {
583 LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) );
587 return AFPERR_BITMAP;
590 if ( flushfork( ofork ) < 0 ) {
591 LOG(log_error, logtype_afpd, "afp_setforkparams(%s): flushfork: %s", of_name(ofork), strerror(errno) );
606 return AFPERR_ACCESS;
617 /* for this to work correctly, we need to check for locks before each
618 * read and write. that's most easily handled by always doing an
619 * appropriate check before each ad_read/ad_write. other things
620 * that can change files like truncate are handled internally to those
623 #define ENDBIT(a) ((a) & 0x80)
624 #define UNLOCKBIT(a) ((a) & 0x01)
627 /* ---------------------- */
628 static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
631 off_t offset, length;
639 /* figure out parameters */
641 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
643 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
644 ibuf += sizeof(ofrefnum);
646 if (NULL == ( ofork = of_find( ofrefnum )) ) {
647 LOG(log_error, logtype_afpd, "byte_lock: of_find(%d) could not locate fork", ofrefnum );
648 return( AFPERR_PARAM );
651 if ( ofork->of_flags & AFPFORK_DATA) {
653 } else if (ofork->of_flags & AFPFORK_RSRC) {
658 offset = get_off_t(&ibuf, is64);
659 length = get_off_t(&ibuf, is64);
662 length = BYTELOCK_MAX;
663 else if (!length || is_neg(is64, length)) {
665 } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
670 offset += ad_size(ofork->of_ad, eid);
671 /* FIXME what do we do if file size > 2 GB and
672 it's not byte_lock_ext?
675 if (offset < 0) /* error if we have a negative offset */
678 /* if the file is a read-only file, we use read locks instead of
679 * write locks. that way, we can prevent anyone from initiating
681 lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
682 if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
683 ofork->of_refnum) < 0) {
687 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
693 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
701 *rbuflen = set_off_t (offset, rbuf, is64);
705 /* --------------------------- */
706 int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
708 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
711 /* --------------------------- */
712 int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
714 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
719 static ssize_t read_file(struct ofork *ofork, int eid,
720 off_t offset, u_char nlmask,
721 u_char nlchar, char *rbuf,
728 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
730 LOG(log_error, logtype_afpd, "afp_read(%s): ad_read: %s", of_name(ofork), strerror(errno) );
732 return( AFPERR_PARAM );
734 if ( (size_t)cc < *rbuflen ) {
742 for ( p = rbuf, q = p + cc; p < q; ) {
743 if (( *p++ & nlmask ) == nlchar ) {
755 return( AFPERR_EOF );
760 /* -----------------------------
761 * with ddp, afp_read can return fewer bytes than in reqcount
762 * so return EOF only if read actually past end of file not
763 * if offset +reqcount > size of file
765 * getfork size ==> 10430
766 * read fork offset 0 size 10752 ???? ==> 4264 bytes (without EOF)
767 * read fork offset 4264 size 6128 ==> 4264 (without EOF)
768 * read fork offset 9248 size 1508 ==> 1182 (EOF)
769 * 10752 is a bug in Mac 7.5.x finder
771 * with dsi, should we check that reqcount < server quantum?
773 static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
776 off_t offset, saveoff, reqcount, savereqcount;
780 u_char nlmask, nlchar;
783 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
784 ibuf += sizeof( u_short );
786 if (NULL == ( ofork = of_find( ofrefnum )) ) {
787 LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum );
792 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
796 offset = get_off_t(&ibuf, is64);
797 reqcount = get_off_t(&ibuf, is64);
799 LOG(log_debug, logtype_afpd,
800 "afp_read(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", offset, reqcount,
801 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
810 /* if we wanted to be picky, we could add in the following
811 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
813 if (reqcount < 0 || offset < 0) {
818 if ( ofork->of_flags & AFPFORK_DATA) {
820 } else if (ofork->of_flags & AFPFORK_RSRC) {
822 } else { /* fork wasn't opened. this should never really happen. */
827 /* zero request count */
833 LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)",
834 of_name(ofork), (intmax_t)offset, (intmax_t)reqcount);
836 savereqcount = reqcount;
838 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
843 *rbuflen = MIN(reqcount, *rbuflen);
844 LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): reading %jd bytes from file",
845 of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
847 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen);
850 LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file",
851 of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
853 /* dsi can stream requests. we can only do this if we're not checking
854 * for an end-of-line character. oh well. */
855 if ((*rbuflen < reqcount) && !nlmask) {
859 /* reqcount isn't always truthful. we need to deal with that. */
860 size = ad_size(ofork->of_ad, eid);
862 /* subtract off the offset */
864 if (reqcount > size) {
871 /* dsi_readinit() returns size of next read buffer. by this point,
872 * we know that we're sending some data. if we fail, something
873 * horrible happened. */
874 if ((cc = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
877 /* due to the nature of afp packets, we have to exit if we get
878 an error. we can't do this with translation on. */
882 fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
884 if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) {
885 if (errno == EINVAL || errno == ENOSYS)
888 LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", of_name(ofork), strerror(errno));
899 /* fill up our buffer. */
900 while (*rbuflen > 0) {
901 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen);
906 /* dsi_read() also returns buffer size of next allocation */
907 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
916 LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno));
918 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
919 obj->exit(EXITERR_CLNT);
923 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
931 /* ---------------------- */
932 int afp_read(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
934 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
937 /* ---------------------- */
938 int afp_read_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
940 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
943 /* ---------------------- */
944 int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
952 memcpy(&vid, ibuf, sizeof(vid));
953 if (NULL == ( vol = getvolbyvid( vid )) ) {
954 return( AFPERR_PARAM );
961 int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
968 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
970 if (NULL == ( ofork = of_find( ofrefnum )) ) {
971 LOG(log_error, logtype_afpd, "afp_flushfork: of_find(%d) could not locate fork", ofrefnum );
972 return( AFPERR_PARAM );
975 LOG(log_debug, logtype_afpd, "afp_flushfork(fork: %s)",
976 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
978 if ( flushfork( ofork ) < 0 ) {
979 LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) );
987 There is a lot to tell about fsync, fdatasync, F_FULLFSYNC.
988 fsync(2) on OSX is implemented differently than on other platforms.
989 see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf.
991 int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
999 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
1000 ibuf += sizeof( ofrefnum );
1002 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1003 LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum );
1004 return( AFPERR_PARAM );
1007 LOG(log_debug, logtype_afpd, "afp_syncfork(fork: %s)",
1008 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
1010 if ( flushfork( ofork ) < 0 ) {
1011 LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
1018 /* this is very similar to closefork */
1019 int flushfork(struct ofork *ofork)
1023 int err = 0, doflush = 0;
1025 if ( ad_data_fileno( ofork->of_ad ) != -1 &&
1026 fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
1027 LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
1028 of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) );
1032 if ( ad_reso_fileno( ofork->of_ad ) != -1 && /* HF */
1033 (ofork->of_flags & AFPFORK_RSRC)) {
1035 /* read in the rfork length */
1036 ad_refresh(NULL, ofork->of_ad);
1038 /* set the date if we're dirty */
1039 if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
1040 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1041 ofork->of_flags &= ~AFPFORK_DIRTY;
1045 /* flush the header */
1046 if (doflush && ad_flush(ofork->of_ad) < 0)
1049 if (fsync( ad_reso_fileno( ofork->of_ad )) < 0)
1053 LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s",
1054 of_name(ofork), ad_reso_fileno(ofork->of_ad), strerror(errno) );
1060 int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
1062 struct ofork *ofork;
1067 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1069 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1070 LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum );
1071 return( AFPERR_PARAM );
1074 LOG(log_debug, logtype_afpd, "afp_closefork(fork: %s)",
1075 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
1077 if ( of_closefork( ofork ) < 0 ) {
1078 LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
1079 return( AFPERR_PARAM );
1086 static ssize_t write_file(struct ofork *ofork, int eid,
1087 off_t offset, char *rbuf,
1093 LOG(log_debug, logtype_afpd, "write_file(off: %ju, size: %zu)",
1094 (uintmax_t)offset, rbuflen);
1096 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1097 rbuf, rbuflen)) < 0 ) {
1102 return( AFPERR_DFULL );
1104 return AFPERR_ACCESS;
1106 LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", of_name(ofork), strerror(errno) );
1107 return( AFPERR_PARAM );
1115 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1116 * the client may have sent us a bunch of data that's not reflected
1117 * in reqcount et al. */
1118 static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
1120 struct ofork *ofork;
1121 off_t offset, saveoff, reqcount, oldsize, newsize;
1122 int endflag, eid, err = AFP_OK;
1126 /* figure out parameters */
1128 endflag = ENDBIT(*ibuf);
1130 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1131 ibuf += sizeof( ofrefnum );
1133 offset = get_off_t(&ibuf, is64);
1134 reqcount = get_off_t(&ibuf, is64);
1136 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1137 LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum );
1142 LOG(log_debug, logtype_afpd, "afp_write(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
1143 offset, reqcount, (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
1145 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1146 err = AFPERR_ACCESS;
1151 writtenfork = ofork;
1154 if ( ofork->of_flags & AFPFORK_DATA) {
1156 } else if (ofork->of_flags & AFPFORK_RSRC) {
1159 err = AFPERR_ACCESS; /* should never happen */
1163 oldsize = ad_size(ofork->of_ad, eid);
1167 /* handle bogus parameters */
1168 if (reqcount < 0 || offset < 0) {
1173 newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize;
1175 /* offset can overflow on 64-bit capable filesystems.
1176 * report disk full if that's going to happen. */
1177 if (sum_neg(is64, offset, reqcount)) {
1182 if (!reqcount) { /* handle request counts of 0 */
1184 *rbuflen = set_off_t (offset, rbuf, is64);
1189 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1190 reqcount, ofork->of_refnum) < 0) {
1195 DSI *dsi = obj->dsi;
1196 /* find out what we have already and write it out. */
1197 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1199 if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc)) < 0) {
1200 dsi_writeflush(dsi);
1202 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1208 #if 0 /*def HAVE_SENDFILE_WRITE*/
1209 if (!(obj->options.flags & OPTION_DEBUG)) {
1210 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1211 offset, dsi->datasize)) < 0) {
1219 LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
1220 goto afp_write_loop;
1222 dsi_writeflush(dsi);
1224 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1225 reqcount, ofork->of_refnum);
1230 goto afp_write_done;
1232 #endif /* 0, was HAVE_SENDFILE_WRITE */
1234 /* loop until everything gets written. currently
1235 * dsi_write handles the end case by itself. */
1236 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1237 if ((cc = write_file(ofork, eid, offset, rbuf, cc)) < 0) {
1238 dsi_writeflush(dsi);
1240 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1241 reqcount, ofork->of_refnum);
1247 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1248 if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */
1249 ofork->of_flags |= AFPFORK_DIRTY;
1251 /* we have modified any fork, remember until close_fork */
1252 ofork->of_flags |= AFPFORK_MODIFIED;
1254 /* update write count */
1255 ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0;
1257 *rbuflen = set_off_t (offset, rbuf, is64);
1261 dsi_writeinit(obj->dsi, rbuf, *rbuflen);
1262 dsi_writeflush(obj->dsi);
1264 if (err != AFP_OK) {
1270 /* ---------------------------- */
1271 int afp_write(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
1273 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
1276 /* ----------------------------
1277 * FIXME need to deal with SIGXFSZ signal
1279 int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
1281 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
1284 /* ---------------------------- */
1285 int afp_getforkparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
1287 struct ofork *ofork;
1289 uint16_t ofrefnum, bitmap;
1292 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1293 ibuf += sizeof( ofrefnum );
1294 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1295 bitmap = ntohs( bitmap );
1296 ibuf += sizeof( bitmap );
1299 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1300 LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum );
1301 return( AFPERR_PARAM );
1304 if (AD_META_OPEN(ofork->of_ad)) {
1305 if ( ad_refresh(NULL, ofork->of_ad ) < 0 ) {
1306 LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) );
1307 return( AFPERR_PARAM );
1311 if (AFP_OK != (ret = getforkparams(obj, ofork, bitmap, rbuf + sizeof( u_short ), &buflen ))) {
1315 *rbuflen = buflen + sizeof( u_short );
1316 bitmap = htons( bitmap );
1317 memcpy(rbuf, &bitmap, sizeof( bitmap ));