+ // Check if we need to set UF_COMPRESSED.
+ // If so, ask decmpfs if we're allowed to (and if so, if we need to truncate
+ // the data fork to 0).
+ if (!(cas->expected_flags & UF_COMPRESSED) && (cas->new_flags & UF_COMPRESSED)) {
+ struct vnode_attr vap;
+ VATTR_INIT(&vap);
+ VATTR_SET(&vap, va_flags, cas->new_flags);
+
+ error = decmpfs_update_attributes(vp, &vap);
+ if (error) {
+ return (error);
+ }
+
+ // Similar to hfs_vnop_setattr(), we call decmpfs_update_attributes()
+ // as it is the ultimate arbiter of whether or not UF_COMPRESSED can be set.
+ // (If the decmpfs xattr is not present or invalid, for example,
+ // UF_COMPRESSED should *not* be set.)
+ // It will also tell us if we need to truncate the data fork to 0.
+ if (!(vap.va_flags & UF_COMPRESSED)) {
+ // The request to update UF_COMPRESSED is denied.
+ // (Note that decmpfs_update_attributes() won't touch va_active
+ // in this case.) Error out.
+ return (EPERM);
+ }
+
+ if (VATTR_IS_ACTIVE(&vap, va_data_size) && (vap.va_data_size == 0)) {
+ // We must also truncate this file's data fork to 0.
+ need_truncate = true;
+ }
+ }
+