www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - dirEntries throws exception on broken symlinks

reply "dennis" <dennisr visi.com> writes:
I a using dirEntries to list recursively build a list of all 
files in all subdirectories but dirEntries is throwing an 
exception when it encounters a broken link.

I want just report the exception, then ignore the broken link and 
then continue processing the rest of the dir's and files.

Do I need to create my own implementation of a dirEntries 
function to solve this?

Also in the example code below I am getting a segfault when I try 
to extract the errno from the exception object and I am not sure 
why the segfault is happening, is it my code or a bug?

Example Code:

import std.stdio;
import std.file;


void main(string[] args)
{

     try {
         foreach (string name; dirEntries(args[1], 
SpanMode.breadth))
         {
             writefln(name);
         }
     }
     catch(Exception o) {
         writefln(o.toString());
         writefln("%d",(cast(FileException)o).errno);

     }
}
Jan 05 2014
parent reply "FreeSlave" <freeslave93 gmail.com> writes:
You must not cast base class to derived class, when you don't 
know actual type (and even if you know exact type it's still bad 
practice to cast instance of more generic type to more specific 
one). Use multiple catch statements instead:

catch(FileException o)
{
//handle FileException
}
catch(Exception o)
{
//handle all other types of exceptions
}

About dirEntries, you need to move your try/catch statements into 
loop somehow. You probably should save result of dirEntries to 
variable and then make manual loop instead of foreach. Result of 
dirEntries is lazy, so it will not throw exception when you just 
get it.

It may look like

auto entries = dirEntries(your args);
while(!entries.empty)
{
     try
     {
         entry = entries.front;
         //do your stuff
     }
     //"catch" statements
     finally
     {
         entries.popFront();
     }
}
Jan 05 2014
parent reply "dennis" <dennisr visi.com> writes:
On Sunday, 5 January 2014 at 21:33:56 UTC, FreeSlave wrote:
 You must not cast base class to derived class, when you don't 
 know actual type (and even if you know exact type it's still 
 bad practice to cast instance of more generic type to more 
 specific one). Use multiple catch statements instead:

 catch(FileException o)
 {
 //handle FileException
 }
 catch(Exception o)
 {
 //handle all other types of exceptions
 }

 About dirEntries, you need to move your try/catch statements 
 into loop somehow. You probably should save result of 
 dirEntries to variable and then make manual loop instead of 
 foreach. Result of dirEntries is lazy, so it will not throw 
 exception when you just get it.

 It may look like

 auto entries = dirEntries(your args);
 while(!entries.empty)
 {
     try
     {
         entry = entries.front;
         //do your stuff
     }
     //"catch" statements
     finally
     {
         entries.popFront();
     }
 }
Thank you for the quick feedback. Your explanation of the two problems works for me.
Jan 05 2014
parent Timothee Cour <thelastmammoth gmail.com> writes:
I reported this here some time ago:
http://d.puremagic.com/issues/show_bug.cgi?id=11501 (dup of
http://d.puremagic.com/issues/show_bug.cgi?id=8298)
and there's a pull request ready, not sure why it isn't being merged


On Sun, Jan 5, 2014 at 10:20 PM, dennis <dennisr visi.com> wrote:

 On Sunday, 5 January 2014 at 21:33:56 UTC, FreeSlave wrote:

 You must not cast base class to derived class, when you don't know actual
 type (and even if you know exact type it's still bad practice to cast
 instance of more generic type to more specific one). Use multiple catch
 statements instead:

 catch(FileException o)
 {
 //handle FileException
 }
 catch(Exception o)
 {
 //handle all other types of exceptions
 }

 About dirEntries, you need to move your try/catch statements into loop
 somehow. You probably should save result of dirEntries to variable and then
 make manual loop instead of foreach. Result of dirEntries is lazy, so it
 will not throw exception when you just get it.

 It may look like

 auto entries = dirEntries(your args);
 while(!entries.empty)
 {
     try
     {
         entry = entries.front;
         //do your stuff
     }
     //"catch" statements
     finally
     {
         entries.popFront();
     }
 }
Thank you for the quick feedback. Your explanation of the two problems works for me.
Jan 07 2014