memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
ad_flush( adp );
}
- if (adp == &ad)
- ad_close_metadata( adp);
+ ad_close_metadata( adp);
return( AFP_OK );
}
if (opened) {
char *upath;
- int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
+ int 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);
- if ( adp == &ad ) {
- ad_close_metadata( adp);
- }
+ ad_close_metadata( adp);
return( rc );
}
if (isad) {
ad_flush( adp);
- if (adp == &ad)
- ad_close_metadata( adp);
+ ad_close_metadata( adp);
}
if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
setvoltime(obj, d_vol );
copy_exit:
- if (adp == &ad)
- ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
+ ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
return( retvalue );
}
* moreover sometimes deletefile is called with a no existent file and
* ad_open would create a 0 byte resource fork
*/
- if ( ad_metadataat(dirfd, file, ADFLAGS_OPENFORKS, &ad) == 0 ) {
+ if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
if ((err = check_attrib(&ad))) {
ad_close_metadata(&ad);
return err;
strlcpy( ad->ad_m_name, path, ad->ad_m_namelen);
}
+ ad_ref(ad);
of->of_ad = ad;
of->of_vol = vol;
of->of_did = dir->d_did;
}
}
ret = 0;
- if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
- ret = -1;
+
+
+ if (ad_unref(ofork->of_ad) == 0) {
+ if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
+ ret = -1;
+ }
}
of_dealloc( ofork );
struct ad_fd *ad_md; /* either ad_resource or ad_metadata */
int ad_flags; /* Our adouble version info (AD_VERSION*) */
int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */
- unsigned int ad_inited;
+ uint32_t ad_inited;
int ad_options;
+ int ad_refcount; /* multiple forks may open one adouble */
void *ad_resforkbuf; /* buffer for AD_VERSION_EA ressource fork */
size_t ad_resforkbufsize; /* size of ad_resforkbuf */
off_t ad_rlen; /* ressource fork len with AFP 3.0 *
#define ADFLAGS_HF (1<<2)
#define ADFLAGS_DIR (1<<3)
#define ADFLAGS_NOHF (1<<4) /* not an error if no ressource fork */
-#define ADFLAGS_OPENFORKS (1<<5) /* check for open fork in ad_metadata function */
+#define ADFLAGS_CHECK_OF (1<<6) /* check for open forks from us and other afpd's */
#define ADVOL_NODEV (1 << 0)
#define ADVOL_CACHE (1 << 1)
#define ad_get_RF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
#define ad_get_MD_flags(ad) ((ad)->ad_md->adf_flags)
+/* Refcounting open forks using one struct adouble */
+#define ad_ref(ad) (ad)->ad_refcount++
+#define ad_unref(ad) (ad)->ad_refcount--
+
/* ad_flush.c */
extern int ad_rebuild_adouble_header (struct adouble *);
extern int ad_rebuild_sfm_header (struct adouble *);
cfrombstr(ad->ad_fullpath),
adflags2logstr(adflags));
+ if (ad->ad_refcount) {
+ LOG(log_debug, logtype_default, "ad_close(\"%s\"): adouble in use by fork, not closing",
+ cfrombstr(ad->ad_fullpath));
+ return 0;
+ }
+
if (ad_data_fileno(ad) != -1) {
if ((ad_data_fileno(ad) == -2) && (ad->ad_data_fork.adf_syml != NULL)) {
free(ad->ad_data_fork.adf_syml);
strlcat(buf, "DIR", 64);
first = 0;
}
- if (adflags & ADFLAGS_OPENFORKS) {
+ if (adflags & ADFLAGS_CHECK_OF) {
if (!first)
strlcat(buf, "|", 64);
strlcat(buf, "OF", 64);
* @endcode
*
* Open a files data fork, metadata fork or ressource fork.
+ *
* For each fork to be opened specify the open flags and mode in case you want to create it
* (O_CREAT in open flags). The order in which forks are opened is:
* 1) ADFLAGS_DF, 2) ADFLAGS_HF, 3) ADFLAGS_RF.
* 2. Store the full path to the object the first time ad_open is called for it.
* 3. Check if the fork has already been opened.
*
+ * ad_close accompanies ad_open and closes a struct adouble. In order to tigh together the
+ * semantics of struct adouble/ad_open/ad_close and versus forks, which use and keep a ref to
+ * the according struct adouble for the fork, we open forks refcount their struct adouble
+ * in struct adouble.ad_refcount. An ad_close is ignored when ad_refcount != 0, because
+ * ad_refcount != 0 means an open fork is using this very struct adouble.
+ *
* @param ad (rw) pointer to struct adouble
* @param path (r) Path to file or directory
* @param adflags (r) ADFLAGS_DF: open data fork \n
* ADFLAGS_NOHF: it's not an error if header file couldn't be created \n
* ADFLAGS_DIR: if path is a directory you MUST or ADFLAGS_DIR to adflags \n
* ADFLAGS_RDONLY: dont upgrade mode from r to rw with adouble:v2 headerfile \n
- * ADFLAGS_OPENFORKS: check for open forks from other processes
+ * ADFLAGS_CHECK_OF: check for open forks from us and other afpd's
*
* @returns 0 on success, any other value indicates an error
*/
*
* @param name name of file/dir
* @param flags ADFLAGS_DIR: name is a directory \n
- * ADFLAGS_OPENFORKS: test if name is open by another afpd process
+ * ADFLAGS_CHECK_OF: test if name is open by us or another afpd process
*
* @param adp pointer to struct adouble
*/
errno = err;
}
- if (!ret && (ADFLAGS_OPENFORKS & flags)) {
+ if (!ret && (ADFLAGS_CHECK_OF & flags)) {
/*
we need to check if the file is open by another process.
it's slow so we only do it if we have to: