Chardev-related fixes
Hi Here are some bug fixes worthy for 6.1. thanks -----BEGIN PGP SIGNATURE----- iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmEL3vMcHG1hcmNhbmRy ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5fe7D/0U6k36kb02MePc2OIW OVYijYm4/LiJQ0Tae5yKhvcaG81+sXyjJa3MvU2lscHrLxFsT0Li2N8cDx8Tozfy ob2URg/Wd8sBllze4QSqLlMqpX5Fh7GsKjx+3d+RzFzKW3BE8ZUoxTsRH0f1imd3 lZJmVbhvl5Bo65U0J5xp+VI4BZnEc9R/JHQOiUT+wnmwAbv4knjCz1LiW51LQvNP 2A8cHhftN58ogm3yptSfD/5OHfFsn+16uhhTRtjuiro+9+zuVgBqxJSXENsDhzDU IuL5J9MHhnhSv6/QB4zuVCYZfBlMLB1CXo3bFLalSN5wCAkCxrFEozPVjj2f9gR+ TrM1JxYK0CoAJZosHAlk1J+KGXZ4zs4Y3TyutFdLlhz9KYi4Xve3UYNQc8uK4jD8 7eXbaxTS0b9T1LYZd7YNbyKYuUeZJSt9dwGEXdudZPhp2lRjJ/Bhhkx0RLdR8LTX qcpemc14AwMUh0zaUcXPuxCeWEJO8ffJyVzXY5j36tSIt5LMecDqJHEqv4ZjWgyz mc9AMHRDtzRx0WPV3vNHEEIioXKOqARmWuuUaW5hUDdWue3f1wuU81xoMEN92DKs LftUgetgdqD9vbobtoiYFI7qIjb4IaKKK5TCn6glq4Poyd2tErl/fcjkO60/IZPR bzDygkxX8thipWkxQhTVBaaHVA== =KDK+ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/marcandre/tags/chr-fix-pull-request' into staging Chardev-related fixes Hi Here are some bug fixes worthy for 6.1. thanks # gpg: Signature made Thu 05 Aug 2021 13:52:03 BST # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] # Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5 * remotes/marcandre/tags/chr-fix-pull-request: chardev: report a simpler error about duplicated id chardev: give some context on chardev-add error chardev: fix qemu_chr_open_fd() with fd_in==fd_out chardev: fix qemu_chr_open_fd() being called with fd=-1 chardev: fix fd_chr_add_watch() when in != out chardev: mark explicitly first argument as poisoned chardev/socket: print a more correct command-line address util: fix abstract socket path copy Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
287d53398a
@ -28,6 +28,7 @@
|
|||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "chardev/char.h"
|
#include "chardev/char.h"
|
||||||
|
#include "chardev/char-fe.h"
|
||||||
#include "io/channel-file.h"
|
#include "io/channel-file.h"
|
||||||
|
|
||||||
#include "chardev/char-fd.h"
|
#include "chardev/char-fd.h"
|
||||||
@ -38,6 +39,10 @@ static int fd_chr_write(Chardev *chr, const uint8_t *buf, int len)
|
|||||||
{
|
{
|
||||||
FDChardev *s = FD_CHARDEV(chr);
|
FDChardev *s = FD_CHARDEV(chr);
|
||||||
|
|
||||||
|
if (!s->ioc_out) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return io_channel_send(s->ioc_out, buf, len);
|
return io_channel_send(s->ioc_out, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,10 +85,85 @@ static int fd_chr_read_poll(void *opaque)
|
|||||||
return s->max_size;
|
return s->max_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct FDSource {
|
||||||
|
GSource parent;
|
||||||
|
|
||||||
|
GIOCondition cond;
|
||||||
|
} FDSource;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fd_source_prepare(GSource *source,
|
||||||
|
gint *timeout_)
|
||||||
|
{
|
||||||
|
FDSource *src = (FDSource *)source;
|
||||||
|
|
||||||
|
return src->cond != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fd_source_check(GSource *source)
|
||||||
|
{
|
||||||
|
FDSource *src = (FDSource *)source;
|
||||||
|
|
||||||
|
return src->cond != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fd_source_dispatch(GSource *source, GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
FDSource *src = (FDSource *)source;
|
||||||
|
FEWatchFunc func = (FEWatchFunc)callback;
|
||||||
|
gboolean ret = G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
|
if (src->cond) {
|
||||||
|
ret = func(NULL, src->cond, user_data);
|
||||||
|
src->cond = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs fd_source_funcs = {
|
||||||
|
fd_source_prepare,
|
||||||
|
fd_source_check,
|
||||||
|
fd_source_dispatch,
|
||||||
|
NULL, NULL, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static GSource *fd_source_new(FDChardev *chr)
|
||||||
|
{
|
||||||
|
return g_source_new(&fd_source_funcs, sizeof(FDSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean child_func(GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
FDSource *parent = data;
|
||||||
|
|
||||||
|
parent->cond |= condition;
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GSource *fd_chr_add_watch(Chardev *chr, GIOCondition cond)
|
static GSource *fd_chr_add_watch(Chardev *chr, GIOCondition cond)
|
||||||
{
|
{
|
||||||
FDChardev *s = FD_CHARDEV(chr);
|
FDChardev *s = FD_CHARDEV(chr);
|
||||||
return qio_channel_create_watch(s->ioc_out, cond);
|
g_autoptr(GSource) source = fd_source_new(s);
|
||||||
|
|
||||||
|
if (s->ioc_out) {
|
||||||
|
g_autoptr(GSource) child = qio_channel_create_watch(s->ioc_out, cond & ~G_IO_IN);
|
||||||
|
g_source_set_callback(child, (GSourceFunc)child_func, source, NULL);
|
||||||
|
g_source_add_child_source(source, child);
|
||||||
|
}
|
||||||
|
if (s->ioc_in) {
|
||||||
|
g_autoptr(GSource) child = qio_channel_create_watch(s->ioc_in, cond & ~G_IO_OUT);
|
||||||
|
g_source_set_callback(child, (GSourceFunc)child_func, source, NULL);
|
||||||
|
g_source_add_child_source(source, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_steal_pointer(&source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fd_chr_update_read_handler(Chardev *chr)
|
static void fd_chr_update_read_handler(Chardev *chr)
|
||||||
@ -131,17 +211,32 @@ void qemu_chr_open_fd(Chardev *chr,
|
|||||||
int fd_in, int fd_out)
|
int fd_in, int fd_out)
|
||||||
{
|
{
|
||||||
FDChardev *s = FD_CHARDEV(chr);
|
FDChardev *s = FD_CHARDEV(chr);
|
||||||
char *name;
|
g_autofree char *name = NULL;
|
||||||
|
|
||||||
|
if (fd_out >= 0) {
|
||||||
|
qemu_set_nonblock(fd_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd_out == fd_in && fd_in >= 0) {
|
||||||
|
s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
|
||||||
|
name = g_strdup_printf("chardev-file-%s", chr->label);
|
||||||
|
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
|
||||||
|
s->ioc_out = QIO_CHANNEL(object_ref(s->ioc_in));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd_in >= 0) {
|
||||||
s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
|
s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
|
||||||
name = g_strdup_printf("chardev-file-in-%s", chr->label);
|
name = g_strdup_printf("chardev-file-in-%s", chr->label);
|
||||||
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
|
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
|
||||||
g_free(name);
|
}
|
||||||
|
|
||||||
|
if (fd_out >= 0) {
|
||||||
s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
|
s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
|
||||||
|
g_free(name);
|
||||||
name = g_strdup_printf("chardev-file-out-%s", chr->label);
|
name = g_strdup_printf("chardev-file-out-%s", chr->label);
|
||||||
qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
|
qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
|
||||||
g_free(name);
|
}
|
||||||
qemu_set_nonblock(fd_out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void char_fd_class_init(ObjectClass *oc, void *data)
|
static void char_fd_class_init(ObjectClass *oc, void *data)
|
||||||
|
@ -354,7 +354,7 @@ void qemu_chr_fe_set_open(CharBackend *be, int fe_open)
|
|||||||
}
|
}
|
||||||
|
|
||||||
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
||||||
GIOFunc func, void *user_data)
|
FEWatchFunc func, void *user_data)
|
||||||
{
|
{
|
||||||
Chardev *s = be->chr;
|
Chardev *s = be->chr;
|
||||||
GSource *src;
|
GSource *src;
|
||||||
|
@ -468,9 +468,9 @@ static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix)
|
|||||||
|
|
||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
if (sa->has_abstract && sa->abstract) {
|
if (sa->has_abstract && sa->abstract) {
|
||||||
abstract = ",abstract";
|
abstract = ",abstract=on";
|
||||||
if (sa->has_tight && sa->tight) {
|
if (sa->has_tight && sa->tight) {
|
||||||
tight = ",tight";
|
tight = ",tight=on";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1031,27 +1031,31 @@ Chardev *qemu_chardev_new(const char *id, const char *typename,
|
|||||||
ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
const ChardevClass *cc;
|
const ChardevClass *cc;
|
||||||
ChardevReturn *ret;
|
ChardevReturn *ret;
|
||||||
Chardev *chr;
|
g_autoptr(Chardev) chr = NULL;
|
||||||
|
|
||||||
|
if (qemu_chr_find(id)) {
|
||||||
|
error_setg(errp, "Chardev with id '%s' already exists", id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
|
cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
|
||||||
if (!cc) {
|
if (!cc) {
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
chr = chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
|
chr = chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
|
||||||
backend, NULL, false, errp);
|
backend, NULL, false, errp);
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
return NULL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!object_property_try_add_child(get_chardevs_root(), id, OBJECT(chr),
|
if (!object_property_try_add_child(get_chardevs_root(), id, OBJECT(chr),
|
||||||
errp)) {
|
errp)) {
|
||||||
object_unref(OBJECT(chr));
|
goto err;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
object_unref(OBJECT(chr));
|
|
||||||
|
|
||||||
ret = g_new0(ChardevReturn, 1);
|
ret = g_new0(ChardevReturn, 1);
|
||||||
if (CHARDEV_IS_PTY(chr)) {
|
if (CHARDEV_IS_PTY(chr)) {
|
||||||
@ -1060,6 +1064,10 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
error_prepend(errp, "Failed to add chardev '%s': ", id);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
|
ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
|
||||||
|
@ -288,7 +288,7 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
|
|||||||
uart_update_status(s);
|
uart_update_status(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
|
static gboolean cadence_uart_xmit(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
CadenceUARTState *s = opaque;
|
CadenceUARTState *s = opaque;
|
||||||
|
@ -191,7 +191,7 @@ static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
|
|||||||
/* Try to send tx data, and arrange to be called back later if
|
/* Try to send tx data, and arrange to be called back later if
|
||||||
* we can't (ie the char backend is busy/blocking).
|
* we can't (ie the char backend is busy/blocking).
|
||||||
*/
|
*/
|
||||||
static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
|
static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque)
|
||||||
{
|
{
|
||||||
CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
|
CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -135,7 +135,7 @@ static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
|
|||||||
ibex_uart_update_irqs(s);
|
ibex_uart_update_irqs(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
|
static gboolean ibex_uart_xmit(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
IbexUartState *s = opaque;
|
IbexUartState *s = opaque;
|
||||||
|
@ -75,7 +75,7 @@ static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
|
static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque)
|
||||||
{
|
{
|
||||||
NRF51UARTState *s = NRF51_UART(opaque);
|
NRF51UARTState *s = NRF51_UART(opaque);
|
||||||
int r;
|
int r;
|
||||||
|
@ -220,7 +220,7 @@ static void serial_update_msl(SerialState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond,
|
static gboolean serial_watch_cb(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
SerialState *s = opaque;
|
SerialState *s = opaque;
|
||||||
|
@ -38,7 +38,7 @@ struct VirtConsole {
|
|||||||
* Callback function that's called from chardevs when backend becomes
|
* Callback function that's called from chardevs when backend becomes
|
||||||
* writable.
|
* writable.
|
||||||
*/
|
*/
|
||||||
static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond,
|
static gboolean chr_write_unblocked(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = opaque;
|
VirtConsole *vcon = opaque;
|
||||||
|
@ -270,7 +270,7 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
|
static gboolean usbredir_write_unblocked(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
USBRedirDevice *dev = opaque;
|
USBRedirDevice *dev = opaque;
|
||||||
|
@ -303,7 +303,7 @@ struct vhost_user_read_cb_data {
|
|||||||
int ret;
|
int ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean vhost_user_read_cb(GIOChannel *source, GIOCondition condition,
|
static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition,
|
||||||
gpointer opaque)
|
gpointer opaque)
|
||||||
{
|
{
|
||||||
struct vhost_user_read_cb_data *data = opaque;
|
struct vhost_user_read_cb_data *data = opaque;
|
||||||
|
@ -174,6 +174,9 @@ void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
|
|||||||
void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
||||||
GCC_FMT_ATTR(2, 3);
|
GCC_FMT_ATTR(2, 3);
|
||||||
|
|
||||||
|
|
||||||
|
typedef gboolean (*FEWatchFunc)(void *do_not_use, GIOCondition condition, void *data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemu_chr_fe_add_watch:
|
* qemu_chr_fe_add_watch:
|
||||||
* @cond: the condition to poll for
|
* @cond: the condition to poll for
|
||||||
@ -188,10 +191,13 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
|||||||
* Note that you are responsible to update the front-end sources if
|
* Note that you are responsible to update the front-end sources if
|
||||||
* you are switching the main context with qemu_chr_fe_set_handlers().
|
* you are switching the main context with qemu_chr_fe_set_handlers().
|
||||||
*
|
*
|
||||||
|
* Warning: DO NOT use the first callback argument (it may be either
|
||||||
|
* a GIOChannel or a QIOChannel, depending on the underlying chardev)
|
||||||
|
*
|
||||||
* Returns: the source tag
|
* Returns: the source tag
|
||||||
*/
|
*/
|
||||||
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
||||||
GIOFunc func, void *user_data);
|
FEWatchFunc func, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemu_chr_fe_write:
|
* qemu_chr_fe_write:
|
||||||
|
@ -156,7 +156,7 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
|
|||||||
|
|
||||||
static void monitor_flush_locked(Monitor *mon);
|
static void monitor_flush_locked(Monitor *mon);
|
||||||
|
|
||||||
static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
|
static gboolean monitor_unblocked(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
Monitor *mon = opaque;
|
Monitor *mon = opaque;
|
||||||
|
@ -208,7 +208,7 @@ static NetClientInfo net_vhost_user_info = {
|
|||||||
.set_vnet_le = vhost_user_set_vnet_endianness,
|
.set_vnet_le = vhost_user_set_vnet_endianness,
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean net_vhost_user_watch(GIOChannel *chan, GIOCondition cond,
|
static gboolean net_vhost_user_watch(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
NetVhostUserState *s = opaque;
|
NetVhostUserState *s = opaque;
|
||||||
|
@ -1345,13 +1345,16 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
|
|||||||
SocketAddress *addr;
|
SocketAddress *addr;
|
||||||
struct sockaddr_un *su = (struct sockaddr_un *)sa;
|
struct sockaddr_un *su = (struct sockaddr_un *)sa;
|
||||||
|
|
||||||
|
assert(salen >= sizeof(su->sun_family) + 1 &&
|
||||||
|
salen <= sizeof(struct sockaddr_un));
|
||||||
|
|
||||||
addr = g_new0(SocketAddress, 1);
|
addr = g_new0(SocketAddress, 1);
|
||||||
addr->type = SOCKET_ADDRESS_TYPE_UNIX;
|
addr->type = SOCKET_ADDRESS_TYPE_UNIX;
|
||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
if (!su->sun_path[0]) {
|
if (!su->sun_path[0]) {
|
||||||
/* Linux abstract socket */
|
/* Linux abstract socket */
|
||||||
addr->u.q_unix.path = g_strndup(su->sun_path + 1,
|
addr->u.q_unix.path = g_strndup(su->sun_path + 1,
|
||||||
sizeof(su->sun_path) - 1);
|
salen - sizeof(su->sun_family) - 1);
|
||||||
addr->u.q_unix.has_abstract = true;
|
addr->u.q_unix.has_abstract = true;
|
||||||
addr->u.q_unix.abstract = true;
|
addr->u.q_unix.abstract = true;
|
||||||
addr->u.q_unix.has_tight = true;
|
addr->u.q_unix.has_tight = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user