/win32/compat/dirent.c

https://github.com/bogus/mydlp-host-win32 · C · 109 lines · 80 code · 9 blank · 20 comment · 22 complexity · 35b5944640c16c6246967369189acc04 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009 Sourcefire, Inc.
  3. *
  4. * Authors: aCaB <acab@clamav.net>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18. * MA 02110-1301, USA.
  19. */
  20. #include <errno.h>
  21. #include "others.h"
  22. #include "dirent.h"
  23. #include "w32_stat.h"
  24. #include "shared/misc.h"
  25. DIR *opendir(const char *name) {
  26. DIR *d;
  27. DWORD attrs;
  28. int len;
  29. struct stat sb;
  30. wchar_t *wpath;
  31. if(stat(name, &sb) < 0)
  32. return NULL;
  33. if(!S_ISDIR(sb.st_mode)) {
  34. errno = ENOTDIR;
  35. return NULL;
  36. }
  37. if(!(d = cli_malloc(sizeof(*d)))) {
  38. errno = ENOMEM;
  39. return NULL;
  40. }
  41. wpath = uncpath(name);
  42. if(!wpath)
  43. return NULL;
  44. wcsncpy(d->entry, wpath, sizeof(d->entry) / sizeof(d->entry[0]));
  45. free(wpath);
  46. d->entry[sizeof(d->entry) / sizeof(d->entry[0])] = L'\0';
  47. len = wcslen(d->entry);
  48. if(len >= sizeof(d->entry) / sizeof(d->entry[0]) - 4) {
  49. free(d);
  50. errno = ENAMETOOLONG;
  51. return NULL;
  52. }
  53. while(len--) {
  54. if(d->entry[len] == L'\\')
  55. d->entry[len] = L'\0';
  56. else
  57. break;
  58. }
  59. wcsncat(d->entry, L"\\*.*", 4);
  60. d->dh = INVALID_HANDLE_VALUE;
  61. return d;
  62. }
  63. struct dirent *readdir(DIR *dirp) {
  64. while(1) {
  65. BOOL cant_convert;
  66. if(dirp->dh == INVALID_HANDLE_VALUE) {
  67. if((dirp->dh = FindFirstFileW(dirp->entry, &dirp->wfd)) == INVALID_HANDLE_VALUE) {
  68. errno = ENOENT;
  69. return NULL;
  70. }
  71. } else {
  72. if(!(FindNextFileW(dirp->dh, &dirp->wfd))) {
  73. errno = (GetLastError() == ERROR_NO_MORE_FILES) ? 0 : ENOENT;
  74. return NULL;
  75. }
  76. }
  77. if(
  78. (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, dirp->wfd.cFileName, -1, dirp->ent.d_name, sizeof(dirp->ent.d_name), NULL, &cant_convert) || cant_convert) &&
  79. (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, dirp->wfd.cAlternateFileName, -1, dirp->ent.d_name, sizeof(dirp->ent.d_name), NULL, &cant_convert) || cant_convert)
  80. ) {
  81. /* FIXME: WARN HERE ! */
  82. continue;
  83. }
  84. dirp->ent.d_ino = dirp->wfd.ftCreationTime.dwLowDateTime ^ dirp->wfd.nFileSizeLow;
  85. if(!dirp->ent.d_ino) dirp->ent.d_ino = 0x1337;
  86. dirp->ent.d_type = (dirp->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
  87. break;
  88. }
  89. return &dirp->ent;
  90. }
  91. void rewinddir(DIR *dirp) {
  92. if(dirp->dh != INVALID_HANDLE_VALUE)
  93. FindClose(dirp->dh);
  94. dirp->dh = INVALID_HANDLE_VALUE;
  95. }
  96. int closedir(DIR *dirp) {
  97. rewinddir(dirp);
  98. free(dirp);
  99. return 0;
  100. }