}
}
+ LOG(log_debug, logtype_afpd, "write_file(off: %ju, size: %zu)",
+ (uintmax_t)offset, rbuflen);
+
if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
rbuf, rbuflen)) < 0 ) {
switch ( errno ) {
case AFPPROTO_DSI:
{
DSI *dsi = obj->handle;
-
/* find out what we have already and write it out. */
cc = dsi_writeinit(dsi, rbuf, *rbuflen);
+
if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
dsi_writeflush(dsi);
*rbuflen = 0;
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
return cc;
}
+
offset += cc;
#if 0 /*def HAVE_SENDFILE_WRITE*/
extern int ad_copy_header (struct adouble *, struct adouble *);
extern int ad_flush (struct adouble *);
extern int ad_close (struct adouble *, int);
+extern int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags);
/* ad_lock.c */
extern int ad_testlock (struct adouble *adp, int eid, off_t off);
#define EID_DISK(a) (set_eid[a])
+int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags)
+{
+ if ((ad->ad_maxeafssize == 0) || (ad->ad_maxeafssize >= size)) {
+ LOG(log_debug, logtype_default, "fsetrsrcea(\"%s\"): size: %zu", eaname, size);
+ if (sys_fsetxattr(fd, eaname, value, size, 0) == -1)
+ return -1;
+ return 0;
+ }
+
+ /* rsrcfork is larger then maximum EA support by fs so we have to split it */
+ int i;
+ int eas = (size / ad->ad_maxeafssize);
+ size_t remain = size - (eas * ad->ad_maxeafssize);
+ bstring eachunk;
+
+ LOG(log_debug, logtype_default, "fsetrsrcea(\"%s\"): size: %zu, maxea: %zu, eas: %d, remain: %zu",
+ eaname, size, ad->ad_maxeafssize, eas, remain);
+
+ for (i = 0; i < eas; i++) {
+ if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
+ return -1;
+ if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), ad->ad_maxeafssize, 0) == -1) {
+ LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
+ bdestroy(eachunk);
+ return -1;
+ }
+ bdestroy(eachunk);
+ }
+
+ if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
+ return -1;
+ if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), remain, 0) == -1) {
+ LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
+ return -1;
+ }
+ bdestroy(eachunk);
+
+ return 0;
+}
+
/*
* Rebuild any header information that might have changed.
*/
int ad_flush(struct adouble *ad)
{
int len;
+
+ LOG(log_debug, logtype_default, "ad_flush(%s)", adflags2logstr(ad->ad_adflags));
+
struct ad_fd *adf;
switch (ad->ad_vers) {
}
break;
case AD_VERSION_EA:
- if (sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
- LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s",
- strerror(errno));
- return -1;
+ if (AD_META_OPEN(ad)) {
+ if (sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
+ LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s",
+ strerror(errno));
+ return -1;
+ }
+ }
+#ifndef HAVE_EAFD
+ if (AD_RSRC_OPEN(ad) && (ad->ad_rlen > 0)) {
+ if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
+ return -1;
}
+#endif
break;
default:
LOG(log_error, logtype_afpd, "ad_flush: unexpected adouble version");
return( 0 );
}
+static int ad_data_closefd(struct adouble *ad)
+{
+ int ret = 0;
+
+ if (ad_data_fileno(ad) == -2) {
+ free(ad->ad_data_fork.adf_syml);
+ ad->ad_data_fork.adf_syml = NULL;
+ } else {
+ if (close(ad_data_fileno(ad)) < 0)
+ ret = -1;
+ }
+ ad_data_fileno(ad) = -1;
+ return ret;
+}
+
/*!
* Close a struct adouble freeing all resources
*/
if ((adflags & ADFLAGS_DF)
&& (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
&& --ad->ad_data_fork.adf_refcount == 0) {
- if (ad->ad_data_fork.adf_syml != NULL) {
- free(ad->ad_data_fork.adf_syml);
- ad->ad_data_fork.adf_syml = 0;
- } else {
- if ( close( ad_data_fileno(ad) ) < 0 )
- err = -1;
- }
- ad_data_fileno(ad) = -1;
+ if (ad_data_closefd(ad) < 0)
+ err = -1;
adf_lock_free(&ad->ad_data_fork);
}
case AD_VERSION_EA:
if ((ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
&& !(--ad->ad_data_fork.adf_refcount)) {
- if (close( ad_data_fileno(ad) ) < 0)
+ if (ad_data_closefd(ad) < 0)
err = -1;
- ad_data_fileno(ad) = -1;
adf_lock_free(&ad->ad_data_fork);
}
break;
break;
case AD_VERSION_EA:
+#ifndef HAVE_EAFD
+ LOG(log_debug, logtype_default, "ad_close: ad->ad_rlen: %zu", ad->ad_rlen);
+ if (ad->ad_rlen > 0)
+ if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
+ err = -1;
+#endif
if ((ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
&& !(--ad->ad_data_fork.adf_refcount)) {
- if (close( ad_data_fileno(ad) ) < 0)
+ if (ad_data_closefd(ad) < 0)
err = -1;
- ad_data_fileno(ad) = -1;
adf_lock_free(&ad->ad_data_fork);
+ if (ad->ad_resforkbuf)
+ free(ad->ad_resforkbuf);
+ ad->ad_resforkbuf = NULL;
+ ad->ad_rlen = 0;
}
break;
return 0;
}
-static int ad_rsrc_len_ea(struct adouble *ad)
+static int ad_read_rf_ea(struct adouble *ad)
{
+ EC_INIT;
ssize_t rlen;
if ((rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) {
switch (errno) {
case ENOATTR:
case ENOENT:
- ad->ad_rlen = 0;
- break;
+ return 0;
default:
LOG(log_error, logtype_default, "ad_refresh_rsrc_len_ea: %s", strerror(errno));
- ad->ad_rlen = 0;
return -1;
}
}
+
+ if (ad->ad_resforkbuf == NULL) {
+ EC_NULL_LOG( ad->ad_resforkbuf = malloc(rlen) );
+ } else {
+ if (rlen > ad->ad_rlen) {
+ EC_ZERO_LOG( ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, rlen) );
+ }
+ }
ad->ad_rlen = rlen;
- return 0;
+
+ EC_NEG1_LOG( sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) );
+
+EC_CLEANUP:
+ EC_EXIT;
}
static int ad_mkrf(const char *path)
*/
static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad)
{
- int ret = 0;
+ EC_INIT;
int oflags;
ssize_t rlen;
return -1;
}
} else {
- if ((ad_data_fileno(ad) = open(path, oflags)) == -1)
- goto exit;
+ EC_NEG1( (ad_data_fileno(ad) = open(path, oflags)) );
ad->ad_data_fork.adf_flags = oflags;
adf_lock_init(&ad->ad_data_fork);
+#ifndef HAVE_EAFD
+ EC_ZERO_LOG( ad_read_rf_ea(ad) );
+#endif
}
- if ((ret = ad_rsrc_len_ea(ad)) != 0)
- goto exit;
-
ad->ad_data_fork.adf_refcount++;
-exit:
- return ret;
+EC_CLEANUP:
+ if (ret != 0) {
+ ad->ad_rlen = 0;
+ ad->ad_adflags &= ~ADFLAGS_RF;
+ }
+ EC_EXIT;
}
/***********************************************************************************
ad->ad_data_fork.adf_refcount = 0;
ad->ad_data_fork.adf_syml = 0;
ad->ad_inited = 0;
+// ad->ad_maxeafssize = 3500; /* FIXME: option from vol */
+ ad->ad_maxeafssize = 0; /* no limit */
return;
}
{
ad->ad_vers = vol->v_adouble;
ad->ad_options = vol->v_ad_options;
-// ad->ad_maxeafssize = 3500; /* FIXME: option from vol */
- ad->ad_maxeafssize = 0; /* no limit */
ad_init_func(ad);
}
case AD_VERSION_EA:
if (ad_data_fileno(ad) == -1)
return -1;
- if (ad_rsrc_len_ea(ad) != 0)
+#ifndef HAVE_EAFD
+ if (ad_read_rf_ea(ad) != 0)
return -1;
+#endif
return ad->ad_ops->ad_header_read(ad, NULL);
break;
default:
break;
case AD_VERSION_EA:
- if ((rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) {
- switch (errno) {
- case ENOATTR:
- case ENOENT:
- cc = ad->ad_rlen = 0;
- break;
- default:
- LOG(log_error, logtype_default, "ad_read: %s", strerror(errno));
- return -1;
- }
- }
- ad->ad_rlen = rlen;
-
+#ifndef HAVE_EAFD
if (off > ad->ad_rlen) {
errno = ERANGE;
return -1;
}
-
- if (ad->ad_resforkbuf == NULL) {
- if ((ad->ad_resforkbuf = malloc(ad->ad_rlen)) == NULL) {
- ad->ad_rlen = 0;
- return -1;
- }
- } else {
- if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, ad->ad_rlen)) == NULL) {
- ad->ad_rlen = 0;
- return -1;
- }
- }
-
- if (sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) {
- ad->ad_rlen = 0;
- return -1;
- }
-
if ((off + buflen) > ad->ad_rlen)
- cc = ad->ad_rlen;
+ cc = off + buflen - ad->ad_rlen;
memcpy(buf, ad->ad_resforkbuf + off, cc);
+#endif
break;
- } /* switch (ad->ad_vers) */
+ }
}
return( cc );
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
#include <atalk/logger.h>
-
-#ifndef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#endif /* ! MIN */
-
-static int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags)
-{
- if ((ad->ad_maxeafssize == 0) || (ad->ad_maxeafssize >= size)) {
- if (sys_fsetxattr(fd, eaname, value, size, 0) == -1)
- return -1;
- return 0;
- }
-
- /* rsrcfork is larger then maximum EA support by fs so we have to split it */
- int i;
- int eas = (size / ad->ad_maxeafssize);
- size_t remain = size - (eas * ad->ad_maxeafssize);
- bstring eachunk;
-
- LOG(log_debug, logtype_default, "fsetrsrcea(\"%s\"): size: %zu, maxea: %zu, eas: %d, remain: %zu",
- eaname, size, ad->ad_maxeafssize, eas, remain);
-
- for (i = 0; i < eas; i++) {
- if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
- return -1;
- if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), ad->ad_maxeafssize, 0) == -1) {
- LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
- bdestroy(eachunk);
- return -1;
- }
- bdestroy(eachunk);
- }
-
- if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
- return -1;
- if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), remain, 0) == -1) {
- LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
- return -1;
- }
- bdestroy(eachunk);
-
- return 0;
-}
-
-
+#include <atalk/util.h>
+#include <atalk/errchk.h>
/* XXX: locking has to be checked before each stream of consecutive
* ad_writes to prevent a lock in the middle from causing problems.
/* end is always 0 */
ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const char *buf, size_t buflen)
{
+ EC_INIT;
struct stat st;
ssize_t cc;
size_t roundup;
errno = EACCES;
return -1;
}
+
+ LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+ (uintmax_t)off, buflen, ad->ad_rlen);
if ( eid == ADEID_DFORK ) {
if ( end ) {
break;
case AD_VERSION_EA:
- if (ad->ad_resforkbuf == NULL) {
+#ifndef HAVE_EAFD
+ LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+ (uintmax_t)off, buflen, ad->ad_rlen);
+ if (ad->ad_rlen == 0) {
+ EC_NULL_LOG( ad->ad_resforkbuf = malloc(off + buflen) );
ad->ad_rlen = off + buflen;
- if ((ad->ad_resforkbuf = malloc(ad->ad_rlen)) == NULL) {
- ad->ad_rlen = 0;
- return -1;
- }
- }
- if ((off + buflen) > ad->ad_rlen) {
- if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, off + buflen)) == NULL)
- return -1;
+ } else if ((off + buflen) > ad->ad_rlen) {
+ EC_NULL_LOG( ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, off + buflen) );
ad->ad_rlen = off + buflen;
}
+
memcpy(ad->ad_resforkbuf + off, buf, buflen);
-
- if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
- return -1;
+ if (ad->ad_rlen > 0)
+ if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
+ ret = -1;
cc = buflen;
+ LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+ (uintmax_t)off, buflen, ad->ad_rlen);
+#endif
break;
default:
return -1; /* we don't know how to write if it's not a ressource or data fork */
}
+EC_CLEANUP:
+ if (ret != 0)
+ return ret;
return( cc );
}