From 3369536cb83531bd83923e6017729960ecddafd4 Mon Sep 17 00:00:00 2001 From: Quantum Date: Sat, 31 Jul 2021 07:04:53 -0400 Subject: [PATCH] [common] paths: add library to manage platform-specific paths This abstracts away stuff like XDG base directory specification. Currently, this is implemented for Linux only. --- common/include/common/paths.h | 28 ++++++++ common/src/platform/linux/CMakeLists.txt | 1 + common/src/platform/linux/paths.c | 90 ++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 common/include/common/paths.h create mode 100644 common/src/platform/linux/paths.c diff --git a/common/include/common/paths.h b/common/include/common/paths.h new file mode 100644 index 00000000..458c5dd1 --- /dev/null +++ b/common/include/common/paths.h @@ -0,0 +1,28 @@ +/** + * Looking Glass + * Copyright (C) 2017-2021 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _H_LG_COMMON_DIRS_ +#define _H_LG_COMMON_DIRS_ + +void lgPathsInit(const char * appName); +const char * lgConfigDir(void); +const char * lgDataDir(void); + +#endif diff --git a/common/src/platform/linux/CMakeLists.txt b/common/src/platform/linux/CMakeLists.txt index 405e795f..4cdf0bda 100644 --- a/common/src/platform/linux/CMakeLists.txt +++ b/common/src/platform/linux/CMakeLists.txt @@ -14,6 +14,7 @@ add_library(lg_common_platform_code STATIC event.c ivshmem.c time.c + paths.c ) if(ENABLE_BACKTRACE) diff --git a/common/src/platform/linux/paths.c b/common/src/platform/linux/paths.c new file mode 100644 index 00000000..a36cb9e7 --- /dev/null +++ b/common/src/platform/linux/paths.c @@ -0,0 +1,90 @@ +/** + * Looking Glass + * Copyright (C) 2017-2021 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "common/paths.h" +#include "common/debug.h" + +#include +#include +#include +#include +#include +#include + +static char configDir[PATH_MAX]; +static char dataDir[PATH_MAX]; + +static void ensureDir(char * path, mode_t mode) +{ + struct stat st; + if (stat(path, &st) >= 0) + { + if (S_ISDIR(st.st_mode)) + return; + + DEBUG_ERROR("Expected to be a directory: %s", path); + exit(2); + } + + for (char * p = strchr(path + 1, '/'); p; p = strchr(p + 1, '/')) { + *p = '\0'; + if (mkdir(path, mode) < 0 && errno != EEXIST) + { + *p = '/'; + DEBUG_ERROR("Failed to create directory: %s", path); + return; + } + *p = '/'; + } + + if (mkdir(path, mode) < 0 && errno != EEXIST) + DEBUG_ERROR("Failed to create directory: %s", path); +} + +void lgPathsInit(const char * appName) +{ + const char * home = getenv("HOME"); + if (!home) + home = getpwuid(getuid())->pw_dir; + + const char * dir; + if ((dir = getenv("XDG_CONFIG_HOME")) != NULL) + snprintf(configDir, sizeof(configDir), "%s/%s", dir, appName); + else + snprintf(configDir, sizeof(configDir), "%s/.config/%s", home, appName); + + if ((dir = getenv("XDG_DATA_HOME")) != NULL) + snprintf(dataDir, sizeof(configDir), "%s/%s", dir, appName); + else + snprintf(dataDir, sizeof(configDir), "%s/.local/share/%s", home, appName); + + ensureDir(configDir, S_IRWXU); + ensureDir(dataDir, S_IRWXU); +} + +const char * lgConfigDir(void) +{ + return configDir; +} + +const char * lgDataDir(void) +{ + return dataDir; +}