5387e64b |
/*
* Copyright (C) 2009 Sourcefire, Inc.
*
* 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.
*/
|
72c63093 |
#include <errno.h> |
6e246c11 |
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h> |
72c63093 |
|
5387e64b |
#include "others.h" |
72c63093 |
#include "shared/misc.h" |
5387e64b |
|
72c63093 |
wchar_t *uncpath(const char *path) {
DWORD len = 0;
wchar_t *dest = cli_malloc((PATH_MAX + 1) * sizeof(wchar_t));
if(!dest)
return NULL;
if(strncmp(path, "\\\\", 2)) {
/* NOT already UNC */
memcpy(dest, L"\\\\?\\", 8);
if(!cli_is_abspath(path)) {
/* Relative path */
len = GetCurrentDirectoryW(PATH_MAX - 5, &dest[4]);
if(!len || len > PATH_MAX - 5) {
free(dest);
errno = (len || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ? ENAMETOOLONG : ENOENT;
return NULL;
}
len += 4;
dest[len] = L'\\';
len++;
} else {
/* C:\ and friends */
len = 4;
}
} else {
/* UNC already */
len = 0; |
5387e64b |
} |
72c63093 |
if(!(len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, path, -1, &dest[len], PATH_MAX - len)) || len > PATH_MAX - len) {
free(dest);
errno = (len || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ? ENAMETOOLONG : ENOENT;
return NULL; |
5387e64b |
} |
72c63093 |
len = wcslen(dest);
if(len == 6 && !wcsncmp(dest, L"\\\\?\\", 4) && (dest[5] == L':') && ((dest[4] >= L'A' && dest[4] <= L'Z') || (dest[4] >= L'a' && dest[4] <= L'z'))) {
dest[6] = L'\\';
dest[7] = L'\0'; |
5387e64b |
} |
72c63093 |
return dest;
}
|
6e246c11 |
int safe_open(const char *path, int flags, ... ) {
wchar_t *wpath = uncpath(path);
int ret;
if(!wpath)
return -1;
if(flags & O_CREAT) {
int mode;
va_list ap;
va_start(ap, flags);
mode = va_arg(ap, int);
va_end(ap);
ret = _wopen(wpath, flags, mode);
} else
ret = _wopen(wpath, flags);
free(wpath);
return ret;
}
|
72c63093 |
w32_stat(const char *path, struct stat *buf) {
int len;
wchar_t *wpath = uncpath(path);
WIN32_FILE_ATTRIBUTE_DATA attrs;
if(!wpath)
return -1;
len = wcslen(wpath);
if(len > 2 && wpath[len-1] == L'.' && wpath[len-2] == L'\\')
wpath[len-2] = L'\0'; /* windoze can't stat '.' ... */ |
5387e64b |
len = GetFileAttributesExW(wpath, GetFileExInfoStandard, &attrs);
free(wpath);
if(!len) { |
72c63093 |
len = GetLastError(); |
5387e64b |
errno = ENOENT;
return -1;
}
buf->st_dev = 1;
buf->st_rdev = 1;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_ino = 1;
buf->st_atime = ((time_t)attrs.ftLastAccessTime.dwHighDateTime<<32) | attrs.ftLastAccessTime.dwLowDateTime;
buf->st_ctime = ((time_t)attrs.ftCreationTime.dwHighDateTime<<32) | attrs.ftCreationTime.dwLowDateTime;
buf->st_mtime = ((time_t)attrs.ftLastWriteTime.dwHighDateTime<<32) | attrs.ftLastWriteTime.dwLowDateTime;
buf->st_mode = (attrs.dwFileAttributes == FILE_ATTRIBUTE_READONLY) ? S_IRUSR: S_IWUSR;
buf->st_mode |= (attrs.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG;
buf->st_nlink = 1;
buf->st_size = ((uint64_t)attrs.nFileSizeHigh << (sizeof(attrs.nFileSizeLow)*8)) | attrs.nFileSizeLow;
return 0;
} |