OSDN Git Service

- trim any trailing whitespace
[uclinux-h8/uClibc.git] / libc / misc / dirent / scandir64.c
1 /* Copyright (C) 1992-1998, 2000 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
20 /* Modified for uClibc by Erik Andersen
21    */
22
23 #include <_lfs_64.h>
24
25 #include <dirent.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include "dirstream.h"
32
33 /* Experimentally off - libc_hidden_proto(memcpy) */
34 libc_hidden_proto(opendir)
35 libc_hidden_proto(closedir)
36 libc_hidden_proto(qsort)
37 libc_hidden_proto(readdir64)
38
39 int scandir64(const char *dir, struct dirent64 ***namelist,
40         int (*selector) (const struct dirent64 *),
41         int (*compar) (const void *, const void *))
42 {
43     DIR *dp = opendir (dir);
44     struct dirent64 *current;
45     struct dirent64 **names = NULL;
46     size_t names_size = 0, pos;
47     int save;
48
49     if (dp == NULL)
50         return -1;
51
52     save = errno;
53     __set_errno (0);
54
55     pos = 0;
56     while ((current = readdir64 (dp)) != NULL)
57         if (selector == NULL || (*selector) (current))
58         {
59             struct dirent64 *vnew;
60             size_t dsize;
61
62             /* Ignore errors from selector or readdir64 */
63             __set_errno (0);
64
65             if (unlikely(pos == names_size))
66             {
67                 struct dirent64 **new;
68                 if (names_size == 0)
69                     names_size = 10;
70                 else
71                     names_size *= 2;
72                 new = (struct dirent64 **) realloc (names, names_size * sizeof (struct dirent64 *));
73                 if (new == NULL)
74                     break;
75                 names = new;
76             }
77
78             dsize = &current->d_name[_D_ALLOC_NAMLEN (current)] - (char *) current;
79             vnew = (struct dirent64 *) malloc (dsize);
80             if (vnew == NULL)
81                 break;
82
83             names[pos++] = (struct dirent64 *) memcpy (vnew, current, dsize);
84         }
85
86     if (unlikely(errno != 0))
87     {
88         save = errno;
89         closedir (dp);
90         while (pos > 0)
91             free (names[--pos]);
92         free (names);
93         __set_errno (save);
94         return -1;
95     }
96
97     closedir (dp);
98     __set_errno (save);
99
100     /* Sort the list if we have a comparison function to sort with.  */
101     if (compar != NULL)
102         qsort (names, pos, sizeof (struct dirent64 *), compar);
103     *namelist = names;
104     return pos;
105 }