00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2009--2010 Petter Urkedal <paurkedal@eideticdew.org> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef CUOS_USER_DIRS_H 00019 #define CUOS_USER_DIRS_H 00020 00021 #include <cuos/dirpile.h> 00022 #include <cu/installdirs.h> 00023 #include <atomic_ops.h> 00024 00025 CU_BEGIN_DECLARATIONS 00026 /** \defgroup cuos_user_dirs_h cuos/user_dirs.h: User Directories as Defined by XDG 00027 ** @{ \ingroup cuos_mod 00028 ** 00029 ** This implements the 00030 ** <a href="http://standards.freedesktop.org/basedir-spec/latest/">XDG Base 00031 ** Directory Specification</a> with a few adjustments. 00032 **/ 00033 00034 typedef enum { 00035 CUOS_USER_CONFIG, 00036 CUOS_USER_DATA, 00037 CUOS_USER_CACHE, 00038 } cuos_user_dir_usage_t; 00039 00040 /** This functions forces re-probing of the user directories. The may be 00041 ** useful if directories where created or the XDG_* environment variables 00042 ** where changed with \c setenv(3), \c unsetenv(3), etc. */ 00043 void cuos_reset_user_dirs(void); 00044 00045 /** The parent of the per-application user configuration directories. This is 00046 ** the environment variable \c $XDG_CONFIG_HOME if set, otherwise 00047 ** <tt>$HOME/.config</tt>. */ 00048 cu_str_t cuos_user_config_home(void) CU_ATTR_PURE; 00049 00050 /** The parent of the per-application user data directories. This is the 00051 ** environment variable \c $XDG_DATA_HOME if set, otherwise 00052 ** <tt>$HOME/.local/share</tt>. */ 00053 cu_str_t cuos_user_data_home(void) CU_ATTR_PURE; 00054 00055 /** The parent of per-application user cache directories. This is the 00056 ** environment variable \c $XDG_CACHE_HOME if set, otherwise 00057 ** <tt>$HOME/.cache</tt>. */ 00058 cu_str_t cuos_user_cache_home(void) CU_ATTR_PURE; 00059 00060 cu_str_t cuos_user_config_path(char const *pkg_name, cu_str_t subpath); 00061 cu_str_t cuos_user_data_path(char const *pkg_name, cu_str_t subpath); 00062 cu_str_t cuos_user_cache_path(char const *pkg_name, cu_str_t subpath); 00063 00064 /** A structure which holds package specific user directories for 00065 ** configuration, data, and cache, based on various environment variables and 00066 ** the package installation directories. Use \ref CUOS_PKG_USER_DIRS_INITZ as 00067 ** a static initialiser. */ 00068 struct cuos_pkg_user_dirs 00069 { 00070 char const *pkg_name, *var_prefix; 00071 cu_installdirs_t installdirs; 00072 AO_t init_done; 00073 pthread_mutex_t init_mutex; 00074 struct cuos_dirpile dirs[2]; 00075 cu_str_t homes[3]; 00076 }; 00077 00078 /** A static initialiser for \ref cuos_pkg_user_dirs to be used as 00079 ** \code 00080 ** struct cuos_pkg_user_dirs foo_user_dirs 00081 ** = CUOS_PKG_USER_DIRS_INITZ("foo", "FOO", foo_installdirs); 00082 ** \endcode 00083 ** after which <tt>cuos_pkg_user_config_dir(&foo_user_dirs)</tt> would give 00084 ** something like <tt>/home/jdoe/.config/foo</tt>. If you prefer to skip the 00085 ** \ref cu_installdirs_h "installdirs" initialisation, you can pass \a NULL as 00086 ** the last parameter and instead call \ref cuos_pkg_user_dirs_init on program 00087 ** start-up. 00088 ** 00089 ** This initialises part of the structure. The rest is initialised on demand 00090 ** when calling the \c cuos_pkg_* functions. The on-demand initalisation will 00091 ** look for environment variables starting with \a var_prefix, in particular 00092 ** if \a var_prefix is \c "FOO", then 00093 ** - <tt>$<i>FOO</i>_CONFIG_HOME</tt> is the primary user config directory, 00094 ** - <tt>$<i>FOO</i>_DATA_HOME</tt> is the primary user data directory, and 00095 ** - <tt>$<i>FOO</i>_CACHE_HOME</tt> is the primary user cache diretory 00096 ** 00097 ** for this package. If either of these are not set the subdirectory \a 00098 ** pkg_name under the corresponding XDG base directory is used instead. 00099 ** 00100 ** Finally, \a foo_installdirs is used to set up additional paths for 00101 ** searching for package-installed files with \ref cuos_pkg_user_config_search 00102 ** and \ref cuos_pkg_user_data_search. 00103 ** You may pass \c NULL for foo_installdirs, but that means that if your 00104 ** package is installed under a prefix other than \c /usr/local or \c usr, 00105 ** installed files will not be found unless the user includes the location in 00106 ** the corresponding variables 00107 ** - <tt>$<i>FOO</i>_CONFIG_DIRS</tt> or <tt>$XDG_CONFIG_DIRS</tt>, and 00108 ** - <tt>$<i>FOO</i>_DATA_DIRS</tt> or <tt>$XDG_DATA_DIRS</tt>. 00109 ** 00110 ** See \ref cuos_pkg_user_config_search and \ref cuos_pkg_user_data_search for 00111 ** the search order. 00112 **/ 00113 #define CUOS_PKG_USER_DIRS_INITZ(pkg_name, var_prefix, app_installdirs) \ 00114 { pkg_name, var_prefix, app_installdirs, 0, CU_MUTEX_INITIALISER } 00115 00116 /** Optionally call this on start-up to initialize \a udirs with the given 00117 ** package-specific installation directories. You only need to do this if you 00118 ** want to skip the initialization of a \ref cu_installdirs_t array. */ 00119 void cuos_pkg_user_dirs_init(cuos_pkg_user_dirs_t udirs, 00120 char const *sysconfdir, char const *datadir); 00121 00122 /** Finish initialisation of \a udirs if not already done. This is called by 00123 ** the other \c cuos_pkg_* functions, so you normally don't need to call it 00124 ** explicitely. \a udirs must be statically initalised with \ref 00125 ** CUOS_PKG_USER_DIRS_INITZ in advance. */ 00126 CU_SINLINE void 00127 cuos_pkg_user_dirs_ensure_init(cuos_pkg_user_dirs_t udirs) 00128 { 00129 if (!AO_load_acquire_read(&udirs->init_done)) 00130 cuos_pkg_user_dirs_init(udirs, NULL, NULL); 00131 } 00132 00133 /** The user config path from \a udirs. */ 00134 cu_str_t cuos_pkg_user_config_dir(cuos_pkg_user_dirs_t udirs); 00135 00136 /** The user data path from \a udirs. */ 00137 cu_str_t cuos_pkg_user_data_dir(cuos_pkg_user_dirs_t udirs); 00138 00139 /** The user cache path from \a udirs. */ 00140 cu_str_t cuos_pkg_user_cache_dir(cuos_pkg_user_dirs_t udirs); 00141 00142 /** Resolve a relative \a path under the config home of \a udirs. */ 00143 cu_str_t cuos_pkg_user_config_path(cuos_pkg_user_dirs_t udirs, cu_str_t path); 00144 00145 /** Reslove a relative \a path under the data home of \a udirs. */ 00146 cu_str_t cuos_pkg_user_data_path(cuos_pkg_user_dirs_t udirs, cu_str_t path); 00147 00148 /** Resolve a relative \a path under the cache home of \a udirs. */ 00149 cu_str_t cuos_pkg_user_cache_path(cuos_pkg_user_dirs_t udirs, cu_str_t path); 00150 00151 /** Locate \a path in the list of config search directories of \a udirs. This 00152 ** returns the first existing match under 00153 ** - The primary config location as described in \ref 00154 ** CUOS_PKG_USER_DIRS_INITZ. 00155 ** - If <tt>$<i>FOO</i>_CONFIG_DIRS</tt> is set, any of this colon separated 00156 ** list of directories in order. 00157 ** - Else if <tt>$XDG_CONFIG_DIRS</tt> is set, any subdirectory \a pkg_name 00158 ** under that colon separated list in order. 00159 ** - Else if \a app_installdirs was passed to \ref CUOS_PKG_USER_DIRS_INITZ, 00160 ** then the \a pkg_name subdir under the \ref CU_INSTALLDIR_SYSCONFDIR 00161 ** location. 00162 ** - Else <tt>/etc/xdg/<i>pkg_name</i></tt>, then 00163 ** <tt>/etc/<i>pkg_name</i></tt>. 00164 **/ 00165 cu_str_t cuos_pkg_user_config_search(cuos_pkg_user_dirs_t udirs, cu_str_t path); 00166 00167 /** Locate \a path in the list of data search directories of \a udirs. This 00168 ** returns the first existing match under 00169 ** - The primary config location as described in \ref 00170 ** CUOS_PKG_USER_DIRS_INITZ. 00171 ** - If <tt>$<i>FOO</i>_DATA_DIRS</tt> is set, any of this colon separated 00172 ** list of directories in order. 00173 ** - Else if <tt>$XDG_DATA_DIRS</tt> is set, any subdirectory \a pkg_name 00174 ** under that colon separated list in order. 00175 ** - Else if \a app_installdirs was passed to \ref CUOS_PKG_USER_DIRS_INITZ, 00176 ** then the \a pkg_name subdir under the \ref CU_INSTALLDIR_DATADIR 00177 ** location. 00178 ** - Else <tt>/usr/local/<i>pkg_name</i></tt> then 00179 ** <tt>/usr/<i>pkg_name</i></tt>. 00180 **/ 00181 cu_str_t cuos_pkg_user_data_search(cuos_pkg_user_dirs_t udirs, cu_str_t path); 00182 00183 CU_SINLINE cucon_list_t 00184 cuos_pkg_user_dirs_list(cuos_pkg_user_dirs_t udirs, cuos_user_dir_usage_t which) 00185 { 00186 return &udirs->dirs[which].top_dirs; 00187 } 00188 00189 /** @} */ 00190 CU_END_DECLARATIONS 00191 00192 #endif