OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [sysdeps/] [linux/] [common/] [getdents64.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* Copyright (C) 1993, 1995-2002 Free Software Foundation, Inc.
2
   This file is part of the GNU C Library.
3
 
4
   The GNU C Library is free software; you can redistribute it and/or
5
   modify it under the terms of the GNU Lesser General Public
6
   License as published by the Free Software Foundation; either
7
   version 2.1 of the License, or (at your option) any later version.
8
 
9
   The GNU C Library is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
   Lesser General Public License for more details.
13
 
14
   You should have received a copy of the GNU Lesser General Public
15
   License along with the GNU C Library; if not, write to the Free
16
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17
   02111-1307 USA.  */
18
 
19
#include <features.h>
20
#include <alloca.h>
21
#include <assert.h>
22
#include <errno.h>
23
#include <dirent.h>
24
#include <stddef.h>
25
#include <stdint.h>
26
#include <string.h>
27
#include <unistd.h>
28
#include <sysdep.h>
29
#include <sys/param.h>
30
#include <sys/types.h>
31
#include <sys/syscall.h>
32
 
33
#if defined __UCLIBC_HAS_LFS__ && defined __NR_getdents64 
34
 
35
 
36
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
37
 
38
struct kernel_dirent64
39
{
40
    uint64_t            d_ino;
41
    int64_t             d_off;
42
    unsigned short      d_reclen;
43
    unsigned char       d_type;
44
    char                d_name[256];
45
};
46
 
47
 
48
#define __NR___syscall_getdents64 __NR_getdents64
49
static inline _syscall3(int, __syscall_getdents64, int, fd, unsigned char *, dirp, size_t, count);
50
 
51
 
52
ssize_t __getdents64 (int fd, char *buf, size_t nbytes)
53
{
54
    struct dirent64 *dp;
55
    off64_t last_offset = -1;
56
    ssize_t retval;
57
    size_t red_nbytes;
58
    struct kernel_dirent64 *skdp, *kdp;
59
    const size_t size_diff = (offsetof (struct dirent64, d_name)
60
            - offsetof (struct kernel_dirent64, d_name));
61
 
62
    red_nbytes = MIN (nbytes - ((nbytes /
63
                    (offsetof (struct dirent64, d_name) + 14)) * size_diff),
64
            nbytes - size_diff);
65
 
66
    dp = (struct dirent64 *) buf;
67
    skdp = kdp = alloca (red_nbytes);
68
 
69
    retval = __syscall_getdents64(fd, (char *)kdp, red_nbytes);
70
    if (retval == -1)
71
        return -1;
72
 
73
    while ((char *) kdp < (char *) skdp + retval) {
74
        const size_t alignment = __alignof__ (struct dirent64);
75
        /* Since kdp->d_reclen is already aligned for the kernel structure
76
           this may compute a value that is bigger than necessary.  */
77
        size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
78
                & ~(alignment - 1));
79
        if ((char *) dp + new_reclen > buf + nbytes) {
80
            /* Our heuristic failed.  We read too many entries.  Reset
81
               the stream.  */
82
            assert (last_offset != -1);
83
            lseek64(fd, last_offset, SEEK_SET);
84
 
85
            if ((char *) dp == buf) {
86
                /* The buffer the user passed in is too small to hold even
87
                   one entry.  */
88
                __set_errno (EINVAL);
89
                return -1;
90
            }
91
            break;
92
        }
93
 
94
        last_offset = kdp->d_off;
95
        dp->d_ino = kdp->d_ino;
96
        dp->d_off = kdp->d_off;
97
        dp->d_reclen = new_reclen;
98
        dp->d_type = DT_UNKNOWN;
99
        memcpy (dp->d_name, kdp->d_name,
100
                kdp->d_reclen - offsetof (struct kernel_dirent64, d_name));
101
        dp = (struct dirent64 *) ((char *) dp + new_reclen);
102
        kdp = (struct kernel_dirent64 *) (((char *) kdp) + kdp->d_reclen);
103
    }
104
    return (char *) dp - buf;
105
}
106
#else
107
ssize_t __getdents (int fd, char *buf, size_t nbytes);
108
ssize_t __getdents64 (int fd, char *buf, size_t nbytes)
109
{
110
    return(__getdents(fd, buf, nbytes));
111
}
112
#endif /* __UCLIBC_HAS_LFS__ */
113
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.