C编程 - 统计系统调用 - 错误

问题描述 投票:4回答:4

我是C的新手但尝试了一些系统调用。

我正在编写程序,遍历目录中的所有文件并打印当前文件名和大小。我可以让程序打印文件名,但是当我执行stat系统调用时它会出错。

以下是一些代码:

while (dptr = readdir(dirp)) { 
            if (stat(dptr->d_name, &buf) != 0) {
                //Always does this and it does print the file name
                printf("Error on when getting size of %s \n", dptr->d_name);
            } else {
                //Never gets here
                printf("%u", buf.st_size);
              }         
}

我有这样描述的结构:

struct stat buf;
struct dirent *dptr;
DIR *dirp;

如果我改变:

if (stat(dptr->d_name, &buf) != 0)

if (stat(dptr->d_name, &buf) != [EACCES])

它仍然进入循环,这使我认为它无法读取文件名,但它在错误语句中打印它没有问题。

有人能指出我正确的方向吗?谢谢!

阿尔卡季

c linux system-calls stat
4个回答
4
投票

首先,如果遇到错误,stat()返回-1,而不是实际的错误代码。错误代码将在errno中设置。打印错误的简单方法是使用perror()。

其次,dptr-> d_name仅提供文件的相对文件名,而不是完整文件名。要获取完整文件名,必须从相对文件名和目录名生成它。

这是一个例子:

int cwdloop(void)
{
   DIR           * dirp;
   struct stat     buff;
   struct dirent * dptr;
   char            filename[1024];
   char            dirname[1024];

   if (!(getcwd(dirname, 1024)))
   {
       perror("getcwd");
       return(1);
   };

   dirp = opendir(dirname);
   if (!(dirp))
   {
      perror("opendir()");
      return(1);
   };

   while ((dptr = readdir(dirp)))
   {
      snprintf(filename, 1024, "%s/%s", dirname, dptr->d_name);
      if (stat(filename, &buff) != 0)
      {
         perror("stat()");
         return(1);
      } else {
         printf("size: %u\n", (unsigned)buff.st_size);
      };
   };

   closedir(dirp);

   return(0);
}

3
投票

如果您知道确切的错误,这些事情会更容易处理。尝试

printf("error = %d: %s", errno, strerror(errno));

3
投票

这种代码的一个常见问题是仅使用文件名作为路径名。 dirent结构的d_name条目不提供完整路径名,但提供相对于您的目录的路径名。

要解决此问题,您可以

  1. 构造完整的路径名,然后将其传递给stat
  2. chdir在调用stat之前到目录。

0
投票

其他答案涵盖了问题的直接答案。我提供这个作为一个免费的答案。在调试stat()系统调用时,您可能会发现以下函数有助于很好地格式化返回的stat缓冲区。

如何格式化,打印或记录stat()系统调用:

static void logstat(struct stat *sp)
{
    int mode = sp->st_mode;

    if (sp->st_size > 1000000000)
        printf("  File Size:        %lluGB\n", sp->st_size / 1000000000);
    else if(sp->st_size > 1000000)
        printf("  File Size:        %lluMB\n", sp->st_size / 1000000);
    else
        printf("  File Size:        %llu bytes\n", sp->st_size);

    printf("  Number of Links:  %d\n", sp->st_nlink);
    printf("  File inode:       %d\n", sp->st_ino);
    printf("  File type:        ");
    switch (mode & S_IFMT) {
    case S_IFBLK:
        printf("BLK\n");
        break;
    case S_IFCHR:
        printf("CHR\n");
        break;
    case S_IFDIR:
        printf("DIR\n");
        break;
    case S_IFIFO:
        printf("FIFO\n");
        break;
    case S_IFLNK:
        printf("LINK\n");
        break;
    case S_IFREG:
        printf("REG\n");
        break;
    case S_IFSOCK:
        printf("SOCK\n");
        break;
    }
    printf("  File Permissions: ");
    printf( (S_ISDIR(sp->st_mode)  ? "d" : "-");
    printf( (sp->st_mode & S_IRUSR) ? "r" : "-");
    printf( (sp->st_mode & S_IWUSR) ? "w" : "-");
    printf( (sp->st_mode & S_IXUSR) ? "x" : "-");
    printf( (sp->st_mode & S_IRGRP) ? "r" : "-");
    printf( (sp->st_mode & S_IWGRP) ? "w" : "-");
    printf( (sp->st_mode & S_IXGRP) ? "x" : "-");
    printf( (sp->st_mode & S_IROTH) ? "r" : "-");
    printf( (sp->st_mode & S_IWOTH) ? "w" : "-");
    printf( (sp->st_mode & S_IXOTH) ? "x" : "-");
    printf("\n\n");
}
© www.soinside.com 2019 - 2024. All rights reserved.