win32/compat/dirent.c
02daaed6
 /*
e1cbc270
  *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  *  Copyright (C) 2009-2013 Sourcefire, Inc.
02daaed6
  *
  *  Authors: aCaB <acab@clamav.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
  */
 
13829b14
 #include <errno.h>
c7ad4bea
 
60d8d2c3
 #include "clamav.h"
13829b14
 #include "others.h"
02daaed6
 #include "dirent.h"
72c63093
 #include "w32_stat.h"
13829b14
 #include "shared/misc.h"
02daaed6
 
288057e9
 DIR *opendir(const char *name)
 {
129911d6
     DIR *d;
     DWORD attrs;
     int len;
5387e64b
     struct stat sb;
72c63093
     wchar_t *wpath;
02daaed6
 
288057e9
     if (stat(name, &sb) < 0)
         return NULL;
72c63093
 
288057e9
     if (!S_ISDIR(sb.st_mode)) {
         errno = ENOTDIR;
         return NULL;
5387e64b
     }
288057e9
     if (!(d = cli_malloc(sizeof(*d)))) {
         errno = ENOMEM;
         return NULL;
129911d6
     }
72c63093
     wpath = uncpath(name);
288057e9
     if (!wpath)
         return NULL;
72c63093
     wcsncpy(d->entry, wpath, sizeof(d->entry) / sizeof(d->entry[0]));
     free(wpath);
     d->entry[sizeof(d->entry) / sizeof(d->entry[0])] = L'\0';
288057e9
     len                                              = wcslen(d->entry);
72c63093
 
288057e9
     if (len >= sizeof(d->entry) / sizeof(d->entry[0]) - 4) {
         free(d);
         errno = ENAMETOOLONG;
         return NULL;
129911d6
     }
288057e9
     while (len--) {
         if (d->entry[len] == L'\\')
             d->entry[len] = L'\0';
         else
             break;
129911d6
     }
72c63093
 
129911d6
     wcsncat(d->entry, L"\\*.*", 4);
     d->dh = INVALID_HANDLE_VALUE;
     return d;
 }
 
288057e9
 struct dirent *readdir(DIR *dirp)
 {
     while (1) {
         if (dirp->dh == INVALID_HANDLE_VALUE) {
             if ((dirp->dh = FindFirstFileW(dirp->entry, &dirp->wfd)) == INVALID_HANDLE_VALUE) {
                 errno = ENOENT;
                 return NULL;
             }
         } else {
             if (!(FindNextFileW(dirp->dh, &dirp->wfd))) {
                 errno = (GetLastError() == ERROR_NO_MORE_FILES) ? 0 : ENOENT;
                 return NULL;
             }
         }
         if (!WideCharToMultiByte(CP_UTF8, 0, dirp->wfd.cFileName, -1, dirp->ent.d_name, sizeof(dirp->ent.d_name), NULL, NULL))
             continue; /* FIXME: WARN HERE ! */
         dirp->ent.d_ino = dirp->wfd.ftCreationTime.dwLowDateTime ^ dirp->wfd.nFileSizeLow;
         if (!dirp->ent.d_ino) dirp->ent.d_ino = 0x1337;
         dirp->ent.d_type = (dirp->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
         break;
129911d6
     }
     return &dirp->ent;
13829b14
 }
 
288057e9
 void rewinddir(DIR *dirp)
 {
     if (dirp->dh != INVALID_HANDLE_VALUE)
         FindClose(dirp->dh);
129911d6
     dirp->dh = INVALID_HANDLE_VALUE;
13829b14
 }
 
288057e9
 int closedir(DIR *dirp)
 {
129911d6
     rewinddir(dirp);
     free(dirp);
     return 0;
c7ad4bea
 }