清单目录在Linux中从C [英] Listing directories in Linux from C

查看:131
本文介绍了清单目录在Linux中从C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图模拟使用Linux API从C的Linux命令ls。纵观code这有一定道理,但是当我运行它,我得到统计错误:没有这样的文件或目录。我已经检查了执行opendir好的工作。我认为这个问题是在统计,这是返回-1,即使我认为它应该返回0。

我在想什么?

感谢您的帮助。

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&dirent.h GT;
#包括LT&; SYS / stat.h>
#包括LT&;&errno.h中GT;INT主(INT ARGC,CHAR *的argv [])
{
 DIR * dirp;
 结构的dirent * direntp;
 结构统计stat_buf;
 字符*海峡; 如果(的argc!= 2)
 {
  fprintf中(标准错误,用法:%s的DIR_NAME \\ n,argv的[0]);
  出口(1);
 } 如果((dirp =执行opendir(的argv [1]))== NULL)
 {
  PERROR(ARGV [1]);
  出口(2);
 } 而((direntp = READDIR(dirp))!= NULL)
 {
  如果(STAT(direntp-> d_name,&安培; stat_buf)== - 1)
  {
   PERROR(stat错误);
   出口(3);
  }
  如果(S_ISREG(stat_buf.st_mode))海峡=正规军;
  否则,如果(S_ISDIR(stat_buf.st_mode))海峡=目录;
  否则海峡=其他;
  的printf(% - 25秒 - %S \\ n,direntp-> d_name,STR);
 } closedir(dirp);
 出口(0);
}


解决方案

这是因为你没有说明实际的文件。这是在不同的目录。如果你想真正的文件名,将的argv [1] direntp-> d_name 以'/'之间它们。

此外,匈牙利命名是恶心,甚至未成年人有点像年底P。如果你有这么多的变量,你需要跟踪它们的类型在它们的名字你所做的是错的。

下面是你的程序的修订版:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&STDDEF.H GT;
#包括LT&;&string.h中GT;
#包括LT&;&dirent.h GT;
#包括LT&; SYS / stat.h>
#包括LT&;&errno.h中GT;
#包括LT&;&limits.h中GT;
#包括LT&;了sys / param.h>INT主(INT ARGC,CHAR *的argv [])
{
 DIR * dirp;
 结构的dirent * direntp;
 结构统计stat_buf;
 字符*海峡;
 焦炭完整路径[MAXPATHLEN + 1];
 为size_t dirnamelen; 如果(的argc!= 2)
 {
  fprintf中(标准错误,用法:%s的DIR_NAME \\ n,argv的[0]);
  出口(1);
 }
 函数strncpy(完整路径,ARGV [1],MAXPATHLEN - 1); / *账户尾随'/'* /
 完整路径[MAXPATHLEN - 1] ='\\ 0';
 dirnamelen = strlen的(完整路径);
 如果(strlen的(的argv [1])> dirnamelen){
  fprintf中(标准错误,目录名太长:%S,ARGV [1]);
  出口(2);
 } 完整路径[dirnamelen ++] ='/';
 完整路径[dirnamelen] ='\\ 0'; 如果((dirp =执行opendir(的argv [1]))== NULL)
 {
  PERROR(ARGV [1]);
  出口(2);
 } 而((direntp = READDIR(dirp))!= NULL)
 {
  完整路径[dirnamelen] ='\\ 0';
  如果((dirnamelen +的strlen(direntp-> d_name))> MAXPATHLEN){
   fprintf中(标准错误,文件%s +目录%s太长。direntp-> d_name,完整路径);
   继续;
  }其他{
   / *函数strncpy温和矫枉过正,因为if语句已证实,
      有足够的空间。 * /
   函数strncpy(完整路径+ dirnamelen,direntp-> d_name,MAXPATHLEN - dirnamelen);
   完整路径[MAXPATHLEN] ='\\ 0';
  }
  如果(STAT(完整路径,&安培; stat_buf)== - 1)
  {
   PERROR(stat错误);
   出口(3);
  }
  如果(S_ISREG(stat_buf.st_mode))海峡=正规军;
  否则,如果(S_ISDIR(stat_buf.st_mode))海峡=目录;
  否则海峡=其他;
  的printf(% - 25秒 - %S \\ n,direntp-> d_name,STR);
 } closedir(dirp);
 出口(0);
}

请注意,我用 MAXPATHLEN (从< limits.h中> ),并仔细检查,以确保有没有任何缓冲区溢出。你应该做同样的在你的code。

编辑:改code使用 STRN 家庭功能增加安全性。

I am trying to simulate linux command ls using linux api from c. Looking at the code it does make sense, but when I run it I get "stat error: No such file or directory". I have checked that opendir is working ok. I think the problem is in stat, which is returning -1 even though I think it should return 0.

What am I missing?

Thanks for your help.

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

int main(int argc, char *argv[])
{
 DIR *dirp;
 struct dirent *direntp;
 struct stat stat_buf;
 char *str;

 if (argc != 2)
 {
  fprintf( stderr, "Usage: %s dir_name\n", argv[0]);
  exit(1);
 }

 if ((dirp = opendir( argv[1])) == NULL)
 {
  perror(argv[1]);
  exit(2);
 }

 while ((direntp = readdir( dirp)) != NULL)
 {
  if (stat(direntp->d_name, &stat_buf)==-1)
  {
   perror("stat ERROR");
   exit(3);
  }
  if (S_ISREG(stat_buf.st_mode)) str = "regular";
  else if (S_ISDIR(stat_buf.st_mode)) str = "directory";
  else str = "other";
  printf("%-25s - %s\n", direntp->d_name, str);
 }

 closedir(dirp);
 exit(0);
}

解决方案

It's because you aren't stating the actual file. It's in a different directory. If you want the real filename, combine argv[1] and direntp->d_name with a '/' between them.

Also, hungarian naming is icky, even the minor bit like 'p' on the end. If you have so many variables you need to keep track of their types in their names you're doing something wrong.

Here is a revised version of your program:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <sys/param.h>

int main(int argc, char *argv[])
{
 DIR *dirp;
 struct dirent *direntp;
 struct stat stat_buf;
 char *str;
 char fullpath[MAXPATHLEN + 1];
 size_t dirnamelen;

 if (argc != 2)
 {
  fprintf( stderr, "Usage: %s dir_name\n", argv[0]);
  exit(1);
 }
 strncpy(fullpath, argv[1], MAXPATHLEN - 1); /* account for trailing '/' */
 fullpath[MAXPATHLEN - 1] = '\0';
 dirnamelen = strlen(fullpath);
 if (strlen(argv[1]) > dirnamelen) {
  fprintf( stderr, "Directory name is too long: %s", argv[1] );
  exit(2);
 }

 fullpath[dirnamelen++] = '/';
 fullpath[dirnamelen] = '\0';

 if ((dirp = opendir( argv[1])) == NULL)
 {
  perror(argv[1]);
  exit(2);
 }

 while ((direntp = readdir( dirp)) != NULL)
 {
  fullpath[dirnamelen] = '\0';
  if ((dirnamelen + strlen(direntp->d_name)) > MAXPATHLEN) {
   fprintf(stderr, "File %s + directory %s is too long.", direntp->d_name, fullpath);
   continue;
  } else {
   /* strncpy is mild overkill because the if statement has verified that
      there's enough space.  */
   strncpy(fullpath + dirnamelen, direntp->d_name, MAXPATHLEN - dirnamelen);
   fullpath[MAXPATHLEN] = '\0';
  }
  if (stat(fullpath, &stat_buf)==-1)
  {
   perror("stat ERROR");
   exit(3);
  }
  if (S_ISREG(stat_buf.st_mode)) str = "regular";
  else if (S_ISDIR(stat_buf.st_mode)) str = "directory";
  else str = "other";
  printf("%-25s - %s\n", direntp->d_name, str);
 }

 closedir(dirp);
 exit(0);
}

Note that I use MAXPATHLEN (from <limits.h>) and carefully check to make sure there aren't any buffer overflows. You should do the same in your code.

Edit: Changed code to use strn family functions for added safety.

这篇关于清单目录在Linux中从C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆