KWin
Loading...
Searching...
No Matches
wl-socket.c
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2020 <davidedmundson@kde.org>
6 SPDX-FileCopyrightText: 2008 Kristian Høgsberg
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10
11#define _DEFAULT_SOURCE
12#include <assert.h>
13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <sys/file.h>
19#include <sys/socket.h>
20#include <sys/stat.h>
21#include <sys/un.h>
22#include <unistd.h>
23
24/* This is the size of the char array in struct sock_addr_un.
25 * No Wayland socket can be created with a path longer than this,
26 * including the null terminator.
27 */
28#ifndef UNIX_PATH_MAX
29#define UNIX_PATH_MAX 108
30#endif
31
32#define LOCK_SUFFIX ".lock"
33#define LOCK_SUFFIXLEN 5
34
35struct wl_socket {
36 int fd;
38 struct sockaddr_un addr;
40 char display_name[20];
41};
42
43static struct wl_socket *wl_socket_alloc(void)
44{
45 struct wl_socket *s;
46
47 s = malloc(sizeof *s);
48 if (!s)
49 return NULL;
50
51 s->fd = -1;
52 s->fd_lock = -1;
53
54 return s;
55}
56
57static int wl_socket_lock(struct wl_socket *socket)
58{
59 struct stat socket_stat;
60
61 snprintf(socket->lock_addr, sizeof socket->lock_addr, "%s%s", socket->addr.sun_path, LOCK_SUFFIX);
62
63 socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC | O_RDWR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
64
65 if (socket->fd_lock < 0) {
66 printf("unable to open lockfile %s check permissions\n", socket->lock_addr);
67 goto err;
68 }
69
70 if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
71 printf("unable to lock lockfile %s, maybe another compositor is running\n", socket->lock_addr);
72 goto err_fd;
73 }
74
75 if (lstat(socket->addr.sun_path, &socket_stat) < 0) {
76 if (errno != ENOENT) {
77 printf("did not manage to stat file %s\n", socket->addr.sun_path);
78 goto err_fd;
79 }
80 } else if (socket_stat.st_mode & S_IWUSR || socket_stat.st_mode & S_IWGRP) {
81 unlink(socket->addr.sun_path);
82 }
83
84 return 0;
85err_fd:
86 close(socket->fd_lock);
87 socket->fd_lock = -1;
88err:
89 *socket->lock_addr = 0;
90 /* we did not set this value here, but without lock the
91 * socket won't be created anyway. This prevents the
92 * wl_socket_destroy from unlinking already existing socket
93 * created by other compositor */
94 *socket->addr.sun_path = 0;
95
96 return -1;
97}
98
100{
101 if (s->addr.sun_path[0])
102 unlink(s->addr.sun_path);
103 if (s->fd >= 0)
104 close(s->fd);
105 if (s->lock_addr[0])
106 unlink(s->lock_addr);
107 if (s->fd_lock >= 0)
108 close(s->fd_lock);
109
110 free(s);
111}
112
114{
115 return s->display_name;
116}
117
119{
120 return s->fd;
121}
122
124{
125 struct wl_socket *s;
126 int displayno = 0;
127 int name_size;
128
129 /* A reasonable number of maximum default sockets. If
130 * you need more than this, use the explicit add_socket API. */
131 const int MAX_DISPLAYNO = 32;
132 const char *runtime_dir = getenv("XDG_RUNTIME_DIR");
133 if (!runtime_dir) {
134 printf("XDG_RUNTIME_DIR not set");
135 return NULL;
136 }
137
138 s = wl_socket_alloc();
139 if (s == NULL)
140 return NULL;
141
142 do {
143 snprintf(s->display_name, sizeof s->display_name, "wayland-%d", displayno);
144 s->addr.sun_family = AF_LOCAL;
145 name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path, "%s/%s", runtime_dir, s->display_name) + 1;
146 assert(name_size > 0);
147
148 if (name_size > (int)sizeof s->addr.sun_path) {
149 goto fail;
150 }
151
152 if (wl_socket_lock(s) < 0)
153 continue;
154
155 s->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
156
157 int size = SUN_LEN(&s->addr);
158 int ret = bind(s->fd, (struct sockaddr*)&s->addr, size);
159 if (ret < 0) {
160 goto fail;
161 }
162 ret = listen(s->fd, 128);
163 if (ret < 0) {
164 goto fail;
165 }
166 return s;
167 } while (displayno++ < MAX_DISPLAYNO);
168
169fail:
171 return NULL;
172}
struct sockaddr_un addr
Definition wl-socket.c:38
char display_name[20]
Definition wl-socket.c:40
char lock_addr[UNIX_PATH_MAX+LOCK_SUFFIXLEN]
Definition wl-socket.c:39
int fd_lock
Definition wl-socket.c:37
#define LOCK_SUFFIX
Definition wl-socket.c:32
struct wl_socket * wl_socket_create()
Definition wl-socket.c:123
#define LOCK_SUFFIXLEN
Definition wl-socket.c:33
void wl_socket_destroy(struct wl_socket *s)
Definition wl-socket.c:99
#define UNIX_PATH_MAX
Definition wl-socket.c:29
int wl_socket_get_fd(struct wl_socket *s)
Definition wl-socket.c:118
const char * wl_socket_get_display_name(struct wl_socket *s)
Definition wl-socket.c:113