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>
32 #include "directory.h"
37 struct ofork *writtenfork;
40 static int getforkparams(const AFPObj *obj, struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen)
50 /* can only get the length of the opened fork */
51 if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
52 && (ofork->of_flags & AFPFORK_RSRC))
54 ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
55 && (ofork->of_flags & AFPFORK_DATA))) {
56 return( AFPERR_BITMAP );
59 if (! AD_META_OPEN(ofork->of_ad)) {
66 dir = dirlookup(vol, ofork->of_did);
68 if (NULL == (path.m_name = utompath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) {
69 return( AFPERR_MISC );
71 path.u_name = of_name(ofork);
74 if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
75 (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
76 (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
77 if ( ad_data_fileno( ofork->of_ad ) <= 0 ) {
78 /* 0 is for symlink */
79 if (movecwd(vol, dir) < 0)
80 return( AFPERR_NOOBJ );
81 if ( lstat( path.u_name, st ) < 0 )
82 return( AFPERR_NOOBJ );
84 if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) {
85 return( AFPERR_BITMAP );
89 return getmetadata(obj, vol, bitmap, &path, dir, buf, buflen, adp );
92 static off_t get_off_t(char **ibuf, int is64)
98 memcpy(&temp, *ibuf, sizeof( temp ));
99 ret = ntohl(temp); /* ntohl is unsigned */
100 *ibuf += sizeof(temp);
103 memcpy(&temp, *ibuf, sizeof( temp ));
104 *ibuf += sizeof(temp);
105 ret = ntohl(temp)| (ret << 32);
108 ret = (int)ret; /* sign extend */
113 static int set_off_t(off_t offset, char *rbuf, int is64)
120 temp = htonl(offset >> 32);
121 memcpy(rbuf, &temp, sizeof( temp ));
122 rbuf += sizeof(temp);
123 ret = sizeof( temp );
124 offset &= 0xffffffff;
126 temp = htonl(offset);
127 memcpy(rbuf, &temp, sizeof( temp ));
128 ret += sizeof( temp );
133 static int is_neg(int is64, off_t val)
135 if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
140 static int sum_neg(int is64, off_t offset, off_t reqcount)
142 if (is_neg(is64, offset +reqcount) )
147 static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
155 if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
156 return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
159 if ((access & (OPENACC_RD | OPENACC_DRD))) {
160 if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
162 if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
165 if ((access & OPENACC_RD) && denyreadset) {
169 if ((access & OPENACC_DRD) && readset) {
173 /* boolean logic is not enough, because getforkmode is not always telling the
176 if ((access & OPENACC_RD)) {
177 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
181 if ((access & OPENACC_DRD)) {
182 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
187 /* ------------same for writing -------------- */
188 if ((access & (OPENACC_WR | OPENACC_DWR))) {
189 if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
191 if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
194 if ((access & OPENACC_WR) && denywriteset) {
198 if ((access & OPENACC_DWR) && writeset) {
202 if ((access & OPENACC_WR)) {
203 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
207 if ((access & OPENACC_DWR)) {
208 ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
217 /* ----------------------- */
218 int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
222 struct ofork *ofork, *opened;
223 struct adouble *adsame = NULL;
225 int ret, adflags, eid;
227 uint16_t vid, bitmap, access, ofrefnum;
228 char fork, *path, *upath;
236 memcpy(&vid, ibuf, sizeof( vid ));
240 if (NULL == ( vol = getvolbyvid( vid ))) {
241 return( AFPERR_PARAM );
244 memcpy(&did, ibuf, sizeof( did ));
245 ibuf += sizeof( int );
247 if (NULL == ( dir = dirlookup( vol, did ))) {
251 memcpy(&bitmap, ibuf, sizeof( bitmap ));
252 bitmap = ntohs( bitmap );
253 ibuf += sizeof( bitmap );
254 memcpy(&access, ibuf, sizeof( access ));
255 access = ntohs( access );
256 ibuf += sizeof( access );
258 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
262 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
263 return get_afp_errno(AFPERR_PARAM);
266 if (*s_path->m_name == '\0') {
268 return AFPERR_BADTYPE;
271 /* stat() data fork st is set because it's not a dir */
272 switch ( s_path->st_errno ) {
278 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
280 LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno));
283 /* FIXME should we check it first ? */
284 upath = s_path->u_name;
285 if (!vol_unix_priv(vol)) {
286 if (check_access(obj, vol, upath, access ) < 0) {
287 return AFPERR_ACCESS;
290 if (file_access(obj, vol, s_path, access ) < 0) {
291 return AFPERR_ACCESS;
296 /* XXX: this probably isn't the best way to do this. the already
297 open bits should really be set if the fork is opened by any
298 program, not just this one. however, that's problematic to do
299 if we can't write lock files somewhere. opened is also passed to
300 ad_open so that we can keep file locks together.
301 FIXME: add the fork we are opening?
303 if ((opened = of_findname(s_path))) {
304 adsame = opened->of_ad;
307 if ( fork == OPENFORK_DATA ) {
309 adflags = ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF;
312 adflags = ADFLAGS_RF | ADFLAGS_HF | ADFLAGS_NOHF;
313 if (!(access & OPENACC_WR))
314 adflags |= ADFLAGS_NORF;
317 path = s_path->m_name;
318 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
319 adsame, st)) == NULL ) {
320 return( AFPERR_NFILE );
323 LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\", %s, %s)",
324 fullpathname(s_path->u_name),
325 (fork == OPENFORK_DATA) ? "data" : "reso",
326 !(access & OPENACC_WR) ? "O_RDONLY" : "O_RDWR");
329 if (access & OPENACC_WR) {
330 /* try opening in read-write mode */
331 if (ad_open(ofork->of_ad, upath,
332 adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD) < 0) {
339 if (fork == OPENFORK_DATA) {
340 /* try to open only the data fork */
341 if (ad_open(ofork->of_ad, upath,
342 ADFLAGS_DF | ADFLAGS_RDWR | ADFLAGS_SETSHRMD) < 0) {
345 adflags = ADFLAGS_DF;
347 /* here's the deal. we only try to create the resource
348 * fork if the user wants to open it for write acess. */
349 if (ad_open(ofork->of_ad, upath,
350 adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD | ADFLAGS_CREATE, 0666) < 0)
352 ofork->of_flags |= AFPFORK_META;
360 ret = AFPERR_BADTYPE;
363 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
369 /* the ressource fork is open too */
370 ofork->of_flags |= AFPFORK_META;
373 /* try opening in read-only mode */
375 if (ad_open(ofork->of_ad, upath, adflags | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
383 /* see if client asked for a read only data fork */
384 if (fork == OPENFORK_DATA) {
385 if (ad_open(ofork->of_ad, upath, ADFLAGS_DF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
388 adflags = ADFLAGS_DF;
390 /* else we don't set AFPFORK_META because there's no ressource fork file
391 * We need to check AFPFORK_META in afp_closefork(). eg fork open read-only
392 * then create in open read-write.
393 * FIXME , it doesn't play well with byte locking example:
394 * ressource fork open read only
395 * locking set on it (no effect, there's no file!)
396 * ressource fork open read write now
404 ret = AFPERR_BADTYPE;
407 LOG(log_error, logtype_afpd, "afp_openfork(\"%s\"): %s",
408 fullpathname(s_path->m_name), strerror(errno) );
412 ofork->of_flags |= AFPFORK_META;
416 if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) {
417 if (ad_setname(ofork->of_ad, path)) {
418 ad_flush( ofork->of_ad );
422 if ((ret = getforkparams(obj, ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
423 ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
427 *rbuflen = buflen + 2 * sizeof( uint16_t );
428 bitmap = htons( bitmap );
429 memcpy(rbuf, &bitmap, sizeof( uint16_t ));
430 rbuf += sizeof( uint16_t );
432 /* check WriteInhibit bit if we have a ressource fork
433 * the test is done here, after some Mac trafic capture
435 if (ad_meta_fileno(ofork->of_ad) != -1) { /* META */
436 ad_getattr(ofork->of_ad, &bshort);
437 if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
438 ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
441 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
442 return(AFPERR_OLOCK);
447 * synchronization locks:
450 /* don't try to lock non-existent rforks. */
451 if ((eid == ADEID_DFORK)
452 || (ad_reso_fileno(ofork->of_ad) != -1)
453 || (ofork->of_ad->ad_vers == AD_VERSION_EA)) {
454 ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
455 /* can we access the fork? */
457 ofork->of_flags |= AFPFORK_ERROR;
459 ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
462 case EAGAIN: /* return data anyway */
466 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
467 return( AFPERR_DENYCONF );
471 LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) );
472 return( AFPERR_PARAM );
475 if ((access & OPENACC_WR))
476 ofork->of_flags |= AFPFORK_ACCWR;
478 /* the file may be open read only without ressource fork */
479 if ((access & OPENACC_RD))
480 ofork->of_flags |= AFPFORK_ACCRD;
482 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
488 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
492 int afp_setforkparams(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen)
496 uint16_t ofrefnum, bitmap;
504 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
505 ibuf += sizeof( ofrefnum );
507 memcpy(&bitmap, ibuf, sizeof(bitmap));
508 bitmap = ntohs(bitmap);
509 ibuf += sizeof( bitmap );
512 if (NULL == ( ofork = of_find( ofrefnum )) ) {
513 LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum );
514 return( AFPERR_PARAM );
517 if (ofork->of_vol->v_flags & AFPVOL_RO)
520 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
521 return AFPERR_ACCESS;
523 if ( ofork->of_flags & AFPFORK_DATA) {
525 } else if (ofork->of_flags & AFPFORK_RSRC) {
530 if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
531 && eid == ADEID_RFORK
533 ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
534 && eid == ADEID_DFORK)) {
535 return AFPERR_BITMAP;
539 if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
540 if (obj->afp_version >= 30) {
544 return AFPERR_BITMAP;
547 if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
548 return AFPERR_PARAM ;
550 size = get_off_t(&ibuf, is64);
553 return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
556 if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
557 st_size = ad_size(ofork->of_ad, eid);
559 if (st_size > size &&
560 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
561 goto afp_setfork_err;
563 err = ad_dtruncate( ofork->of_ad, size );
565 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
567 goto afp_setfork_err;
568 } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
569 ad_refresh(NULL, ofork->of_ad );
571 st_size = ad_size(ofork->of_ad, eid);
573 if (st_size > size &&
574 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
575 goto afp_setfork_err;
578 err = ad_rtruncate(ofork->of_ad, size);
580 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
582 goto afp_setfork_err;
584 if (ad_flush( ofork->of_ad ) < 0) {
585 LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) );
589 return AFPERR_BITMAP;
592 if ( flushfork( ofork ) < 0 ) {
593 LOG(log_error, logtype_afpd, "afp_setforkparams(%s): flushfork: %s", of_name(ofork), strerror(errno) );
608 return AFPERR_ACCESS;
619 /* for this to work correctly, we need to check for locks before each
620 * read and write. that's most easily handled by always doing an
621 * appropriate check before each ad_read/ad_write. other things
622 * that can change files like truncate are handled internally to those
625 #define ENDBIT(a) ((a) & 0x80)
626 #define UNLOCKBIT(a) ((a) & 0x01)
629 /* ---------------------- */
630 static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
633 off_t offset, length;
641 /* figure out parameters */
643 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
645 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
646 ibuf += sizeof(ofrefnum);
648 if (NULL == ( ofork = of_find( ofrefnum )) ) {
649 LOG(log_error, logtype_afpd, "byte_lock: of_find(%d) could not locate fork", ofrefnum );
650 return( AFPERR_PARAM );
653 if ( ofork->of_flags & AFPFORK_DATA) {
655 } else if (ofork->of_flags & AFPFORK_RSRC) {
660 offset = get_off_t(&ibuf, is64);
661 length = get_off_t(&ibuf, is64);
664 length = BYTELOCK_MAX;
665 else if (!length || is_neg(is64, length)) {
667 } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
672 offset += ad_size(ofork->of_ad, eid);
673 /* FIXME what do we do if file size > 2 GB and
674 it's not byte_lock_ext?
677 if (offset < 0) /* error if we have a negative offset */
680 /* if the file is a read-only file, we use read locks instead of
681 * write locks. that way, we can prevent anyone from initiating
683 lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
684 if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
685 ofork->of_refnum) < 0) {
689 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
695 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
703 *rbuflen = set_off_t (offset, rbuf, is64);
707 /* --------------------------- */
708 int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
710 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
713 /* --------------------------- */
714 int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
716 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
721 static ssize_t read_file(struct ofork *ofork, int eid,
722 off_t offset, u_char nlmask,
723 u_char nlchar, char *rbuf,
730 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
732 LOG(log_error, logtype_afpd, "afp_read(%s): ad_read: %s", of_name(ofork), strerror(errno) );
734 return( AFPERR_PARAM );
736 if ( (size_t)cc < *rbuflen ) {
744 for ( p = rbuf, q = p + cc; p < q; ) {
745 if (( *p++ & nlmask ) == nlchar ) {
757 return( AFPERR_EOF );
762 /* -----------------------------
763 * with ddp, afp_read can return fewer bytes than in reqcount
764 * so return EOF only if read actually past end of file not
765 * if offset +reqcount > size of file
767 * getfork size ==> 10430
768 * read fork offset 0 size 10752 ???? ==> 4264 bytes (without EOF)
769 * read fork offset 4264 size 6128 ==> 4264 (without EOF)
770 * read fork offset 9248 size 1508 ==> 1182 (EOF)
771 * 10752 is a bug in Mac 7.5.x finder
773 * with dsi, should we check that reqcount < server quantum?
775 static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
778 off_t offset, saveoff, reqcount, savereqcount;
782 u_char nlmask, nlchar;
785 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
786 ibuf += sizeof( u_short );
788 if (NULL == ( ofork = of_find( ofrefnum )) ) {
789 LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum );
794 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
798 offset = get_off_t(&ibuf, is64);
799 reqcount = get_off_t(&ibuf, is64);
801 LOG(log_debug, logtype_afpd,
802 "afp_read(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", offset, reqcount,
803 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
812 /* if we wanted to be picky, we could add in the following
813 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
815 if (reqcount < 0 || offset < 0) {
820 if ( ofork->of_flags & AFPFORK_DATA) {
822 } else if (ofork->of_flags & AFPFORK_RSRC) {
824 } else { /* fork wasn't opened. this should never really happen. */
829 /* zero request count */
835 LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)",
836 of_name(ofork), (intmax_t)offset, (intmax_t)reqcount);
838 savereqcount = reqcount;
840 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
845 *rbuflen = MIN(reqcount, *rbuflen);
846 LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): reading %jd bytes from file",
847 of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
849 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen);
852 LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file",
853 of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
855 /* dsi can stream requests. we can only do this if we're not checking
856 * for an end-of-line character. oh well. */
857 if ((*rbuflen < reqcount) && !nlmask) {
861 /* reqcount isn't always truthful. we need to deal with that. */
862 size = ad_size(ofork->of_ad, eid);
864 /* subtract off the offset */
866 if (reqcount > size) {
873 /* dsi_readinit() returns size of next read buffer. by this point,
874 * we know that we're sending some data. if we fail, something
875 * horrible happened. */
876 if ((cc = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
879 /* due to the nature of afp packets, we have to exit if we get
880 an error. we can't do this with translation on. */
882 if (!(obj->options.flags & OPTION_NOSENDFILE)) {
883 if (dsi_stream_read_file(dsi,
884 ad_readfile_init(ofork->of_ad, eid, &offset, 0),
886 dsi->datasize) < 0) {
892 LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", of_name(ofork), strerror(errno));
903 /* fill up our buffer. */
904 while (*rbuflen > 0) {
905 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen);
910 /* dsi_read() also returns buffer size of next allocation */
911 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
920 LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno));
922 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
923 obj->exit(EXITERR_CLNT);
927 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
935 /* ---------------------- */
936 int afp_read(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
938 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
941 /* ---------------------- */
942 int afp_read_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
944 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
947 /* ---------------------- */
948 int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
956 memcpy(&vid, ibuf, sizeof(vid));
957 if (NULL == ( vol = getvolbyvid( vid )) ) {
958 return( AFPERR_PARAM );
965 int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
972 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
974 if (NULL == ( ofork = of_find( ofrefnum )) ) {
975 LOG(log_error, logtype_afpd, "afp_flushfork: of_find(%d) could not locate fork", ofrefnum );
976 return( AFPERR_PARAM );
979 LOG(log_debug, logtype_afpd, "afp_flushfork(fork: %s)",
980 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
982 if ( flushfork( ofork ) < 0 ) {
983 LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) );
991 There is a lot to tell about fsync, fdatasync, F_FULLFSYNC.
992 fsync(2) on OSX is implemented differently than on other platforms.
993 see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf.
995 int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
1003 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
1004 ibuf += sizeof( ofrefnum );
1006 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1007 LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum );
1008 return( AFPERR_PARAM );
1011 LOG(log_debug, logtype_afpd, "afp_syncfork(fork: %s)",
1012 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
1014 if ( flushfork( ofork ) < 0 ) {
1015 LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
1022 /* this is very similar to closefork */
1023 int flushfork(struct ofork *ofork)
1027 int err = 0, doflush = 0;
1029 if ( ad_data_fileno( ofork->of_ad ) != -1 &&
1030 fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
1031 LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
1032 of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) );
1036 if ( ad_reso_fileno( ofork->of_ad ) != -1 && /* HF */
1037 (ofork->of_flags & AFPFORK_RSRC)) {
1039 /* read in the rfork length */
1040 ad_refresh(NULL, ofork->of_ad);
1042 /* set the date if we're dirty */
1043 if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
1044 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1045 ofork->of_flags &= ~AFPFORK_DIRTY;
1049 /* flush the header */
1050 if (doflush && ad_flush(ofork->of_ad) < 0)
1053 if (fsync( ad_reso_fileno( ofork->of_ad )) < 0)
1057 LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s",
1058 of_name(ofork), ad_reso_fileno(ofork->of_ad), strerror(errno) );
1064 int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
1066 struct ofork *ofork;
1071 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1073 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1074 LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum );
1075 return( AFPERR_PARAM );
1078 LOG(log_debug, logtype_afpd, "afp_closefork(fork: %s)",
1079 (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
1081 if ( of_closefork( ofork ) < 0 ) {
1082 LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
1083 return( AFPERR_PARAM );
1090 static ssize_t write_file(struct ofork *ofork, int eid,
1091 off_t offset, char *rbuf,
1097 LOG(log_debug, logtype_afpd, "write_file(off: %ju, size: %zu)",
1098 (uintmax_t)offset, rbuflen);
1100 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1101 rbuf, rbuflen)) < 0 ) {
1106 return( AFPERR_DFULL );
1108 return AFPERR_ACCESS;
1110 LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", of_name(ofork), strerror(errno) );
1111 return( AFPERR_PARAM );
1119 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1120 * the client may have sent us a bunch of data that's not reflected
1121 * in reqcount et al. */
1122 static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
1124 struct ofork *ofork;
1125 off_t offset, saveoff, reqcount, oldsize, newsize;
1126 int endflag, eid, err = AFP_OK;
1130 /* figure out parameters */
1132 endflag = ENDBIT(*ibuf);
1134 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1135 ibuf += sizeof( ofrefnum );
1137 offset = get_off_t(&ibuf, is64);
1138 reqcount = get_off_t(&ibuf, is64);
1140 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1141 LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum );
1146 LOG(log_debug, logtype_afpd, "afp_write(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
1147 offset, reqcount, (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
1149 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1150 err = AFPERR_ACCESS;
1155 writtenfork = ofork;
1158 if ( ofork->of_flags & AFPFORK_DATA) {
1160 } else if (ofork->of_flags & AFPFORK_RSRC) {
1163 err = AFPERR_ACCESS; /* should never happen */
1167 oldsize = ad_size(ofork->of_ad, eid);
1171 /* handle bogus parameters */
1172 if (reqcount < 0 || offset < 0) {
1177 newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize;
1179 /* offset can overflow on 64-bit capable filesystems.
1180 * report disk full if that's going to happen. */
1181 if (sum_neg(is64, offset, reqcount)) {
1186 if (!reqcount) { /* handle request counts of 0 */
1188 *rbuflen = set_off_t (offset, rbuf, is64);
1193 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1194 reqcount, ofork->of_refnum) < 0) {
1199 DSI *dsi = obj->dsi;
1200 /* find out what we have already and write it out. */
1201 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1203 if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc)) < 0) {
1204 dsi_writeflush(dsi);
1206 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1212 #if 0 /*def HAVE_SENDFILE_WRITE*/
1213 if (!(obj->options.flags & OPTION_DEBUG)) {
1214 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1215 offset, dsi->datasize)) < 0) {
1223 LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
1224 goto afp_write_loop;
1226 dsi_writeflush(dsi);
1228 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1229 reqcount, ofork->of_refnum);
1234 goto afp_write_done;
1236 #endif /* 0, was HAVE_SENDFILE_WRITE */
1238 /* loop until everything gets written. currently
1239 * dsi_write handles the end case by itself. */
1240 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1241 if ((cc = write_file(ofork, eid, offset, rbuf, cc)) < 0) {
1242 dsi_writeflush(dsi);
1244 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1245 reqcount, ofork->of_refnum);
1251 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1252 if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */
1253 ofork->of_flags |= AFPFORK_DIRTY;
1255 /* we have modified any fork, remember until close_fork */
1256 ofork->of_flags |= AFPFORK_MODIFIED;
1258 /* update write count */
1259 ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0;
1261 *rbuflen = set_off_t (offset, rbuf, is64);
1265 dsi_writeinit(obj->dsi, rbuf, *rbuflen);
1266 dsi_writeflush(obj->dsi);
1268 if (err != AFP_OK) {
1274 /* ---------------------------- */
1275 int afp_write(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
1277 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
1280 /* ----------------------------
1281 * FIXME need to deal with SIGXFSZ signal
1283 int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
1285 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
1288 /* ---------------------------- */
1289 int afp_getforkparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
1291 struct ofork *ofork;
1293 uint16_t ofrefnum, bitmap;
1296 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1297 ibuf += sizeof( ofrefnum );
1298 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1299 bitmap = ntohs( bitmap );
1300 ibuf += sizeof( bitmap );
1303 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1304 LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum );
1305 return( AFPERR_PARAM );
1308 if (AD_META_OPEN(ofork->of_ad)) {
1309 if ( ad_refresh(NULL, ofork->of_ad ) < 0 ) {
1310 LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) );
1311 return( AFPERR_PARAM );
1315 if (AFP_OK != (ret = getforkparams(obj, ofork, bitmap, rbuf + sizeof( u_short ), &buflen ))) {
1319 *rbuflen = buflen + sizeof( u_short );
1320 bitmap = htons( bitmap );
1321 memcpy(rbuf, &bitmap, sizeof( bitmap ));