Программирование на C - Стат системный вызов - Ошибка - PullRequest
4 голосов
/ 15 декабря 2011

Я новичок в 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])

Это все еще входит в цикл, который заставляет меня думать, что он не может прочитать файлимя, но он печатает его в сообщении об ошибке без проблем.

Может ли кто-нибудь указать мне правильное направление?Спасибо!

Аркадий

Ответы [ 4 ]

4 голосов
/ 15 декабря 2011

Сначала 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 голосов
/ 15 декабря 2011

Одной из распространенных проблем с этим типом кода является использование только имени файла в качестве имени пути.Запись d_name структуры dirent не предоставляет вам полный путь, но предоставляет путь относительно вашего каталога.

Чтобы решить эту проблему, вы можете либо

  1. создать полный путьимя и затем передайте его stat или

  2. chdir в каталог перед вызовом stat.

3 голосов
/ 15 декабря 2011

С этими вещами намного легче справиться, если вы знаете точную ошибку.Попробуйте

printf("error = %d: %s", errno, strerror(errno));
0 голосов
/ 02 сентября 2018

Прямой ответ на вопрос покрыт другими ответами. Я даю это как бесплатный ответ. Во время отладки системного вызова 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");
}
...