struct adouble ad, *adp;
int opened = 0;
int rc;
+ int flags;
LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
if (opened) {
char *upath;
- int flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
+ flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
adp = of_ad(vol, path, &ad);
upath = path->u_name;
}
}
rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
- ad_close(adp, ADFLAGS_HF);
+ ad_close(adp, ADFLAGS_HF | flags);
return( rc );
}
setvoltime(obj, d_vol );
copy_exit:
- ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
+ ad_close( adp, ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_SETSHRMD);
return( retvalue );
}
dfd = ad_reso_fileno(add);
}
- if (add->ad_version == AD_VERSION2)
- soff = doff = ad_getentryoff(ads, eid);
- else {
- if (eid == ADEID_DFORK)
- soff = doff = ad_getentryoff(ads, eid);
- else {
-#ifdef HAVE_EAFD
- soff = doff = 0;
-#else
- soff = doff = ADEDOFF_RFORK_OSX;
-#endif
- }
- }
+ soff = doff = ad_getentryoff(ads, eid);
if ((off_t)-1 == lseek(sfd, soff, SEEK_SET))
return -1;
}
adflags = ADFLAGS_DF | ADFLAGS_RF | ADFLAGS_NORF;
- if (newname) {
- adflags |= ADFLAGS_HF;
- }
if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF | ADFLAGS_RDONLY) < 0) {
ret_err = errno;
return AFPERR_EXIST;
}
+#if 0
if (AD_RSRC_OPEN(adp))
err = copy_fork(ADEID_RFORK, &add, adp);
-
+#endif
+
if (err == 0)
err = copy_fork(ADEID_DFORK, &add, adp);
- if ((err == 0) && (ad_meta_fileno(adp) != -1))
+ if (err == 0)
err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
if (err < 0)
*/
if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
if ((err = check_attrib(&ad))) {
- ad_close(&ad, ADFLAGS_HF);
+ ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF);
return err;
}
meta = 1;
end:
if (meta)
- ad_close(&ad, ADFLAGS_HF);
+ ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF);
if (adp)
ad_close( &ad, adflags ); /* ad_close removes locks if any */
}
if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
- ad_close( ofork->of_ad, adflags );
+ ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
goto openfork_err;
}
if (ad_meta_fileno(ofork->of_ad) != -1) { /* META */
ad_getattr(ofork->of_ad, &bshort);
if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
- ad_close( ofork->of_ad, adflags );
+ ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
of_dealloc( ofork );
ofrefnum = 0;
memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
/* can we access the fork? */
if (ret < 0) {
+ ofork->of_flags |= AFPFORK_ERROR;
ret = errno;
- ad_close( ofork->of_ad, adflags );
+ ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
of_dealloc( ofork );
switch (ret) {
case EAGAIN: /* return data anyway */
#define AFPFORK_ACCWR (1<<5)
#define AFPFORK_ACCMASK (AFPFORK_ACCRD | AFPFORK_ACCWR)
#define AFPFORK_MODIFIED (1<<6) /* used in FCE for modified files */
+#define AFPFORK_ERROR (1<<7) /* used to indicate an error in opening the fork */
#ifdef AFS
extern struct ofork *writtenfork;
free( of->of_ad->ad_m_name );
free( of->of_ad);
} else {/* someone's still using it. just free this user's locks */
- ad_unlock(of->of_ad, of->of_refnum);
+ ad_unlock(of->of_ad, of->of_refnum, of->of_flags & AFPFORK_ERROR ? 0 : 1);
}
free( of );
}
ret = 0;
- if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
+ if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) {
ret = -1;
}
#define ad_getentrylen(ad,eid) ((ad)->ad_eid[(eid)].ade_len)
#define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len))
-#define ad_getentryoff(ad,eid) ((ad)->ad_eid[(eid)].ade_off)
#define ad_setentryoff(ad,eid,off) ((ad)->ad_eid[(eid)].ade_off = (off))
#define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
/* ad_lock.c */
extern int ad_testlock (struct adouble *adp, int eid, off_t off);
extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
-extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
-extern void ad_unlock(struct adouble *, int user);
-extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
+extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork);
+extern void ad_unlock(struct adouble *, int fork, int unlckbrl);
+extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork);
/* ad_open.c */
+extern off_t ad_getentryoff(const struct adouble *ad, int eid);
extern const char *adflags2logstr(int adflags);
extern int ad_setfuid (const uid_t );
extern uid_t ad_getfuid (void );
ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+ if ((ad->ad_vers == AD_VERSION2) && (adflags & (ADFLAGS_SETSHRMD | ADFLAGS_CHECK_OF))) {
+ /* sharemode locks are stored in the data fork, adouble:v2 needs this extra handling */
+ adflags |= ADFLAGS_DF;
+ }
+
if ((ad->ad_vers == AD_VERSION2) && (adflags & ADFLAGS_RF))
adflags |= ADFLAGS_HF;
#include <atalk/logger.h>
#include <atalk/compat.h>
#include <atalk/errchk.h>
+#include <atalk/util.h>
#include <stdio.h>
#include <stdlib.h>
* i converted to using arrays of locks. everytime a lock
* gets removed, we shift all of the locks down.
*/
-static void adf_unlock(struct ad_fd *ad, const int fork)
+static void adf_unlock(struct adouble *ad, struct ad_fd *adf, const int fork, int unlckbrl)
{
- adf_lock_t *lock = ad->adf_lock;
+ adf_lock_t *lock = adf->adf_lock;
int i;
- for (i = 0; i < ad->adf_lockcount; i++) {
- if (lock[i].lock.l_start < AD_FILELOCK_BASE
+ for (i = 0; i < adf->adf_lockcount; i++) {
+ if ((unlckbrl && lock[i].lock.l_start < AD_FILELOCK_BASE)
|| lock[i].user == fork) {
/* we're really going to delete this lock. note: read locks
are the only ones that allow refcounts > 1 */
- adf_freelock(ad, i);
+ adf_freelock(adf, i);
/* we shifted things down, so we need to backtrack */
i--;
/* unlikely but realloc may have change adf_lock */
- lock = ad->adf_lock;
+ lock = adf->adf_lock;
}
}
}
* 2) if the header file doesn't exist, we stick the locks
* in the locations specified by AD_FILELOCK_RD/WR.
*/
-#define LOCK_DATA_WR (0)
-#define LOCK_DATA_RD (1)
-#define LOCK_RSRC_WR (2)
-#define LOCK_RSRC_RD (3)
-
-#define LOCK_RSRC_DRD (4)
-#define LOCK_RSRC_DWR (5)
-#define LOCK_DATA_DRD (6)
-#define LOCK_DATA_DWR (7)
-
-#define LOCK_RSRC_NONE (8)
-#define LOCK_DATA_NONE (9)
-
-/* --------------
- translate a data fork lock to an offset
-*/
-
-static off_t df2off(off_t off)
-{
- off_t start = off;
- if (off == AD_FILELOCK_OPEN_WR)
- start = LOCK_DATA_WR;
- else if (off == AD_FILELOCK_OPEN_RD)
- start = LOCK_DATA_RD;
- else if (off == AD_FILELOCK_DENY_RD)
- start = LOCK_DATA_DRD;
- else if (off == AD_FILELOCK_DENY_WR)
- start = LOCK_DATA_DWR;
- else if (off == AD_FILELOCK_OPEN_NONE)
- start = LOCK_DATA_NONE;
- return start;
-}
-
-/* --------------
- translate a resource fork lock to an offset
-*/
-
-static off_t hf2off(off_t off)
-{
- off_t start = off;
- if (off == AD_FILELOCK_OPEN_WR)
- start = LOCK_RSRC_WR;
- else if (off == AD_FILELOCK_OPEN_RD)
- start = LOCK_RSRC_RD;
- else if (off == AD_FILELOCK_DENY_RD)
- start = LOCK_RSRC_DRD;
- else if (off == AD_FILELOCK_DENY_WR)
- start = LOCK_RSRC_DWR;
- else if (off == AD_FILELOCK_OPEN_NONE)
- start = LOCK_RSRC_NONE;
- return start;
-}
/* --------------
translate a resource fork lock to an offset
return 1;
}
-static uint16_t ad_openforks_v2(struct adouble *ad, uint16_t attrbits)
-{
- uint16_t ret = 0;
- struct ad_fd *adf;
- off_t off;
-
- if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
- off_t len;
- /* XXX know the locks layout:
- AD_FILELOCK_OPEN_WR is first
- and use it for merging requests
- */
- if (ad_meta_fileno(ad) != -1) {
- /* there's a resource fork test the four bytes for
- * data RW/RD and fork RW/RD locks in one request
- */
- adf = ad->ad_mdp;
- off = LOCK_DATA_WR;
- len = 4;
- }
- else {
- /* no resource fork, only data RD/RW may exist */
- adf = &ad->ad_data_fork;
- off = AD_FILELOCK_OPEN_WR;
- len = 2;
- }
- if (!testlock(adf, off, len))
- return ret;
- }
- /* either there's a lock or we already know one
- fork is open
- */
- if (!(attrbits & ATTRBIT_DOPEN)) {
- if (ad_meta_fileno(ad) != -1) {
- adf = ad->ad_mdp;
- off = LOCK_DATA_WR;
- }
- else {
- adf = &ad->ad_data_fork;
- off = AD_FILELOCK_OPEN_WR;
- }
- ret = testlock(adf, off, 2) > 0? ATTRBIT_DOPEN : 0;
- }
-
- if (!(attrbits & ATTRBIT_ROPEN)) {
- if (ad_meta_fileno(ad) != -1) {
- adf = ad->ad_mdp;
- off = LOCK_RSRC_WR;
- ret |= testlock(adf, off, 2) > 0? ATTRBIT_ROPEN : 0;
- }
- }
-
- return ret;
-}
-
-/* test for sharemode locks, adouble:ea stores them on the datafork */
-static uint16_t ad_openforks_ea(struct adouble *ad, uint16_t attrbits)
-{
- uint16_t ret = 0;
- struct ad_fd *adf;
- off_t off;
- off_t len;
-
- if (ad_data_fileno(ad) == -1)
- return 0;
-
- if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
- /* Test all 4 locks at once */
- off = AD_FILELOCK_OPEN_WR;
- len = 4;
- if (testlock(&ad->ad_data_fork, off, len) == 0)
- return 0;
- }
-
- /* either there's a lock or we already know one fork is open */
-
- if (!(attrbits & ATTRBIT_DOPEN)) {
- off = AD_FILELOCK_OPEN_WR;
- ret = testlock(&ad->ad_data_fork, off, 2) > 0 ? ATTRBIT_DOPEN : 0;
- }
-
- if (!(attrbits & ATTRBIT_ROPEN)) {
- off = AD_FILELOCK_RSRC_OPEN_WR;
- ret |= testlock(&ad->ad_data_fork, off, 2) > 0? ATTRBIT_ROPEN : 0;
- }
-
- return ret;
-}
-
-static int ad_testlock_v2(struct adouble *ad, int eid, const off_t off)
-{
- struct ad_fd *adf;
- off_t lock_offset;
-
- lock_offset = off;
- if (eid == ADEID_DFORK) {
- adf = &ad->ad_data_fork;
- if (ad_meta_fileno(ad) != -1) {
- adf = ad->ad_mdp;
- lock_offset = df2off(off);
- }
- } else { /* rfork */
- if (ad_meta_fileno(ad) == -1) {
- /* there's no resource fork. return no lock */
- return 0;
- }
- adf = ad->ad_mdp;
- lock_offset = hf2off(off);
- }
- return testlock(adf, lock_offset, 1);
-}
-
-static int ad_testlock_ea(struct adouble *ad, int eid, const off_t off)
-{
- off_t lock_offset;
-
- if (eid == ADEID_DFORK) {
- lock_offset = off;
- } else { /* rfork */
- lock_offset = rf2off(off);
- }
- return testlock(&ad->ad_data_fork, lock_offset, 1);
-}
-
#define LTYPE2STRBUFSIZ 128
static const char *locktypetostr(int type)
{
shmdstrfromoff(off),
(intmax_t)len);
- if ((locktype & ADLOCK_FILELOCK) && (len != 1)) {
- /* safety check */
- ret = -1;
- goto exit;
- }
+ if ((locktype & ADLOCK_FILELOCK) && (len != 1))
+ AFP_PANIC("lock API error");
- lock.l_start = off;
type = locktype;
if (eid == ADEID_DFORK) {
adf = &ad->ad_data_fork;
- if ((ad->ad_vers == AD_VERSION2) && (type & ADLOCK_FILELOCK)) {
- if (ad_meta_fileno(ad) != -1) { /* META */
- adf = ad->ad_mdp;
- lock.l_start = df2off(off);
- }
- }
+ lock.l_start = off;
} else { /* rfork */
- switch (ad->ad_vers) {
- case AD_VERSION2:
- if (ad_meta_fileno(ad) == -1 || ad_reso_fileno(ad) == -1) {
- /* there's no meta data. return a lock error
- * otherwise if a second process is able to create it
- * locks are a mess. */
- errno = EACCES;
- ret= -1;
- goto exit;
- }
- if (type & ADLOCK_FILELOCK) {
- adf = ad->ad_mdp; /* either resource or meta data (set in ad_open) */
- lock.l_start = hf2off(off);
- } else {
- /* we really want the resource fork it's a byte lock */
- adf = &ad->ad_resource_fork;
- lock.l_start += ad_getentryoff(ad, eid);
- }
- break;
-
- case AD_VERSION_EA:
- if (type & ADLOCK_FILELOCK) {
- adf = &ad->ad_data_fork;
- lock.l_start = rf2off(off);
- } else {
- adf = ad->ad_rfp;
-#if HAVE_EAFD
- lock.l_start = off;
-#else
- lock.l_start= ADEDOFF_RFORK_OSX + off;
-#endif
- }
- break;
-
- default:
- ret = -1;
- goto exit;
+ if (type & ADLOCK_FILELOCK) {
+ adf = &ad->ad_data_fork;
+ lock.l_start = rf2off(off);
+ } else {
+ adf = ad->ad_rfp;
+ lock.l_start = off + ad_getentryoff(ad, ADEID_RFORK);
}
}
lock.l_start = off;
type = locktype;
+
if (eid == ADEID_DFORK) {
adf = &ad->ad_data_fork;
} else {
- /* FIXME META */
adf = &ad->ad_resource_fork;
if (adf->adf_fd == -1) {
/* there's no resource fork. return success */
}
/* --------------------- */
-void ad_unlock(struct adouble *ad, const int fork)
+void ad_unlock(struct adouble *ad, const int fork, int unlckbrl)
{
- LOG(log_debug, logtype_default, "ad_unlock(\"%s\"): BEGIN", ad->ad_m_name ? ad->ad_m_name : "???");
+ LOG(log_debug, logtype_default, "ad_unlock(\"%s\", unlckbrl: %d): BEGIN",
+ ad->ad_m_name ? ad->ad_m_name : "???", unlckbrl);
if (ad_data_fileno(ad) != -1) {
- adf_unlock(&ad->ad_data_fork, fork);
+ adf_unlock(ad, &ad->ad_data_fork, fork, unlckbrl);
}
if (ad_reso_fileno(ad) != -1) {
- adf_unlock(&ad->ad_resource_fork, fork);
+ adf_unlock(ad, &ad->ad_resource_fork, fork, unlckbrl);
}
LOG(log_debug, logtype_default, "ad_unlock(\"%s\"): END", ad->ad_m_name ? ad->ad_m_name : "???");
int ad_testlock(struct adouble *ad, int eid, const off_t off)
{
int ret = 0;
+ off_t lock_offset;
LOG(log_debug, logtype_default, "ad_testlock(\"%s\", %s, off: %jd (%s): BEGIN",
ad->ad_m_name ? ad->ad_m_name : "???",
(intmax_t)off,
shmdstrfromoff(off));
- switch (ad->ad_vers) {
- case AD_VERSION2:
- ret = ad_testlock_v2(ad, eid, off);
- break;
- case AD_VERSION_EA:
- ret = ad_testlock_ea(ad, eid, off);
- break;
- default:
- ret = -1;
- break;
+ if (eid == ADEID_DFORK) {
+ lock_offset = off;
+ } else { /* rfork */
+ lock_offset = rf2off(off);
}
+ ret = testlock(&ad->ad_data_fork, lock_offset, 1);
+
LOG(log_debug, logtype_default, "ad_testlock: END: %d", ret);
return ret;
}
*/
uint16_t ad_openforks(struct adouble *ad, uint16_t attrbits)
{
- switch (ad->ad_vers) {
- case AD_VERSION2:
- return ad_openforks_v2(ad, attrbits);
- case AD_VERSION_EA:
- return ad_openforks_ea(ad, attrbits);
- default:
- return -1;
+ uint16_t ret = 0;
+ struct ad_fd *adf;
+ off_t off;
+ off_t len;
+
+ if (ad_data_fileno(ad) == -1)
+ return 0;
+
+ if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
+ /* Test all 4 locks at once */
+ off = AD_FILELOCK_OPEN_WR;
+ len = 4;
+ if (testlock(&ad->ad_data_fork, off, len) == 0)
+ return 0;
}
+
+ /* either there's a lock or we already know one fork is open */
+
+ if (!(attrbits & ATTRBIT_DOPEN)) {
+ off = AD_FILELOCK_OPEN_WR;
+ ret = testlock(&ad->ad_data_fork, off, 2) > 0 ? ATTRBIT_DOPEN : 0;
+ }
+
+ if (!(attrbits & ATTRBIT_ROPEN)) {
+ off = AD_FILELOCK_RSRC_OPEN_WR;
+ ret |= testlock(&ad->ad_data_fork, off, 2) > 0? ATTRBIT_ROPEN : 0;
+ }
+
+ return ret;
}
if (adflags & ADFLAGS_NOHF) { /* 1 */
return 0;
}
- if (adflags & ADFLAGS_DF) { /* 2 */
+ if (adflags & (ADFLAGS_DF | ADFLAGS_SETSHRMD | ADFLAGS_CHECK_OF)) { /* 2 */
ad_close( ad, ADFLAGS_DF );
err = errno;
}
return -1 ;
}
-/* Map ADFLAGS to open() flags */
-static int ad2openflags(int adflags)
+/*!
+ * Map ADFLAGS to open() flags
+ *
+ * @param adfile (r) the file you really want to open: ADFLAGS_DF or ADFLAGS_HF
+ * @param adflags (r) flags from ad_open(..., adflags, ...)
+ * @returns mapped flags suitable for calling open()
+ */
+static int ad2openflags(int adfile, int adflags)
{
int oflags = 0;
if (adflags & ADFLAGS_RDWR)
oflags |= O_RDWR;
if (adflags & ADFLAGS_RDONLY) {
- if (adflags & ADFLAGS_SETSHRMD)
+ if ((adfile & ADFLAGS_DF) && (adflags & ADFLAGS_SETSHRMD))
oflags |= O_RDWR;
else
oflags |= O_RDONLY;
static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad)
{
+ EC_INIT;
struct stat st_dir;
int oflags;
mode_t admode;
int st_invalid = -1;
ssize_t lsz;
- LOG(log_debug, logtype_default, "ad_open_df(\"%s\", %04o)",
- fullpathname(path), mode);
+ LOG(log_debug, logtype_default,
+ "ad_open_df(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+ fullpathname(path), adflags2logstr(adflags),
+ ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+ ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+ ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
if (ad_data_fileno(ad) != -1) {
/* the file is already open, but we want write access: */
/* it's not new anymore */
ad->ad_data_fork.adf_flags &= ~( O_TRUNC | O_CREAT );
ad->ad_data_fork.adf_refcount++;
- return 0;
+ goto EC_CLEANUP;
}
- oflags = O_NOFOLLOW | ad2openflags(adflags);
+ oflags = O_NOFOLLOW | ad2openflags(ADFLAGS_DF, adflags);
admode = mode;
if ((adflags & ADFLAGS_CREATE)) {
if ((adflags & ADFLAGS_SETSHRMD) && (adflags & ADFLAGS_RDONLY)) {
oflags &= ~O_RDWR;
oflags |= O_RDONLY;
- if ((ad->ad_data_fork.adf_fd = open(path, oflags, admode)) == -1)
- return -1;
+ EC_NEG1( ad->ad_data_fork.adf_fd = open(path, oflags, admode) );
break;
}
return -1;
ad->ad_data_fork.adf_syml = malloc(MAXPATHLEN+1);
if ((lsz = readlink(path, ad->ad_data_fork.adf_syml, MAXPATHLEN)) <= 0) {
free(ad->ad_data_fork.adf_syml);
- return -1;
+ EC_FAIL;
}
ad->ad_data_fork.adf_syml[lsz] = 0;
ad->ad_data_fork.adf_fd = -2; /* -2 means its a symlink */
break;
default:
- return -1;
+ EC_FAIL;
}
}
adf_lock_init(&ad->ad_data_fork);
ad->ad_data_fork.adf_refcount++;
- return 0;
+EC_CLEANUP:
+ LOG(log_debug, logtype_default,
+ "ad_open_df(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+ fullpathname(path), adflags2logstr(adflags), ret,
+ ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+ ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+ ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+ EC_EXIT;
}
-/* TODO: error handling */
static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adouble *ad)
{
+ EC_INIT;
struct stat st_dir;
struct stat st_meta;
struct stat *pst = NULL;
const char *ad_p;
- int oflags, nocreatflags;
+ int oflags, nocreatflags, opened = 0;
mode_t admode;
int st_invalid = -1;
+ LOG(log_debug, logtype_default,
+ "ad_open_hf_v2(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+ fullpathname(path), adflags2logstr(adflags),
+ ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+ ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+ ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+
if (ad_meta_fileno(ad) != -1) {
/* the file is already open, but we want write access: */
if ((adflags & ADFLAGS_RDWR) &&
/* and it was already denied: */
(ad->ad_mdp->adf_flags & O_RDONLY)) {
errno = EACCES;
- return -1;
+ EC_FAIL;
}
ad_refresh(path, ad);
/* it's not new anymore */
ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT );
ad->ad_mdp->adf_refcount++;
- return 0;
+ goto EC_CLEANUP;
}
ad_p = ad->ad_ops->ad_path(path, adflags);
- oflags = O_NOFOLLOW | ad2openflags(adflags);
+ oflags = O_NOFOLLOW | ad2openflags(ADFLAGS_HF, adflags);
nocreatflags = oflags & ~(O_CREAT | O_EXCL);
- ad->ad_mdp->adf_fd = open(ad_p, nocreatflags);
+ ad_meta_fileno(ad) = open(ad_p, nocreatflags);
- if (ad->ad_mdp->adf_fd != -1) {
+ if (ad_meta_fileno(ad) != -1) {
ad->ad_mdp->adf_flags = nocreatflags;
} else {
switch (errno) {
if ((adflags & ADFLAGS_RDONLY) && (adflags & ADFLAGS_SETSHRMD)) {
nocreatflags &= ~O_RDWR;
nocreatflags |= O_RDONLY;
- if ((ad->ad_mdp->adf_fd = open(ad_p, nocreatflags)) == -1)
- return -1;
+ EC_NEG1( ad_meta_fileno(ad) = open(ad_p, nocreatflags) );
ad->ad_mdp->adf_flags = nocreatflags;
break;
}
- return -1;
+ EC_FAIL;
case ENOENT:
if (!(oflags & O_CREAT))
- return ad_error(ad, adflags);
+ EC_FAIL;
/*
* We're expecting to create a new adouble header file here
*/
admode = mode;
admode = ad_hf_mode(admode);
if (errno == ENOENT) {
- if (ad->ad_ops->ad_mkrf( ad_p) < 0) {
- return ad_error(ad, adflags);
- }
+ EC_NEG1_LOG( ad->ad_ops->ad_mkrf(ad_p) );
admode = mode;
st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
if ((ad->ad_options & ADVOL_UNIXPRIV))
}
/* retry with O_CREAT */
- ad->ad_mdp->adf_fd = open(ad_p, oflags, admode);
- if ( ad->ad_mdp->adf_fd < 0 )
- return ad_error(ad, adflags);
-
+ EC_NEG1_LOG( ad_meta_fileno(ad) = open(ad_p, oflags, admode) );
ad->ad_mdp->adf_flags = oflags;
/* just created, set owner if admin owner (root) */
if (!st_invalid)
ad_chown(ad_p, &st_dir);
break;
default:
- return -1;
+ EC_FAIL;
}
}
+ /* Now we've got a new opened fd, we need to check that in the error case */
+ opened = 1;
+
if (!(ad->ad_mdp->adf_flags & O_CREAT)) {
/* check for 0 length files, treat them as new. */
if (fstat(ad->ad_mdp->adf_fd, &st_meta) == 0) {
if ((ad->ad_mdp->adf_flags & ( O_TRUNC | O_CREAT ))) {
/* This is a new adouble header file, create it */
- if (new_ad_header(ad, path, pst, adflags) < 0) {
- int err = errno;
- /* the file is already deleted, perm, whatever, so return an error */
- ad_close(ad, adflags);
- errno = err;
- return -1;
- }
+ EC_NEG1_LOG( new_ad_header(ad, path, pst, adflags) );
ad_flush(ad);
} else {
/* Read the adouble header in and parse it.*/
- if (ad->ad_ops->ad_header_read(path, ad, pst) < 0
- || ad->ad_ops->ad_header_upgrade(ad, ad_p) < 0) {
- int err = errno;
- ad_close(ad, adflags);
- errno = err;
- return -1;
- }
+ EC_NEG1_LOG( ad->ad_ops->ad_header_read(path, ad, pst) );
}
- return 0;
+EC_CLEANUP:
+ if (ret != 0 && opened && ad_meta_fileno(ad) != -1) {
+ close(ad_meta_fileno(ad));
+ ad_meta_fileno(ad) = -1;
+ ad->ad_mdp->adf_refcount = 0;
+ }
+ LOG(log_debug, logtype_default,
+ "ad_open_hf_v2(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+ fullpathname(path), adflags2logstr(adflags), ret,
+ ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+ ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+ ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+ EC_EXIT;
}
static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble *ad)
ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
- oflags = O_NOFOLLOW | (ad2openflags(adflags) & ~(O_CREAT | O_TRUNC));
+ oflags = O_NOFOLLOW | (ad2openflags(ADFLAGS_DF, adflags) & ~(O_CREAT | O_TRUNC));
if (ad_meta_fileno(ad) == -2)
/* symlink */
LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): BEGIN", fullpathname(path));
- oflags = O_NOFOLLOW | (ad2openflags(adflags) & ~O_CREAT);
+ oflags = O_NOFOLLOW | (ad2openflags(ADFLAGS_HF, adflags) & ~O_CREAT);
if (ad_reso_fileno(ad) != -1) {
/* the file is already open, but we want write access: */
* API functions
********************************************************************************* */
+off_t ad_getentryoff(const struct adouble *ad, int eid)
+{
+ if (ad->ad_vers == AD_VERSION2)
+ return ad->ad_eid[ADEID_RFORK].ade_off;
+
+ if (eid == ADEID_DFORK) {
+ return 0;
+ } else if (eid == ADEID_RFORK) {
+#ifdef HAVE_EAFD
+ return 0;
+#else
+ return ADEDOFF_RFORK_OSX;
+#endif
+ } else {
+ return ad->ad_eid[eid].ade_off;
+ }
+}
+
const char *ad_path_ea( const char *path, int adflags _U_)
{
return path;
/* Checking for open forks requires sharemode lock support (ie RDWR instead of RDONLY) */
adflags |= ADFLAGS_SETSHRMD;
+ if ((ad->ad_vers == AD_VERSION2) && (adflags & ADFLAGS_SETSHRMD)) {
+ /* sharemode locks are stored in the data fork, adouble:v2 needs this extra handling */
+ adflags |= ADFLAGS_DF;
+ }
+
if ((ad->ad_vers == AD_VERSION2) && (adflags & ADFLAGS_RF)) {
adflags |= ADFLAGS_HF;
if (adflags & ADFLAGS_NORF)
static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE)
/* const struct vol *vol, int sfd, const char *src, const char *dst */
{
- return 0;
-#if 0
EC_INIT;
bstring s = NULL, d = NULL;
char *dup1 = NULL;
EC_ZERO(bcatcstr(d, name));
}
- EC_ZERO(copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666));
+ /* ignore errors */
+ if (copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666) != 0)
+ if (errno != ENOENT)
+ EC_FAIL;
EC_CLEANUP:
bdestroy(s);
if (dup4) free(dup4);
EC_EXIT;
-#endif
}
#ifdef HAVE_SOLARIS_ACLS
}
static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
{
+ /* the EA VFS module does this all for us */
return 0;
#if 0
EC_INIT;