diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-03-31 21:33:32 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-03-31 21:33:32 -0700 |
commit | c2c6c3c8c66855d9ccbe079015355ae8db8ff5e5 (patch) | |
tree | 379ebb7a4e9388d938b711256dba03d4c2d989a0 | |
parent | c27f83bdae5eb00206a478f7764df4fdaa48fc76 (diff) | |
download | txr-c2c6c3c8c66855d9ccbe079015355ae8db8ff5e5.tar.gz txr-c2c6c3c8c66855d9ccbe079015355ae8db8ff5e5.tar.bz2 txr-c2c6c3c8c66855d9ccbe079015355ae8db8ff5e5.zip |
Bugfix: support abstract UNIX socket addresses on Linux.
Making it work as already documented.
* socket.c (MIN): New macro.
(sockaddr_pack): Use utf8_dup_to_buf to convert
Unix socket path to a buffer of UTF-8 bytes, possibly with one
or more embedded null bytes. Copy as much of this as fits into
the sun_path member of struct sockaddr_un.
* txr.1: Improve documentation about the abstract names
on Linux.
-rw-r--r-- | socket.c | 7 | ||||
-rw-r--r-- | txr.1 | 38 |
2 files changed, 39 insertions, 6 deletions
@@ -51,6 +51,8 @@ #include "arith.h" #include "socket.h" +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + struct dgram_stream { struct strm_base a; val stream; @@ -244,11 +246,12 @@ static void sockaddr_pack(val sockaddr, val family, *len = sizeof *sa; } else if (addr_type == sockaddr_un_s) { val path = slot(sockaddr, path_s); - char *path_u8 = utf8_dup_to(c_str(path)); struct sockaddr_un *sa = coerce(struct sockaddr_un *, buf); + size_t size; + unsigned char *path_u8 = utf8_dup_to_buf(c_str(path), &size, 0); memset(sa, 0, sizeof *sa); sa->sun_family = AF_UNIX; - strncpy(sa->sun_path, path_u8, sizeof sa->sun_path - 1); + memcpy(sa->sun_path, path_u8, MIN(size, sizeof sa->sun_path)); free(path_u8); *len = sizeof *sa; } else { @@ -37932,10 +37932,40 @@ address family. This structure has only one slot, .code path which holds the rendezvous name for connecting pairs of socket endpoints. -This names appears in the filesystem. Linux systems have support for "abstract" -names which do not appear in the filesystem. These abstract names are distinguished -by starting with a null byte. In \*(TX, a null byte can be encoded in a string -using the pseudo-null code point U+DC00. +This name appears in the filesystem. + +When the +.code sockaddr-un +structure is converted to the C structure +.code "struct sockaddr_un" , +the +.code path +slot undergoes conversion to UTF-8. The resulting bytes are stored in the +.code sun_path +member of the C structure. If the resulting UTF-8 byte string +is larger than the +.code sun_path +array, it is silently truncated. + +Note: Linux systems have support for "abstract" names which do not appear in +the filesystem. These abstract names are distinguished by starting with a null +byte. For more information, consult Linux documentation. +This convention is supported in the +.code path +slot of the +.code sockaddr-un +structure. If +.code path +contains occurrences of the pseudo-null character U+DC00, these translate +to null bytes in the +.code sun_path +member of the corresponding C structure +.codn "struct sockaddr_un" . +For example, the path +.str "\exDC00;foo" +is valid and represents an abstract address consisting of the three bytes +.str "foo" +followed by null padding bytes. .coNP Structure @ addrinfo .synb |