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:
committed by
Dustin L. Howett
parent
ffde04f272
commit
50d44b4202
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <share.h>
|
||||
|
||||
#ifndef PRId64
|
||||
#define PRId64 "I64"
|
||||
|
||||
27
tar/write.c
27
tar/write.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user