bus: extend memfd api so that we can label memfds for debugging purposes

This commit is contained in:
Lennart Poettering 2014-01-22 13:06:04 +01:00
parent 3736955368
commit 7f96b1d814
5 changed files with 124 additions and 17 deletions

View File

@ -215,6 +215,7 @@ global:
sd_memfd_get_sealed;
sd_memfd_get_size;
sd_memfd_set_size;
sd_memfd_get_name;
/* sd-event functions */
sd_event_default;

View File

@ -23,22 +23,26 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include "util.h"
#include "kdbus.h"
#include "sd-memfd.h"
#include "sd-bus.h"
struct sd_memfd {
int fd;
FILE *f;
};
_public_ int sd_memfd_new(sd_memfd **m) {
struct kdbus_cmd_memfd_make cmd = {
.size = sizeof(struct kdbus_cmd_memfd_make),
};
_public_ int sd_memfd_new(const char *name, sd_memfd **m) {
struct kdbus_cmd_memfd_make *cmd;
struct kdbus_item *item;
_cleanup_close_ int kdbus = -1;
_cleanup_free_ char *g = NULL;
size_t sz, l;
sd_memfd *n;
assert_return(m, -EINVAL);
@ -47,16 +51,64 @@ _public_ int sd_memfd_new(sd_memfd **m) {
if (kdbus < 0)
return -errno;
if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &cmd) < 0)
if (name) {
/* The kernel side is pretty picky about the character
* set here, let's do the usual bus escaping to deal
* with that. */
g = sd_bus_label_escape(name);
if (!g)
return -ENOMEM;
name = g;
} else {
char pr[17] = {};
/* If no name is specified we generate one. We include
* a hint indicating our library implementation, and
* add the thread name to it */
assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
if (isempty(pr))
name = "sd";
else {
_cleanup_free_ char *e = NULL;
e = sd_bus_label_escape(pr);
if (!e)
return -ENOMEM;
g = strappend("sd-", e);
if (!g)
return -ENOMEM;
name = g;
}
}
l = strlen(name);
sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) +
ALIGN8(offsetof(struct kdbus_item, str)) +
l + 1;
cmd = alloca0(sz);
cmd->size = sz;
item = cmd->items;
item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1;
item->type = KDBUS_ITEM_MEMFD_NAME;
memcpy(item->str, name, l + 1);
if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, cmd) < 0)
return -errno;
n = new0(struct sd_memfd, 1);
if (!n) {
close_nointr_nofail(cmd.fd);
close_nointr_nofail(cmd->fd);
return -ENOMEM;
}
n->fd = cmd.fd;
n->fd = cmd->fd;
*m = n;
return 0;
}
@ -195,11 +247,11 @@ _public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
return r;
}
_public_ int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p) {
_public_ int sd_memfd_new_and_map(const char *name, sd_memfd **m, size_t sz, void **p) {
sd_memfd *n;
int r;
r = sd_memfd_new(&n);
r = sd_memfd_new(name, &n);
if (r < 0)
return r;
@ -218,3 +270,50 @@ _public_ int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p) {
*m = n;
return 0;
}
_public_ int sd_memfd_get_name(sd_memfd *m, char **name) {
char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e;
const char *delim, *end;
_cleanup_free_ char *n = NULL;
ssize_t k;
assert_return(m, -EINVAL);
assert_return(name, -EINVAL);
sprintf(path, "/proc/self/fd/%i", m->fd);
k = readlink(path, buf, sizeof(buf));
if (k < 0)
return -errno;
if ((size_t) k >= sizeof(buf))
return -E2BIG;
buf[k] = 0;
delim = strstr(buf, ":[");
if (!delim)
return -EIO;
delim = strchr(delim + 2, ':');
if (!delim)
return -EIO;
delim++;
end = strchr(delim, ']');
if (!end)
return -EIO;
n = strndup(delim, end - delim);
if (!n)
return -ENOMEM;
e = sd_bus_label_unescape(n);
if (!e)
return -ENOMEM;
*name = e;
return 0;
}

View File

@ -30,7 +30,7 @@
int main(int argc, char *argv[]) {
sd_memfd *m;
char *s;
char *s, *name;
uint64_t sz;
int r, fd;
FILE *f;
@ -40,10 +40,16 @@ int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
r = sd_memfd_new(&m);
r = sd_memfd_new(NULL, &m);
if (r == -ENOENT)
return EXIT_TEST_SKIP;
assert_se(r >= 0);
assert_se(sd_memfd_get_name(m, &name) >= 0);
log_info("name: %s", name);
free(name);
r = sd_memfd_map(m, 0, 12, (void**) &s);
assert_se(r >= 0);

View File

@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {
memset(p+1, 'L', FIRST_ARRAY-2);
p[FIRST_ARRAY-1] = '>';
r = sd_memfd_new_and_map(&f, STRING_SIZE, (void**) &s);
r = sd_memfd_new_and_map(NULL, &f, STRING_SIZE, (void**) &s);
assert_se(r >= 0);
s[0] = '<';
@ -112,7 +112,7 @@ int main(int argc, char *argv[]) {
sd_memfd_free(f);
r = sd_memfd_new_and_map(&f, SECOND_ARRAY, (void**) &p);
r = sd_memfd_new_and_map(NULL, &f, SECOND_ARRAY, (void**) &p);
assert_se(r >= 0);
p[0] = '<';

View File

@ -32,16 +32,15 @@ _SD_BEGIN_DECLARATIONS;
typedef struct sd_memfd sd_memfd;
int sd_memfd_new(sd_memfd **m);
int sd_memfd_new(const char *name, sd_memfd **m);
int sd_memfd_new_and_map(const char *name, sd_memfd **m, size_t sz, void **p);
int sd_memfd_make(int fd, sd_memfd **m);
int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p);
void sd_memfd_free(sd_memfd *m);
int sd_memfd_get_fd(sd_memfd *m);
int sd_memfd_get_file(sd_memfd *m, FILE **f);
int sd_memfd_dup_fd(sd_memfd *n);
int sd_memfd_get_file(sd_memfd *m, FILE **f);
int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p);
@ -51,6 +50,8 @@ int sd_memfd_get_sealed(sd_memfd *m);
int sd_memfd_get_size(sd_memfd *m, uint64_t *sz);
int sd_memfd_set_size(sd_memfd *m, uint64_t sz);
int sd_memfd_get_name(sd_memfd *m, char **name);
_SD_END_DECLARATIONS;
#endif