Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.8 KiB

  1. /*
  2. * Copyright (c) 1983 Regents of the University of California.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by the University of
  16. * California, Berkeley and its contributors.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #ifdef DF_POSIX //MSS prototype for __P not in included .h's
  34. #include <sys/cdefs.h>
  35. #endif
  36. #if defined(LIBC_SCCS) && !defined(lint)
  37. static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
  38. #endif /* LIBC_SCCS and not lint */
  39. /*
  40. * Scan the directory dirname calling select to make a list of selected
  41. * directory entries then sort using qsort and compare routine dcomp.
  42. * Returns the number of entries and a pointer to a list of pointers to
  43. * struct dirent (through namelist). Returns -1 if there were any errors.
  44. */
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <dirent.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. extern void bcopy();
  51. /*
  52. * The DIRSIZ macro gives the minimum record length which will hold
  53. * the directory entry. This requires the amount of space in struct dirent
  54. * without the d_name field, plus enough space for the name with a terminating
  55. * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
  56. */
  57. #undef DIRSIZ
  58. #define DIRSIZ(dp) \
  59. ((sizeof (struct dirent) - (_POSIX_NAME_MAX+1)) + ((strlen((dp)->d_name)+1 + 3) &~ 3))
  60. int
  61. scandir(dirname, namelist, select, dcomp)
  62. const char *dirname;
  63. struct dirent ***namelist;
  64. int (*select) __P((struct dirent *));
  65. int (*dcomp) __P((const void *, const void *));
  66. {
  67. register struct dirent *d, *p, **names;
  68. register size_t nitems;
  69. struct stat stb;
  70. long arraysz;
  71. DIR *dirp;
  72. if ((dirp = opendir(dirname)) == NULL)
  73. return(-1);
  74. #ifndef _POSIX_SOURCE
  75. if (fstat(dirp->dd_fd, &stb) < 0)
  76. return(-1);
  77. #else
  78. stb.st_size = 1024;
  79. #endif
  80. /*
  81. * estimate the array size by taking the size of the directory file
  82. * and dividing it by a multiple of the minimum size entry.
  83. */
  84. arraysz = (stb.st_size / 24);
  85. names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
  86. if (names == NULL)
  87. return(-1);
  88. nitems = 0;
  89. while ((d = readdir(dirp)) != NULL) {
  90. if (select != NULL && !(*select)(d))
  91. continue; /* just selected names */
  92. /*
  93. * Make a minimum size copy of the data
  94. */
  95. p = (struct dirent *)malloc(DIRSIZ(d));
  96. if (p == NULL)
  97. return(-1);
  98. #ifndef _POSIX_SOURCE
  99. p->d_ino = d->d_ino;
  100. p->d_reclen = d->d_reclen;
  101. #endif
  102. #ifdef _POSIX_SOURCE
  103. bcopy(d->d_name, p->d_name, strlen(d->d_name) + 1);
  104. #else
  105. p->d_namlen = d->d_namlen;
  106. bcopy(d->d_name, p->d_name, p->d_namlen + 1);
  107. #endif
  108. /*
  109. * Check to make sure the array has space left and
  110. * realloc the maximum size.
  111. */
  112. if (++nitems >= (unsigned long)arraysz) {
  113. #ifndef _POSIX_SOURCE
  114. if (fstat(dirp->dd_fd, &stb) < 0)
  115. return(-1); /* just might have grown */
  116. #endif
  117. arraysz = stb.st_size / 12;
  118. names = (struct dirent **)realloc((char *)names,
  119. arraysz * sizeof(struct dirent *));
  120. if (names == NULL)
  121. return(-1);
  122. }
  123. names[nitems-1] = p;
  124. }
  125. closedir(dirp);
  126. if (nitems && dcomp != NULL)
  127. qsort(names, nitems, sizeof(struct dirent *), dcomp);
  128. *namelist = names;
  129. return(nitems);
  130. }
  131. /*
  132. * Alphabetic order comparison routine for those who want it.
  133. */
  134. int
  135. alphasort(d1, d2)
  136. const void *d1;
  137. const void *d2;
  138. {
  139. return(strcmp((*(struct dirent **)d1)->d_name,
  140. (*(struct dirent **)d2)->d_name));
  141. }