Skip to content

Commit ecbed1d

Browse files
committed
bind: give same treatment as connect in NixOS#8544, dedup
It is good to propogate the underlying error so whether or not we use a proccess to deal with path length issues is not observable. Also, as these helper functions got more and more complex, the code duplication got worse and worse. Deduplicate.
1 parent 7115edc commit ecbed1d

File tree

1 file changed

+24
-39
lines changed

1 file changed

+24
-39
lines changed

src/libutil/unix-domain-socket.cc

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,39 +38,10 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
3838
return fdSocket;
3939
}
4040

41-
42-
void bind(int fd, const std::string & path)
43-
{
44-
unlink(path.c_str());
45-
46-
struct sockaddr_un addr;
47-
addr.sun_family = AF_UNIX;
48-
49-
if (path.size() + 1 >= sizeof(addr.sun_path)) {
50-
Pid pid = startProcess([&]() {
51-
Path dir = dirOf(path);
52-
if (chdir(dir.c_str()) == -1)
53-
throw SysError("chdir to '%s' failed", dir);
54-
std::string base(baseNameOf(path));
55-
if (base.size() + 1 >= sizeof(addr.sun_path))
56-
throw Error("socket path '%s' is too long", base);
57-
memcpy(addr.sun_path, base.c_str(), base.size() + 1);
58-
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
59-
throw SysError("cannot bind to socket '%s'", path);
60-
_exit(0);
61-
});
62-
int status = pid.wait();
63-
if (status != 0)
64-
throw Error("cannot bind to socket '%s'", path);
65-
} else {
66-
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
67-
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
68-
throw SysError("cannot bind to socket '%s'", path);
69-
}
70-
}
71-
72-
73-
void connect(int fd, const std::string & path)
41+
static void bindConnectProcHelper(
42+
std::string_view operationName, auto && operation,
43+
int fd, const std::string & path
44+
)
7445
{
7546
struct sockaddr_un addr;
7647
addr.sun_family = AF_UNIX;
@@ -88,8 +59,8 @@ void connect(int fd, const std::string & path)
8859
if (base.size() + 1 >= sizeof(addr.sun_path))
8960
throw Error("socket path '%s' is too long", base);
9061
memcpy(addr.sun_path, base.c_str(), base.size() + 1);
91-
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
92-
throw SysError("cannot connect to socket at '%s'", path);
62+
if (operation(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
63+
throw SysError("cannot %s to socket at '%s'", operationName, path);
9364
writeFull(pipe.writeSide.get(), "0\n");
9465
} catch (SysError & e) {
9566
writeFull(pipe.writeSide.get(), fmt("%d\n", e.errNo));
@@ -100,16 +71,30 @@ void connect(int fd, const std::string & path)
10071
pipe.writeSide.close();
10172
auto errNo = string2Int<int>(chomp(drainFD(pipe.readSide.get())));
10273
if (!errNo || *errNo == -1)
103-
throw Error("cannot connect to socket at '%s'", path);
74+
throw Error("cannot %s to socket at '%s'", operationName, path);
10475
else if (*errNo > 0) {
10576
errno = *errNo;
106-
throw SysError("cannot connect to socket at '%s'", path);
77+
throw SysError("cannot %s to socket at '%s'", operationName, path);
10778
}
10879
} else {
10980
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
110-
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
111-
throw SysError("cannot connect to socket at '%s'", path);
81+
if (operation(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
82+
throw SysError("cannot %s to socket at '%s'", operationName, path);
11283
}
84+
85+
}
86+
87+
void bind(int fd, const std::string & path)
88+
{
89+
unlink(path.c_str());
90+
91+
bindConnectProcHelper("bind", ::bind, fd, path);
92+
}
93+
94+
95+
void connect(int fd, const std::string & path)
96+
{
97+
bindConnectProcHelper("connect", ::connect, fd, path);
11398
}
11499

115100
}

0 commit comments

Comments
 (0)