struct stat *st;
uint16_t bshort;
struct path *s_path;
+ struct stat xxx;
ibuf++;
fork = *ibuf++;
ret = AFPERR_VLOCK;
case EACCES:
goto openfork_err;
- break;
case ENOENT:
if (fork == OPENFORK_DATA) {
/* try to open only the data fork */
if (ad_open(ofork->of_ad, upath,
adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD | ADFLAGS_CREATE, 0666) < 0)
goto openfork_err;
- ofork->of_flags |= AFPFORK_OPEN;
+ ofork->of_flags |= AFPFORK_META;
}
break;
case EMFILE :
case ENFILE :
ret = AFPERR_NFILE;
goto openfork_err;
- break;
case EISDIR :
ret = AFPERR_BADTYPE;
goto openfork_err;
- break;
default:
LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
ret = AFPERR_PARAM;
goto openfork_err;
- break;
}
}
else {
/* the ressource fork is open too */
- ofork->of_flags |= AFPFORK_OPEN;
+ ofork->of_flags |= AFPFORK_META;
}
} else {
/* try opening in read-only mode */
}
adflags = ADFLAGS_DF;
}
- /* else we don't set AFPFORK_OPEN because there's no ressource fork file
- * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
+ /* else we don't set AFPFORK_META because there's no ressource fork file
+ * We need to check AFPFORK_META in afp_closefork(). eg fork open read-only
* then create in open read-write.
* FIXME , it doesn't play well with byte locking example:
* ressource fork open read only
case ENFILE :
ret = AFPERR_NFILE;
goto openfork_err;
- break;
case EISDIR :
ret = AFPERR_BADTYPE;
goto openfork_err;
- break;
default:
LOG(log_error, logtype_afpd, "afp_openfork(\"%s\"): %s",
fullpathname(s_path->m_name), strerror(errno) );
goto openfork_err;
- break;
}
- }
- else {
- /* the ressource fork is open too */
- ofork->of_flags |= AFPFORK_OPEN;
+ } else {
+ ofork->of_flags |= AFPFORK_META;
}
}
#define OPENACC_DWR (1<<5)
/* ofork.of_flags bits */
-#define AFPFORK_OPEN (1<<0)
-#define AFPFORK_RSRC (1<<1)
-#define AFPFORK_DATA (1<<2)
+#define AFPFORK_DATA (1<<0) /* open datafork */
+#define AFPFORK_RSRC (1<<1) /* open rsrcfork */
+#define AFPFORK_META (1<<2) /* open metadata */
#define AFPFORK_DIRTY (1<<3)
#define AFPFORK_ACCRD (1<<4)
#define AFPFORK_ACCWR (1<<5)
int of_closefork(struct ofork *ofork)
{
struct timeval tv;
- int adflags, doflush = 0;
+ int adflags = 0;
int ret;
adflags = 0;
- if ((ofork->of_flags & AFPFORK_DATA) && (ad_data_fileno( ofork->of_ad ) != -1)) {
+ if (ofork->of_flags & AFPFORK_DATA)
adflags |= ADFLAGS_DF;
- }
- if ( (ofork->of_flags & AFPFORK_OPEN) && ad_reso_fileno( ofork->of_ad ) != -1 ) {
+ if (ofork->of_flags & AFPFORK_META)
adflags |= ADFLAGS_HF;
- /*
- * Only set the rfork's length if we're closing the rfork.
- */
- if ((ofork->of_flags & AFPFORK_RSRC)) {
- ad_refresh( ofork->of_ad );
- if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
- ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec);
- doflush++;
- }
- if ( doflush ) {
- ad_flush( ofork->of_ad );
- }
+ if (ofork->of_flags & AFPFORK_RSRC) {
+ adflags |= ADFLAGS_RF;
+ /* Only set the rfork's length if we're closing the rfork. */
+ ad_refresh( ofork->of_ad );
+ if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
+ ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec);
+ ad_flush( ofork->of_ad );
}
}
}
}
+ if ((adflags & ADFLAGS_RF)) {
+ switch (ad->ad_flags) {
+ case AD_VERSION2:
+ /* Do nothing as ADFLAGS_RF == ADFLAGS_HF */
+ break;
+
+ 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)
+ err = -1;
+ ad_data_fileno(ad) = -1;
+ adf_lock_free(&ad->ad_data_fork);
+ }
+ break;
+
+ default:
+ LOG(log_error, logtype_default, "ad_close: unknown AD version");
+ errno = EIO;
+ return -1;
+ }
+ }
+
return err;
}
off_t lock_offset;
if (eid == ADEID_DFORK) {
- lock_offset = df2off(off);
+ lock_offset = off;
} else { /* rfork */
lock_offset = rf2off(off);
}
static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad)
{
int ret = 0;
+ int oflags;
if (ad->ad_flags != 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);
+
+ 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));
+ 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);
+ }
if ((ad->ad_rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) {
switch (errno) {
}
}
+ ad->ad_data_fork.adf_refcount++;
+
exit:
if (ret != 0) {
- free(ad->ad_resforkbuf);
+ if (ad->ad_resforkbuf)
+ free(ad->ad_resforkbuf);
ad->ad_resforkbuf = NULL;
ad->ad_rlen = 0;
ad->ad_resforkbufsize = 0;