昨天,公司的美国客户发邮件给我,说我的软件出问题了,我查来查去,发现居然是服务器上一个目录无法删除,一删除就报 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. npm安装出错Unexpected end of input at 1:2307

    执行命令: npm cache clean --force 然后再安装 搞定

  2. Docker容器技术-镜像分发

    一.镜像分发 1.镜像及镜像库的命名方式 指定镜像名称和标签的方法: 在狗偶见镜像时 通过docker tag命令 [root@bogon ~]# cd identidock/ [root@bogon ...

  3. Linux的压缩命令(tar,gzip,zip)

    打包和压缩.打包是指将一大堆文件或目录变成一个总的文件:压缩则是将一个大的文件通过一些压缩算法变成一个小文件. 这源于Linux中很多压缩程序只能针对一个文件进行压缩,这样当你想要压缩一大堆文件时,你 ...

  4. Flume+Kafka+storm的连接整合

    Flume-ng Flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统. Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html ...

  5. 20145240 《Java程序设计》第一次实验报告

    20145240 <Java程序设计>第一次实验报告 实验内容 一.命令行下java程序开发 1.建立Code目录,输入mkdir 20145240命令建立实验目录,并使用dir命令查看目 ...

  6. SpringCloud Bus消息总线

    在微服务架构中,通常会使用轻量级的消息代理来构建一个共用的消息主题来连接各个微服务实例,它广播的消息会被所有在注册中心的微服务实例监听和消费,也称消息总线. SpringCloud中也有对应的解决方案 ...

  7. 在shell中使用sendmail发送邮件

    cat > sendmymail.sh #!/bin/bash/usr/sbin/sendmail -t <<EOFFrom: Mail testing <abc@gmail. ...

  8. composer启用国内镜像网站的配置更改办法

    用法: 有两种方式启用本镜像服务: 将以下配置信息添加到 Composer 的配置文件 config.json 中(系统全局配置).见“例1” 将以下配置信息添加到你的项目的 composer.jso ...

  9. 执行Oracle存储过程报权限不足的解决方法

    当前Oracle用户sofa拥有connect.dba.resource的角色权限,但奇怪的是却没有执行Oracle Procedure的权限.后来通过查找资料发现:如果sofa用户需要执行Proce ...

  10. CSU 1786 莫队+KDTree

    题意 给出n个二维点(2e5) 和 q个询问(1e4) 每个询问给lr 问点l到r间有多少对点的曼哈顿距离<=d 点的坐标<=108 想出了莫队算法 复杂度n^1.5 看起来很科学 但是每 ...