简体   繁体   English

为什么此C代码无法列出目录?

[英]Why doesn't this C code for listing a directory work?

I thought the following C code would list what is in the root directory. 我认为以下C代码将列出根目录中的内容。 Why does it loop forever? 为什么会永远循环?

#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct linux_dirent {
  unsigned long d_ino;
  unsigned long d_off;
  unsigned short d_reclen;
  char d_name[];
} linux_dirent;
extern int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count)
{
    return syscall(SYS_getdents, fd, dirp, count);
}

int main(void)
{
  linux_dirent* entryPtr = malloc(20000000);
  linux_dirent* buffer = entryPtr;
  int fd = open("/", O_RDONLY | O_DIRECTORY);
  int numentries = getdents((unsigned int)fd, entryPtr, 20000000);
  close(fd);
  for(;(entryPtr - buffer) < numentries; entryPtr += entryPtr->d_reclen)
  {
    puts(entryPtr->d_name);
  }
}

(entryPtr - buffer) will return (difference between the pointers) / (sizeof(linux_dirent)), while numentries is in bytes. (entryPtr-缓冲区)将返回(指针之间的差异)/(sizeof(linux_dirent)),而numentries以字节为单位。 If you were to use a char ptr and cast it to an entry_ptr it would probably work -- ie 如果您要使用char ptr并将其转换为entry_ptr,则可能会起作用-即

int main(void)
{
  char *entryPtr = malloc(20000000);
  char* buffer = entryPtr;
  int fd = open("/", O_RDONLY | O_DIRECTORY);
  int numentries = getdents((unsigned int)fd, (linux_dirent *)entryPtr, 20000000);
  close(fd);
  for(;(entryPtr - buffer) < numentries; entryPtr += ((linux_dirent *)entryPtr)->d_reclen)
  {
    puts(((linux_dirent *)entryPtr)->d_name);
  }
}

it would likely work. 它可能会工作。 However, I agree that you should be using readdir, not getdents. 但是,我同意您应该使用readdir,而不是getdents。

It should be 它应该是

for(;
    (entryPtr - buffer) < numentries; 
    entryPtr = (char*)((entryPtr+1)+entryPtr->d_reclen+2)
   )
 {
   puts(entryPtr->d_name);
 }

The +2 is for the the padding byte and the d_type field +2用于填充字节和d_type字段

since according to getdents(2) the entries are variable length. 因为根据getdents(2) ,条目的长度是可变的。

But you really want to use readdir(3) . 但是您真的想使用readdir(3) getdents is only useful to those implementing readdir , like readdir.c from MUSL libc . getdents是只对那些执行有用readdir ,像readdir.cMUSL的libc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM