#include <atalk/bstradd.h>
#include <atalk/compat.h>
#include <atalk/errchk.h>
+#include <atalk/volume.h>
#include "ad_lock.h"
struct stat st;
ad->ad_magic = AD_MAGIC;
- ad->ad_version = ad->ad_flags & 0x0f0000;
+ ad->ad_version = ad->ad_vers & 0x0f0000;
if (!ad->ad_version) {
ad->ad_version = AD_VERSION;
}
memset(ad->ad_data, 0, sizeof(ad->ad_data));
- if (ad->ad_flags == AD_VERSION2)
+ if (ad->ad_vers == AD_VERSION2)
eid = entry_order2;
- else if (ad->ad_flags == AD_VERSION_EA)
+ else if (ad->ad_vers == AD_VERSION_EA)
eid = entry_order_ea;
else {
return -1;
/* Now parse entries */
parse_entries(ad, buf + AD_HEADER_LEN, nentries);
+
+ return 0;
+}
+
+static int ad_rsrc_len_ea(struct adouble *ad)
+{
+ 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;
+ default:
+ LOG(log_error, logtype_default, "ad_refresh_rsrc_len_ea: %s", strerror(errno));
+ ad->ad_rlen = 0;
+ return -1;
+ }
+ }
+ ad->ad_rlen = rlen;
return 0;
}
/* ----------------
return access right and inode of path parent directory
*/
-static int ad_mode_st(const char *path, int *mode, struct stat *stbuf)
+static int ad_mode_st(const char *path, mode_t *mode, struct stat *stbuf)
{
if (*mode == 0) {
return -1;
static int ad_error(struct adouble *ad, int adflags)
{
int err = errno;
- if ((adflags & ADFLAGS_NOHF)) { /* 1 */
- /* FIXME double check : set header offset ?*/
+ if (adflags & ADFLAGS_NOHF) { /* 1 */
+ ad->ad_adflags &= ~ADFLAGS_HF;
return 0;
}
- if ((adflags & ADFLAGS_DF)) { /* 2 */
+ if (adflags & ADFLAGS_DF) { /* 2 */
ad_close( ad, ADFLAGS_DF );
err = errno;
}
if (ad_meta_fileno(ad) != -1) {
/* the file is already open, but we want write access: */
- if (!(adflags & ADFLAGS_RDONLY) &&
+ if ((adflags & ADFLAGS_RDWR) &&
/* and it was already denied: */
- !(ad->ad_mdp->adf_flags & O_RDWR)) {
+ (ad->ad_mdp->adf_flags & O_RDONLY)) {
errno = EACCES;
return -1;
}
ssize_t rforklen;
int oflags = O_NOFOLLOW;
- oflags = ad2openflags(adflags) & ~(O_CREAT | O_TRUNC);
+ LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\", %04o)", path, mode);
+
+ oflags |= ad2openflags(adflags) & ~(O_CREAT | O_TRUNC);
- if (ad_meta_fileno(ad) == -1) {
- if ((ad_meta_fileno(ad) = open(path, oflags)) == -1)
+ if (ad_data_fileno(ad) != -1) {
+ /* the file is already open, but we want write access: */
+ if ((adflags & ADFLAGS_RDWR) &&
+ /* and it was already denied: */
+ (ad->ad_data_fork.adf_flags & O_RDONLY)) {
+ LOG(log_error, logtype_default, "ad_open_hf_ea(%s): rw request for ro file: %s",
+ fullpathname(path), strerror(errno));
+ errno = EACCES;
+ return -1;
+ }
+
+ /* it's not new anymore */
+ ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT );
+ } else {
+ if ((ad_data_fileno(ad) = open(path, oflags)) == -1)
goto error;
- ad->ad_mdp->adf_flags = oflags;
- ad->ad_mdp->adf_refcount = 1;
- adf_lock_init(ad->ad_mdp);
+ ad->ad_data_fork.adf_flags = oflags;
+ adf_lock_init(&ad->ad_data_fork);
}
/* Read the adouble header in and parse it.*/
LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): created metadata EA", path);
}
- ad->ad_mdp->adf_refcount++;
+ ad->ad_data_fork.adf_refcount++;
- if ((rforklen = sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, NULL, 0)) > 0)
+ if ((rforklen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) > 0)
ad->ad_rlen = rforklen;
return 0;
error:
- if (ad_meta_fileno(ad) != -1) {
- close(ad_meta_fileno(ad));
- ad_meta_fileno(ad) = -1;
+ if (ad_data_fileno(ad) != -1) {
+ close(ad_data_fileno(ad));
+ ad_data_fileno(ad) = -1;
}
return ad_error(ad, adflags);
}
memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
ad->ad_rlen = 0;
- switch (ad->ad_flags) {
+ switch (ad->ad_vers) {
case AD_VERSION2:
ret = ad_open_hf_v2(path, adflags, mode, ad);
break;
return ret;
}
+
/*!
* Open ressource fork
*
static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad)
{
int ret = 0;
+ int oflags;
+ ssize_t rlen;
- if (ad->ad_flags != AD_VERSION_EA)
+ if (ad->ad_vers != AD_VERSION_EA)
return 0;
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", %04o)",
- path, mode);
+ LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", %04o)", path, mode);
- if ((ad->ad_rlen = sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) {
- switch (errno) {
- case ENOATTR:
- ad->ad_rlen = 0;
- break;
- default:
- LOG(log_warning, logtype_default, "ad_open_rf(\"%s\"): %s",
+ oflags |= ad2openflags(adflags) & ~(O_CREAT | O_TRUNC);
+
+ if (ad_data_fileno(ad) != -1) {
+ /* the file is already open, but we want write access: */
+ if ((adflags & ADFLAGS_RDWR) &&
+ /* and it was already denied: */
+ (ad->ad_data_fork.adf_flags & O_RDONLY)) {
+ LOG(log_error, logtype_default, "ad_open_rf(%s): rw request for ro file: %s",
fullpathname(path), strerror(errno));
- ret = -1;
- goto exit;
+ errno = EACCES;
+ return -1;
}
+ } else {
+ if ((ad_data_fileno(ad) = open(path, oflags)) == -1)
+ goto exit;
+ ad->ad_data_fork.adf_flags = oflags;
+ adf_lock_init(&ad->ad_data_fork);
}
- /* Round up and allocate buffer */
- size_t roundup = ((ad->ad_rlen / RFORK_EA_ALLOCSIZE) + 1) * RFORK_EA_ALLOCSIZE;
- if ((ad->ad_resforkbuf = malloc(roundup)) == NULL) {
- ret = -1;
+ if ((ret = ad_rsrc_len_ea(ad)) != 0)
goto exit;
- }
- ad->ad_resforkbufsize = roundup;
-
- /* Read the EA into the buffer */
- if (ad->ad_rlen > 0) {
- if (sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) {
- ret = -1;
- goto exit;
- }
- }
+ ad->ad_data_fork.adf_refcount++;
exit:
- if (ret != 0) {
- free(ad->ad_resforkbuf);
- ad->ad_resforkbuf = NULL;
- ad->ad_rlen = 0;
- ad->ad_resforkbufsize = 0;
- }
-
return ret;
}
/* ----------------
return access right of path parent directory
*/
-int ad_mode( const char *path, int mode)
+int ad_mode( const char *path, mode_t mode)
{
struct stat stbuf;
ad_mode_st(path, &mode, &stbuf);
/*
* Use mkdir() with mode bits taken from ad_mode().
*/
-int ad_mkdir( const char *path, int mode)
+int ad_mkdir( const char *path, mode_t mode)
{
int ret;
int st_invalid;
return ret;
}
-void ad_init(struct adouble *ad, int flags, int options)
+static void ad_init_func(struct adouble *ad)
{
- switch (flags) {
+ switch (ad->ad_vers) {
case AD_VERSION2:
ad->ad_ops = &ad_adouble;
ad->ad_rfp = &ad->ad_resource_fork;
break;
case AD_VERSION_EA:
ad->ad_ops = &ad_adouble_ea;
- ad->ad_rfp = &ad->ad_data_fork;
- ad->ad_mdp = &ad->ad_data_fork;
+ ad->ad_rfp = &ad->ad_resource_fork;
+ ad->ad_mdp = &ad->ad_resource_fork;
break;
default:
- LOG(log_error, logtype_default, "ad_init: unknown AD version");
- errno = EIO;
- return;
+ AFP_PANIC("ad_init: unknown AD version");
}
- ad->ad_flags = flags;
- ad->ad_options = options;
ad_data_fileno(ad) = -1;
ad_reso_fileno(ad) = -1;
ad_meta_fileno(ad) = -1;
ad->ad_resource_fork.adf_refcount = 0;
ad->ad_resforkbuf = NULL;
ad->ad_data_fork.adf_refcount = 0;
- ad->ad_data_fork.adf_syml=0;
+ ad->ad_data_fork.adf_syml = 0;
ad->ad_inited = 0;
+ return;
+}
+
+void ad_init_old(struct adouble *ad, int flags, int options)
+{
+ ad->ad_vers = flags;
+ ad->ad_options = options;
+ ad_init_func(ad);
+}
+
+void ad_init(struct adouble *ad, const struct vol * restrict vol)
+{
+ 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);
}
/*!
int ad_refresh(struct adouble *ad)
{
-
- if (ad_meta_fileno(ad) == -1)
+ switch (ad->ad_vers) {
+ case AD_VERSION2:
+ if (ad_meta_fileno(ad) == -1)
+ return -1;
+ return ad->ad_ops->ad_header_read(ad, NULL);
+ break;
+ case AD_VERSION_EA:
+ if (ad_data_fileno(ad) == -1)
+ return -1;
+ if (ad_rsrc_len_ea(ad) != 0)
+ return -1;
+ return ad->ad_ops->ad_header_read(ad, NULL);
+ break;
+ default:
return -1;
+ break;
+ }
- return ad->ad_ops->ad_header_read(ad, NULL);
}
int ad_openat(struct adouble *ad,