Unix Programming - Recursion problem using C

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > January 2006 > Recursion problem using C





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Recursion problem using C
Dreamcatcher

2006-01-29, 9:32 pm

Hello,

I'm trying to learn some C, reading my book, Beginning Linux Programming
I came across the following program. The program is supposed to walk
through directory's and print all its subdirectories. However the
program never seems to get out of the loop its in. I tried finding the
error but I don't see where it goes wrong, hopefully someone can shed a
light on this, source code is pasted below


/*
* This program should list the directory's + subdirs
* The search should begin on the location specief in
* main()
*
* This is a program taken from "Beginning Linux Programming"
*/

#include <unistd.h>
#include <stdio.h>
#include <dirent.h> /* All header files */
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>

/* Here we write the printdir function */
void printdir(char *dir, int depth)
{

DIR *dp;
struct dirent *entry;
struct stat statbuf;

/* We use opendir() to check wether the
directory from main() exists */
if((dp = opendir(dir)) == NULL) {
fprintf(stderr,"cannot open directory: %s\n", dir);
return;
}

/* If the directory exists we use chdir() to go into the
directory.
If the directory does not exist we printf above error

We use a recursive while loop to make sure it continues
aslong as
there are unlisted directory's */

chdir(dir);
while((entry = readdir(dp)) != NULL) {
lstat(entry -> d_name, &statbuf);
if(S_ISDIR(statbuf.st_mode)) {
if (strcmp(".", entry -> d_name) == 0)
continue;
printf("%*s%s/\n", depth,"", entry -> d_name);
printdir(entry -> d_name, depth + 4);
}
else printf("%*s%s/\n", depth,"", entry -> d_name);
}

/* When the program is doen crawling through the directory's
it use chdir()
to go back to the parent directory where it calls
closedir() to close the
opendir stram */

chdir("..");
closedir(dp);
}

int main()
{

printf("Directory scan of /home/roeland/programming:\n");
printdir("/home/roeland/programming",0); /* The
directory that needs to be listed */
printf("Done!\n");

return 0;
}

I have tried to debug the code and I think the program lies in the
"printdir(entry -> d_name, depth + 4);" line however, I still don't see
why this happens
Casper H.S. Dik

2006-01-29, 9:32 pm

Dreamcatcher <roeland.hemsteede@gmail.com> writes:

> if(S_ISDIR(statbuf.st_mode)) {
> if (strcmp(".", entry -> d_name) == 0)
> continue;


You are forgetting to skip "..".


Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Giorgos Keramidas

2006-01-29, 9:32 pm

On Fri, 27 Jan 2006 14:32:27 +0100, Dreamcatcher <roeland.hemsteede@gmail.com> wrote:
> I'm trying to learn some C, reading my book, Beginning Linux Programming
> I came across the following program. The program is supposed to walk
> through directory's and print all its subdirectories. However the program
> never seems to get out of the loop its in. I tried finding the error but
> I don't see where it goes wrong, hopefully someone can shed a light on
> this, source code is pasted below


The program has some logical errors. You use something similar to this:

opendir(foo);
chdir(foo);
while (readdir(foo)) {
}
chdir("..");

This is wrong, because you have no guarantee that ".." is the right path to
take after the loop exits.

Thomas Maier-Komor

2006-01-29, 9:32 pm

Dreamcatcher wrote:
> Hello,
>
> I'm trying to learn some C, reading my book, Beginning Linux Programming
> I came across the following program. The program is supposed to walk
> through directory's and print all its subdirectories. However the
> program never seems to get out of the loop its in. I tried finding the
> error but I don't see where it goes wrong, hopefully someone can shed a
> light on this, source code is pasted below
>
>
> /*
> * This program should list the directory's + subdirs
> * The search should begin on the location specief in
> * main()
> *
> * This is a program taken from "Beginning Linux Programming"
> */
>
> #include <unistd.h>
> #include <stdio.h>
> #include <dirent.h> /* All header files */
> #include <string.h>
> #include <sys/stat.h>
> #include <stdlib.h>
>
> /* Here we write the printdir function */
> void printdir(char *dir, int depth)
> {
>
> DIR *dp;
> struct dirent *entry;
> struct stat statbuf;
>
> /* We use opendir() to check wether the
> directory from main() exists */
> if((dp = opendir(dir)) == NULL) {
> fprintf(stderr,"cannot open directory: %s\n", dir);
> return;
> }
>
> /* If the directory exists we use chdir() to go into the
> directory.
> If the directory does not exist we printf above error
>
> We use a recursive while loop to make sure it continues
> aslong as
> there are unlisted directory's */
>
> chdir(dir);
> while((entry = readdir(dp)) != NULL) {
> lstat(entry -> d_name, &statbuf);
> if(S_ISDIR(statbuf.st_mode)) {
> if (strcmp(".", entry -> d_name) == 0)
> continue;
> printf("%*s%s/\n", depth,"", entry -> d_name);
> printdir(entry -> d_name, depth + 4);
> }
> else printf("%*s%s/\n", depth,"", entry -> d_name);
> }
>
> /* When the program is doen crawling through the directory's it
> use chdir()
> to go back to the parent directory where it calls
> closedir() to close the
> opendir stram */
>
> chdir("..");
> closedir(dp);
> }
>
> int main()
> {
>
> printf("Directory scan of /home/roeland/programming:\n");
> printdir("/home/roeland/programming",0); /* The directory
> that needs to be listed */
> printf("Done!\n");
>
> return 0;
> }
>
> I have tried to debug the code and I think the program lies in the
> "printdir(entry -> d_name, depth + 4);" line however, I still don't see
> why this happens


I guess you are trying to run this program under Linux. In this case you
might want to know about strace (which has been inspired by Solaris'
truss). Try running your executable with strace, then you might
understand much faster what is going on and why it doesn't do what you
expect.
e.g.:
$ strace ./a.out

HTH,
Tom
Pascal Bourguignon

2006-01-29, 9:32 pm

Dreamcatcher <roeland.hemsteede@gmail.com> writes:

> Hello,
>
> I'm trying to learn some C, reading my book, Beginning Linux
> programming I came across the following program. The program is
> supposed to walk through directory's and print all its
> subdirectories. However the program never seems to get out of the loop
> its in. I tried finding the error but I don't see where it goes wrong,
> hopefully someone can shed a light on this, source code is pasted
> below
> [...]
> if (strcmp(".", entry -> d_name) == 0)
> continue;


You need to special case the directory ".." too. This is the parent directory.

Since . and .. are the first two entries normally, the directories
you'll be walking will be:

/home/roeland/programming
/home/roeland/programming/. (ignored)
/home/roeland/programming/.. = /home/roeland
/home/roeland/. (ignored)
/home/roeland/.. = /home
/home/. (ignored)
/home/.. = /
/. (ignored)
/.. = /
/. (ignored)
/.. = /
/. (ignored)
/.. = /
/. (ignored)
/.. = /

....

> I have tried to debug the code and I think the program lies in the
> "printdir(entry -> d_name, depth + 4);" line however, I still don't
> see why this happens


Before using gdb or any other debugger on a program, you should insert
printf statement at strategical points.
For example if you added:

printf("dir=%s\n",dir);
before:
if((dp = opendir(dir)) == NULL) {

you would see the problem immediately.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"Klingon function calls do not have "parameters" -- they have
"arguments" and they ALWAYS WIN THEM."
Alex Fraser

2006-01-29, 9:32 pm

"Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
news:86bqxxn5ay.fsf@flame.pc...
> On Fri, 27 Jan 2006 14:32:27 +0100, Dreamcatcher

<roeland.hemsteede@gmail.com> wrote:
[snip][vbcol=seagreen]
> The program has some logical errors. You use something similar to this:
>
> opendir(foo);
> chdir(foo);
> while (readdir(foo)) {
> }
> chdir("..");
>
> This is wrong, because you have no guarantee that ".." is the right path
> to take after the loop exits.


What else could it reasonably be?

Alex


Dreamcatcher

2006-01-29, 9:32 pm

Alex Fraser wrote:
> "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
> news:86bqxxn5ay.fsf@flame.pc...
> <roeland.hemsteede@gmail.com> wrote:
> [snip]
>
> What else could it reasonably be?
>
> Alex
>
>


It is sorted, I changed "if (strcmp(".", entry -> d_name) == 0)" to "if
(strcmp(".", entry -> d_name) == 0 || strcmp("..", entry -> d_name) == 0)"

Thanks for the help!
Victor Wagner

2006-01-29, 9:32 pm

Alex Fraser <me@privacy.net> wrote:
: "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
: >
: > opendir(foo);
: > chdir(foo);
: > while (readdir(foo)) {
: > }
: > chdir("..");
: >
: > This is wrong, because you have no guarantee that ".." is the right path
: > to take after the loop exits.

: What else could it reasonably be?

Any place in the file system where there is a symbolic link to
directory.


--
Giorgos Keramidas

2006-01-29, 9:32 pm

On Fri, 27 Jan 2006 14:47:08 -0000, "Alex Fraser" <me@privacy.net> wrote:
> "Giorgos Keramidas" <keramida@ceid.upatras.gr> wrote in message
> news:86bqxxn5ay.fsf@flame.pc...
> <roeland.hemsteede@gmail.com> wrote:
> [snip]
>
> What else could it reasonably be?


Pretty much anything. Just think of:

chdir("/tmp");
printdir("/etc", 0);

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com