mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-04 19:52:28 +00:00
Share file offset across processes
This change ensures that if a file descriptor for an open disk file gets shared by multiple processes within a process tree, then lseek() changes will be visible across processes, and read() / write() are synchronized. Note this only applies to Windows, because UNIX kernels already do this.
This commit is contained in:
parent
a80ab3f8fe
commit
761c6ad615
15 changed files with 256 additions and 63 deletions
|
@ -62,9 +62,10 @@ static dontinline textwindows ssize_t sys_sendfile_nt(
|
|||
int outfd, int infd, int64_t *opt_in_out_inoffset, uint32_t uptobytes) {
|
||||
ssize_t rc;
|
||||
uint32_t flags = 0;
|
||||
bool locked = false;
|
||||
int64_t ih, oh, eof, offset;
|
||||
struct NtByHandleFileInformation wst;
|
||||
if (!__isfdkind(infd, kFdFile))
|
||||
if (!__isfdkind(infd, kFdFile) || !g_fds.p[infd].shared)
|
||||
return ebadf();
|
||||
if (!__isfdkind(outfd, kFdSocket))
|
||||
return ebadf();
|
||||
|
@ -73,7 +74,9 @@ static dontinline textwindows ssize_t sys_sendfile_nt(
|
|||
if (opt_in_out_inoffset) {
|
||||
offset = *opt_in_out_inoffset;
|
||||
} else {
|
||||
offset = g_fds.p[infd].pointer;
|
||||
locked = true;
|
||||
__fd_lock(&g_fds.p[infd]);
|
||||
offset = g_fds.p[infd].shared->pointer;
|
||||
}
|
||||
if (GetFileInformationByHandle(ih, &wst)) {
|
||||
// TransmitFile() returns EINVAL if `uptobytes` goes past EOF.
|
||||
|
@ -82,9 +85,10 @@ static dontinline textwindows ssize_t sys_sendfile_nt(
|
|||
uptobytes = eof - offset;
|
||||
}
|
||||
} else {
|
||||
if (locked)
|
||||
__fd_unlock(&g_fds.p[infd]);
|
||||
return ebadf();
|
||||
}
|
||||
BLOCK_SIGNALS;
|
||||
struct NtOverlapped ov = {.hEvent = WSACreateEvent(), .Pointer = offset};
|
||||
cosmo_once(&g_transmitfile.once, transmitfile_init);
|
||||
if (g_transmitfile.lpTransmitFile(oh, ih, uptobytes, 0, &ov, 0, 0) ||
|
||||
|
@ -95,7 +99,7 @@ static dontinline textwindows ssize_t sys_sendfile_nt(
|
|||
if (opt_in_out_inoffset) {
|
||||
*opt_in_out_inoffset = offset + rc;
|
||||
} else {
|
||||
g_fds.p[infd].pointer = offset + rc;
|
||||
g_fds.p[infd].shared->pointer = offset + rc;
|
||||
}
|
||||
} else {
|
||||
rc = __winsockerr();
|
||||
|
@ -103,8 +107,9 @@ static dontinline textwindows ssize_t sys_sendfile_nt(
|
|||
} else {
|
||||
rc = __winsockerr();
|
||||
}
|
||||
if (locked)
|
||||
__fd_unlock(&g_fds.p[infd]);
|
||||
WSACloseEvent(ov.hEvent);
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -186,7 +191,9 @@ ssize_t sendfile(int outfd, int infd, int64_t *opt_in_out_inoffset,
|
|||
} else if (IsFreebsd() || IsXnu()) {
|
||||
rc = sys_sendfile_bsd(outfd, infd, opt_in_out_inoffset, uptobytes);
|
||||
} else if (IsWindows()) {
|
||||
BLOCK_SIGNALS;
|
||||
rc = sys_sendfile_nt(outfd, infd, opt_in_out_inoffset, uptobytes);
|
||||
ALLOW_SIGNALS;
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue