#include <sys/fsctl.h>
#include <sys/vnode_internal.h>
#include <sys/kauth.h>
-#include <sys/cprotect.h>
#include <sys/uio_internal.h>
#include "hfs.h"
#include "hfs_endian.h"
#include "hfs_btreeio.h"
#include "hfs_fsctl.h"
+#include "hfs_cprotect.h"
#include "hfscommon/headers/BTreesInternal.h"
btdata.bufferAddress = recp;
btdata.itemSize = sizeof(HFSPlusAttrRecord);
btdata.itemCount = 1;
-
+
result = hfs_buildattrkey(target_id, ap->a_name, (HFSPlusAttrKey *)&iterator->key);
if (result) {
goto exit;
cp->c_bsdflags &= ~UF_HIDDEN;
}
- result = hfs_update(vp, FALSE);
+ result = hfs_update(vp, 0);
hfs_unlock(cp);
return (result);
int exists = 0;
int allocatedblks = 0;
u_int32_t target_id;
- int takelock = 1;
if (cp) {
target_id = cp->c_fileid;
} else {
target_id = fileid;
- if (target_id != 1) {
- /*
- * If we are manipulating something other than
- * the root folder (id 1), and do not have a cnode-in-hand,
- * then we must already hold the requisite b-tree locks from
- * earlier up the call stack. (See hfs_makenode)
- */
- takelock = 0;
- }
}
/* Start a transaction for our changes. */
hfsmp->hfs_max_inline_attrsize = getmaxinlineattrsize(hfsmp->hfs_attribute_vp);
}
- if (takelock) {
- /* Take exclusive access to the attributes b-tree. */
- lockflags = hfs_systemfile_lock(hfsmp, SFL_ATTRIBUTE, HFS_EXCLUSIVE_LOCK);
- }
+ lockflags = hfs_systemfile_lock(hfsmp, SFL_ATTRIBUTE, HFS_EXCLUSIVE_LOCK);
/* Build the b-tree key. */
MALLOC(iterator, BTreeIterator *, sizeof(*iterator), M_TEMP, M_WAITOK);
if (btfile && started_transaction) {
(void) BTFlushPath(btfile);
}
- if (lockflags) {
- hfs_systemfile_unlock(hfsmp, lockflags);
- }
+ hfs_systemfile_unlock(hfsmp, lockflags);
if (result == 0) {
if (vp) {
cp = VTOC(vp);
* modified time of the file.
*/
cp->c_touch_chgtime = TRUE;
+ cp->c_flag |= C_MODIFIED;
cp->c_attr.ca_recflags |= kHFSHasAttributesMask;
if ((bcmp(ap->a_name, KAUTH_FILESEC_XATTR, sizeof(KAUTH_FILESEC_XATTR)) == 0)) {
cp->c_attr.ca_recflags |= kHFSHasSecurityMask;
if (result == 0) {
cp->c_touch_chgtime = TRUE;
cp->c_flag |= C_MODIFIED;
- result = hfs_update(vp, FALSE);
+ result = hfs_update(vp, 0);
}
hfs_end_transaction(hfsmp);
/* Updating finderInfo updates change time and modified time */
cp->c_touch_chgtime = TRUE;
cp->c_flag |= C_MODIFIED;
- hfs_update(vp, FALSE);
+ hfs_update(vp, 0);
hfs_unlock(cp);
result = file_attribute_exist(hfsmp, cp->c_fileid);
if (result == 0) {
cp->c_attr.ca_recflags &= ~kHFSHasAttributesMask;
+ cp->c_flag |= C_MODIFIED;
}
if (result == EEXIST) {
result = 0;
/* If ACL was removed, clear security bit */
if ((bcmp(ap->a_name, KAUTH_FILESEC_XATTR, sizeof(KAUTH_FILESEC_XATTR)) == 0)) {
cp->c_attr.ca_recflags &= ~kHFSHasSecurityMask;
+ cp->c_flag |= C_MODIFIED;
}
(void) hfs_update(vp, 0);
}
*
* This function takes the necessary locks on the attribute
* b-tree file and the allocation (bitmap) file.
+ *
+ * NOTE: Upon sucecss, this function will return with an open
+ * transaction. The reason we do it this way is because when we
+ * delete the last attribute, we must make sure the flag in the
+ * catalog record that indicates there are no more records is cleared.
+ * The caller is responsible for doing this and *must* do it before
+ * ending the transaction.
*/
int
-hfs_removeallattr(struct hfsmount *hfsmp, u_int32_t fileid)
+hfs_removeallattr(struct hfsmount *hfsmp, u_int32_t fileid,
+ bool *open_transaction)
{
BTreeIterator *iterator = NULL;
HFSPlusAttrKey *key;
struct filefork *btfile;
- int result, lockflags;
+ int result, lockflags = 0;
+
+ *open_transaction = false;
+
+ if (hfsmp->hfs_attribute_vp == NULL)
+ return 0;
- if (hfsmp->hfs_attribute_vp == NULL) {
- return (0);
- }
btfile = VTOF(hfsmp->hfs_attribute_vp);
MALLOC(iterator, BTreeIterator *, sizeof(BTreeIterator), M_TEMP, M_WAITOK);
key = (HFSPlusAttrKey *)&iterator->key;
/* Loop until there are no more attributes for this file id */
- for(;;) {
+ do {
+ if (!*open_transaction)
+ lockflags = hfs_systemfile_lock(hfsmp, SFL_ATTRIBUTE, HFS_SHARED_LOCK);
+
+ (void) hfs_buildattrkey(fileid, NULL, key);
+ result = BTIterateRecord(btfile, kBTreeNextRecord, iterator, NULL, NULL);
+ if (result || key->fileID != fileid)
+ goto exit;
+
+ hfs_systemfile_unlock(hfsmp, lockflags);
+ lockflags = 0;
+
+ if (*open_transaction) {
+ hfs_end_transaction(hfsmp);
+ *open_transaction = false;
+ }
+
if (hfs_start_transaction(hfsmp) != 0) {
result = EINVAL;
goto exit;
}
- /* Lock the attribute b-tree and the allocation (bitmap) files */
+ *open_transaction = true;
+
lockflags = hfs_systemfile_lock(hfsmp, SFL_ATTRIBUTE | SFL_BITMAP, HFS_EXCLUSIVE_LOCK);
- /*
- * Go to first possible attribute key/record pair
- */
- (void) hfs_buildattrkey(fileid, NULL, key);
- result = BTIterateRecord(btfile, kBTreeNextRecord, iterator, NULL, NULL);
- if (result || key->fileID != fileid) {
- hfs_systemfile_unlock(hfsmp, lockflags);
- hfs_end_transaction(hfsmp);
- goto exit;
- }
result = remove_attribute_records(hfsmp, iterator);
#if HFS_XATTR_VERBOSE
printf("hfs_removeallattr: unexpected err %d\n", result);
}
#endif
+ } while (!result);
+
+exit:
+ FREE(iterator, M_TEMP);
+
+ if (lockflags)
hfs_systemfile_unlock(hfsmp, lockflags);
+
+ result = result == btNotFound ? 0 : MacToVFSError(result);
+
+ if (result && *open_transaction) {
hfs_end_transaction(hfsmp);
- if (result)
- break;
+ *open_transaction = false;
}
-exit:
- FREE(iterator, M_TEMP);
- return (result == btNotFound ? 0: MacToVFSError(result));
+
+ return result;
}
__private_extern__