+/*
+ * Given the attributes listed in asp and those supported
+ * in the vap, fixup the asp attributes to reflect any
+ * missing attributes from the file system
+ */
+static void
+getattrlist_fixupattrs(attribute_set_t *asp, struct vnode_attr *vap)
+{
+ struct getattrlist_attrtab *tab;
+
+ if (asp->commonattr) {
+ tab = getattrlist_common_tab;
+ do {
+ /*
+ * This if() statement is slightly confusing. We're trying to
+ * iterate through all of the bits listed in the array
+ * getattr_common_tab, and see if the filesystem was expected
+ * to support it, and whether or not we need to do anything about this.
+ *
+ * This array is full of structs that have 4 fields (attr, bits, size, action).
+ * The first is used to store the ATTR_CMN_* bit that was being requested
+ * from userland. The second stores the VATTR_BIT corresponding to the field
+ * filled in vnode_attr struct. If it is 0, then we don't typically expect
+ * the filesystem to fill in this field. The third is the size of the field,
+ * and the fourth is the type of kauth actions needed.
+ *
+ * So, for all of the ATTR_CMN bits listed in this array, we iterate through
+ * them, and check to see if it was both passed down to the filesystem via the
+ * va_active bitfield, and whether or not we expect it to be emitted from
+ * the filesystem. If it wasn't supported, then we un-twiddle the bit and move
+ * on. This is done so that we can uncheck those bits and re-request
+ * a vnode_getattr from the filesystem again.
+ */
+
+ if ((tab->attr & asp->commonattr) &&
+ (tab->bits & vap->va_active) &&
+ (tab->bits & vap->va_supported) == 0) {
+ asp->commonattr &= ~tab->attr;
+ }
+ } while ((++tab)->attr != 0);
+ }
+ if (asp->dirattr) {
+ tab = getattrlist_dir_tab;
+ do {
+ if ((tab->attr & asp->dirattr) &&
+ (tab->bits & vap->va_active) &&
+ (vap->va_supported & tab->bits) == 0) {
+ asp->dirattr &= ~tab->attr;
+ }
+ } while ((++tab)->attr != 0);
+ }
+ if (asp->fileattr) {
+ tab = getattrlist_file_tab;
+ do {
+ if ((tab->attr & asp->fileattr) &&
+ (tab->bits & vap->va_active) &&
+ (vap->va_supported & tab->bits) == 0) {
+ asp->fileattr &= ~tab->attr;
+ }
+ } while ((++tab)->attr != 0);
+ }
+}
+
+static int
+setattrlist_setfinderinfo(vnode_t vp, char *fndrinfo, struct vfs_context *ctx)
+{
+ uio_t auio;
+ char uio_buf[UIO_SIZEOF(1)];
+ int error;
+
+ if ((auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_WRITE, uio_buf, sizeof(uio_buf))) == NULL) {
+ error = ENOMEM;
+ } else {
+ uio_addiov(auio, CAST_USER_ADDR_T(fndrinfo), 32);
+ error = vn_setxattr(vp, XATTR_FINDERINFO_NAME, auio, XATTR_NOSECURITY, ctx);
+ uio_free(auio);
+ }
+
+#if CONFIG_FSE
+ if (error == 0 && need_fsevent(FSE_FINDER_INFO_CHANGED, vp)) {
+ add_fsevent(FSE_FINDER_INFO_CHANGED, ctx, FSE_ARG_VNODE, vp, FSE_ARG_DONE);
+ }
+#endif
+ return (error);
+}
+