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

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:675

675 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)

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

static

void _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

gboolean

traverse_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日 把对软链的操作更改过来了。以后全部操作只对软链本身有效。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值