mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-07 03:38:31 +00:00
Make improvements
- Introduce ualarm() function - Make rename() report EISEMPTY on Windows - Always raise EINVAL upon open(O_RDONLY|O_TRUNC) - Add macro so ./configure will detect SOCK_CLOEXEC - Fix O_TRUNC without O_CREAT not working on Windows - Let fcntl(F_SETFL) change O_APPEND status on Windows - Make sure pwrite() / pread() report ESPIPE on sockets - Raise ESPIPE on Windows when pwrite() is used on pipe - Properly compute O_APPEND CreateFile() flags on Windows - Don't require O_DIRECTORY to open directories on Windows - Fix more instances of Windows reporting EISDIR and ENOTDIR - Normalize EFTYPE and EMLINK to ELOOP on NetBSD and FreeBSD - Make unlink() / rmdir() work on read-only files on Windows - Validate UTF-8 on Windows paths to fix bug with overlong NUL - Always print signal name to stderr when crashing due to SIG_DFL - Fix Windows bug where denormalized paths >260 chars didn't work - Block signals on BSDs when thread exits before trashing its own stack
This commit is contained in:
parent
ec957491ea
commit
ebf784d4f5
76 changed files with 1019 additions and 568 deletions
|
@ -33,48 +33,7 @@
|
|||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
* Performs synchronization on directory of pathname.
|
||||
*
|
||||
* This code is intended to help prevent subsequent i/o operations
|
||||
* from failing for no reason at all. For example a unit test that
|
||||
* repeatedly opens and unlinks the same filename.
|
||||
*/
|
||||
static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX], int n) {
|
||||
int rc;
|
||||
int64_t fh;
|
||||
char16_t *p;
|
||||
if ((p = memrchr16(path, '\\', n))) {
|
||||
if (p - path == 2 && path[1] == ':') return 0; // XXX: avoid syncing volume
|
||||
*p = 0;
|
||||
} else {
|
||||
if (df != AT_FDCWD) {
|
||||
if (FlushFileBuffers(df)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
path[0] = '.';
|
||||
path[1] = 0;
|
||||
}
|
||||
if ((fh = CreateFile(
|
||||
path, kNtFileGenericWrite,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
|
||||
kNtOpenExisting, kNtFileAttributeNormal | kNtFileFlagBackupSemantics,
|
||||
0)) != -1) {
|
||||
if (FlushFileBuffers(fh)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
CloseHandle(fh);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows bool IsDirectorySymlink(const char16_t *path) {
|
||||
int e;
|
||||
|
@ -102,13 +61,11 @@ static textwindows int sys_rmdir_nt(const char16_t *path) {
|
|||
if (RemoveDirectory(path)) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Files can linger, for absolutely no reason.
|
||||
* Possibly some Windows Defender bug on Win7.
|
||||
* Sleep for up to one second w/ expo backoff.
|
||||
* Alternative is use Microsoft internal APIs.
|
||||
* Never could have imagined it'd be this bad.
|
||||
*/
|
||||
// Files can linger, for absolutely no reason.
|
||||
// Possibly some Windows Defender bug on Win7.
|
||||
// Sleep for up to one second w/ expo backoff.
|
||||
// Alternative is use Microsoft internal APIs.
|
||||
// Never could have imagined it'd be this bad.
|
||||
if (GetLastError() == kNtErrorDirNotEmpty && ms <= 2048) {
|
||||
errno = e;
|
||||
Sleep(ms);
|
||||
|
@ -130,19 +87,45 @@ static textwindows int sys_unlink_nt(const char16_t *path) {
|
|||
}
|
||||
}
|
||||
|
||||
textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) {
|
||||
int n, rc;
|
||||
char16_t path16[PATH_MAX];
|
||||
if ((n = __mkntpathat(dirfd, path, 0, path16)) == -1) {
|
||||
rc = -1;
|
||||
} else if (flags & AT_REMOVEDIR) {
|
||||
rc = sys_rmdir_nt(path16);
|
||||
textwindows int sys_unlinkat_nt_impl(const char16_t *path, int flags) {
|
||||
if (flags & AT_REMOVEDIR) {
|
||||
return sys_rmdir_nt(path);
|
||||
} else {
|
||||
rc = sys_unlink_nt(path16);
|
||||
if (rc != -1) {
|
||||
// TODO(jart): prove that it helps first
|
||||
// rc = SyncDirectory(dirfd, path16, n);
|
||||
return sys_unlink_nt(path);
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) {
|
||||
char16_t path16[PATH_MAX];
|
||||
|
||||
// check validity of flags
|
||||
if (flags & ~AT_REMOVEDIR) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
// translate unix to windows path
|
||||
int n;
|
||||
if ((n = __mkntpathat(dirfd, path, 0, path16)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// optimistic first attempt
|
||||
int e = errno;
|
||||
int rc = sys_unlinkat_nt_impl(path16, flags);
|
||||
|
||||
// reactively ensure unlink() deletes read-only files
|
||||
if (rc == -1 && errno == kNtErrorAccessDenied) {
|
||||
uint32_t attr;
|
||||
if ((attr = GetFileAttributes(path16)) != -1u &&
|
||||
(attr & kNtFileAttributeReadonly) &&
|
||||
SetFileAttributes(path16, attr & ~kNtFileAttributeReadonly)) {
|
||||
errno = e;
|
||||
rc = sys_unlinkat_nt_impl(path16, flags);
|
||||
} else {
|
||||
errno = kNtErrorAccessDenied;
|
||||
}
|
||||
}
|
||||
|
||||
// return status
|
||||
return __fix_enotdir(rc, path16);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue