/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 David Herrmann
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 David Herrmann
***/
#include <fcntl.h>
return sd_bus_send(sd->session->manager->bus, m, NULL);
}
-static int sd_eviocrevoke(int fd) {
- static bool warned;
- int r;
+static void sd_eviocrevoke(int fd) {
+ static bool warned = false;
assert(fd >= 0);
- r = ioctl(fd, EVIOCREVOKE, NULL);
- if (r < 0) {
- r = -errno;
- if (r == -EINVAL && !warned) {
+ if (ioctl(fd, EVIOCREVOKE, NULL) < 0) {
+
+ if (errno == EINVAL && !warned) {
+ log_warning_errno(errno, "Kernel does not support evdev-revocation: %m");
warned = true;
- log_warning("kernel does not support evdev-revocation");
}
}
-
- return 0;
}
static int sd_drmsetmaster(int fd) {
} else
/* DRM-Master is granted to the first user who opens a device automatically (ughh,
* racy!). Hence, we just drop DRM-Master in case we were the first. */
- sd_drmdropmaster(fd);
+ (void) sd_drmdropmaster(fd);
break;
case DEVICE_TYPE_EVDEV:
switch (sd->type) {
case DEVICE_TYPE_DRM:
+ if (sd->fd < 0) {
+ log_error("Failed to re-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
+ return -EBADF;
+ }
+
/* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
* keep the device paused. Maybe at some point we have a drmStealMaster(). */
r = sd_drmsetmaster(sd->fd);
case DEVICE_TYPE_UNKNOWN:
default:
- /* fallback for devices wihout synchronizations */
+ /* fallback for devices without synchronizations */
break;
}
return;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
+ if (sd->fd < 0) {
+ log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
+ return;
+ }
+
/* On DRM devices we simply drop DRM-Master but keep it open.
* This allows the user to keep resources allocated. The
* CAP_SYS_ADMIN restriction to DRM-Master prevents users from
* circumventing this. */
sd_drmdropmaster(sd->fd);
break;
+
case DEVICE_TYPE_EVDEV:
/* Revoke access on evdev file-descriptors during deactivation.
* This will basically prevent any operations on the fd and
* protection this way. */
sd_eviocrevoke(sd->fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices without synchronization */
goto error;
r = hashmap_put(s->devices, &sd->dev, sd);
- if (r < 0) {
- r = -ENOMEM;
+ if (r < 0)
goto error;
- }
if (open_device) {
/* Open the device for the first time. We need a valid fd to pass back
void session_device_free(SessionDevice *sd) {
assert(sd);
+ /* Make sure to remove the pushed fd. */
if (sd->pushed_fd) {
- const char *m;
-
- /* Remove the pushed fd again, just in case. */
-
- m = strjoina("FDSTOREREMOVE=1\n"
- "FDNAME=session-", sd->session->id);
-
- (void) sd_notify(false, m);
+ _cleanup_free_ char *m = NULL;
+ const char *id;
+ int r;
+
+ /* Session ID does not contain separators. */
+ id = sd->session->id;
+ assert(*(id + strcspn(id, "-\n")) == '\0');
+
+ r = asprintf(&m, "FDSTOREREMOVE=1\n"
+ "FDNAME=session-%s-device-%u-%u\n",
+ id, major(sd->dev), minor(sd->dev));
+ if (r >= 0)
+ (void) sd_notify(false, m);
}
session_device_stop(sd);
session_device_notify(sd, SESSION_DEVICE_RELEASE);
- close_nointr(sd->fd);
+ safe_close(sd->fd);
LIST_REMOVE(sd_by_device, sd->device->session_devices, sd);
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (!sd->active) {
- if (session_device_start(sd) < 0)
- continue;
- if (session_device_save(sd) < 0)
- continue;
- session_device_notify(sd, SESSION_DEVICE_RESUME);
- }
+ if (sd->active)
+ continue;
+
+ if (session_device_start(sd) < 0)
+ continue;
+ if (session_device_save(sd) < 0)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_RESUME);
}
}
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_stop(sd);
- session_device_notify(sd, SESSION_DEVICE_PAUSE);
- }
+ if (!sd->active)
+ continue;
+
+ session_device_stop(sd);
+ session_device_notify(sd, SESSION_DEVICE_PAUSE);
}
}
unsigned int session_device_try_pause_all(Session *s) {
+ unsigned num_pending = 0;
SessionDevice *sd;
Iterator i;
- unsigned int num_pending = 0;
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
- ++num_pending;
- }
+ if (!sd->active)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
+ num_pending++;
}
return num_pending;
}
int session_device_save(SessionDevice *sd) {
- const char *m;
+ _cleanup_free_ char *m = NULL;
+ const char *id;
int r;
assert(sd);
if (sd->pushed_fd)
return 0;
- m = strjoina("FDSTORE=1\n"
- "FDNAME=session", sd->session->id);
+ /* Session ID does not contain separators. */
+ id = sd->session->id;
+ assert(*(id + strcspn(id, "-\n")) == '\0');
+
+ r = asprintf(&m, "FDSTORE=1\n"
+ "FDNAME=session-%s-device-%u-%u\n",
+ id, major(sd->dev), minor(sd->dev));
+ if (r < 0)
+ return r;
r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1);
if (r < 0)
}
void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
- assert(fd > 0);
+ assert(fd >= 0);
assert(sd);
assert(sd->fd < 0);
assert(!sd->active);
sd->fd = fd;
+ sd->pushed_fd = true;
sd->active = active;
}