Skip to content

Commit c1e72a6

Browse files
committed
fix(fnos-mount-manager): 修复设备路径中包含空格时的挂载问题
当设备路径包含空格时,findmnt 命令会返回转义序列(如 \x20), 这导致路径解析错误。现在添加了转义序列解码功能,确保带空格的 设备路径能正确处理。 同时调整了 mkdir 命令的执行顺序,确保在需要时目录已存在。
1 parent 04bcc26 commit c1e72a6

5 files changed

Lines changed: 131 additions & 6 deletions

File tree

linux/fnos/fnos-mount-manager/commands/alias.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ fm_alias_disk() {
3939
return 0
4040
fi
4141

42-
fm_run_privileged mkdir -p "${FM_DISK_STATE_MOUNTPOINT}"
43-
4442
local alias_state
4543
alias_state="$(
4644
fm_describe_bind_alias_state \
@@ -61,6 +59,8 @@ fm_alias_disk() {
6159
;;
6260
esac
6361

62+
fm_run_privileged mkdir -p "${FM_DISK_STATE_MOUNTPOINT}"
63+
6464
if fm_run_privileged mount --bind "${FM_DISK_STATE_MOUNTED_TARGET}" "${FM_DISK_STATE_MOUNTPOINT}" >/dev/null 2>&1; then
6565
FM_OPERATION_LAST_ACTION="alias_synced"
6666
fm_log "info" "Bound ${FM_DISK_STATE_NAME} from ${FM_DISK_STATE_MOUNTED_TARGET} to ${FM_DISK_STATE_MOUNTPOINT}"

linux/fnos/fnos-mount-manager/common.sh

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,21 @@ fm_find_mount_target_for_device() {
200200
local device_path="$1"
201201
local resolved_device
202202
resolved_device="$(fm_resolve_device_path "${device_path}")"
203+
local mounted_target=""
203204

204-
findmnt -rn -S "${resolved_device}" -o TARGET 2>/dev/null | head -n 1 || true
205+
mounted_target="$(findmnt -rn -S "${resolved_device}" -o TARGET 2>/dev/null | head -n 1 || true)"
206+
if [[ -n "${mounted_target}" ]]; then
207+
fm_decode_findmnt_value "${mounted_target}"
208+
return 0
209+
fi
210+
211+
return 0
212+
}
213+
214+
# 把 findmnt 输出里的转义序列还原成真实路径,避免带空格型号路径被误判成不存在。
215+
fm_decode_findmnt_value() {
216+
local value="$1"
217+
printf '%b' "${value}"
205218
}
206219

207220
# 解析单块受管磁盘的运行时状态。
@@ -246,6 +259,7 @@ fm_is_exact_mountpoint() {
246259
local mountpoint="$1"
247260
local mounted_target
248261
mounted_target="$(findmnt -rn -M "${mountpoint}" -o TARGET 2>/dev/null || true)"
262+
mounted_target="$(fm_decode_findmnt_value "${mounted_target}")"
249263
[[ "${mounted_target}" == "${mountpoint}" ]]
250264
}
251265

linux/fnos/fnos-mount-manager/fnos-mount-manager.sh

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,21 @@ fm_find_mount_target_for_device() {
206206
local device_path="$1"
207207
local resolved_device
208208
resolved_device="$(fm_resolve_device_path "${device_path}")"
209+
local mounted_target=""
209210

210-
findmnt -rn -S "${resolved_device}" -o TARGET 2>/dev/null | head -n 1 || true
211+
mounted_target="$(findmnt -rn -S "${resolved_device}" -o TARGET 2>/dev/null | head -n 1 || true)"
212+
if [[ -n "${mounted_target}" ]]; then
213+
fm_decode_findmnt_value "${mounted_target}"
214+
return 0
215+
fi
216+
217+
return 0
218+
}
219+
220+
# 把 findmnt 输出里的转义序列还原成真实路径,避免带空格型号路径被误判成不存在。
221+
fm_decode_findmnt_value() {
222+
local value="$1"
223+
printf '%b' "${value}"
211224
}
212225

213226
# 解析单块受管磁盘的运行时状态。
@@ -252,6 +265,7 @@ fm_is_exact_mountpoint() {
252265
local mountpoint="$1"
253266
local mounted_target
254267
mounted_target="$(findmnt -rn -M "${mountpoint}" -o TARGET 2>/dev/null || true)"
268+
mounted_target="$(fm_decode_findmnt_value "${mounted_target}")"
255269
[[ "${mounted_target}" == "${mountpoint}" ]]
256270
}
257271

@@ -1243,8 +1257,6 @@ fm_alias_disk() {
12431257
return 0
12441258
fi
12451259

1246-
fm_run_privileged mkdir -p "${FM_DISK_STATE_MOUNTPOINT}"
1247-
12481260
local alias_state
12491261
alias_state="$(
12501262
fm_describe_bind_alias_state \
@@ -1265,6 +1277,8 @@ fm_alias_disk() {
12651277
;;
12661278
esac
12671279

1280+
fm_run_privileged mkdir -p "${FM_DISK_STATE_MOUNTPOINT}"
1281+
12681282
if fm_run_privileged mount --bind "${FM_DISK_STATE_MOUNTED_TARGET}" "${FM_DISK_STATE_MOUNTPOINT}" >/dev/null 2>&1; then
12691283
FM_OPERATION_LAST_ACTION="alias_synced"
12701284
fm_log "info" "Bound ${FM_DISK_STATE_NAME} from ${FM_DISK_STATE_MOUNTED_TARGET} to ${FM_DISK_STATE_MOUNTPOINT}"

linux/fnos/fnos-mount-manager/tests/alias.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,62 @@ exit 1
206206
expect(result.exitCode).not.toBe(0)
207207
expect(result.stderr + result.stdout).toContain('bind mount failed')
208208
})
209+
210+
it('accepts escaped findmnt source targets for model paths with spaces', () => {
211+
const workspace = createWorkspace()
212+
workspaces.push(workspace)
213+
214+
ensureFakeDevice(workspace, 'LABEL:local-book')
215+
ensureFakeDevice(workspace, 'UUID:local-debut')
216+
217+
installMockCommand(
218+
workspace,
219+
'findmnt',
220+
`#!/usr/bin/env bash
221+
set -eu
222+
if [[ "\${1:-}" == "-rn" && "\${2:-}" == "-S" ]]; then
223+
case "\${3:-}" in
224+
*local-book)
225+
printf '%s\\n' "/vol00/WDC\\x20WD40EZRZ-00GXCB0"
226+
;;
227+
*local-debut)
228+
printf '%s\\n' "/mnt/local/debutDisk"
229+
;;
230+
esac
231+
exit 0
232+
fi
233+
if [[ "\${1:-}" == "-rn" && "\${2:-}" == "-M" ]]; then
234+
case "\${3:-}" in
235+
"/vol00/WDC WD40EZRZ-00GXCB0")
236+
printf '%s\\n' "/vol00/WDC WD40EZRZ-00GXCB0"
237+
;;
238+
"/mnt/local/debutDisk")
239+
printf '%s\\n' "/mnt/local/debutDisk"
240+
;;
241+
*)
242+
exit 1
243+
;;
244+
esac
245+
exit 0
246+
fi
247+
exit 1
248+
`,
249+
)
250+
installMockCommand(
251+
workspace,
252+
'mount',
253+
`#!/usr/bin/env bash
254+
set -eu
255+
printf '%s\\n' "$*" >> "${workspace.root}/mount.log"
256+
exit 0
257+
`,
258+
)
259+
260+
const result = runSource(workspace, ['alias'])
261+
262+
expect(result.exitCode).toBe(0)
263+
expect(fs.readFileSync(`${workspace.root}/mount.log`, 'utf8')).toContain(
264+
'--bind /vol00/WDC WD40EZRZ-00GXCB0 /mnt/local/books/bookDisk',
265+
)
266+
})
209267
})

linux/fnos/fnos-mount-manager/tests/status.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,45 @@ exit 0
101101
)
102102
})
103103

104+
it('decodes escaped findmnt targets before printing mounted_elsewhere', () => {
105+
const workspace = createWorkspace()
106+
workspaces.push(workspace)
107+
108+
ensureFakeDevice(workspace, 'LABEL:local-book')
109+
ensureFakeDevice(workspace, 'UUID:local-debut')
110+
111+
installMockCommand(
112+
workspace,
113+
'systemctl',
114+
`#!/usr/bin/env bash
115+
set -eu
116+
printf '%s\\n' "inactive"
117+
`,
118+
)
119+
installMockCommand(
120+
workspace,
121+
'findmnt',
122+
`#!/usr/bin/env bash
123+
set -eu
124+
if [[ "\${1:-}" == "-rn" && "\${2:-}" == "-M" ]]; then
125+
exit 1
126+
fi
127+
if [[ "\${1:-}" == "-rn" && "\${2:-}" == "-S" ]]; then
128+
printf '%s\\n' "/vol00/WDC\\x20WD40EZRZ-00GXCB0"
129+
exit 0
130+
fi
131+
exit 0
132+
`,
133+
)
134+
135+
const result = runSource(workspace, ['status'])
136+
137+
expect(result.exitCode).toBe(0)
138+
expect(result.stdout).toContain(
139+
'mounted_elsewhere: /vol00/WDC WD40EZRZ-00GXCB0',
140+
)
141+
})
142+
104143
it('continues printing later disks when the first device is not mounted', () => {
105144
const workspace = createWorkspace()
106145
workspaces.push(workspace)

0 commit comments

Comments
 (0)