Linux下adb push时open()带O_CREAT|O_EXCL的行为困惑及排查
ADB Push 覆盖已存在文件的原因分析
问题现象
- 运行环境:搭载kernel-5.10.188的嵌入式Linux系统,目标系统运行adbd服务
- 操作流程:
- 在目标系统执行命令
echo "hello" > /data/open创建文件 - 在Windows PC执行
adb push C:\test\open /data/推送本地文件到目标系统
- 在目标系统执行命令
- 异常结果:目标系统中已存在的
/data/open被直接覆盖,不符合代码逻辑预期
排查过程
- 查看adbd源码逻辑:定位到
file_sync_service.c中的handle_send_file()函数,该函数通过adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode)调用打开文件。根据POSIX标准,O_CREAT搭配O_EXCL时,若文件已存在,open()应返回-1且errno设为EEXIST,之后代码会走O_WRONLY分支打开已存在文件写入,但实际测试中该调用未报错,文件描述符正常返回。 - 编写测试程序验证逻辑:编写与源码逻辑一致的测试代码,调用
open(path, O_WRONLY | O_CREAT | O_EXCL, mode),测试中确实触发了EEXIST错误,符合预期逻辑,排除系统调用本身的问题。 - 确认adbd实际调用:检查预编译后的adbd二进制代码,确认其确实直接调用
open()系统调用,无额外封装层干扰。 - strace追踪进程行为:通过
strace追踪adbd进程的系统调用,发现执行adb push操作时,adbd会先调用unlink()删除目标路径下的文件,之后再执行open()创建新文件——此时目标文件已不存在,O_EXCL条件无法触发,因此open()正常返回,最终导致原有文件被覆盖。
结论
adb push操作时,adbd内部会先执行unlink()删除目标文件,再执行创建/写入操作,这一前置步骤导致源码中O_EXCL的文件存在检测逻辑失效,最终造成已存在文件被覆盖。
内容的提问来源于stack exchange,提问作者wangt13
相关产品推荐
相关产品推荐

