0
0
mirror of https://github.com/libarchive/libarchive.git synced 2026-01-18 17:11:25 +01:00

win32: shim wopen, and make both open/wopen use _s "secure" variant

The new `__la_wopen` wrapper is a copy of `__la_open` that
expects--rather than converts--a wcs parameter.

The `sopen` variants are offered as "more secure" variants of `open` and
`wopen`; I cannot vouch for their security, but some build systems are
strict about the use of "banned insecure APIs".

I've confirmed that `_wsopen_s` and `_open_s` are present in the Windows
Vista SDK.

I did not confirm that they are available in the Windows XP Platform
SDK, in part because in e61afbd463 (2016!) Tim says:

> I'd like to completely remove support for WinXP and earlier.
This commit is contained in:
Dustin Howett
2021-10-15 17:47:53 -05:00
committed by Dustin L. Howett
parent ffde04f272
commit 50d44b4202
4 changed files with 122 additions and 3 deletions

View File

@@ -313,6 +313,10 @@ __la_open(const char *path, int flags, ...)
pmode = va_arg(ap, int);
va_end(ap);
ws = NULL;
/* _(w)sopen_s fails if we provide any other modes */
pmode = pmode & (_S_IREAD | _S_IWRITE);
if ((flags & ~O_BINARY) == O_RDONLY) {
/*
* When we open a directory, _open function returns
@@ -374,7 +378,7 @@ __la_open(const char *path, int flags, ...)
TODO: Fix mode of new file. */
r = _open(path, flags);
#else
r = _open(path, flags, pmode);
_sopen_s(&r, path, flags, _SH_DENYNO, pmode);
#endif
if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
/* Simulate other POSIX system action to pass our test suite. */
@@ -395,7 +399,7 @@ __la_open(const char *path, int flags, ...)
return (-1);
}
}
r = _wopen(ws, flags, pmode);
_wsopen_s(&r, ws, flags, _SH_DENYNO, pmode);
if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
/* Simulate other POSIX system action to pass our test suite. */
attr = GetFileAttributesW(ws);
@@ -410,6 +414,93 @@ __la_open(const char *path, int flags, ...)
return (r);
}
int
__la_wopen(const wchar_t *path, int flags, ...)
{
va_list ap;
wchar_t *fullpath;
int r, pmode;
DWORD attr;
va_start(ap, flags);
pmode = va_arg(ap, int);
va_end(ap);
fullpath = NULL;
/* _(w)sopen_s fails if we provide any other modes */
pmode = pmode & (_S_IREAD | _S_IWRITE);
if ((flags & ~O_BINARY) == O_RDONLY) {
/*
* When we open a directory, _open function returns
* "Permission denied" error.
*/
attr = GetFileAttributesW(path);
#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND)
#endif
{
fullpath = __la_win_permissive_name_w(path);
if (fullpath == NULL) {
errno = EINVAL;
return (-1);
}
path = fullpath;
attr = GetFileAttributesW(fullpath);
}
if (attr == (DWORD)-1) {
la_dosmaperr(GetLastError());
free(fullpath);
return (-1);
}
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
HANDLE handle;
#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
if (fullpath != NULL)
handle = CreateFileW(fullpath, 0, 0, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_ATTRIBUTE_READONLY,
NULL);
else
handle = CreateFileW(path, 0, 0, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_ATTRIBUTE_READONLY,
NULL);
#else /* !WINAPI_PARTITION_DESKTOP */
CREATEFILE2_EXTENDED_PARAMETERS createExParams;
ZeroMemory(&createExParams, sizeof(createExParams));
createExParams.dwSize = sizeof(createExParams);
createExParams.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
handle = CreateFile2(fullpath, 0, 0,
OPEN_EXISTING, &createExParams);
#endif /* !WINAPI_PARTITION_DESKTOP */
free(fullpath);
if (handle == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
return (-1);
}
r = _open_osfhandle((intptr_t)handle, _O_RDONLY);
return (r);
}
}
_wsopen_s(&r, path, flags, _SH_DENYNO, pmode);
if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
/* Simulate other POSIX system action to pass our test suite. */
attr = GetFileAttributesW(path);
if (attr == (DWORD)-1)
la_dosmaperr(GetLastError());
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
errno = EISDIR;
else
errno = EACCES;
}
free(fullpath);
return (r);
}
ssize_t
__la_read(int fd, void *buf, size_t nbytes)
{

View File

@@ -106,6 +106,7 @@
#endif
#define lstat __la_stat
#define open __la_open
#define _wopen __la_wopen
#define read __la_read
#if !defined(__BORLANDC__) && !defined(__WATCOMC__)
#define setmode _setmode
@@ -269,6 +270,7 @@ extern int __la_lstat(const char *path, struct stat *st);
extern __int64 __la_lseek(int fd, __int64 offset, int whence);
#endif
extern int __la_open(const char *path, int flags, ...);
extern int __la_wopen(const wchar_t *path, int flags, ...);
extern ssize_t __la_read(int fd, void *buf, size_t nbytes);
extern int __la_stat(const char *path, struct stat *st);
extern pid_t __la_waitpid(HANDLE child, int *status, int option);

View File

@@ -11,6 +11,7 @@
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <share.h>
#ifndef PRId64
#define PRId64 "I64"

View File

@@ -111,7 +111,32 @@ seek_file(int fd, int64_t offset, int whence)
return (SetFilePointerEx((HANDLE)_get_osfhandle(fd),
distance, NULL, FILE_BEGIN) ? 1 : -1);
}
#define open _open
static int
_open_wrap_sopen(char const *const path, int const oflag, ...)
{
va_list ap;
int r, pmode;
pmode = 0;
if (oflag & _O_CREAT)
{
va_start(ap, oflag);
pmode = va_arg(ap, int);
va_end(ap);
}
_sopen_s(&r, path, oflag, _SH_DENYNO, pmode & 0600);
if (r < 0)
{
/* _sopen_s populates errno */
return -1;
}
return r;
}
#define open _open_wrap_sopen
#define close _close
#define read _read
#ifdef lseek