標籤:style http ar os 使用 sp for 檔案 on
在 CentOS 5.5 上使用 sed 遇到一個bug
$ echo AAA > config$ ln -s config cfg$ sed -i ‘s/AAA/aaa/‘ cfgsed: 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 > tmpmv 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 的行為和之前版本一致
在CentOS 5.5上使用sed遇到的一個bug