]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
config: Add support for XDG config
authorOlliver Schinagl <oliver@schinagl.nl>
Sat, 10 Jun 2023 13:35:26 +0000 (15:35 +0200)
committerFlole998 <Flole998@users.noreply.github.com>
Fri, 16 Jun 2023 11:11:41 +0000 (13:11 +0200)
Over the last years, the freedesktop organization has promoted the use
of XDG_HOME_CONFIG for storing configuration data.

Since TVHeadend also wants to help declutter the home directory, lets
follow the spec for our own configuration. While here, reduce the path
from `hts/tvheaded` to just `hts`.

The implementation does not change behavior of existing installations!
If `.hts/tvheadend` exists, it will be used as before.

New installations, will try to use `.config/hts` instead, and
'migrating' is as easy as `mv .hts/tvheadend .config/hts`.

Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
src/config.c

index 7889d160a59da14bfe0c3fc1d4689a06a6f83c5a..63657b597086174b9348b0b3acbddda615729659 100644 (file)
  */
 
 #include <ctype.h>
+#include <linux/limits.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include "tvheadend.h"
 #include "settings.h"
@@ -1690,6 +1693,45 @@ config_check ( void )
 
 static int config_newcfg = 0;
 
+static char *config_get_dir ( void )
+{
+  char hts_home[PATH_MAX + sizeof("/.hts/tvheadend")]; /* Must be largest of the 3 config strings! */
+  char config_home[PATH_MAX];
+  char home_dir[PATH_MAX];
+  struct stat st;
+
+  if (realpath(getenv("HOME"), home_dir) == NULL) {
+    tvherror(LS_CONFIG, "environment variable HOME is not set");
+    return NULL;
+  }
+
+  snprintf(hts_home, sizeof(hts_home), "%s/.hts/tvheadend", home_dir);
+  if (stat(hts_home, &st) == 0) {
+    if (S_ISLNK(st.st_mode)) {
+      char hts_home_link[PATH_MAX];
+
+      if ((readlink(hts_home, hts_home_link, sizeof(hts_home_link)) == -1) ||
+          (stat(hts_home_link, &st) == -1)) {
+        tvherror(LS_CONFIG, ".hts/tvheadend is inaccessable: %s", strerror(errno));
+        return NULL;
+      }
+      strncpy(hts_home, hts_home_link, sizeof(hts_home));
+    }
+    if (!S_ISDIR(st.st_mode)) {
+      tvherror(LS_CONFIG, ".hts/tvheadend exists, but is not a directory");
+      return NULL;
+    }
+    tvhwarn(LS_CONFIG, "Found legacy '.hts/tvheadend', consider moving this to '.config/hts' instead.");
+  } else if ((realpath(getenv("XDG_CONFIG_HOME"), config_home) != NULL) &&
+      (config_home[0] != 0)) {
+    snprintf(hts_home, sizeof(hts_home), "%s/hts", config_home);
+  } else {
+    snprintf(hts_home, sizeof(hts_home), "%s/.config/hts", home_dir);
+  }
+
+  return strndup(hts_home, sizeof(hts_home));
+}
+
 void
 config_boot
   ( const char *path, gid_t gid, uid_t uid, const char *http_user_agent )
@@ -1725,18 +1767,14 @@ config_boot
   config.local_port = 0;
 
   /* Generate default */
-  if (!path) {
-    const char *homedir = getenv("HOME");
-    char buf[PATH_MAX];
-
-    if (homedir == NULL) {
-      tvherror(LS_START, "environment variable HOME is not set");
-      exit(EXIT_FAILURE);
-    }
-    snprintf(buf, sizeof(buf), "%s/.hts/tvheadend", homedir);
-    config.confdir = strndup(buf, sizeof(buf));
-  } else {
+  if (!path)
+    config.confdir = config_get_dir();
+  else
     config.confdir = strndup(path, PATH_MAX);
+
+  if (config.confdir == NULL) {
+    tvherror(LS_START, "unable to determine tvheadend home\n");
+    exit(EXIT_FAILURE);
   }
 
   tvhinfo(LS_CONFIG, "Using configuration from '%s'\n", config.confdir);