我正在开发Cygwin,它既没有实现getdents,也没有实现getdirentries。
我正在处理的代码取决于知道读取的字节数,这是这些调用的返回。我似乎只有readdir。
Cygwin中缺少手册页。关于如何使这些接口兼容或如何从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];
};
编辑
使用
getdents
的code在功能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
syscall的返回中提供的。名称countde
可能代表“计数目录条目”。从循环中可以看到,
countde
的返回代表getdents
调用返回的条目数。循环中的每次迭代都会处理一个目录条目(de = (struct dirent*)p;
),然后找到下一个目录条目(p += de->d_reclen;
)。转换为使用
readdir
应该很简单,因为它只会返回一个条目。