#include <atalk/globals.h>
#include <atalk/fce_api.h>
#include <atalk/netatalk_conf.h>
+#include <atalk/spotlight.h>
#include "directory.h"
#include "dircache.h"
#include "file.h"
#include "filedir.h"
#include "unix.h"
-#include "spotlight.h"
/* the format for the finderinfo fields (from IM: Toolbox Essentials):
* field bytes subfield bytes
}
else {
memcpy(data, ufinderi, ADEDLEN_FINDERI);
+ chk_ext = 1;
if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
uint16_t ashort;
catching moved files */
adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp); /* (1) */
+ AFP_CNID_START("cnid_add");
dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid); /* (2) */
+ AFP_CNID_DONE();
+
/* Throw errors if cnid_add fails. */
if (dbcnid == CNID_INVALID) {
switch (errno) {
|| (bconchar(fullpath, '/') != BSTR_OK)
|| (bcatcstr(fullpath, upath)) != BSTR_OK) {
LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno));
+ bdestroy(fullpath);
return AFPERR_MISC;
}
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
+ ashort &= ~htons(vol->v_ignattr);
#if 0
/* FIXME do we want a visual clue if the file is read only
*/
data += sizeof( aint );
break;
- case FILPBIT_RFLEN :
- if ( adp ) {
+ case FILPBIT_RFLEN: {
+ off_t rlen;
+ if (adp) {
if (adp->ad_rlen > 0xffffffff)
aint = 0xffffffff;
else
aint = htonl( adp->ad_rlen);
} else {
- aint = 0;
+ rlen = ad_reso_size(path->u_name, 0, NULL);
+ if (rlen > 0xffffffff)
+ rlen = 0xffffffff;
+ aint = htonl(rlen);
}
memcpy(data, &aint, sizeof( aint ));
data += sizeof( aint );
break;
+ }
/* Current client needs ProDOS info block for this file.
Use simple heuristic and let the Mac "type" string tell
data += sizeof( aint );
break;
case FILPBIT_EXTRFLEN:
- aint = 0;
- if (adp)
+ if (adp) {
aint = htonl(adp->ad_rlen >> 32);
- memcpy(data, &aint, sizeof( aint ));
- data += sizeof( aint );
- if (adp)
+ memcpy(data, &aint, sizeof( aint ));
+ data += sizeof( aint );
aint = htonl(adp->ad_rlen);
- memcpy(data, &aint, sizeof( aint ));
- data += sizeof( aint );
+ memcpy(data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+ } else {
+ int64_t rlen = hton64(ad_reso_size(path->u_name, 0, NULL));
+ memcpy(data, &rlen, sizeof(rlen));
+ data += sizeof(rlen);
+ }
break;
case FILPBIT_UNIXPR :
/* accessmode may change st_mode with ACLs */
ad_getattr(adp, &bshort);
oshort = bshort;
if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
+ ashort &= ~htons(vol->v_ignattr);
bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
} else {
bshort &= ~ashort;
WRITE lock on read only file.
*/
-static int check_attrib(struct adouble *adp)
+static int check_attrib(const struct vol *vol, struct adouble *adp)
{
uint16_t bshort = 0;
/*
* Does kFPDeleteInhibitBit (bit 8) set?
*/
- if ((bshort & htons(ATTRBIT_NODELETE))) {
+ if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (bshort & htons(ATTRBIT_NODELETE))) {
return AFPERR_OLOCK;
}
- if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
+ if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
return AFPERR_BUSY;
}
return 0;
* ad_open would create a 0 byte resource fork
*/
if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
- if ((err = check_attrib(&ad))) {
+ if ((err = check_attrib(vol, &ad))) {
ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF);
return err;
}
adp = &ad;
}
- if ( adp && AD_RSRC_OPEN(adp) != -1 ) { /* there's a resource fork */
+ if ( adp && AD_RSRC_OPEN(adp) ) { /* there's a resource fork */
adflags |= ADFLAGS_RF;
/* FIXME we have a pb here because we want to know if a file is open
* there's a 'priority inversion' if you can't open the ressource fork RW
err = AFPERR_BUSY;
} else if (!(err = vol->vfs->vfs_deletefile(vol, dirfd, file)) && !(err = netatalk_unlinkat(dirfd, file )) ) {
cnid_t id;
- if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)))) {
- cnid_delete(vol->v_cdb, id);
+ if (checkAttrib) {
+ AFP_CNID_START("cnid_get");
+ id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file));
+ AFP_CNID_DONE();
+ if (id) {
+ AFP_CNID_START("cnid_delete");
+ cnid_delete(vol->v_cdb, id);
+ AFP_CNID_DONE();
+ }
}
}
return AFPERR_PARAM;
}
st = &s_path->st;
- if ((id = cnid_lookup(vol->v_cdb, st, did, upath, len = strlen(upath)))) {
+ AFP_CNID_START("cnid_lookup");
+ id = cnid_lookup(vol->v_cdb, st, did, upath, len = strlen(upath));
+ AFP_CNID_DONE();
+ if (id) {
memcpy(rbuf, &id, sizeof(id));
*rbuflen = sizeof(id);
return AFPERR_EXISTID;
return 0;
/* update or add to cnid */
+ AFP_CNID_START("cnid_add");
aint = cnid_add(vol->v_cdb, &path.st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */
+ AFP_CNID_DONE();
return 0;
}
return AFPERR_NOID;
}
retry:
- if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
+ AFP_CNID_START("cnid_resolve");
+ upath = cnid_resolve(vol->v_cdb, &id, buffer, len);
+ AFP_CNID_DONE();
+ if (upath == NULL) {
return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
}
ibuf += sizeof(id);
fileid = id;
- if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
+ AFP_CNID_START("cnid_resolve");
+ upath = cnid_resolve(vol->v_cdb, &id, buffer, len);
+ AFP_CNID_DONE();
+ if (upath == NULL) {
return AFPERR_NOID;
}
return AFPERR_BADTYPE;
delete:
+ AFP_CNID_START("cnid_delete");
if (cnid_delete(vol->v_cdb, fileid)) {
+ AFP_CNID_DONE();
switch (errno) {
case EROFS:
return AFPERR_VLOCK;
return AFPERR_PARAM;
}
}
-
+ AFP_CNID_DONE();
return err;
}
/* look for the source cnid. if it doesn't exist, don't worry about
* it. */
+ AFP_CNID_START("cnid_lookup");
sid = cnid_lookup(vol->v_cdb, &srcst, sdir->d_did, supath,slen = strlen(supath));
+ AFP_CNID_DONE();
if (NULL == ( dir = dirlookup( vol, did )) ) {
err = afp_errno; /* was AFPERR_PARAM */
/* look for destination id. */
upath = path->u_name;
+ AFP_CNID_START("cnid_lookup");
did = cnid_lookup(vol->v_cdb, &destst, curdir->d_did, upath, dlen = strlen(upath));
+ AFP_CNID_DONE();
/* construct a temp name.
* NOTE: the temp file will be in the dest file's directory. it
goto err_dest_to_src;
of_rename(vol, s_of, curdir, temp, curdir, path->m_name);
- /* id's need switching. src -> dest and dest -> src.
+ /*
+ * id's need switching. src -> dest and dest -> src.
* we need to re-stat() if it was a cross device copy.
- */
- if (sid)
+ */
+ if (sid) {
+ AFP_CNID_START("cnid_delete");
cnid_delete(vol->v_cdb, sid);
- if (did)
+ AFP_CNID_DONE();
+ }
+ if (did) {
+ AFP_CNID_START("cnid_delete");
cnid_delete(vol->v_cdb, did);
+ AFP_CNID_DONE();
+ }
if ((did && ( (crossdev && ostat(upath, &srcst, vol_syml_opt(vol)) < 0) ||
cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0))
}
goto err_temp_to_dest;
}
+
+ if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) {
+ struct adouble adtmp;
+ bool opened_ads, opened_add;
+
+ ad_init(&adtmp, vol);
+ ad_init_offsets(&adtmp);
+
+ if (!AD_META_OPEN(adsp)) {
+ if (ad_open(adsp, p, ADFLAGS_HF) != 0)
+ return -1;
+ opened_ads = true;
+ }
+
+ if (!AD_META_OPEN(addp)) {
+ if (ad_open(addp, upath, ADFLAGS_HF) != 0)
+ return -1;
+ opened_add = true;
+ }
+
+ if (ad_copy_header(&adtmp, adsp) != 0)
+ goto err_temp_to_dest;
+ if (ad_copy_header(adsp, addp) != 0)
+ goto err_temp_to_dest;
+ if (ad_copy_header(addp, &adtmp) != 0)
+ goto err_temp_to_dest;
+ ad_flush(adsp);
+ ad_flush(addp);
+
+ if (opened_ads)
+ ad_close(adsp, ADFLAGS_HF);
+ if (opened_add)
+ ad_close(addp, ADFLAGS_HF);
+ }
+
+ /* FIXME: we should switch ressource fork too */
/* here we need to reopen if crossdev */
if (sid && ad_setid(addp, destst.st_dev, destst.st_ino, sid, sdir->d_did, vol->v_stamp))