Stop folding '..' across a usbfs node
/dev/bus/usb/001/001/.. answers as the bus directory where Linux answers ENOTDIR, because a .. after a usbfs node is folded away, and /dev/bus/../null answers ENOENT, because a .. that climbs out of /dev/bus reaches a backing that cannot apply it. The first commit gives the relative-name join one home without changing behavior, and the second makes a /dev/bus descriptor and cwd report the directory reached rather than a spelling with .. in it.
Reproduce with the fixture devices and a static aarch64 busybox:
$ ELFUSE_USB_FIXTURE=1 build/elfuse busybox stat -c %F /dev/bus/usb/001/001/..
$ ELFUSE_USB_FIXTURE=1 build/elfuse busybox stat -c %F /dev/bus/../null
On main these print directory and No such file or directory. With this series they print Not a directory and character special file, as Linux does.
Tested on macOS 15.6.1 (24G90) with the 15.5 SDK on an Apple M1 (MacBookAir10,1). make check passes 100 of 101 and make test-matrix-elfuse-aarch64 gives 298 passed, 1 failed and 10 skipped. Main gives the same on this machine: the one failure in both is test-thread-churn timing out, and it passes when run alone.
Summary by cubic
Stops folding .. after a usbfs node and rewrites .. climbs out of /dev/bus, so names like /dev/bus/usb/001/001/.. and /dev/bus/../null answer as Linux does (ENOTDIR and /dev/null, respectively) instead of resolving to the wrong directory or ENOENT.
- A
..after a usbfs node now stops the fold, keeping the rest as written, so every entry point answersENOTDIRas Linux does. - A
..that climbs out of/dev/busover the layer's directories is rewritten inpath_translate_atto/devplus what follows, so/dev/bus/../nullresolves; a climb that ends the name becomes/dev/., keepingrmdirandrenamefrom acting on/dev. - Descriptors and the cwd on a synthetic
/dev/busdirectory now report the directory reached, not the guest's spelling with..or a trailing slash. - Relative names against a
/dev/buscwd or dirfd fold components up to a usbfs node, which the earlier relative-name join refactor (path_rebuild_under) makes a single code path. statfsasks the/dev/buslayer before the/sysfold so a..through a node answersENOTDIR.- Matrix coverage adds
dev-climb,dev-climb-f, andnode-dotdotcolumns, recorded against Linux 7.0;test-usb-sysfs-sysrootpins thatrmdirandrenameof a final..leave the sysroot's/devin place.