转到使用getdents()列出Linux目录中的文件的代码

时间:2014-07-29 18:29:14

标签: c linux go system-calls

作为练习,我想将一些使用了很多系统调用的C代码翻译成Golang。我在Unix上发现了这个nice code example& Linux StackExchange:

/*
 * List directories using getdents() because ls, find and Python libraries
 * use readdir() which is slower (but uses getdents() underneath.
 *
 * Compile with 
 * ]$ gcc  getdents.c -o getdents
 */
#define _GNU_SOURCE
#include <dirent.h>     /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>

#define handle_error(msg) \
       do { perror(msg); exit(EXIT_FAILURE); } while (0)

struct linux_dirent {
   long           d_ino;
   off_t          d_off;
   unsigned short d_reclen;
   char           d_name[];
};

#define BUF_SIZE 1024*1024*5

int
main(int argc, char *argv[])
{
   int fd, nread;
   char buf[BUF_SIZE];
   struct linux_dirent *d;
   int bpos;
   char d_type;

   fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
   if (fd == -1)
       handle_error("open");

   for ( ; ; ) {
       nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
       if (nread == -1)
           handle_error("getdents");

       if (nread == 0)
           break;

       for (bpos = 0; bpos < nread;) {
           d = (struct linux_dirent *) (buf + bpos);
           d_type = *(buf + bpos + d->d_reclen - 1);
           if( d->d_ino != 0 && d_type == DT_REG ) {
              printf("%s\n", (char *)d->d_name );
           }
           bpos += d->d_reclen;
       }
   }

   exit(EXIT_SUCCESS);
}

我只能使用ioutil.ReadDir对此进行编码,这违背了目的。有没有人知道如何翻译这个?

1 个答案:

答案 0 :(得分:2)

我会避免使用此代码。如上所述,这是错误的:在32位系统上,甚至可能是某些64位系统,SYS_getdents是遗留的系统调用,它不提供d_type并且缺乏对64的支持-bit inode数字,这意味着你在现代文件系统上得到了无偿错误。即使你修复它,它也不比内联readdir更好,它在内部基本完全相同。