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

发布于 2024-12-21 10:55:23 字数 857 浏览 4 评论 0原文

我是 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)

to

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

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

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

阿尔卡代伊

I'm new to C but trying some system calls.

I'm writing program that iterates through all files in a directory and prints the current file name and size. I can get the program to print the file name but it errors when I preform the stat system call.

Here is some of the code:

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

I have the structs described like this:

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

If I change:

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

to

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

It still goes into the loop which makes me think it can't read the file name but it's printing it in the error statement without a problem.

Can someone point me in the right direction? Thanks!

Аркадий

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鸩远一方 2024-12-28 10:55:23

首先,如果遇到错误,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);
}

First, stat() returns -1 if an error is encountered, not the actual error code. The error code will be set in errno. An easy way to print the error is to use perror().

Second, dptr->d_name only provides a relative filename of the file and not the full filename. To obtain the full filename, you must generate it from the relative filename and the directory name.

Here is an example:

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);
}
迷你仙 2024-12-28 10:55:23

如果您知道确切的错误,那么处理这些事情就会容易得多。尝试

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

These things are a lot easier to deal with if you know the exact error. Try

printf("error = %d: %s", errno, strerror(errno));
摘星┃星的人 2024-12-28 10:55:23

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

要解决此问题,您可以

  1. 构造完整路径名,然后将其传递给 stat

  2. chdir 到调用 stat 之前的目录。

One common problem with this kind of code is using just the filename as path name. The d_name entry of dirent structure does not provide you full pathname but provides pathname relative to your directory.

To resolve this you can either

  1. construct the full path name and then pass it to stat or

  2. chdir to the directory before calling stat.

贪了杯 2024-12-28 10:55:23

该问题的直接答案已被其他答案覆盖。我将此作为免费答案提供。当您调试 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");
}

The direct answer to the question is covered by other answers. I'm providing this as a complimentary answer. While you're debugging stat() system call, you may find the following function helpful for nicely formatting the stat buffer that's returned.

How to format, and print or log stat() system call:

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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文