c - readdir 和 getdents 接口(interface)——读取的字节数?

标签 c unix posix

我正在开发 Cygwin,它没有实现 getdents ,也不是 getdirentries .

我正在处理的代码依赖于了解读取的字节数,这是这些调用的返回值。我似乎只有readdir .

Cygwin 中缺少手册页。关于如何使这些接口(interface)兼容或如何获取从 readdir 读取的字节数的任何想法或现有文档?

Cygwin 的 struct dirent,如果相关的话:

struct dirent
{
  uint32_t __d_version;                 /* Used internally */
  ino_t d_ino;
  unsigned char d_type;
  unsigned char __d_unused1[3];
  __uint32_t __d_internal1;
  char d_name[NAME_MAX + 1];
};

编辑

code使用 getdents 位于函数 readdir 中(请参阅完整文件的链接):

static int
mygetdents(int fd, struct dirent *buf, int n) {
  return syscall (getdents, fd, (void*) buf, n);
}

long
dirread(int fd, Dir **dp)
{
    char *buf;
    struct stat st;
    int n;

    *dp = 0;

    if(fstat(fd, &st) < 0)
        return -1;

    if(st.st_blksize < 8192)
        st.st_blksize = 8192;

    buf = malloc(st.st_blksize);
    if(buf == nil)
        return -1;

    n = mygetdents(fd, (void*)buf, st.st_blksize);
    if(n < 0){
        free(buf);
        return -1;
    }
    n = dirpackage(fd, buf, n, dp);
    free(buf);
    return n;
}

static int
dirpackage(int fd, char *buf, int n, Dir **dp)
{
    int oldwd;
    char *p, *str, *estr;
    int i, nstr, m;
    struct dirent *de;
    struct stat st, lst;
    Dir *d;

    n = countde(buf, n);
    if(n <= 0)
        return n;

    if((oldwd = open(".", O_RDONLY)) < 0)
        return -1;
    if(fchdir(fd) < 0)
        return -1;

    p = buf;
    nstr = 0;

    for(i=0; i<n; i++){
        de = (struct dirent*)p;
        memset(&lst, 0, sizeof lst);
        if(de->d_name[0] == 0)
            /* nothing */ {}
        else if(lstat(de->d_name, &lst) < 0)
            de->d_name[0] = 0;
        else{
            st = lst;
            if(S_ISLNK(lst.st_mode))
                stat(de->d_name, &st);
            nstr += _p9dir(&lst, &st, de->d_name, nil, nil, nil);
        }
        p += de->d_reclen;
    }

    d = malloc(sizeof(Dir)*n+nstr);
    if(d == nil){
        fchdir(oldwd);
        close(oldwd);
        return -1;
    }
    str = (char*)&d[n];
    estr = str+nstr;

    p = buf;
    m = 0;
    for(i=0; i<n; i++){
        de = (struct dirent*)p;
        if(de->d_name[0] != 0 && lstat(de->d_name, &lst) >= 0){
            st = lst;
            if((lst.st_mode&S_IFMT) == S_IFLNK)
                stat(de->d_name, &st);
            _p9dir(&lst, &st, de->d_name, &d[m++], &str, estr);
        }
        p += de->d_reclen;
    }

    fchdir(oldwd);
    close(oldwd);
    *dp = d;
    return m;
}

static int
countde(char *p, int n)
{
    char *e;
    int m;
    struct dirent *de;

    e = p+n;
    m = 0;
    while(p < e){
        de = (struct dirent*)p;
        if(de->d_reclen <= 4+2+2+1 || p+de->d_reclen > e)
            break;
        if(de->d_name[0]=='.' && de->d_name[1]==0)
            de->d_name[0] = 0;
        else if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)
            de->d_name[0] = 0;
        m++;
        p += de->d_reclen;
    }
    return m;
}

我还没有理解dirpackage,但我认为如果我能得到getdents的返回,我可能会绕过这个细节> 以另一种方式。

最佳答案

从您发布到 dirpackage 方法的链接:

for(i=0; i<n; i++){
    de = (struct dirent*)p;
    memset(&lst, 0, sizeof lst);
    if(de->d_name[0] == 0)
        /* nothing */ {}
    else if(lstat(de->d_name, &lst) < 0)
        de->d_name[0] = 0;
    else{
        st = lst;
        if(S_ISLNK(lst.st_mode))
            stat(de->d_name, &st);
        nstr += _p9dir(&lst, &st, de->d_name, nil, nil, nil);
    }
    p += de->d_reclen;
}

这里n来自:

n = countde(buf, n);

...其中 n 的原始值由 getdents 系统调用的返回值提供。名称 countde 可能代表“计数目录条目”。

正如您从循环中看到的,countde 的返回值表示getdents 调用返回的条目数。循环中的每次迭代都会处理一个目录条目 (de = (struct dirent*)p;),然后查找下一个目录条目 (p += de->d_reclen;) .

这应该非常简单地转换为使用 readdir,因为它只返回一个条目。

关于c - readdir 和 getdents 接口(interface)——读取的字节数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37354526/

相关文章:

c++ - pselect() 无法识别具有任何 IO 事件的套接字

c - 为什么有些函数既返回返回值又返回写入指针传递的结果?

c++ - 通过套接字进行数据传输[TCP]如何在c/c++中打包多个整数并使用send()recv()传输数据?

关于 Char 数组到 Unsigned Long 的困惑

c++ - 如何等待命名管道的另一端打开?

linux - 从文本文件中指定的位置复制文件或将文件复制到文本文件中指定的位置

unix - sed 或 awk : delete n lines following a pattern

c - 结构指针总是被初始化为 nil

c - 位操作

linux - POSIX 共享内存和信号量权限由 open 调用错误设置