(先叹一口气,今天帮别人建站点,从2.53升级到2.66,
到3:00am以为可以睡觉了的,突然发现这么一个BUG,一直弄到4:30才总算搞定)
一. 首先测试一下你的BBS站有没有这个问题
(只有版主权限的可以在本版测试)
1. 最好找一个没设过文摘的版面来测试,比如test,notpad版
然后按文章顺序依次将3篇文章收入文摘,(三篇足够测试了)
即先g第X篇,再g第X+1篇,再g第X+2篇。
2. 好,现在看看文摘模式,应该依次有第X,X+1,X+2篇文章的标题
3. 回到普通模式,取消第X+1篇文章的文摘标记(再按一下g)
4. 现在再看看文摘模式里的文章,显示的是第X,X+1的标题
这证明你的BBS系统存在这个BUG
二. 哪里来的BUG
(开始我一直以为是我移植老站代码到新站造成的,对比了半天相关的新旧代码,
发现没有什么不同,于是只好怀疑FB系统的原始代码了,只是不敢相信这个一个
常用的功能居然存在BUG)
1. 先看看bbs.c里的删除文摘的函数int dele_digest(dname,direc)
它调用下面这个语句去搜索digest_name(文摘的文件名)在目录文件new_dir里
的位置,返回相关的fileheader结构给fh,其中cmpfilename是用来比较读取
到的fileheader->filename与digest_name是否匹配的函数。
search_record(new_dir, &fh, sizeof(fh), cmpfilename, digest_name);
2. 再看看search_record()函数,它每读取一个fileheader结构就调用
if((*fptr)(farg,rptr)) 去比较异同,在dele_digest的调用中
即等同于调用 comfilename(digest_name,&fh);
3. 再看看comfilename函数
int cmpfilename(struct fileheader *fhdr)
{
if(!strncmp(fhdr->filename,currfile,STRLEN)) return 1 ;
return 0 ;
}
天!居然和第2步调用的接口不一样。
首先digest_name的定义是 char[STRLEN],而不是srtuct fileheader;
不过好在struct fileheader里的第一个item就是char filename[STRLEN];
在这个函数里歪打正着没有内存指针错误。
但是它比较的却是digest_name和currentfile,faint..
4. 回去看看currentfile是什么东东,这却是一个全局量。
一直找到最近一次给currentfile赋值的地方,在dele_digest函数里,
即调用search_record()前,却是一句滑稽的strcpy(currfile,digest_name);
原来这个comfilename的结果恒定为真,嘿嘿,所以search_record返回的值
多半是第一条记录的值。
5. 这么一来,错误就是....(困了,懒得写了 :( )
三. 解决BUG
最好的方法当然是自己写一个comfilename的函数来适应search_record()的调用啦
那么那一句strcpy(currentfile,digest_name)是不是就没用了呢?
no,no,no,还是有用的,下面delete_file函数要用到它。
另外看了comfilename的源码也就知道啦,它比较的是strncmp(str1,str2,STRLEN)
而不时strcmp(),所以你最好用strncpy(currentfile,str,STRLEN);
把bbs.c里那些所有用strcpy(currentfile,str)的语句都改成strncpy吧。
不过好象就是dele_digest函数里的要改,别的函数都用对了,啧啧
我手头的FireBird 2.5X, 2.66M版的源码都有这个BUG,想必是一个老BUG(怎么突然
想起了楚留香) ,改正的源码我这里就不贴出来了,很简单的
--
FROM 203.196.2.250