プロが教える店舗&オフィスのセキュリティ対策術

linux(ubuntu11.04)でコマンドラインからもらったディレクトリをトラバースするプログラムを作りたいんですがうまくいきません。
一応書けたのですがどうも予想と違う動きをしてしまいます。


#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<string.h>

static void do_traverse(char *patht, int t);

int main(int argc, char *argv[])
{
int i;
if(argc<2)
{
fprintf(stderr,"%s: no arguments\n",argv[0]);
exit(1);
}
for(i=1;i<argc;i++)
{
do_traverse(argv[i],0);
}
return 0;
}

static void do_traverse(char *path, int t)
{
DIR *d;
struct dirent *ent;
int i;

d=opendir(path);
if(!d)
{
perror(path);
exit(1);
}

while((ent=readdir(d))!=NULL)
{
struct stat st;
if(lstat(ent->d_name,&st)<0)
{
perror(ent->d_name);
exit(1);
}
for(i=0;i<t;i++)
{
printf(" ");
}
printf("%s\n",ent->d_name);

if((strcmp(".",ent->d_name))==0 || (strcmp("..",ent->d_name))==0 || S_ISLNK(st.st_mode))
{
continue;
}

if(S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
{
do_traverse(ent->d_name,t+1);

}
}
closedir(d);
}

例えばディレクトリaにファイルbとディレクトリcがあり、ディレクトリcの中にはファイルdとディレクトリeがあり、ディレクトリeの中にはファイルfがあるとします。
僕の理想では
$./traverse a
とすると
..
.
b
c
..
.
d
e
..
.
f

となるはずなんですが(表示の順番は適当です)、実際は

b
..
.
c

となってしまいうまくトラバースしてくれません
どうしてこうなるかわかりません
誰か助けてください
お願いします

A 回答 (3件)

失礼ですが、プログラムが間違ってますよ。


引数pathにディレクトリ名を渡してます。
このままだと"c"をlstatしてしまいます。
カレントにディレクトリ"c"は存在していませんので、ここでエラーです。
正しくはlstat("a/c", &st);ですよね。

そんな風になおして以下のようなテストコードを書いてみたところ
動きましたので貼っておきます。


#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<string.h>

static void do_traverse(char *patht, int t);

int main(int argc, char *argv[])
{
  int i;
  if (argc < 2) {
    fprintf(stderr, "%s: no arguments\n", argv[0]);
    exit(1);
  }
  for (i = 1; i < argc; i++) {
    do_traverse(argv[i], 0);
  }
  return 0;
}

static void do_traverse(char *path, int t)
{
  DIR *d;
  struct dirent *ent;
  int i;

  d = opendir(path);
  if (!d) {
    perror(path);
    exit(1);
  }

  while ((ent = readdir(d)) != NULL) {
    struct stat st;
    char newpath[BUFSIZ];
    sprintf(newpath, "%s/%s", path, ent->d_name);
    if (lstat(newpath, &st) < 0) {
      perror(newpath);
      exit(1);
    }
    for (i = 0; i < t; i++) {
      printf(" ");
    }
    printf("%s\n", ent->d_name);

    if ((strcmp(".", ent->d_name)) == 0
      || (strcmp("..", ent->d_name)) == 0 || S_ISLNK(st.st_mode)) {
      continue;
    }

    if (S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) {
      do_traverse(newpath, t + 1);

    }
  }
  closedir(d);
}
    • good
    • 0

質問文中の「例えば~」の状況で


./traverse c
と実行した場合, どうなると思いますか?
    • good
    • 0

do_traverse の引数がどうなっているか確認しましたか?

この回答への補足

どう考えてもこのプログラムに間違いがあると思えません
確認してもどこに間違いがあるのか検討もつきません

補足日時:2012/02/21 14:56
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!