mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
core: Add socket type for usb functionfs endpoints
For handling functionfs endpoints additional socket type is added.
This commit is contained in:
parent
15087cdbd6
commit
602524469e
@ -68,6 +68,7 @@ static int property_get_listen(
|
|||||||
case SOCKET_SPECIAL:
|
case SOCKET_SPECIAL:
|
||||||
case SOCKET_MQUEUE:
|
case SOCKET_MQUEUE:
|
||||||
case SOCKET_FIFO:
|
case SOCKET_FIFO:
|
||||||
|
case SOCKET_USB_FUNCTION:
|
||||||
a = p->path;
|
a = p->path;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -244,6 +244,7 @@ Socket.ListenFIFO, config_parse_socket_listen, SOCKET_FIFO
|
|||||||
Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCKET, 0
|
Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCKET, 0
|
||||||
Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0
|
Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0
|
||||||
Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0
|
Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0
|
||||||
|
Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0
|
||||||
Socket.BindIPv6Only, config_parse_socket_bind, 0, 0,
|
Socket.BindIPv6Only, config_parse_socket_bind, 0, 0,
|
||||||
Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
|
Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
|
||||||
Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
|
Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
|
||||||
|
@ -259,7 +259,7 @@ static int socket_add_mount_links(Socket *s) {
|
|||||||
|
|
||||||
if (p->type == SOCKET_SOCKET)
|
if (p->type == SOCKET_SOCKET)
|
||||||
path = socket_address_get_path(&p->address);
|
path = socket_address_get_path(&p->address);
|
||||||
else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL)
|
else if (IN_SET(p->type, SOCKET_FIFO, SOCKET_SPECIAL, SOCKET_USB_FUNCTION))
|
||||||
path = p->path;
|
path = p->path;
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
@ -650,6 +650,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
|||||||
free(k);
|
free(k);
|
||||||
} else if (p->type == SOCKET_SPECIAL)
|
} else if (p->type == SOCKET_SPECIAL)
|
||||||
fprintf(f, "%sListenSpecial: %s\n", prefix, p->path);
|
fprintf(f, "%sListenSpecial: %s\n", prefix, p->path);
|
||||||
|
else if (p->type == SOCKET_USB_FUNCTION)
|
||||||
|
fprintf(f, "%sListenUSBFunction: %s\n", prefix, p->path);
|
||||||
else if (p->type == SOCKET_MQUEUE)
|
else if (p->type == SOCKET_MQUEUE)
|
||||||
fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path);
|
fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path);
|
||||||
else
|
else
|
||||||
@ -1063,6 +1065,33 @@ fail:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ffs_address_create(
|
||||||
|
const char *path,
|
||||||
|
int *_fd) {
|
||||||
|
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
assert(path);
|
||||||
|
assert(_fd);
|
||||||
|
|
||||||
|
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
|
||||||
|
if (fd < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (fstat(fd, &st) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
/* Check whether this is a regular file (ffs endpoint)*/
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
return -EEXIST;
|
||||||
|
|
||||||
|
*_fd = fd;
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mq_address_create(
|
static int mq_address_create(
|
||||||
const char *path,
|
const char *path,
|
||||||
mode_t mq_mode,
|
mode_t mq_mode,
|
||||||
@ -1136,6 +1165,60 @@ static int socket_symlink(Socket *s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int select_ep(const struct dirent *d) {
|
||||||
|
return d->d_name[0] != '.' && !streq(d->d_name, "ep0");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ffs_dispatch_eps(SocketPort *p) {
|
||||||
|
_cleanup_free_ struct dirent **ent = NULL;
|
||||||
|
int r, i, n, k;
|
||||||
|
_cleanup_free_ char *path = NULL;
|
||||||
|
|
||||||
|
r = path_get_parent(p->path, &path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = scandir(path, &ent, select_ep, alphasort);
|
||||||
|
if (r < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
n = r;
|
||||||
|
p->auxiliary_fds = new(int, n);
|
||||||
|
if (!p->auxiliary_fds)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
p->n_auxiliary_fds = n;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
_cleanup_free_ char *ep = NULL;
|
||||||
|
|
||||||
|
ep = path_make_absolute(ent[i]->d_name, path);
|
||||||
|
if (!ep)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
path_kill_slashes(ep);
|
||||||
|
|
||||||
|
r = ffs_address_create(ep, &p->auxiliary_fds[k]);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
++k;
|
||||||
|
free(ent[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
while (k)
|
||||||
|
safe_close(p->auxiliary_fds[--k]);
|
||||||
|
|
||||||
|
p->auxiliary_fds = mfree(p->auxiliary_fds);
|
||||||
|
p->n_auxiliary_fds = 0;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int socket_open_fds(Socket *s) {
|
static int socket_open_fds(Socket *s) {
|
||||||
SocketPort *p;
|
SocketPort *p;
|
||||||
int r;
|
int r;
|
||||||
@ -1232,6 +1315,17 @@ static int socket_open_fds(Socket *s) {
|
|||||||
&p->fd);
|
&p->fd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto rollback;
|
goto rollback;
|
||||||
|
} else if (p->type == SOCKET_USB_FUNCTION) {
|
||||||
|
|
||||||
|
r = ffs_address_create(
|
||||||
|
p->path,
|
||||||
|
&p->fd);
|
||||||
|
if (r < 0)
|
||||||
|
goto rollback;
|
||||||
|
|
||||||
|
r = ffs_dispatch_eps(p);
|
||||||
|
if (r < 0)
|
||||||
|
goto rollback;
|
||||||
} else
|
} else
|
||||||
assert_not_reached("Unknown port type");
|
assert_not_reached("Unknown port type");
|
||||||
}
|
}
|
||||||
@ -2047,6 +2141,8 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
|
|||||||
unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path);
|
unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path);
|
||||||
else if (p->type == SOCKET_MQUEUE)
|
else if (p->type == SOCKET_MQUEUE)
|
||||||
unit_serialize_item_format(u, f, "mqueue", "%i %s", copy, p->path);
|
unit_serialize_item_format(u, f, "mqueue", "%i %s", copy, p->path);
|
||||||
|
else if (p->type == SOCKET_USB_FUNCTION)
|
||||||
|
unit_serialize_item_format(u, f, "ffs", "%i %s", copy, p->path);
|
||||||
else {
|
else {
|
||||||
assert(p->type == SOCKET_FIFO);
|
assert(p->type == SOCKET_FIFO);
|
||||||
unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path);
|
unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path);
|
||||||
@ -2196,6 +2292,26 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
|
|||||||
p->fd = fdset_remove(fds, fd);
|
p->fd = fdset_remove(fds, fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (streq(key, "ffs")) {
|
||||||
|
int fd, skip = 0;
|
||||||
|
SocketPort *p;
|
||||||
|
|
||||||
|
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
|
||||||
|
log_unit_debug(u, "Failed to parse ffs value: %s", value);
|
||||||
|
else {
|
||||||
|
|
||||||
|
LIST_FOREACH(port, p, s->ports)
|
||||||
|
if (p->type == SOCKET_USB_FUNCTION &&
|
||||||
|
path_equal_or_files_same(p->path, value+skip))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
safe_close(p->fd);
|
||||||
|
p->fd = fdset_remove(fds, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
log_unit_debug(UNIT(s), "Unknown serialization key: %s", key);
|
log_unit_debug(UNIT(s), "Unknown serialization key: %s", key);
|
||||||
|
|
||||||
@ -2278,6 +2394,9 @@ const char* socket_port_type_to_string(SocketPort *p) {
|
|||||||
case SOCKET_FIFO:
|
case SOCKET_FIFO:
|
||||||
return "FIFO";
|
return "FIFO";
|
||||||
|
|
||||||
|
case SOCKET_USB_FUNCTION:
|
||||||
|
return "USBFunction";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ typedef enum SocketType {
|
|||||||
SOCKET_FIFO,
|
SOCKET_FIFO,
|
||||||
SOCKET_SPECIAL,
|
SOCKET_SPECIAL,
|
||||||
SOCKET_MQUEUE,
|
SOCKET_MQUEUE,
|
||||||
|
SOCKET_USB_FUNCTION,
|
||||||
_SOCKET_FIFO_MAX,
|
_SOCKET_FIFO_MAX,
|
||||||
_SOCKET_FIFO_INVALID = -1
|
_SOCKET_FIFO_INVALID = -1
|
||||||
} SocketType;
|
} SocketType;
|
||||||
|
Loading…
Reference in New Issue
Block a user