<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
七、支持长文件名(二)。
4、先在0:/doc下建立好目录:这是一个very long的目录.它里面是空的.txt文档
这次再调用命令flist 0:/doc/这是一个very long的目录.它里面是空的.txt文档。
从串口follow_path(dj, path)输入是,都是以ascii码和GB<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2312码的形式发过去的。程序仍然是调用调用先函数 chk_mounted(),然后调用follow_path(dj, path)。在follow_path(dj, path)里,又分别调用create_name()函数和dir_find()函数。这次的关键是:对于这么一个长目录名,这两个函数分别是怎么处理的。
追踪进入create_name()函数。
if (IsDBCS1(w)) { b = p[si++]; w = (w << 8) + b; }
w = ff_convert(w, 1);
lfn[di++] = w;
它的主要动作使将接收到的 DBCS双字节 和 ASCII码单字节 都转换为unicode码存入dj->lfn长文件名缓冲区。再跟踪短文件名的创建,我发现这次创建的短文件名明显不符合要求。明明是一个目录,也创建了这样的短文件名“这是一个txt”这样的短文件名。再进入dir_find()函数看怎么处理。
追踪进入,这一次它的搜索是在0:/bin目录对应的簇里面,找到长目录项的过程跟dir_read()函数完全一样,只是每次不是pick_lfn(dj->lfn, dir),而是采用cmp_lfn(dj->lfn, dir)了,它的作用是对比当前长目录项里的unicode和dj->lfn存储区的unicode字符,如果一直到ord=0,对比都返回TRUE,则找到相应的长目录项。追踪进入,函数比较简单,逐个比较13个字节。
定位到短文件名目录项后,if (!ord && sum == sum_sfn(dir)) break,根本不对比短文件名,直接跳出搜索循环,这样实际上已经定位到所要找的目录。
回到,取得长目录的起始簇号。再调用f_readdir()函数获得各个目录项的属性就很方便了,上一篇文章已经分析过,这里就不再赘述了。
5、调用fwrite命令在0:/doc下建立文件:这是一个very long的文件.它里面是空的.txt文档
上一篇分析时用到的长文件名,再来分析一下这样的长文件名目录项是如何在文件系统那个里面建立起来的?
输入命令 fwrite 0:/doc/这是一个very long的文件.它里面是空的.txt文档
程序会调用f_open()函数,以创建新文件的方式打开该文档。在调用follow_path进行文件搜索的时候,最后一次在DIR结构里建立了长文件名缓冲和短文件名缓冲:
res = create_name(dj, &path); /* Get a segment */
res = dir_find(dj); 但是在执行这一句是找不到对应的文件(因为还没有建立,现在就是要建立这个文件)。结果follow_path()函数返回FR_NO_FILE。
执行流程回到f_open()函数,函数在FA_CREATE_NEW模式下调用dir_register(&dj)函数进行新目录项的添加。(这里要记住,在create_name()函数里面产生的短目录项名是不符合规定的,那么在dir_register()函数里应该进行新的处理。)追踪进入dir_register(&dj)函数。
进入dir_register(&dj)函数,果然先进行标准短文件名的创建:
gen_numname(fn, sn, lfn, n); /* 按数字规则产生这是一~1.txt或者这是一~2.txt这样的短文件名 */
res = dir_find(dj);//如果对应的n(1、2、3等)没用被使用就跳出循环,如果已被使用,则n+1再次循环。进入 gen_numname(fn, sn, lfn, n)看短文件名是如何产生的。
i=7;
do {
ns[i--] = (num % 10) + '0';
num /= 10;
} while (num);
ns = '~';
这里可以简单看出文件名后缀产生的过程。
回到dir_register(&dj)函数,调用dir_seek(dj, 0),回到0:/bin目录所在簇的开始,接下来要搜寻几个连续的空目录项,这里应该是4个,用于三个长文件目录项和一个短文件目录项,其搜寻方法如下:
ne = (ne + 25) / 13;共需要ne个目录项。29+25/13=3个。
循环搜索目录项:
if (c == 0xE5 || c == 0) { /* 搜索到一个空的 */
if (n == 0) is = dj->index; 长目录项进行定位,继续搜索
if (++n == ne) break; 如果连续碰到ne个,则跳出循环
} else {
n = 0; /* 在没有到ne+1个之前,碰到一个非空,立即清0 */
}
找到ne+1个空的目录项以后,首先res = dir_seek(dj, is)定位到空目录项的第一个。然后调用以下代码:
sum = sum_sfn(dj->fn); /* 计算短文件名的校验和 */
ne--;
do { /* Store LFN entries in bottom first */
res = move_window(dj->fs, dj->sect);
fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); //调用这个函数将dj->lfn缓冲区的unicode依次写入目录项。
dj->fs->wflag = 1;
res = dir_next(dj, FALSE); /* Next entry */
} while (res == FR_OK && --ne);
长目录项写好以后,再写对应的短目录项:
mem_set(dir, 0, 32); /* Clean the entry */
mem_cpy(dir, dj->fn, 11); /* Put SFN */
dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT);
这里实际上只写入了标准文件名和属性,其它的创建时间等信息等待f_open()函数完成。
文件的创建就算是完成了。
6、调用fdel命令在0:/doc下删除文件:这是一个very long的文件.它里面是空的.txt文档
这里主要是要观测长目录项的删除过程。
删除文件由f_unlink()函数调用dir_remove(&dj)函数完成。追踪进入dir_remove(&dj)。
i = dj->index; /* SFN index */
res = dir_seek(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx));
i保存当前短目录项的索引,然后dj->index定位到长目录项的起始索引,将这些目录的首个字母全部写入0xE5,目录项就算全部删除了。
再回到f_unlink()删除该文件的簇链,文件删除完成。
文章评论(0条评论)
登录后参与讨论