在CentOS 5.5上使用sed遇到的一个bug

在 CentOS 5.5 上使用 sed 遇到一个bug

$ echo AAA > config
$ ln -s config cfg
$ sed -i ‘s/AAA/aaa/‘ cfg
sed: ck_follow_symlink: couldn‘t lstat c/config: No such file or directory

这个bug发生在 sed -i do_sth symbolic_links_without_slash 时

下载它的源代码 https://google-search-appliance-mirror.googlecode.com/files/sed-4.1.5-5.fc6.src.rpm

解压开可以看到redhat在sed-4.1.5上打上了3个补丁

sed-4.1.5-bz185374.patch

sed-4.1.5-relsymlink.patch

sed-4.1.5-utf8performance.patch

redhat为什么要为sed打上补丁呢,这源于另外一个问题,当sed -i do_sth file时实际的过程是这样的

sed do_sth file > tmp
mv tmp file

那么问题来了,如果file是指向文件file2的软连接,sed -i do_sth file 的结果是:

sed "剪短" 了 file 到 file2 的软连接
file2 的内容不会改变
file 成为一个file2的副本 它的内容改变了 (如果do_sth会修改)

这本身不是一个大问题 (算 sed 的一个 "小坑"吧)

不过有人试图解决这个问题, 所以就有了 sed-4.1.5-bz185374.patch

这个补丁里面新增了一个函数 ck_follow_symlink

它核心的地方是使用readlink

比如 文件 a -> b 文件 b -> c

ck_follow_symlink能够成功的寻迹到最终的文件 a -> c

不过 ck_follow_symlink 在有种情况下不能正常工作

文件 a -> ../b 而文件 b -> c

也就是说 a -> ../c 而 ck_follow_symlink 把它理解为了 a -> c

也就是说新引入了一个问题

为了解决这个新问题,所以又有了补丁sed-4.1.5-relsymlink.patch

这个补丁就是为了解决 a -> ../b 且 b -> c 这样的场景

解决方案是这样的:(补丁片段)

  //buf 是记录当前文件名的buffer  
  err = readlink (buf, buf2, bufsize);
  buf2 [err] = ‘\0‘;
  if (buf2[0] != ‘/‘)
    {
      dir = dirname (buf);    // dir part of orig path
      int len = strlen (dir); // orig path len
      buf[len] = ‘/‘;
      strncpy (buf+len+1, buf2, bufsize - len - 1);

那么问题来了,dirname 是怎么工作的

char ch[] = "/tmp/123";
char * p = dirname(ch);

dirname(ch) 的行为是 把 ch[4] 从 ‘/‘ 改成了 0 并把ch的地址作为返回值

但当 char ch[] = "tmp"时 dirname(ch) 的行为又是如何呢?

答案是 不对ch做任何修改 dirname(ch) 返回一个指针 这个指针指向一个常字符串 "."

这里对dirname的使用是错误的, 他错误的认为dirname一定会去修改入参并返回入参地址

所以对dirname的错误使用引入了文章开头的那个bug

这个bug在存在于CentOS/RHEL/Fedora这一支的某些版本中, 有无最终修复未考证

对与sed主线,它没有这个问题,对于sed -i 作用与软连接 "剪短" 软连接这个问题

在4.1.5之后的 sed 加了一个新参数--follow-symlinks,它可以保证sed -i 时不“剪断”软连接

没有这个参数时 sed -i 的行为和之前版本一致

时间: 2024-08-26 00:17:13

在CentOS 5.5上使用sed遇到的一个bug的相关文章

android上libevent dns解析的一个bug修复

在测试我们开发的一个 APK(使用了 libevent-2.1.3-alpha 作为网络库) 时发现一个奇怪的问题,域名解析有时报错 Non-recoverable name resolution failure .在公司偶尔报错,后来程序改动了一下,出错时重试几次,问题没再出现,以为好了.昨天换了个网络环境,结果报错几率变得非常大. 互联网搜索到这个错误的一个处理办法,说在使用 getnameinfo() 函数时需要显式指定其第二个参数 salen 为 sizeof(struct sockad

在CentOS 6.4上安装Puppet配置管理工具

在CentOS 6.4上安装Puppet配置管理工具 linux, puppetAdd comments 五052013 上篇说了下在ubuntu12.04上安装puppet,安装的版本为puppet2.7.11版本,今天尝试了下在CentOS6.4系统上安装puppet 3.1.1版本,本文参考chenshake的文章 ? 1 2 3 4 OS:centso 6.4 X64 Puppet 3.1.1 Puppet master: master.canghai.com Puppet client

CentOS 6.5上部署Haproxy

环境说明: 主机名 角色 IP地址 mylinux1.contoso.com Haproxy eth0:192.168.100.121 eth1:172.16.100.121 mylinux3.contoso.com ssh server(做tcp实验用) eth0:192.168.100.181 mylinux4.contoso.com ssh server(做tcp实验用) eth1:192.168.100.182 一.环境准备 以下配置基本上是每一次都要提前准备的,所以准备的命令我就不详细

基于CentOS 7.x上部署Zabbix 3.4

1.安装zabbix最新版epel源: rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm 2.安装zabbix服务端软件包: yum install zabbix-server-mysql zabbix-web-mysql -y CentOS 7.x上MySQL数据库叫mariadb,需要安装以下包,请大家自行yum安装: [[email prot

OpenStack 部署总结之:在CentOS 6.5上使用RDO安装双结算结点的icehouse(ovs+vlan)

本文主要介绍如何在CentOS6.5上通过RDO来安装一个双计算节点的icehouse环境,由于安装的过程中涉及的软件较多,以及依赖关系比较复杂,建议使用一个全新的操作系统来进行安装. 硬件环境 两台Dell的PC机,每台机器有两个网卡,且每个网卡都接有网线.公网和管理网络合用em1,虚拟机网络使用em2 服务器 公网/管理网络 VM Net 角色 服务器1 em1:192.168.40.147 em2 控制节点,网络节点,存储节点,计算节点 服务器2 em2:192.168.40.148 em

YUM安装Centos_linux Centos 6/7上安装GNOME桌面环境

YUM安装Centos_linux Centos 6/7上安装GNOME桌面环境 CentOS 作为服务器的操作系统是很常见的,但是因为需要稳定而没有很时髦的更新,所以很少做为桌面环境. CentOS 作为服务器的操作系统是很常见的,但是因为需要稳定而没有很时髦的更新,所以很少做为桌面环境.在服务器上通常不需要安装桌面环境,最小化地安装 CentOS(也就是 minimal CentOS) 就可以了.不过在最小化安装的 CentOS 中通过 YUM 来安装桌面环境也是非常方便的. 单位的那台服务

在Linux CentOS 6.6上安装Python 2.7.9

在Linux CentOS 6.6上安装Python 2.7.9 CentOS 6.6自带的是Python 2.6.6,而编译llvm需要Python 2.7以上. checking for python... /usr/bin/python checking for python >= 2.7... not found configure: error: found python 2.6.6 (/usr/bin/python); required >= 2.7 yum中最新的也是Python

阿里云CentOS Linux服务器上搭建邮件服务器遇到的问题

参考文章: 阿里云CentOS Linux服务器上用postfix搭建邮件服务器 Linux系统下邮件服务器的搭建(Postfix+Dovecot) 本来想自己搭建邮件服务器,但是看到一篇资料表示阿里云为了禁止垃圾邮件,禁用了25端口. 可以使用阿里云的邮件推送服务. SMTP之PHP调用示例 email.class.php下载

CentOS 6.3上搭建PPTP VPN

系统版本:CentOS 6.3_x86_64 eth0:172.16.10.72(实验环境当公网IP使用) eth1:192.168.100.50 1.检测是否支持ppp模块 # cat /dev/ppp cat: /dev/ppp: No such device or address 如出现上面的结果,表明PPP模块开启,可以继续安装过程. 2.安装ppp # yum -y install ppp iptables 3.安装pptp 下载pptp的rpm包并安装: # wget http://