昨天,公司的美国客户发邮件给我,说我的软件出问题了,我查来查去,发现居然是服务器上一个目录无法删除,一删除就报 cannot read from the source file or disk. 如果用命令行方式删除,则报  cannot find the specified path。一开始以为是文件系统遭破坏了,用 chkdsk 命令检查,没有发现问题,后来仔细一看,那个不能删除的目录名居然以一个空格字符结尾,而我尝试在资源管理器中创建一个目录以空格结尾结果资源管理器会自动将末尾的字符删除,用程序创建,结果也一样,这个美国佬是怎么创建这个古怪的目录的?出现这种情况后不但是无法删除这么简单,列目录什么的也会有问题,这样一来,系统的运行都会有问题,我想到的最坏结果就是可能不得不格式化服务器的硬盘,想到这里我几乎不敢再想下去了!Research了一天,后来终于找到了解决方案,并且由此还发现问题的起因是我程序上的一个Bug造成,可怕的Bug!

Windows 的文件系统可以支持特殊字符的文件名,比如以空格结尾,以点号结尾等,有一篇英文的文章说NTFS 支持这些文件名,但FAT不支持,我试了一下,FAT也支持。但Windows API 却对这些特殊文件名进行了限制,也就是说,我们通过程序是无法创建一个以空格或点号结尾的文件名或路径名的。但Copy 和 Move的API 却不做这方面的限制,这导致我们可以从其他的文件系统拷贝或移动一个特殊文件名的文件到Windows 的文件系统,但一旦在Windows的文件系统上创建成功,就无法通过正常途径删除或改名。因为调用API 删除或改名时,API 会首先进行规则检查,如果发现不符合规则,则直接忽略。这两组API 在处理上的不一致,带来一个非常严重的安全问题,可惜微软到了Windows7 还没有去弥补这个问题。

下面让我们用代码复现这个问题

            try
            {
                string dir = @"C:\Temp\abc";
                System.IO.Directory.CreateDirectory(dir); //在C:\Temp 目录下创建abc 这个目录
 
                string dir1 = @"c:\Temp\Bcd \";
 
                System.IO.Directory.Move(dir, dir1); //将ABC 移动到"Bcd "这个目录去,注意这里 Bcd后面有个空格
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

在运行这段代码前,你一定要有一点思想准备,因为一旦运行成功,你的 C:\temp 目录下就有了一个 “Bcd ”这样的古怪的目录,而且你用正常的方法根本无法删除它。如果我在此打住,你一定会为之抓狂。不过没关系,我已经找到了删除它的方法,下面就和大家共享:

Windows 的命令行工具 Del 和 Rd 支持一种方式可以不对输入文件名的合法性进行检查,这种方式是在完整目录名前加一个 \\?\

比如

del “\\?\C:\Temp\xxx.” 删除xxx. 这个文件

删除目录的话

rd /s “\\?\C:\Temp\xxx.” 删除 xxx. 这个目录

执行这个命令后,就可以删除这些古怪的文件了。注意,这里一定要输入完整的目录才可以,相对路径不行。

讲到这里,我们知道了原因和解决方案,那么在这里我需要提醒大家我们以后在程序中调用 System.IO.Directory.Move 或者 System.IO.File.Copy , System.IO.File.Move 这些函数前,一定要注意先判断一下输入的目标文件名或目录名的结尾是不是空格或点号,可能还要判断其他情况,但目前我只知道这两种情况,而且结尾是空格非常有隐蔽性。

 
分类: 操作系统

一个Bug 差点让服务器的文件系统崩溃的更多相关文章

  1. [置顶]Win2012R2的一个Bug安装群集后可能引发的软件崩溃问题及相应补丁

    [置顶]Win2012R2的一个Bug安装群集后可能引发的软件崩溃问题及相应补丁 如标题,笔者查阅资料发现微软声称安装故障转角色后就可能发生上述描述问题,但不止于SSMS崩溃.建议使用win2012R ...

  2. 我是一个Bug, 终极大Bug

    我是一个Bug ,在这个系统中潜伏很久了,历经多轮测试的严酷考验而屹立不倒,如果Bug界按难度分类的话,我绝对属于地狱模式. 现在,我就等待一个倒霉蛋来触发, 可是他老是不来. 其实不能叫倒霉蛋 , ...

  3. Tomcat一个BUG造成CLOSE_WAIT

    之前应该提过,我们线上架构整体重新架设了,应用层面使用的是Spring Boot,前段日子因为一些第三方的原因,略有些匆忙的提前开始线上的内测了.然后运维发现了个问题,服务器的HTTPS端口有大量的C ...

  4. Linux强化论:15步打造一个安全的Linux服务器

    Linux强化论:15步打造一个安全的Linux服务器 Alpha_h4ck2016-11-30共28761人围观 ,发现 8 个不明物体专题系统安全 可能大多数人都觉得Linux是安全的吧?但我要告 ...

  5. 微软BI 之SSIS 系列 - MVP 们也不解的 Scrip Task 脚本任务中的一个 Bug

    开篇介绍 前些天自己在整理 SSIS 2012 资料的时候发现了一个功能设计上的疑似Bug,在 Script Task 中是可以给只读列表中的变量赋值.我记得以前在 2008 的版本中为了弄明白这个配 ...

  6. Curl的毫秒超时的一个”Bug”

    Curl的毫秒超时的一个”Bug” -- PHP老杨 最近我们的服务在升级php使用的libcurl, 期望新版本的libcurl支持毫秒级的超时, 从而可以更加精细的控制后端的接口超时, 从而提高整 ...

  7. 从修复 testerhome(rubychina)网站的一个 bug 学习 ruby&rails on ruby

    前言 testerhome: http://testerhome.com/topics/1480 对于一个差点脱离前沿技术人,想要学习ruby,就意味着要放弃熟悉的操作系统windows,熟悉的ide ...

  8. cakephp2.3.0 lib中的Model.php有一个bug

    1. cakephp2.3.0 lib中的Model.php有一个bug, 加上 !empty($db->config['prefix']) 这个判断更好.有时候会少进行一次 new PDO() ...

  9. 转:【专题十二】实现一个简单的FTP服务器

    引言: 休息一个国庆节后好久没有更新文章了,主要是刚开始休息完心态还没有调整过来的, 现在差不多进入状态了, 所以继续和大家分享下网络编程的知识,在本专题中将和大家分享如何自己实现一个简单的FTP服务 ...

随机推荐

  1. Bürkert 流体控制系统 (8611 型通用调节器)

    Type Description High-Tech Made EasyThe new universal controller eCONTROL Type 8611 brings an essent ...

  2. Python字符串格式转换

    转换类型 转换类型 说明 d, i 带符号十进制 b 无符号二进制 o 无符号八进制 u 无符号十进制 x 无符号十六进制(小写) X 无符号十六进制(大写) e 科学计数法表示的浮点数(小写) E ...

  3. INSPIRED启示录 读书笔记 - 第40章 最佳实践经验

    十大要点 1.产品管理的职责:许多产品经理将大把的时间浪费在与产品管理无关的工作上 2.用户体验:对于大多数软件产品来说,用户体验就是产品的生命 3.机会评估:用方便快捷的机会评估方法取代过时的市场需 ...

  4. HDU 3466 Proud Merchants 排序 背包

    题意:物品有三个属性,价格p,解锁钱数下线q(手中余额>=q才有机会购买该商品),价值v.钱数为m,问购买到物品价值和最大. 思路:首先是个01背包问题,但购买物品受限所以应先排序.考虑相邻两个 ...

  5. 开机启动顺序rc.local与chkconfig的不同

    /etc/rc.local文件有如下两行/etc/init.d/mysql start/etc/init.d/keepalived start /etc/rc.local是按脚本的顺序一个启动后启动下 ...

  6. Spring Cloud Stream消息总线

    Springcloud 里面对于MQ的整合一个是前一篇的消息总线一个是本文介绍的消息驱动 大体要学习这么几个知识点: 课题:SpringCloud消息驱动Stream1.什么是SpringCloud消 ...

  7. sql server deadlock problem

    https://www.red-gate.com/simple-talk/sql/learn-sql-server/how-to-track-down-deadlocks-using-sql-serv ...

  8. CentOS 7 安装 docker-machine

    https://github.com/docker/machine/releases/ 指令: curl -L https://github.com/docker/machine/releases/d ...

  9. Javascript的this用法---阮一峰

    Javascript的this用法   作者: 阮一峰 日期: 2010年4月30日 this是Javascript语言的一个关键字. 它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用.比 ...

  10. html div + css 下划线

    这里通过边框属性的虚线边框border控制虚线.以下设置的css 高度(css height)和css 宽度(css width)为350像素是为了便于观看演示 其它意思.一.四边为虚线边框borde ...