win32/compat/dirent.c
02daaed6
 /*
c442ca9c
  *  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
 
 DIR *opendir(const char *name) {
129911d6
     DIR *d;
     DWORD attrs;
     int len;
5387e64b
     struct stat sb;
72c63093
     wchar_t *wpath;
02daaed6
 
72c63093
     if(stat(name, &sb) < 0)
5387e64b
 	return NULL;
72c63093
 
5387e64b
     if(!S_ISDIR(sb.st_mode)) {
 	errno = ENOTDIR;
 	return NULL;
     }
129911d6
     if(!(d = cli_malloc(sizeof(*d)))) {
 	errno = ENOMEM;
 	return NULL;
     }
72c63093
     wpath = uncpath(name);
     if(!wpath)
 	return NULL;
     wcsncpy(d->entry, wpath, sizeof(d->entry) / sizeof(d->entry[0]));
     free(wpath);
     d->entry[sizeof(d->entry) / sizeof(d->entry[0])] = L'\0';
     len = wcslen(d->entry);
 
     if(len >= sizeof(d->entry) / sizeof(d->entry[0]) - 4) {
129911d6
 	free(d);
72c63093
 	errno = ENAMETOOLONG;
129911d6
 	return NULL;
     }
72c63093
     while(len--) {
5387e64b
 	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;
 }
 
 struct dirent *readdir(DIR *dirp) {
     while(1) {
 	if(dirp->dh == INVALID_HANDLE_VALUE) {
 	    if((dirp->dh = FindFirstFileW(dirp->entry, &dirp->wfd)) == INVALID_HANDLE_VALUE) {
13829b14
 		errno = ENOENT;
 		return NULL;
129911d6
 	    }
 	} else {
 	    if(!(FindNextFileW(dirp->dh, &dirp->wfd))) {
 		errno = (GetLastError() == ERROR_NO_MORE_FILES) ? 0 : ENOENT;
13829b14
 		return NULL;
129911d6
 	    }
13829b14
 	}
b28d6bf0
 	if(!WideCharToMultiByte(CP_UTF8, 0, dirp->wfd.cFileName, -1, dirp->ent.d_name, sizeof(dirp->ent.d_name), NULL, NULL))
 	    continue;/* FIXME: WARN HERE ! */
129911d6
 	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;
     }
     return &dirp->ent;
13829b14
 }
 
 void rewinddir(DIR *dirp) {
129911d6
     if(dirp->dh != INVALID_HANDLE_VALUE)
 	FindClose(dirp->dh);
     dirp->dh = INVALID_HANDLE_VALUE;
13829b14
 }
 
 int closedir(DIR *dirp) {
129911d6
     rewinddir(dirp);
     free(dirp);
     return 0;
c7ad4bea
 }