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.

win32-glob.c 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* libSoX minimal glob for MS-Windows: (c) 2009 SoX contributors
  2. *
  3. * This library is free software; you can redistribute it and/or modify it
  4. * under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation; either version 2.1 of the License, or (at
  6. * your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
  11. * General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with this library; if not, write to the Free Software Foundation,
  15. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #include "win32-glob.h"
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <errno.h>
  21. #define WIN32_LEAN_AND_MEAN 1
  22. #include <windows.h>
  23. typedef struct file_entry
  24. {
  25. char name[MAX_PATH];
  26. struct file_entry *next;
  27. } file_entry;
  28. static int
  29. insert(
  30. const char* path,
  31. const char* name,
  32. file_entry** phead)
  33. {
  34. int len;
  35. file_entry* cur = malloc(sizeof(file_entry));
  36. if (!cur)
  37. {
  38. return ENOMEM;
  39. }
  40. len = _snprintf(cur->name, MAX_PATH, "%s%s", path, name);
  41. cur->name[MAX_PATH - 1] = 0;
  42. cur->next = *phead;
  43. *phead = cur;
  44. return len < 0 || len >= MAX_PATH ? ENAMETOOLONG : 0;
  45. }
  46. static int
  47. entry_comparer(
  48. const void* pv1,
  49. const void* pv2)
  50. {
  51. const file_entry* const * pe1 = pv1;
  52. const file_entry* const * pe2 = pv2;
  53. return _stricmp((*pe1)->name, (*pe2)->name);
  54. }
  55. int
  56. glob(
  57. const char *pattern,
  58. int flags,
  59. void *unused,
  60. glob_t *pglob)
  61. {
  62. char path[MAX_PATH];
  63. file_entry *head = NULL;
  64. int err = 0;
  65. size_t len;
  66. unsigned entries = 0;
  67. WIN32_FIND_DATAA finddata;
  68. HANDLE hfindfile = FindFirstFileA(pattern, &finddata);
  69. if (!pattern || flags != (flags & GLOB_FLAGS) || unused || !pglob)
  70. {
  71. errno = EINVAL;
  72. return EINVAL;
  73. }
  74. path[MAX_PATH - 1] = 0;
  75. strncpy(path, pattern, MAX_PATH);
  76. if (path[MAX_PATH - 1] != 0)
  77. {
  78. errno = ENAMETOOLONG;
  79. return ENAMETOOLONG;
  80. }
  81. len = strlen(path);
  82. while (len > 0 && path[len - 1] != '/' && path[len - 1] != '\\')
  83. len--;
  84. path[len] = 0;
  85. if (hfindfile == INVALID_HANDLE_VALUE)
  86. {
  87. if (flags & GLOB_NOCHECK)
  88. {
  89. err = insert("", pattern, &head);
  90. entries++;
  91. }
  92. }
  93. else
  94. {
  95. do
  96. {
  97. err = insert(path, finddata.cFileName, &head);
  98. entries++;
  99. } while (!err && FindNextFileA(hfindfile, &finddata));
  100. FindClose(hfindfile);
  101. }
  102. if (err == 0)
  103. {
  104. pglob->gl_pathv = malloc((entries + 1) * sizeof(char*));
  105. if (pglob->gl_pathv)
  106. {
  107. pglob->gl_pathc = entries;
  108. pglob->gl_pathv[entries] = NULL;
  109. for (; head; head = head->next, entries--)
  110. pglob->gl_pathv[entries - 1] = (char*)head;
  111. qsort(pglob->gl_pathv, pglob->gl_pathc, sizeof(char*), entry_comparer);
  112. }
  113. else
  114. {
  115. pglob->gl_pathc = 0;
  116. err = ENOMEM;
  117. }
  118. }
  119. else if (pglob)
  120. {
  121. pglob->gl_pathc = 0;
  122. pglob->gl_pathv = NULL;
  123. }
  124. if (err)
  125. {
  126. file_entry *cur;
  127. while (head)
  128. {
  129. cur = head;
  130. head = head->next;
  131. free(cur);
  132. }
  133. errno = err;
  134. }
  135. return err;
  136. }
  137. void
  138. globfree(
  139. glob_t* pglob)
  140. {
  141. if (pglob)
  142. {
  143. char** cur;
  144. for (cur = pglob->gl_pathv; *cur; cur++)
  145. {
  146. free(*cur);
  147. }
  148. pglob->gl_pathc = 0;
  149. pglob->gl_pathv = NULL;
  150. }
  151. }