X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Ffork.c;h=73abb1e9a102e5a5143303a08011b976cdc982f8;hp=7b24b7f26b99e26a5c648b9686021be229967eea;hb=42a0a094b72577aee3fee7f186da52dc83db001d;hpb=1ae3c8a1f36c4f9d2a5272a0e700463817aaff1b diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 7b24b7f2..73abb1e9 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -66,10 +66,10 @@ static int getforkparams(const AFPObj *obj, struct ofork *ofork, uint16_t bitmap vol = ofork->of_vol; dir = dirlookup(vol, ofork->of_did); - if (NULL == (path.m_name = utompath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) { + if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) { return( AFPERR_MISC ); } - path.u_name = of_name(ofork); + path.m_name = of_name(ofork); path.id = 0; st = &path.st; if ( bitmap & ( (1<of_ad, upath, adflags, 0666) == 0) { ofork->of_flags |= AFPFORK_META; + if (ad_get_MD_flags(ofork->of_ad) & O_CREAT) { + LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\"): setting CNID", upath); + cnid_t id; + if ((id = get_id(vol, ofork->of_ad, st, dir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + goto openfork_err; + } + (void)ad_setid(ofork->of_ad, st->st_dev, st->st_ino, id, dir->d_did, vol->v_stamp); + ad_flush(ofork->of_ad); + } } else { switch (errno) { case EACCES: @@ -575,7 +583,7 @@ int afp_setforkparams(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf _U_, s goto afp_setfork_err; } - err = ad_rtruncate(ofork->of_ad, size); + err = ad_rtruncate(ofork->of_ad, mtoupath(ofork->of_vol, of_name(ofork), ofork->of_did, utf8_encoding(obj)), size); if (st_size > size) ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum); if (err < 0) @@ -791,6 +799,8 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si goto afp_read_err; } + AFP_READ_START((long)reqcount); + /* reqcount isn't always truthful. we need to deal with that. */ size = ad_size(ofork->of_ad, eid); @@ -798,7 +808,7 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si "afp_read(fork: %" PRIu16 " [%s], off: %" PRIu64 ", len: %" PRIu64 ", size: %" PRIu64 ")", ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "reso", offset, reqcount, size); - if (offset > size) { + if (offset >= size) { err = AFPERR_EOF; goto afp_read_err; } @@ -837,11 +847,13 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si } #endif - *rbuflen = MIN(reqcount, *rbuflen); + *rbuflen = MIN(reqcount, dsi->server_quantum); - err = read_file(ofork, eid, offset, rbuf, rbuflen); - if (err < 0) + cc = read_file(ofork, eid, offset, ibuf, rbuflen); + if (cc < 0) { + err = cc; goto afp_read_done; + } LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file", @@ -854,18 +866,22 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si * we know that we're sending some data. if we fail, something * horrible happened. */ - if ((cc = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0) + if ((cc = dsi_readinit(dsi, ibuf, *rbuflen, reqcount, err)) < 0) goto afp_read_exit; *rbuflen = cc; while (*rbuflen > 0) { - cc = read_file(ofork, eid, offset, rbuf, rbuflen); + /* + * This loop isn't really entered anymore, we've already + * sent the whole requested block in dsi_readinit(). + */ + cc = read_file(ofork, eid, offset, ibuf, rbuflen); if (cc < 0) goto afp_read_exit; offset += *rbuflen; /* dsi_read() also returns buffer size of next allocation */ - cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */ + cc = dsi_read(dsi, ibuf, *rbuflen); /* send it off */ if (cc < 0) goto afp_read_exit; *rbuflen = cc; @@ -883,6 +899,8 @@ afp_read_exit: afp_read_done: if (obj->options.flags & OPTION_AFP_READ_LOCK) ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount, ofork->of_refnum); + + AFP_READ_DONE(); return err; afp_read_err: @@ -1153,6 +1171,8 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s goto afp_write_err; } + AFP_WRITE_START((long)reqcount); + saveoff = offset; if (obj->options.flags & OPTION_AFP_READ_LOCK) { if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff, reqcount, ofork->of_refnum) < 0) { @@ -1162,41 +1182,54 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s } /* find out what we have already */ - cc = dsi_writeinit(dsi, rcvbuf, rcvbuflen); - - if (!cc || (cc = write_file(ofork, eid, offset, rcvbuf, cc)) < 0) { - dsi_writeflush(dsi); - *rbuflen = 0; - if (obj->options.flags & OPTION_AFP_READ_LOCK) - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); - return cc; + if ((cc = dsi_writeinit(dsi, rcvbuf, rcvbuflen)) > 0) { + ssize_t written; + if ((written = write_file(ofork, eid, offset, rcvbuf, cc)) != cc) { + dsi_writeflush(dsi); + *rbuflen = 0; + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + if (written > 0) + /* It's used for the read size and as error code in write_file(), ugh */ + written = AFPERR_MISC; + return written; + } } offset += cc; -#if 0 /*def HAVE_SENDFILE_WRITE*/ - if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize)) < 0) { - switch (errno) { - case EDQUOT: - case EFBIG: - case ENOSPC: - cc = AFPERR_DFULL; - break; - default: - LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) ); - goto afp_write_loop; +#ifdef WITH_RECVFILE + if (obj->options.flags & OPTION_RECVFILE) { + LOG(log_maxdebug, logtype_afpd, "afp_write(fork: %" PRIu16 " [%s], off: %" PRIu64 ", size: %" PRIu32 ")", + ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "reso", offset, dsi->datasize); + + if ((cc = ad_recvfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize, obj->options.splice_size)) < dsi->datasize) { + switch (errno) { + case EDQUOT: + case EFBIG: + case ENOSPC: + cc = AFPERR_DFULL; + dsi_writeflush(dsi); + break; + case ENOSYS: + goto afp_write_loop; + default: + /* Low level error, can't do much to back up */ + cc = AFPERR_MISC; + LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno)); + } + *rbuflen = 0; + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + return cc; } - dsi_writeflush(dsi); - *rbuflen = 0; - if (obj->options.flags & OPTION_AFP_READ_LOCK) - ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); - return cc; - } - offset += cc; - goto afp_write_done; -#endif /* 0, was HAVE_SENDFILE_WRITE */ + offset += cc; + goto afp_write_done; + } +#endif +afp_write_loop: /* loop until everything gets written. currently * dsi_write handles the end case by itself. */ while ((cc = dsi_write(dsi, rcvbuf, rcvbuflen))) { @@ -1215,6 +1248,7 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s offset += cc; } +afp_write_done: if (obj->options.flags & OPTION_AFP_READ_LOCK) ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */ @@ -1227,6 +1261,7 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0; *rbuflen = set_off_t (offset, rbuf, is64); + AFP_WRITE_DONE(); return( AFP_OK ); afp_write_err: