Message ID | 1357564549-18031-1-git-send-email-alexander_barabash@mentor.com |
---|---|
State | New |
Headers | show |
Alexander Barabash <alexander_barabash@mentor.com> writes: > The abstract socket namespace is a nonportable Linux extension. > The sockets' names in this namespace have no connection > with file system pathnames. To specify a named AF_UNIX socket > in the abstract socket namespace, start the socket's path option > with a backslash followed by zero: \0. > > Signed-off-by: Alexander Barabash <alexander_barabash@mentor.com> Magic interpretation of path names is a bad thing in general. I think it would be better to add a flag 'abstract=on' which indicates to use the abstract namespace. As an example: qemu -chardev foo,path=bar,abstract=on vs: qemu -chardev foo,path="\\\\0bar" I think the former is quite a bit more user friendly. Regards, Anthony Liguori > --- > qemu-sockets.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 55 insertions(+), 3 deletions(-) > > diff --git a/qemu-sockets.c b/qemu-sockets.c > index 3537bf3..70c8ad5 100644 > --- a/qemu-sockets.c > +++ b/qemu-sockets.c > @@ -663,11 +663,50 @@ int inet_nonblocking_connect(const char *str, > > #ifndef _WIN32 > > +/* > + * The abstract socket namespace is a nonportable Linux extension. > + * The sockets' names in this namespace have no connection > + * with file system pathnames. To specify a named AF_UNIX socket > + * in the abstract socket namespace, start the socket's path option > + * with a backslash followed by zero: \0. > + */ > +static > +char *get_abstract_namespace_path(const char *path, int *abstract_path_length) > +{ > + char *abstract_path; > + char *inp; > + char *outp; > + char c; > + > + *abstract_path_length = 0; > + if ((path == NULL) || (path[0] != '\\') || (path[1] != '0')) { > + return NULL; > + } > + abstract_path = g_strdup(path + 2); > + for (inp = abstract_path, outp = abstract_path; (c = *inp); ++inp, ++outp) { > + if (c == '\\') { > + c = *++inp; > + if (c == '\\') { > + *outp = c; > + } else if (c == '0') { > + *outp = '\0'; > + } > + } else { > + *outp = c; > + } > + } > + *abstract_path_length = outp - abstract_path; > + return abstract_path; > +} > + > int unix_listen_opts(QemuOpts *opts, Error **errp) > { > struct sockaddr_un un; > const char *path = qemu_opt_get(opts, "path"); > + int abstract_path_length; > + char *abstract_path; > int sock, fd; > + socklen_t addrlen = sizeof(un); > > sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); > if (sock < 0) { > @@ -675,9 +714,18 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) > return -1; > } > > + abstract_path = get_abstract_namespace_path(path, &abstract_path_length); > + > memset(&un, 0, sizeof(un)); > un.sun_family = AF_UNIX; > - if (path && strlen(path)) { > + if (abstract_path != NULL) { > + if (abstract_path_length > sizeof(un.sun_path) - 1) { > + abstract_path_length = sizeof(un.sun_path) - 1; > + } > + memcpy(un.sun_path + 1, abstract_path, abstract_path_length); > + addrlen = > + offsetof(struct sockaddr_un, sun_path) + 1 + abstract_path_length; > + } else if (path && strlen(path)) { > snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); > } else { > char *tmpdir = getenv("TMPDIR"); > @@ -694,8 +742,10 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) > qemu_opt_set(opts, "path", un.sun_path); > } > > - unlink(un.sun_path); > - if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { > + if (abstract_path == NULL) { > + unlink(un.sun_path); > + } > + if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) { > error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); > goto err; > } > @@ -704,10 +754,12 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) > goto err; > } > > + g_free(abstract_path); > return sock; > > err: > closesocket(sock); > + g_free(abstract_path); > return -1; > } > > -- > 1.7.9.5
Hi, On 01/07/2013 04:07 PM, Anthony Liguori wrote: > Alexander Barabash <alexander_barabash@mentor.com> writes: > >> The abstract socket namespace is a nonportable Linux extension. >> The sockets' names in this namespace have no connection >> with file system pathnames. To specify a named AF_UNIX socket >> in the abstract socket namespace, start the socket's path option >> with a backslash followed by zero: \0. >> >> Signed-off-by: Alexander Barabash <alexander_barabash@mentor.com> > Magic interpretation of path names is a bad thing in general. > > I think it would be better to add a flag 'abstract=on' which > indicates to use the abstract namespace. As an example: > > qemu -chardev foo,path=bar,abstract=on > > vs: > > qemu -chardev foo,path="\\\\0bar" > > I think the former is quite a bit more user friendly. OK > > Regards, > > Anthony Liguori Regards, Alex > >> --- >> qemu-sockets.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- >> 1 file changed, 55 insertions(+), 3 deletions(-) >> >> diff --git a/qemu-sockets.c b/qemu-sockets.c >> index 3537bf3..70c8ad5 100644 >> --- a/qemu-sockets.c >> +++ b/qemu-sockets.c >> @@ -663,11 +663,50 @@ int inet_nonblocking_connect(const char *str, >> >> #ifndef _WIN32 >> >> +/* >> + * The abstract socket namespace is a nonportable Linux extension. >> + * The sockets' names in this namespace have no connection >> + * with file system pathnames. To specify a named AF_UNIX socket >> + * in the abstract socket namespace, start the socket's path option >> + * with a backslash followed by zero: \0. >> + */ >> +static >> +char *get_abstract_namespace_path(const char *path, int *abstract_path_length) >> +{ >> + char *abstract_path; >> + char *inp; >> + char *outp; >> + char c; >> + >> + *abstract_path_length = 0; >> + if ((path == NULL) || (path[0] != '\\') || (path[1] != '0')) { >> + return NULL; >> + } >> + abstract_path = g_strdup(path + 2); >> + for (inp = abstract_path, outp = abstract_path; (c = *inp); ++inp, ++outp) { >> + if (c == '\\') { >> + c = *++inp; >> + if (c == '\\') { >> + *outp = c; >> + } else if (c == '0') { >> + *outp = '\0'; >> + } >> + } else { >> + *outp = c; >> + } >> + } >> + *abstract_path_length = outp - abstract_path; >> + return abstract_path; >> +} >> + >> int unix_listen_opts(QemuOpts *opts, Error **errp) >> { >> struct sockaddr_un un; >> const char *path = qemu_opt_get(opts, "path"); >> + int abstract_path_length; >> + char *abstract_path; >> int sock, fd; >> + socklen_t addrlen = sizeof(un); >> >> sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); >> if (sock < 0) { >> @@ -675,9 +714,18 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) >> return -1; >> } >> >> + abstract_path = get_abstract_namespace_path(path, &abstract_path_length); >> + >> memset(&un, 0, sizeof(un)); >> un.sun_family = AF_UNIX; >> - if (path && strlen(path)) { >> + if (abstract_path != NULL) { >> + if (abstract_path_length > sizeof(un.sun_path) - 1) { >> + abstract_path_length = sizeof(un.sun_path) - 1; >> + } >> + memcpy(un.sun_path + 1, abstract_path, abstract_path_length); >> + addrlen = >> + offsetof(struct sockaddr_un, sun_path) + 1 + abstract_path_length; >> + } else if (path && strlen(path)) { >> snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); >> } else { >> char *tmpdir = getenv("TMPDIR"); >> @@ -694,8 +742,10 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) >> qemu_opt_set(opts, "path", un.sun_path); >> } >> >> - unlink(un.sun_path); >> - if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { >> + if (abstract_path == NULL) { >> + unlink(un.sun_path); >> + } >> + if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) { >> error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); >> goto err; >> } >> @@ -704,10 +754,12 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) >> goto err; >> } >> >> + g_free(abstract_path); >> return sock; >> >> err: >> closesocket(sock); >> + g_free(abstract_path); >> return -1; >> } >> >> -- >> 1.7.9.5
diff --git a/qemu-sockets.c b/qemu-sockets.c index 3537bf3..70c8ad5 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -663,11 +663,50 @@ int inet_nonblocking_connect(const char *str, #ifndef _WIN32 +/* + * The abstract socket namespace is a nonportable Linux extension. + * The sockets' names in this namespace have no connection + * with file system pathnames. To specify a named AF_UNIX socket + * in the abstract socket namespace, start the socket's path option + * with a backslash followed by zero: \0. + */ +static +char *get_abstract_namespace_path(const char *path, int *abstract_path_length) +{ + char *abstract_path; + char *inp; + char *outp; + char c; + + *abstract_path_length = 0; + if ((path == NULL) || (path[0] != '\\') || (path[1] != '0')) { + return NULL; + } + abstract_path = g_strdup(path + 2); + for (inp = abstract_path, outp = abstract_path; (c = *inp); ++inp, ++outp) { + if (c == '\\') { + c = *++inp; + if (c == '\\') { + *outp = c; + } else if (c == '0') { + *outp = '\0'; + } + } else { + *outp = c; + } + } + *abstract_path_length = outp - abstract_path; + return abstract_path; +} + int unix_listen_opts(QemuOpts *opts, Error **errp) { struct sockaddr_un un; const char *path = qemu_opt_get(opts, "path"); + int abstract_path_length; + char *abstract_path; int sock, fd; + socklen_t addrlen = sizeof(un); sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { @@ -675,9 +714,18 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) return -1; } + abstract_path = get_abstract_namespace_path(path, &abstract_path_length); + memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; - if (path && strlen(path)) { + if (abstract_path != NULL) { + if (abstract_path_length > sizeof(un.sun_path) - 1) { + abstract_path_length = sizeof(un.sun_path) - 1; + } + memcpy(un.sun_path + 1, abstract_path, abstract_path_length); + addrlen = + offsetof(struct sockaddr_un, sun_path) + 1 + abstract_path_length; + } else if (path && strlen(path)) { snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); } else { char *tmpdir = getenv("TMPDIR"); @@ -694,8 +742,10 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) qemu_opt_set(opts, "path", un.sun_path); } - unlink(un.sun_path); - if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { + if (abstract_path == NULL) { + unlink(un.sun_path); + } + if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) { error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); goto err; } @@ -704,10 +754,12 @@ int unix_listen_opts(QemuOpts *opts, Error **errp) goto err; } + g_free(abstract_path); return sock; err: closesocket(sock); + g_free(abstract_path); return -1; }
The abstract socket namespace is a nonportable Linux extension. The sockets' names in this namespace have no connection with file system pathnames. To specify a named AF_UNIX socket in the abstract socket namespace, start the socket's path option with a backslash followed by zero: \0. Signed-off-by: Alexander Barabash <alexander_barabash@mentor.com> --- qemu-sockets.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-)