Browse Source

refactor: Break proc API functions out of the main daemon source

Signed-off-by: Kai Krakow <kai@kaishome.de>
Kai Krakow 6 years ago
parent
commit
748808be7e
4 changed files with 78 additions and 14 deletions
  1. 61 0
      daemon/gamemode-proc.c
  2. 5 14
      daemon/gamemode.c
  3. 11 0
      daemon/gamemode.h
  4. 1 0
      daemon/meson.build

+ 61 - 0
daemon/gamemode-proc.c

@@ -0,0 +1,61 @@
+/*
+
+Copyright (c) 2017-2018, Feral Interactive
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+ * Neither the name of Feral Interactive nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+#define _GNU_SOURCE
+
+#include "gamemode.h"
+#include "helpers.h"
+
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <unistd.h>
+
+/**
+ * Opens the process environment for a specific PID and returns
+ * a file descriptor to the directory /proc/PID. Doing it that way prevents
+ * the directory going MIA when a process exits while we are looking at it
+ * and allows us to handle fewer error cases.
+ */
+procfd_t game_mode_open_proc(const pid_t pid)
+{
+	char buffer[PATH_MAX];
+	const char *proc_path = buffered_snprintf(buffer, "/proc/%d", pid);
+
+	return proc_path ? open(proc_path, O_RDONLY | O_CLOEXEC) : INVALID_PROCFD;
+}
+
+/**
+ * Closes the process environment.
+ */
+int game_mode_close_proc(const procfd_t procfd)
+{
+	return close(procfd);
+}

+ 5 - 14
daemon/gamemode.c

@@ -41,7 +41,6 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include <ctype.h>
 #include <fcntl.h>
-#include <linux/limits.h>
 #include <linux/sched.h>
 #include <pthread.h>
 #include <pwd.h>
@@ -50,7 +49,6 @@ POSSIBILITY OF SUCH DAMAGE.
 #include <stdatomic.h>
 #include <sys/resource.h>
 #include <sys/sysinfo.h>
-#include <sys/types.h>
 #include <systemd/sd-daemon.h>
 
 /* SCHED_ISO may not be defined as it is a reserved value not yet
@@ -725,7 +723,7 @@ GameModeContext *game_mode_context_instance()
  * Lookup the process environment for a specific variable or return NULL.
  * Requires an open directory FD from /proc/PID.
  */
-static char *game_mode_lookup_proc_env(int proc_fd, const char *var)
+static char *game_mode_lookup_proc_env(const procfd_t proc_fd, const char *var)
 {
 	char *environ = NULL;
 
@@ -785,18 +783,11 @@ static char *game_mode_resolve_wine_preloader(pid_t pid)
 {
 	char buffer[PATH_MAX];
 	char *proc_path = NULL, *wine_exe = NULL, *wineprefix = NULL;
-	int proc_fd = -1;
-
-	/* We could use the buffered_snprintf() helper here but it may potentially
-	 * overwrite proc_path when the buffer is re-used later and usage of
-	 * proc_path has not been discarded yet (i.e., it's used in the fail path).
-	 * Let's not introduce this non-obvious pitfall.
-	 */
-	if (!(proc_path = safe_snprintf(buffer, "/proc/%d", pid)))
-		goto fail;
 
 	/* Open the directory, we are potentially reading multiple files from it */
-	if (-1 == (proc_fd = open(proc_path, O_RDONLY | O_CLOEXEC)))
+	procfd_t proc_fd = game_mode_open_proc(pid);
+
+	if (proc_fd == INVALID_PROCFD)
 		goto fail_proc;
 
 	/* Open the command line */
@@ -868,7 +859,7 @@ static char *game_mode_resolve_wine_preloader(pid_t pid)
 		goto fail;
 
 error_cleanup:
-	close(proc_fd);
+	game_mode_close_proc(proc_fd);
 	free(wineprefix);
 	free(proc_path);
 	return wine_exe;

+ 11 - 0
daemon/gamemode.h

@@ -34,6 +34,10 @@ POSSIBILITY OF SUCH DAMAGE.
 #include <stdbool.h>
 #include <sys/types.h>
 
+#define INVALID_PROCFD -1
+
+typedef int procfd_t;
+
 /**
  * Opaque context
  */
@@ -83,3 +87,10 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t pid);
  *          2 if gamemode is active and the client is registered
  */
 int game_mode_context_query_status(GameModeContext *self, pid_t pid);
+
+/** gamemode-proc.c
+ * Provides internal API functions specific to working with process
+ * environments.
+ */
+procfd_t game_mode_open_proc(const pid_t pid);
+int game_mode_close_proc(const procfd_t procfd);

+ 1 - 0
daemon/meson.build

@@ -18,6 +18,7 @@ link_daemon_common = declare_dependency(
 daemon_sources = [
     'main.c',
     'gamemode.c',
+    'gamemode-proc.c',
     'daemonize.c',
     'dbus_messaging.c',
     'governors.c',