c - 从 C 列出 Linux 中的目录

标签 c linux

我正在尝试使用来自 c 的 linux api 模拟 linux 命令 ls。查看代码它确实有意义,但是当我运行它时我得到“统计错误:没有这样的文件或目录”。我检查过 opendir 工作正常。我认为问题出在 stat 上,它返回 -1,尽管我认为它应该返回 0。

我错过了什么?

感谢您的帮助。

#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);
}

最佳答案

这是因为您没有说明实际文件。它在不同的目录中。如果你想要真正的文件名,结合argv[1]direntp->d_name它们之间有一个“/”。

此外,匈牙利语的命名方式令人作呕,即使是末尾的“p”之类的次要名称也是如此。如果你有这么多变量,你需要在它们的名字中跟踪它们的类型,那你就做错了。

这是你的程序的修订版:

#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);
}

请注意,我使用 MAXPATHLEN (来自 <limits.h> )并仔细检查以确保没有任何缓冲区溢出。您应该在代码中执行相同的操作。

编辑:更改代码以使用 strn增加安全性的家庭功能。

关于c - 从 C 列出 Linux 中的目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2607945/

相关文章:

c - 使用 C 的嵌套结构程序

android - 比较 .yml 文件 OpenCV 中的图像 SIFT/SURF 细节?

linux - 当后台进程完成时关闭前台进程

php - 如何制作一个通过 Web 服务器接受命令的 Linux 服务?

python - 解析输入 argv json 字符串

c - 在 Linux 中通过串口通信发送十六进制数据

c - 用C程序杀死一个进程

C2059 对一个函数使用 declspec 宏时出现语法错误;没有它编译得很好

c - 需要有非阻塞的命名管道,能够在 Linux 上的 c 中进行双向通信

linux - 为什么 32 位 .deb 包不能安装在 64 位 Ubuntu 上?