Repository navigation
修复容器内 USB 大容量存储无法访问;本次起版本改为三段 X.Y.Z,三种包的文件名固定不再带版本号。
下载
curl -fLO https://github.com/Yizhou147/Droidspaces-USB-Manager/releases/download/v1.4.1/Droidspaces_USB_Manager_all.deb
curl -fLO https://github.com/Yizhou147/Droidspaces-USB-Manager/releases/download/v1.4.1/Droidspaces_USB_Manager_noarch.rpm
curl -fLO https://github.com/Yizhou147/Droidspaces-USB-Manager/releases/download/v1.4.1/Droidspaces_USB_Manager_any.pkg.tar.zst安装
sudo dpkg -i Droidspaces_USB_Manager_all.deb
sudo apt-get install -f
sudo dnf install ./Droidspaces_USB_Manager_noarch.rpm
sudo pacman -U --config /tmp/pacman-nosig.conf ./Droidspaces_USB_Manager_any.pkg.tar.zst推荐直接用 install.sh(自动检测 apt / dnf / pacman、装依赖、写 sudoers、配权限组):
curl -fLO https://github.com/Yizhou147/Droidspaces-USB-Manager/releases/download/v1.4.1/install.sh本次修复
- 整盘设备节点:容器
/dev只有启动时已存在的节点,之后插入的 USB 盘没有/dev/sdX,任何程序都无法打开/探测/挂载。现在整盘与分区节点都补齐,并按st_rdev比对,拔插导致设备号漂移的失效节点自动删除重建。 - 晚到介质重新校验:相机等多 LUN 设备先以"无介质"枚举,内核只在设备被 open 时才刷新容量。现在会对 size 为 0 的整盘做一次只读打开触发重校验,之后分区与文件系统才会出现;状态列新增"无介质(请在设备上确认)"提示。
- exFAT 访问:Android GKI 的 exFAT 驱动忽略
uid=/gid=/umask=,介质固定为root:1077 0770。安装时创建external_storage(gid 1077)组并把桌面用户加入(与 NTFS 的ntfsusbgid 1023 同一做法),需注销重新登录生效。 - udev 属性回填:设备节点是补建出来的,udev 数据库里没有
ID_FS_*,导致 udisks2 / Dolphin 认不出文件系统类型与卷标。现在检测到这种缺失就对/sys/block/<盘>/<分区>重发一次 change 事件(按 syspath 限流 30s)。 - sudoers:放开
rm -f /dev/sd*|/dev/video*|/dev/bus/usb/*与udevadm trigger --action=change /sys/block/*;此前失效节点自愈因无删除权限而整条路径失效。deb 的postinst与install.sh统一为同一份授权清单,并补上原先完全缺失的权限组配置。 - 幽灵挂载清理改用 lazy umount,避免容器侧一直占用块设备。
实测(真实设备:aigo U393 128GB / NTFS)
- 植入错误设备号(整盘 8:0、分区 8:999)后,普通用户跑扫描 ⇒ 两节点自动重建为与 sysfs 一致的 8:96 / 8:97,权限仍 0666,文件系统重新识别;再扫一次不重复重建。
- 挂载链路免密通过:
root:ntfsusb 770下普通用户直接读写;弹出后findmnt为空,块设备已释放。 - udev 回填做了负对照:停应用删节点后
ID_FS_TYPE归零、udisksctl info的IdType为空;启动本版应用 8 秒内 ⇒IdType=ntfs且带 UUID。 - 合成 sysfs 20/20、真实 PyQt5 冒烟 12/12、udev 回填用例 12/12。
已知未覆盖
- exFAT 免密读写未用真实 exFAT 卷验证(手头设备是 NTFS,测试机的 loop 设备不服务 IO)。
- "机身确认后才出现介质"的真实相机流程未验证,按内核机制实现并以合成数据覆盖。
- 容器与安卓双挂载同一卷时内核不做跨 namespace 排他,本版未加入接管/次序保证(需宿主 root,另行决策)。
版本规范变更
本次起 tag 与包内版本一律三段 X.Y.Z,三种包的文件名固定不带版本号,因此本条安装命令长期有效。v1.0–v1.4 的资产名沿用当时写法(v1.4 的 deb 内部版本甚至还是 1.0.0,装了会覆盖新版),属遗留,历史 release 未改动。
补充(2026-10-13):本 release 的产物已原位替换,包含两处后续修复
沿用同一个 tag v1.4.1 与同一批固定文件名,包内版本号仍是 1.4.1-1,因此已经下载过旧产物的机器不会被包管理器提示更新;需要新修复的请重新下载。tag 已移动到合并 PR #5 后的提交 ce0930ab。
新增内容:
- 幽灵挂载清理修复:拔盘后
~/USB-Storage/<分区>留下的是ENOTCONN的死 FUSE 挂载点,stat()失败使Path.is_dir()返回 False,而清理循环开头正是if not item.is_dir(): continue—— 恰好把最需要清理的情况整个跳过(表现为残留目录显示d?????????且永不清除)。现已去掉该前置过滤,命中挂载表即 lazy umount + 删除;挂载表改从/proc/self/mountinfo解析(mount输出的字段位置随 util-linux 版本变化,内核里挂载点还是八进制转义的)。 - 更正 exFAT 的成因说明:此前写的"Android GKI exFAT 驱动忽略
uid/gid/umask、必须属于 gid 1077"是误判。对照实验表明内核驱动是遵守挂载参数的:让安卓先让出卷后容器单独挂载,/proc/mounts即为uid=1000,gid=1000,fmask=0000,dmask=0000,普通用户无需任何组即可读写;先前看到的gid=1023,fmask=0007是容器复用了安卓已挂载的 superblock、沿用其参数所致。install.sh保留 1023 与 1077 两个组作为双挂兜底,README 已同步更正。
验证:install.sh 本机实测 exit=0;新产物拆包核对 py 与源码 md5 一致(9ff5e712…)、包内版本 1.4.1-1、已不含旧的 is_dir() 过滤;合成用例 7/7、20/20、12/12、12/12,真机失效节点自愈 9/9、双分区盘应用级检查 6/6。