stat()提供错误信息 [英] stat() giving wrong information

查看:197
本文介绍了stat()提供错误信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用循环将目录中每个文件的信息打印出来,以将ls shell函数重新创建为C程序.将程序中的信息与ls命令中的正确信息进行比较时,程序的结果(使用stat())非常错误.

I'm using a loop to print the information of each file in a directory to recreate the ls shell function as a C program. When comparing the information from the program to the correct information from the ls command, the results from the program (using stat()) are very wrong.

这是我对该程序的所有代码:

Here's all of my code for the program:

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

int main(int argc, char* params[])
{
  void printTable(char filepath[], int s, int b);

    // If no modifiers, send error
    if(argc == 1) {
      printf("Error: no directory specified. \n");
      exit(1);
      return 0;
    }
    // If only a directory is provided
    if(argc ==2) {
      printTable(params[1], 0, 0);
    } // end of argc == 2

    // If there are 4 modifiers
    else if(argc == 4) {
    }
    return 0;
}

void printTable (char filepath[], int s, int b) {
  DIR *dp;
  struct dirent *dir;
  struct stat fileStats;
  if((dp = opendir(filepath)) == NULL) {
    fprintf(stderr, "Cannot open directory. \n");
    exit(1);
  }
  printf("Processing files in the directory: %s\n", filepath);
  printf("inode \t Type \t UID \t GID \t SIZE \t       Filename \t                 Modification date \n");
  while((dir = readdir(dp)) != NULL ) {
    if(dir->d_ino != 0 && fileStats.st_ino > 0 && stat(dir->d_name, &fileStats) < 0) {
      // Print the inode
      printf("%d \t ", fileStats.st_ino);
      // Print type
      if(dir->d_type == DT_BLK)
        printf("BLK \t ");
      else if(dir->d_type == DT_CHR)
        printf("CHR \t ");
      else if(dir->d_type == DT_DIR)
        printf("DIR \t ");
      else if(dir->d_type == DT_FIFO)
        printf("FIFO \t ");
      else if(dir->d_type == DT_LNK)
        printf("LNK \t ");
      else if(dir->d_type == DT_SOCK)
        printf("SOCK \t ");
      else if(dir->d_type == DT_REG)
        printf("REG \t ");
      else
        printf("UNKOWN \t ");
      // Print UID
      printf("%d \t ", fileStats.st_uid);
      // Print GID
      printf("%d \t ", fileStats.st_gid);
      // Print SIZE
      printf("%jd bytes \t ", fileStats.st_size);
      // Print file name
      printf("%25s \t ", dir->d_name);
      // Print date modified
      printf("%20s \n", ctime(&fileStats.st_mtime));
    }
  }
  struct tm *lt = localtime(&fileStats.st_mtime);
  int diff = difftime(time(NULL), mktime(lt));
  printf("%d \n", diff);
  closedir(dp);
}

这是shell命令的结果(此目录与该程序无关): shell输出

Here's the results from the shell command (this directory has nothing to do with this program): shell output

这是运行程序的结果:

推荐答案

stat(2)成功返回 0 ,但是您正在测试 stat(dir-> d_name,& fileStats)<0 .因此,只要 stat(2) 失败无法实际统计文件,您的代码就会输出一些内容.同样,条件的链接方式为 fileStats.st_ino>0 是在第一次迭代中涉及未初始化变量的表达式.

stat(2) returns 0 on success and yet you are testing whether stat(dir->d_name, &fileStats) < 0. So your code prints something whenever stat(2) fails to actually stat the file. Also, the way the conditions are chained, fileStats.st_ino > 0 is an expression involving an uninitialised variable in the first iteration.

stat(2)失败的最可行原因是您没有列出当前目录. dirent 结构的 d_name 成员是目录中文件的名称,它不是完整路径,而是相对于目录路径的路径.当您将其传递给 stat(2)时,它仅在文件位于进程的当前工作目录(cwd)中时才起作用.如果不是这种情况,如您的情况, stat(2)调用将失败.您要做的是通过将 filepath dir-> d_name 与路径分隔符/之间的级联连接来构建完整路径:

The most viable reason for stat(2) failing is that you are not listing the current directory. The d_name member of the dirent structure is the name of the file in the directory, which is not the full path but the path relative to the directory path. When you pass it to stat(2), it will only work if the file is in the current working directory (cwd) of the process. If it is not, as in your case, the stat(2) call will fail. What you have to do is build the full path by concatenating filepath and dir->d_name with the path separator / in between:

char fullpath[PATH_MAX];

sprintf(fullpath, "%s/%s", filepath, dir->d_name);
stat(fullpath, &fileStats);

或者,或者,使用 chdir(2)在循环之前更改工作目录:

Or, alternatively, use chdir(2) to change the working directory before the loop:

char olddir[PATH_MAX];

// Save current working directory
getcwd(olddir, PATH_MAX);
// Change working directory to `filepath`
chdir(filepath);

// Do your loop here

// Restore old working directory
chdir(olddir);

现在 stat(2)可以正确地使用相对路径,即仅文件名.

Now stat(2) will work correctly with relative paths, i.e., just file names.

这篇关于stat()提供错误信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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