}
LOG(log_debug, logtype_afpd,
- "afp_openfork(\"%s\", fork: %s)",
+ "afp_openfork(\"%s\", %s)",
abspath(s_path->u_name),
- (fork & OPENFORK_DATA) ? "d" : "r");
+ (fork & OPENFORK_RSCS) ? "OPENFORK_RSCS" : "OPENFORK_DATA");
/* stat() data fork st is set because it's not a dir */
switch ( s_path->st_errno ) {
case EACCES:
return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
default:
- LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
+ LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno));
return AFPERR_PARAM;
}
/* FIXME should we check it first ? */
if ( fork == OPENFORK_DATA ) {
eid = ADEID_DFORK;
- adflags = ADFLAGS_DF | ADFLAGS_HF;
+ adflags = ADFLAGS_DF | ADFLAGS_HF ;
} else {
eid = ADEID_RFORK;
adflags = ADFLAGS_RF | ADFLAGS_HF;
}
}
- if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
+ if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) {
if (ad_setname(ofork->of_ad, path)) {
ad_flush( ofork->of_ad );
}
}
- if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
- &buflen )) != AFP_OK ) {
+ if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
ad_close( ofork->of_ad, adflags );
goto openfork_err;
}
};
struct adouble {
- u_int32_t ad_magic;
- u_int32_t ad_version;
- char ad_filler[ 16 ];
- struct ad_entry ad_eid[ ADEID_MAX ];
- struct ad_fd ad_data_fork, ad_resource_fork, ad_metadata_fork;
- struct ad_fd *ad_md; /* either ad_resource or ad_metadata */
- int ad_flags; /* This really stores version info too (AD_VERSION*) */
- int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */
+ u_int32_t ad_magic; /* Official adouble magic */
+ u_int32_t ad_version; /* Official adouble version number */
+ char ad_filler[16];
+ struct ad_entry ad_eid[ADEID_MAX];
+ struct ad_fd ad_data_fork; /* the data fork */
+ struct ad_fd ad_resource_fork; /* adouble:v2 -> the adouble file *
+ * adouble:ea -> the rfork EA */
+ struct ad_fd ad_metadata_fork; /* adouble:v2 -> unused *
+ * adouble:ea -> the metadata EA */
+ 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;
int ad_options;
- 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
- the header parameter size is too small. */
- char *ad_m_name; /* mac name for open fork */
+ 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 *
+ * the header parameter size is too small. */
+ char *ad_m_name; /* mac name for open fork */
int ad_m_namelen;
- bstring ad_fullpath; /* adouble EA need this */
+ bstring ad_fullpath; /* fullpath of file, adouble:ea need this */
struct adouble_fops *ad_ops;
- uint16_t ad_open_forks; /* open forks (by others) */
+ uint16_t ad_open_forks; /* open forks (by others) */
char ad_data[AD_DATASZ_MAX];
};
#define ad_getentryoff(ad,eid) ((ad)->ad_eid[(eid)].ade_off)
#define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
-#define ad_get_HF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
+#define ad_get_RF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
#define ad_get_MD_flags(ad) ((ad)->ad_md->adf_flags)
/* ad_flush.c */
return 0;
}
+/*!
+ * Error handling for adouble header(=metadata) file open error
+ *
+ * We're called because opening ADFLAGS_HF caused an error.
+ * 1. In case ad_open is called with ADFLAGS_NOHF the error is suppressed.
+ * 2. If ad_open was called with ADFLAGS_DF we may have opened the datafork and thus
+ * ought to close it before returning with an error condition.
+ */
+static int ad_error(struct adouble *ad, int adflags)
+{
+ int err = errno;
+ if ((adflags & ADFLAGS_NOHF)) { /* 1 */
+ /* FIXME double check : set header offset ?*/
+ return 0;
+ }
+ if ((adflags & ADFLAGS_DF)) { /* 2 */
+ ad_close( ad, ADFLAGS_DF );
+ err = errno;
+ }
+ return -1 ;
+}
+
static int ad_open_df(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
struct stat st_dir;
int hoflags, admode;
int st_invalid = -1;
- LOG(log_maxdebug, logtype_default, "ad_open_df(\"%s/%s\", adf: 0x%04x, of: 0x%04x)",
- getcwdpath(), path, adflags, oflags);
+ LOG(log_debug, logtype_default, "ad_open_df(\"%s\", %s, %04o)",
+ abspath(path), oflags2logstr(oflags), mode);
if (ad_data_fileno(ad) == -1) {
hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
admode = ad_hf_mode(admode);
if ((errno == ENOENT)) {
if (ad->ad_ops->ad_mkrf( ad_p) < 0) {
- return -1;
+ return ad_error(ad, adflags);
}
admode = mode;
st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
/* retry with O_CREAT */
ad->ad_md->adf_fd = open(ad_p, oflags, admode);
if ( ad->ad_md->adf_fd < 0 ) {
- return -1;
+ return ad_error(ad, adflags);
}
ad->ad_md->adf_flags = oflags;
/* just created, set owner if admin owner (root) */
ad_chown(ad_p, &st_dir);
}
} else {
- return -1;
+ return ad_error(ad, adflags);
}
} else {
ad->ad_md->adf_flags = hoflags;
pst = &st_meta;
}
}
+
AD_SET(ad->ad_md->adf_off);
if ((ad->ad_md->adf_flags & ( O_TRUNC | O_CREAT ))) {
static int ad_open_hf_ea(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
ssize_t rforklen;
- int ret;
-
- LOG(log_maxdebug, logtype_default, "ad_open_hf_ea(\"%s\", adf: 0x%04x, of: 0x%04x)",
- abspath(path), adflags, oflags);
+ /* we dont use this fd, but open it anyway, maybe we need it sometimes */
if ((ad->ad_md->adf_fd = open(path, O_RDONLY | O_NOFOLLOW)) == -1)
- return -1;
+ goto error;
/* Read the adouble header in and parse it.*/
if (ad->ad_ops->ad_header_read(ad, NULL) != 0) {
if (!(oflags & O_CREAT))
- return -1;
+ goto error;
/* It doesnt exist, EPERM or another error */
if (errno != ENOATTR && errno != ENOENT) {
LOG(log_error, logtype_default, "ad_open_hf_ea: unexpected: %s", strerror(errno));
- ret = -1;
goto error;
}
if (new_ad_header(path, ad, adflags) < 0) {
LOG(log_error, logtype_default, "ad_open_hf_ea: can't create new header: %s",
abspath(path));
- ret = -1;
goto error;
}
-
+ ad->ad_md->adf_flags |= O_CREAT; /* mark as just created */
ad_flush(ad);
+ LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): created metadata EA",
+ cfrombstr(ad->ad_fullpath));
}
- ad->ad_md->adf_flags = O_RDWR; /* Pretend its rw, in fact for the EA API it is */
+ ad->ad_md->adf_flags |= oflags & (O_RDONLY|O_WRONLY|O_RDWR); /* store current flags */
if ((rforklen = sys_lgetxattr(cfrombstr(ad->ad_fullpath), AD_EA_RESO, NULL, 0)) > 0)
ad->ad_rlen = rforklen;
return 0;
error:
- return ret;
+ if (ad->ad_md->adf_fd != -1) {
+ close(ad->ad_md->adf_fd);
+ ad->ad_md->adf_fd = -1;
+ }
+ return ad_error(ad, adflags);
}
static int ad_open_hf(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
int ret = 0;
- LOG(log_maxdebug, logtype_default, "ad_open_hf(\"%s/%s\", adf: 0x%04x, of: 0x%04x)",
- getcwdpath(), path, adflags, oflags);
+ LOG(log_debug, logtype_default, "ad_open_hf(\"%s\", %s, %04o)",
+ cfrombstr(ad->ad_fullpath), oflags2logstr(oflags), mode);
memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
ad->ad_rlen = 0;
}
/*!
- * Open EA with resfork, only for AD_VERSION_EA, a nullop otherwise
+ * Open ressource fork
+ *
+ * Only for adouble:ea, a nullop otherwise because adouble:v2 has the ressource fork as part
+ * of the adouble file which is openend by ADFLAGS_HF.
*/
static int ad_open_rf(const char *path, int adflags, int oflags, int mode, struct adouble *ad)
{
if (ad->ad_flags != AD_VERSION_EA)
return 0;
- LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", adf: 0x%04x, of: 0x%04x)",
- abspath(path), adflags, oflags);
+ LOG(log_debug, logtype_default, "ad_open_rf(\"%s\", %s, %04o)",
+ cfrombstr(ad->ad_fullpath), oflags2logstr(oflags), mode);
if ((ad->ad_rlen = sys_lgetxattr(cfrombstr(ad->ad_fullpath), AD_EA_RESO, NULL, 0)) <= 0) {
switch (errno) {
* 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
- * The variable arguments must be passed according to this order.
+ * 1) ADFLAGS_DF, 2) ADFLAGS_HF, 3) ADFLAGS_RF.
+ * It is possible to call ad_open subsequently opening ADFLAGS_DF first and ADFLAGS_HF in
+ * another ad_open call. Already openend forks are uneffected in subsequent calls (3).
+ * The variable arguments must be passed according to this order. Then:
+ * 1. Ensure the adouble struct has been initialized.
+ * 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.
*
* @param ad (rw) pointer to struct adouble
* @param path (r) Path to file or directory
{
int ret = 0;
int oflags;
- int mode;
+ int mode = 0;
LOG(log_debug, logtype_default, "ad_open(\"%s\", %s)",
abspath(path), adflags2logstr(adflags));
- if (ad->ad_inited != AD_INITED)
+ if (ad->ad_inited != AD_INITED) /* 1 */
AFP_PANIC("ad_open: not initialized");
- if (ad->ad_fullpath == NULL) {
+ if (ad->ad_fullpath == NULL) { /* 2 */
if ((ad->ad_fullpath = bfromcstr(abspath(path))) == NULL) {
ret = -1;
goto exit;
}
}
- if ((adflags & ADFLAGS_DF) && !(ad->ad_adflags & ADFLAGS_DF)) {
+ if ((adflags & ADFLAGS_DF) && !(ad->ad_adflags & ADFLAGS_DF)) { /* 3 */
oflags = va_arg(args, int);
if (oflags & O_CREAT)
mode = va_arg(args, int);
ad->ad_adflags |= ADFLAGS_DF;
}
- if ((adflags & ADFLAGS_HF) && !(ad->ad_adflags & ADFLAGS_HF)) {
+ if ((adflags & ADFLAGS_HF) && !(ad->ad_adflags & ADFLAGS_HF)) { /* 3 */
oflags = va_arg(args, int);
if (oflags & O_CREAT)
mode = va_arg(args, int);
ad->ad_adflags |= ADFLAGS_HF;
}
- if ((adflags & ADFLAGS_RF) && !(ad->ad_adflags & ADFLAGS_RF)) {
+ if ((adflags & ADFLAGS_RF) && !(ad->ad_adflags & ADFLAGS_RF)) { /* 3 */
oflags = va_arg(args, int);
if (oflags & O_CREAT)
mode = va_arg(args, int);