mirror of
https://github.com/logos-co/logos-protocol.git
synced 2026-09-02 06:51:14 +00:00
feat(windows): port logos_socket_paths and add a cross target
logos_socket_paths.cpp is the only POSIX-bound file in logos-protocol. All of it is unix-domain-socket machinery, and on Windows the local transport is named pipes (QLocalServer maps a name to \\.\pipe\<name>), where none of the assumptions hold: a pipe has no inode to lstat/chown/chmod -- access comes from a security descriptor set at CreateNamedPipe time -- and a pipe cannot outlive its last handle, so a hard-killed process leaves nothing behind. isSocketDead and reapStaleSockets are therefore not merely unimplemented on Windows, they are vacuous: the state they detect cannot arise. Both return the fail-closed answer (false / 0), matching the documented contract that an endpoint is never reported dead unless certain. applySocketPerms deliberately does NOT no-op. With no policy requested it returns true, as on POSIX. But when LOGOS_SOCKET_GROUP or LOGOS_SOCKET_MODE *are* set it fails with an explanatory error, because silently returning true would leave the endpoint more permissive than the operator asked for -- the one direction this file is careful never to go (cf. the chgrp-then-chmod ordering in the POSIX branch). Granting a pipe to a group needs a DACL plus a group->SID resolver; until that exists, refuse loudly. Also gates qt6.wrapQtAppsNoGuiHook behind !isWindows and sets dontWrapQtApps. Both halves are required: the hook does not even evaluate for a mingw host, it would be inert anyway (wrap-qt-apps-hook.sh skips anything that is not ELF or Mach-O), and qtbase's setup hook hard-errors in qtPreHook unless dontWrapQtApps is set. Header contract updated per function. POSIX branch unchanged and still compiles. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1e9c93434b
commit
a26de03070
@@ -7,6 +7,7 @@
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
@@ -15,9 +16,66 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace logos {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// On Windows the local transport is backed by NAMED PIPES: QLocalServer maps a
|
||||
// server name to \\.\pipe\<name>. Every assumption this file is built on is a
|
||||
// unix-domain-socket assumption, and none of them survives the move:
|
||||
//
|
||||
// * a pipe has no filesystem inode, so there is nothing to lstat, chown or
|
||||
// chmod — access is governed by a security descriptor supplied at
|
||||
// CreateNamedPipe time, not by mode bits;
|
||||
// * a pipe instance ceases to exist when its last handle closes, so a
|
||||
// hard-killed process cannot leave a stale endpoint behind. There is no
|
||||
// equivalent of the /tmp/logos_<name>_<instance> litter the reaper exists
|
||||
// to clean up.
|
||||
//
|
||||
// So isSocketDead/reapStaleSockets are not merely unimplemented here, they are
|
||||
// vacuous: the condition they detect cannot arise.
|
||||
|
||||
bool applySocketPerms(const std::string& absPath, std::string* errOut)
|
||||
{
|
||||
const char* grpEnv = std::getenv("LOGOS_SOCKET_GROUP");
|
||||
const char* modeEnv = std::getenv("LOGOS_SOCKET_MODE");
|
||||
const bool wantGroup = grpEnv && *grpEnv;
|
||||
const bool wantMode = modeEnv && *modeEnv;
|
||||
|
||||
// Policy unset is the overwhelmingly common case and is a genuine no-op.
|
||||
if (!wantGroup && !wantMode) return true;
|
||||
|
||||
// Policy SET, though, is a request we cannot honour. Returning true here
|
||||
// would silently widen access relative to what the operator asked for --
|
||||
// the one direction this file is careful never to go (see the chgrp-then-
|
||||
// chmod ordering in the POSIX branch). Granting a Windows pipe to a group
|
||||
// means building a DACL and resolving the group to a SID; until that
|
||||
// exists, refuse loudly rather than pretend.
|
||||
if (errOut) {
|
||||
*errOut = "LOGOS_SOCKET_GROUP/LOGOS_SOCKET_MODE are not supported on "
|
||||
"Windows: the local transport uses named pipes, which carry a "
|
||||
"security descriptor rather than owner/group/mode. Unset them, "
|
||||
"or run the node per-user (%LOCALAPPDATA%). Path: " + absPath;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSocketDead(const std::string& /*absPath*/)
|
||||
{
|
||||
// Fail closed, matching the documented contract: never report an endpoint
|
||||
// dead unless certain. A named pipe that still exists still has an owner.
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t reapStaleSockets(const std::string& /*dir*/, const std::string& /*prefix*/)
|
||||
{
|
||||
return 0; // named pipes leave nothing behind to reap
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace {
|
||||
|
||||
// Resolve a "group" env value to a gid. Accepts an all-digits string as a
|
||||
@@ -168,4 +226,6 @@ std::size_t reapStaleSockets(const std::string& dir, const std::string& prefix)
|
||||
return removed;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
} // namespace logos
|
||||
|
||||
Reference in New Issue
Block a user