Merge pull request #1 from jiegec/linux64-syscall

Workaround for tls and use getdents64 to implement fdopendir
master
Wang Runji 6 years ago committed by GitHub
commit fb9a1d5f70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -715,7 +715,9 @@ typedef struct {
struct dirent dents[]; struct dirent dents[];
} DIR; } DIR;
extern __thread int errno; // tls is not fully supported at the time
//extern __thread int errno;
extern int errno;
#define BUFSIZ 4096 #define BUFSIZ 4096
#define L_tmpnam 20 #define L_tmpnam 20

@ -53,6 +53,7 @@
#define SYS_SETRLIMIT 160 #define SYS_SETRLIMIT 160
#define SYS_SYNC 162 #define SYS_SYNC 162
#define SYS_REBOOT 169 #define SYS_REBOOT 169
#define SYS_GETDENTS64 217
#define SYS_NANOSLEEP 230 #define SYS_NANOSLEEP 230
#define SYS_PIPE2 293 #define SYS_PIPE2 293
#define SYS_PROF 31337 #define SYS_PROF 31337
@ -63,7 +64,9 @@
#define SYS_FUTEX 31342 #define SYS_FUTEX 31342
#define SYS_GETTID 31343 #define SYS_GETTID 31343
__thread int errno; // tls is not fully support at the time
//__thread int errno;
int errno;
static int dolock = 1; static int dolock = 1;
@ -579,6 +582,15 @@ reboot(void)
int ret = syscall(0, 0, 0, 0, 0, SYS_REBOOT); int ret = syscall(0, 0, 0, 0, 0, SYS_REBOOT);
ERRNO_NZ(ret); ERRNO_NZ(ret);
return ret; return ret;
}
ssize_t
getdents64(int fd, void *dirent, size_t count)
{
ssize_t ret = syscall(SA(fd), SA(dirent), SA(count), 0, 0, SYS_GETDENTS64);
ERRNO_NEG(ret);
return ret;
} }
ssize_t ssize_t
@ -955,6 +967,10 @@ _pcreate(void *vpcarg)
{ {
struct pcargs_t pcargs = *(struct pcargs_t *)vpcarg; struct pcargs_t pcargs = *(struct pcargs_t *)vpcarg;
free(vpcarg); free(vpcarg);
// use arch_prctl to set $fs manually
syscall(0x1002, (long)pcargs.tls, 0, 0, 0, 158);
long status; long status;
status = (long)(pcargs.fn(pcargs.arg)); status = (long)(pcargs.fn(pcargs.arg));
free(pcargs.tls); free(pcargs.tls);
@ -2255,20 +2271,24 @@ fdopendir(int fd)
if (lseek(fd, 0, SEEK_SET) == -1) if (lseek(fd, 0, SEEK_SET) == -1)
return NULL; return NULL;
// on disk format of directory entries // on disk format of directory entries
struct __attribute__((packed)) _dirent_t { struct __attribute__((packed)) _dirent64_t {
ulong inode;
ulong offset;
ushort reclen;
u8 type;
char name[_POSIX_NAME_MAX]; char name[_POSIX_NAME_MAX];
ulong inum;
}; };
const int nde = BSIZE/sizeof(struct _dirent_t);
size_t c = 0; size_t c = 0;
char buf[BSIZE]; char buf[BSIZE];
ssize_t r; ssize_t r;
while ((r = read(fd, buf, sizeof(buf))) > 0) { while ((r = getdents64(fd, buf, sizeof(buf))) > 0) {
int i; int i = 0;
for (i = 0; i < nde; i++) { while (i < r) {
struct _dirent_t *de = (struct _dirent_t *)buf + i; struct _dirent64_t *de = (struct _dirent64_t *)(buf + i);
if (de->name[0] != '\0') if (de->name[0] != '\0')
c++; c++;
i += de->reclen;
} }
} }
if (r == -1) if (r == -1)
@ -2286,16 +2306,17 @@ fdopendir(int fd)
if (lseek(fd, 0, SEEK_SET) == -1) if (lseek(fd, 0, SEEK_SET) == -1)
goto out; goto out;
struct dirent *p = &ret->dents[0]; struct dirent *p = &ret->dents[0];
while ((r = read(fd, buf, sizeof(buf))) > 0) { while ((r = getdents64(fd, buf, sizeof(buf))) > 0) {
int i; int i = 0;
for (i = 0; i < nde; i++) { while (i < r) {
struct _dirent_t *de = (struct _dirent_t *)buf + i; struct _dirent64_t *de = (struct _dirent64_t *)(buf + i);
if (de->name[0] != '\0') { if (de->name[0] != '\0') {
p->d_ino = de->inum; p->d_ino = de->inode;
strncpy(p->d_name, de->name, strncpy(p->d_name, de->name,
sizeof(p->d_name)); sizeof(p->d_name));
p++; p++;
} }
i += de->reclen;
} }
} }
if (r == -1) if (r == -1)
@ -2341,7 +2362,8 @@ readdir_r(DIR *d, struct dirent *entry, struct dirent **ret)
return 0; return 0;
} }
struct dirent *src = &d->dents[d->cent++]; struct dirent *src = &d->dents[d->cent++];
*entry = *src; // avoid sse instructions generated
memcpy(entry, src, sizeof(struct dirent));
*ret = entry; *ret = entry;
return 0; return 0;
} }

Loading…
Cancel
Save