1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler "\\\.ifnc \\\$r9-\\\$r10-\\\$r11-\\\$r12" } } */
/* Sanity check for asm register operands in syscall failed for
cris-axis-linux-gnu due to regmove bug.
Hans-Peter Nilsson <hp@axis.com>. */
extern void lseek64 (int, long long, int);
extern int *__errno_location (void);
struct dirent64
{
long long d_off;
unsigned short int d_reclen;
char d_name[256];
};
struct kernel_dirent64
{
long long d_off;
unsigned short d_reclen;
char d_name[256];
};
static inline int __attribute__ ((__always_inline__))
__syscall_getdents64 (int fd, char * dirp, unsigned count)
{
register unsigned long __sys_res asm ("r10");
register unsigned long __r10 __asm__ ("r10") = (unsigned long) fd;
register unsigned long __r11 __asm__ ("r11") = (unsigned long) dirp;
register unsigned long __r12 __asm__ ("r12") = (unsigned long) count;
register unsigned long __callno asm ("r9") = (220);
asm volatile (".ifnc %1-%0-%3-%4,$r9-$r10-$r11-$r12\n\t"
".err\n\t"
".endif\n\t"
"break 13"
: "=r" (__sys_res)
: "r" (__callno), "0" (__r10), "r" (__r11), "r" (__r12)
: "memory");
if (__sys_res >= (unsigned long) -4096)
{
(*__errno_location ()) = - __sys_res;
__sys_res = -1;
}
return __sys_res;
}
int
__getdents64 (int fd, char *buf, unsigned nbytes)
{
struct dirent64 *dp;
long long last_offset = -1;
int retval;
struct kernel_dirent64 *skdp, *kdp;
dp = (struct dirent64 *) buf;
skdp = kdp = __builtin_alloca (nbytes);
retval = __syscall_getdents64(fd, (char *)kdp, nbytes);
if (retval == -1)
return -1;
while ((char *) kdp < (char *) skdp + retval)
{
if ((char *) dp > buf + nbytes)
{
lseek64(fd, last_offset, 0);
break;
}
last_offset = kdp->d_off;
__builtin_memcpy (dp->d_name, kdp->d_name, kdp->d_reclen - 10);
dp = (struct dirent64 *) ((char *) dp + sizeof (*dp));
kdp = (struct kernel_dirent64 *) (((char *) kdp) + kdp->d_reclen);
}
return (char *) dp - buf;
}
|