# HG changeset patch # Parent c814d923812134a237675121bf3e75f13ef6893b Implement VOP_PARSEPATH() for hfs. This checks for a following "/rsrc" at the end of the pathname (to indicate the resource fork of a file) and assimilates it into the component name to be looked up. Then cn_namelen will already include this text in lookup, and it's no longer necessary to muck with cn_consume. Invalid uses of "/rsrc" are ignored rather than rejected, which appears to be the same as the old behavior. It is possible that the parsepath logic should only consume the "/rsrc" if the name names a file and not a directory, which would require looking it up in parsepath and be a general nuisance; I hope not. It's also possible that the whole thing doesn't work at all now, or it didn't before, as I don't have any way to test it. diff -r c814d9238121 sys/fs/hfs/hfs_vnops.c --- a/sys/fs/hfs/hfs_vnops.c Sun Apr 17 01:14:45 2016 -0400 +++ b/sys/fs/hfs/hfs_vnops.c Sun Apr 17 01:21:04 2016 -0400 @@ -132,6 +132,7 @@ #include +int hfs_vop_parsepath(void *); int hfs_vop_lookup(void *); int hfs_vop_open(void *); int hfs_vop_close(void *); @@ -328,6 +329,29 @@ { &hfs_fifoop_p, hfs_fifoop_entries }; int +hfs_vop_parsepath(void *v) +{ + struct vop_parsepath_args /* { + struct vnode *a_dvp; + const char *a_name; + size_t *a_retval; + } */ *ap = v; + size_t len; + int error; + + error = genfs_parsepath(v); + if (error) { + return error; + } + + len = *ap->a_retval; + if (!strcmp(ap->a_name + len, "/rsrc")) { + *ap->a_retval += 5; + } + return 0; +} + +int hfs_vop_lookup(void *v) { struct vop_lookup_v2_args /* { @@ -343,6 +367,8 @@ struct vnode *vdp; /* vnode for directory being searched */ hfs_catalog_key_t key; /* hfs+ catalog search key for requested child */ hfs_catalog_keyed_record_t rec; /* catalog record of requested child */ + size_t namelen; + int use_resource_fork = 0; unichar_t* unicn; /* name of component, in Unicode */ const char *pname; int error; @@ -417,12 +443,18 @@ hfslib_init_cbargs(&cbargs); + namelen = cnp->cn_namelen; + if (namelen > 5 && + !strcmp(cnp->cn_nameptr + namelen - 5, "/rsrc")) { + namelen -= 5; + use_resource_fork = 1; + } + /* XXX: when decomposing, string could grow and we have to handle overflow */ - unicn = malloc(cnp->cn_namelen * sizeof(unicn[0]), - M_TEMP, M_WAITOK); - len = utf8_to_utf16(unicn, cnp->cn_namelen, - cnp->cn_nameptr, cnp->cn_namelen, 0, NULL); + unicn = malloc(namelen * sizeof(unicn[0]), M_TEMP, M_WAITOK); + len = utf8_to_utf16(unicn, namelen, + cnp->cn_nameptr, namelen, 0, NULL); for (ni = 0; ni < len; ni++) if (unicn[ni] == (unichar_t)':') unicn[ni] = (unichar_t)'/'; @@ -459,13 +491,11 @@ } if (rec.type == HFS_REC_FILE - && strcmp(cnp->cn_nameptr+cnp->cn_namelen, "/rsrc") == 0 + && use_resource_fork && rec.file.rsrc_fork.logical_size > 0) { - /* advance namei next pointer to end of stirng */ - cnp->cn_consume = 5; - cnp->cn_flags &= ~REQUIREDIR; /* XXX: needed? */ - error = hfs_vget_internal(vdp->v_mount, rec.file.cnid, - HFS_RSRCFORK, &tdp); + /* advance namei next pointer to end of string */ + error = hfs_vget_internal(vdp->v_mount, rec.file.cnid, + HFS_RSRCFORK, &tdp); } else error = hfs_vget_internal(vdp->v_mount, rec.file.cnid, HFS_DATAFORK, &tdp);