DDE后端之dentry(三):用bug说明对symbolic_link的处理

来源:互联网 发布:顾客特殊要求矩阵 编辑:程序博客网 时间:2024/05/22 04:49

bug见tower:

https://tower.im/projects/1c0cd0c59ef941298c6e6b2ba6833b91/todos/3d7855eea6cb4beda149c9754a736717/#e5910d43abda42c5b07e554e97c3f0ea

重现方式:(注此bug已于20130716日修复)

首先在文件管理器中创建一个文件夹的软链(文件夹中要有文件),然后下面是两种不同方法,都会挂掉

1. 在软链上右键复制--->到桌面上粘贴

2.  在软链上剪切---->在桌面粘贴这个软链--->然后在桌面再次复制粘贴软链。

会弹出是否覆盖的提示,这个随意选择,最后会报错误: “当复制文件时出错”

最后点击确定,桌面必挂。

 

gdb 打印信息:

 

Program received signal SIGSEGV, Segmentation fault.0x0000000000422dd4 in _copy_files_async (src=0xc1b340, data=0xc0b770)    at /home/ycl/dde/lib/dentry/fileops.c:675675 if (response->apply_to_all)(gdb) bt#0  0x0000000000422dd4 in _copy_files_async (src=0xc1b340, data=0xc0b770)    at /home/ycl/dde/lib/dentry/fileops.c:675#1  0x0000000000422f53 in _copy_files_async (src=0xc1b340, data=0xc0b770)    at /home/ycl/dde/lib/dentry/fileops.c:719#2  0x0000000000421bcd in traverse_directory (src=0xc1b340,     pre_hook=0x422b43 <_copy_files_async>, post_hook=0x42253f <_dummy_func>,     data=0xc0b770) at /home/ycl/dde/lib/dentry/fileops.c:88#3  0x0000000000421dc8 in traverse_directory (src=0x730c80,     pre_hook=0x422b43 <_copy_files_async>, post_hook=0x42253f <_dummy_func>,     data=0xb6bd80) at /home/ycl/dde/lib/dentry/fileops.c:154#4  0x0000000000421dc8 in traverse_directory (src=0x730b20,     pre_hook=0x422b43 <_copy_files_async>, post_hook=0x42253f <_dummy_func>,     data=0xb65c10) at /home/ycl/dde/lib/dentry/fileops.c:154#5  0x00000000004224c2 in fileops_copy (file_list=0x9bff60, num=1,     dest_dir=0x6e66a0) at /home/ycl/dde/lib/dentry/fileops.c:375#6  0x0000000000426178 in fileops_paste (dest_dir=0x6e66a0)    at /home/ycl/dde/lib/dentry/fileops_clipboard.c:134#7  0x00000000004219be in dentry_clipboard_paste (dest_dir=0x6e66a0)    at /home/ycl/dde/lib/dentry/entry.c:894#8  0x0000000000417c61 in __clipboard_paste__ (context=0x7fff92fe20d0,     function=0x7fff9046d920, thisObject=0x7fff9046eaa0, argumentCount=1,     arguments=0x7fffffffcd28, exception=0x7fffffffcce8)    at /home/ycl/dde/build/app/desktop/_gen_dentry.c:1363

 

 

1.先记录一下:

dentry_copy:只复制symlink本身,不复制软链对应的文件或者文件夹

dentry_copy_dereference_symlink:还会进入symlink遍历。但是这样很容易由树成图,进入死循环。

 

现在的问题在于前端现在没有对软链进行单独处理,而是当做一般文件处理,然后进入traverse_directory中遍历(但是核心问题在于traverse_directory中把软链当成文件夹进行复制的,本来设置的是G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)  并使用_copy_files_async进行复制。

此处还需进一步查找问题。

 

2.虽然有单独的软链复制函数

JS_EXPORT_API

void dentry_copy_dereference_symlink(ArrayContainer fs, GFile* dest_dir)

但是这个函数是把软链当单个文件处理的,此处显然有问题!

staticvoid _do_dereference_symlink_copy(GFile* src, GFile* dest){    GError* error = NULL;    if (!g_file_copy(src, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &error)) {        g_warning("error message: %s, error code: %d\n", error->message, error->code);        FileOpsResponse* response;        response = fileops_move_copy_error_show_dialog(_("copy"), error, src, dest, NULL);

 

没有分开处理单个文件的软链和文件夹的软链这两种不同的情况。

 

3.乾哥找出如下bug

a.shift+delete 删软链时,文件夹内部文件被删除,但是软链对应的文件夹本身没有被删除

b. 直接delete时,文件夹内部文件每被删除,仅仅删除了软链

 

4.

进一步查找1中的疑问发现,虽然设置了 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,但是没有先检测是否是symbolic_link,如果是,应直接goto  post_processing

gbooleantraverse_directory (GFile* src, GFileProcessingFunc pre_hook, GFileProcessingFunc post_hook, gpointer data){。。。。。。。。。。。。。。  //here, we must be in a directory.    //check if it's a symbolic link    if (pre_hook (src, data) == FALSE) //src_enumerator must be freed    {retval = FALSE;goto post_processing;    }#if 1    char* src_uri = NULL;    src_uri = g_file_get_uri (src);    g_debug ("traverse_directory: chdir to : %s", src_uri);#endif    //begin g_file_enumerator_next_file ,we must check if the file type is symbolic_link then goto post_processing:    GFileType type = g_file_query_file_type (src, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL);    if (type == G_FILE_TYPE_SYMBOLIC_LINK)    {        //TODO: symbolic links        g_debug ("-------------src type is symbolic_link----------------");        goto post_processing;    }    GFileInfo* file_info = NULL;    while ((file_info = g_file_enumerator_next_file (src_enumerator, NULL, &error)) != NULL)    {。。。。。。。。。。。。。。。。。。。。。。。

 

 

总结:

其实对于软链,如果当做文件夹那样复制或者删除等操作,后果很有可能会进入死循环(软链中还有软链,这种情况不是没可能出现)。

故最好的解决方案,应该如同nautilus中那样,不论单个文件软链,还是文件夹软链,仅仅只是当做单个文件进行复制剪切粘贴,而不遍历进文件夹内部操作。

所有操作只对软链本身而言,而不对内部文件产生任何影响。

注:code中已经于20130716日 把对软链的操作更改过来了。以后全部操作只对软链本身有效。

 

原创粉丝点击