昨天,公司的美国客户发邮件给我,说我的软件出问题了,我查来查去,发现居然是服务器上一个目录无法删除,一删除就报 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. Shell编程之while循环和until循环

    一.当型和直到型循环 1.while循环语句 while < 条件表达式 > do 指令... done while循环执行流程对应的逻辑图 2.until循环语句 until < ...

  2. awk中的常用关于处理字符串的函数

    1.替换字符串中的某一部分. 函数:gensub(/rexpr/,"replace","g","string"),gensub返回一个新的字 ...

  3. Vue.js学习笔记 第七篇 表单控件绑定

    本篇主要说明表单控件的数据绑定,这次没有新的知识点 文本框 1.普通文本框 <div id="app-1"> <p><input v-model=&q ...

  4. 关于读取本地text文件,自动被添加空格的问题

    最近做一个小程序,读取本地指定路径下的text文件,逐行获取text文本然后再进行处理,结果遇到了一个奇葩问题,先插个图片给各位看官 坑:本地text文件中数据为1123/10(数据反复检查无空格,换 ...

  5. RDLC 微软报表 导出Excel时产生多个工作表 (worksheet)

    . I have added two obejcts data source to Report Viewer. 2. in RDLC i have created two tables and in ...

  6. iptables基础知识详解

    iptables防火墙可以用于创建过滤(filter)与NAT规则.所有Linux发行版都能使用iptables,因此理解如何配置 iptables将会帮助你更有效地管理Linux防火墙.如果你是第一 ...

  7. 互联网高并发之Hystrix实现服务隔离和降级

    当大多数人在使用Tomcat时,多个HTTP服务会共享一个线程池,假设其中一个HTTP服务访问的数据库响应非常慢,这将造成服务响应时间延迟增加,大多数线程阻塞等待数据响应返回,导致整个Tomcat线程 ...

  8. MapReduce-从HBase读取数据处理后再写入HBase

    MapReduce-从HBase读取处理后再写入HBase 代码如下 package com.hbase.mapreduce; import java.io.IOException; import o ...

  9. 电子商务的几种模式,b2b,c2c等

    B2B(Business to Business) ——这是指商家与商家建立的商业关系.(最早的一种模式) C2C (Customer to Consumer) ——个人与个人的商业关系,也就是消费者 ...

  10. js命令模式

    命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 从命令模式的结构图可以看出,它涉及到五个角色,它们分别是 ...