+/*
+ * Check the header of a ._ file to verify that it is in fact an Apple Double
+ * file. Returns 0 if the header is valid, non-zero if invalid.
+ */
+int check_appledouble_header(vnode_t vp, vfs_context_t ctx)
+{
+ int error = 0;
+ attr_info_t ainfo;
+ struct vnode_attr va;
+ uio_t auio = NULL;
+ void *buffer = NULL;
+ int iosize;
+
+ ainfo.filevp = vp;
+ ainfo.context = ctx;
+ VATTR_INIT(&va);
+ VATTR_WANTED(&va, va_data_size);
+ if ((error = vnode_getattr(vp, &va, ctx))) {
+ goto out;
+ }
+ ainfo.filesize = va.va_data_size;
+
+ iosize = MIN(ATTR_MAX_HDR_SIZE, ainfo.filesize);
+ if (iosize == 0) {
+ error = ENOATTR;
+ goto out;
+ }
+ ainfo.iosize = iosize;
+
+ MALLOC(buffer, void *, iosize, M_TEMP, M_WAITOK);
+ if (buffer == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ auio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ);
+ uio_addiov(auio, (uintptr_t)buffer, iosize);
+
+ /* Read the header */
+ error = VNOP_READ(vp, auio, 0, ctx);
+ if (error) {
+ goto out;
+ }
+ ainfo.rawsize = iosize - uio_resid(auio);
+ ainfo.rawdata = (u_int8_t *)buffer;
+
+ error = check_and_swap_apple_double_header(&ainfo);
+ if (error) {
+ goto out;
+ }
+
+ /* If we made it here, then the header is ok */
+
+out:
+ if (auio) {
+ uio_free(auio);
+ }
+ if (buffer) {
+ FREE(buffer, M_TEMP);
+ }
+
+ return error;
+}
+