LCOV - code coverage report
Current view: top level - libsystemd/sd-path - sd-path.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 66 325 20.3 %
Date: 2019-08-22 15:41:25 Functions: 4 8 50.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "sd-path.h"
       4             : 
       5             : #include "alloc-util.h"
       6             : #include "architecture.h"
       7             : #include "fd-util.h"
       8             : #include "fileio.h"
       9             : #include "fs-util.h"
      10             : #include "missing.h"
      11             : #include "path-util.h"
      12             : #include "string-util.h"
      13             : #include "strv.h"
      14             : #include "user-util.h"
      15             : #include "util.h"
      16             : 
      17          16 : static int from_environment(const char *envname, const char *fallback, const char **ret) {
      18          16 :         assert(ret);
      19             : 
      20          16 :         if (envname) {
      21             :                 const char *e;
      22             : 
      23          16 :                 e = secure_getenv(envname);
      24          16 :                 if (e && path_is_absolute(e)) {
      25          15 :                         *ret = e;
      26          15 :                         return 0;
      27             :                 }
      28             :         }
      29             : 
      30           1 :         if (fallback) {
      31           0 :                 *ret = fallback;
      32           0 :                 return 0;
      33             :         }
      34             : 
      35           1 :         return -ENXIO;
      36             : }
      37             : 
      38          56 : static int from_home_dir(const char *envname, const char *suffix, char **buffer, const char **ret) {
      39          56 :         _cleanup_free_ char *h = NULL;
      40          56 :         char *cc = NULL;
      41             :         int r;
      42             : 
      43          56 :         assert(suffix);
      44          56 :         assert(buffer);
      45          56 :         assert(ret);
      46             : 
      47          56 :         if (envname) {
      48          56 :                 const char *e = NULL;
      49             : 
      50          56 :                 e = secure_getenv(envname);
      51          56 :                 if (e && path_is_absolute(e)) {
      52           0 :                         *ret = e;
      53           0 :                         return 0;
      54             :                 }
      55             :         }
      56             : 
      57          56 :         r = get_home_dir(&h);
      58          56 :         if (r < 0)
      59           0 :                 return r;
      60             : 
      61          56 :         cc = path_join(h, suffix);
      62          56 :         if (!cc)
      63           0 :                 return -ENOMEM;
      64             : 
      65          56 :         *buffer = cc;
      66          56 :         *ret = cc;
      67          56 :         return 0;
      68             : }
      69             : 
      70           0 : static int from_user_dir(const char *field, char **buffer, const char **ret) {
      71           0 :         _cleanup_fclose_ FILE *f = NULL;
      72           0 :         _cleanup_free_ char *b = NULL;
      73           0 :         _cleanup_free_ const char *fn = NULL;
      74           0 :         const char *c = NULL;
      75             :         size_t n;
      76             :         int r;
      77             : 
      78           0 :         assert(field);
      79           0 :         assert(buffer);
      80           0 :         assert(ret);
      81             : 
      82           0 :         r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c);
      83           0 :         if (r < 0)
      84           0 :                 return r;
      85             : 
      86           0 :         fn = path_join(c, "user-dirs.dirs");
      87           0 :         if (!fn)
      88           0 :                 return -ENOMEM;
      89             : 
      90           0 :         f = fopen(fn, "re");
      91           0 :         if (!f) {
      92           0 :                 if (errno == ENOENT)
      93           0 :                         goto fallback;
      94             : 
      95           0 :                 return -errno;
      96             :         }
      97             : 
      98             :         /* This is an awful parse, but it follows closely what
      99             :          * xdg-user-dirs does upstream */
     100             : 
     101           0 :         n = strlen(field);
     102           0 :         for (;;) {
     103           0 :                 _cleanup_free_ char *line = NULL;
     104             :                 char *l, *p, *e;
     105             : 
     106           0 :                 r = read_line(f, LONG_LINE_MAX, &line);
     107           0 :                 if (r < 0)
     108           0 :                         return r;
     109           0 :                 if (r == 0)
     110           0 :                         break;
     111             : 
     112           0 :                 l = strstrip(line);
     113             : 
     114           0 :                 if (!strneq(l, field, n))
     115           0 :                         continue;
     116             : 
     117           0 :                 p = l + n;
     118           0 :                 p += strspn(p, WHITESPACE);
     119             : 
     120           0 :                 if (*p != '=')
     121           0 :                         continue;
     122           0 :                 p++;
     123             : 
     124           0 :                 p += strspn(p, WHITESPACE);
     125             : 
     126           0 :                 if (*p != '"')
     127           0 :                         continue;
     128           0 :                 p++;
     129             : 
     130           0 :                 e = strrchr(p, '"');
     131           0 :                 if (!e)
     132           0 :                         continue;
     133           0 :                 *e = 0;
     134             : 
     135             :                 /* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */
     136           0 :                 if (startswith(p, "$HOME/")) {
     137           0 :                         _cleanup_free_ char *h = NULL;
     138             :                         char *cc;
     139             : 
     140           0 :                         r = get_home_dir(&h);
     141           0 :                         if (r < 0)
     142           0 :                                 return r;
     143             : 
     144           0 :                         cc = path_join(h, p+5);
     145           0 :                         if (!cc)
     146           0 :                                 return -ENOMEM;
     147             : 
     148           0 :                         *buffer = cc;
     149           0 :                         *ret = cc;
     150           0 :                         return 0;
     151           0 :                 } else if (streq(p, "$HOME")) {
     152             : 
     153           0 :                         r = get_home_dir(buffer);
     154           0 :                         if (r < 0)
     155           0 :                                 return r;
     156             : 
     157           0 :                         *ret = *buffer;
     158           0 :                         return 0;
     159           0 :                 } else if (path_is_absolute(p)) {
     160             :                         char *copy;
     161             : 
     162           0 :                         copy = strdup(p);
     163           0 :                         if (!copy)
     164           0 :                                 return -ENOMEM;
     165             : 
     166           0 :                         *buffer = copy;
     167           0 :                         *ret = copy;
     168           0 :                         return 0;
     169             :                 }
     170             :         }
     171             : 
     172           0 : fallback:
     173             :         /* The desktop directory defaults to $HOME/Desktop, the others to $HOME */
     174           0 :         if (streq(field, "XDG_DESKTOP_DIR")) {
     175           0 :                 _cleanup_free_ char *h = NULL;
     176             :                 char *cc;
     177             : 
     178           0 :                 r = get_home_dir(&h);
     179           0 :                 if (r < 0)
     180           0 :                         return r;
     181             : 
     182           0 :                 cc = path_join(h, "Desktop");
     183           0 :                 if (!cc)
     184           0 :                         return -ENOMEM;
     185             : 
     186           0 :                 *buffer = cc;
     187           0 :                 *ret = cc;
     188             :         } else {
     189             : 
     190           0 :                 r = get_home_dir(buffer);
     191           0 :                 if (r < 0)
     192           0 :                         return r;
     193             : 
     194           0 :                 *ret = *buffer;
     195             :         }
     196             : 
     197           0 :         return 0;
     198             : }
     199             : 
     200          76 : static int get_path(uint64_t type, char **buffer, const char **ret) {
     201             :         int r;
     202             : 
     203          76 :         assert(buffer);
     204          76 :         assert(ret);
     205             : 
     206          76 :         switch (type) {
     207             : 
     208           0 :         case SD_PATH_TEMPORARY:
     209           0 :                 return tmp_dir(ret);
     210             : 
     211           0 :         case SD_PATH_TEMPORARY_LARGE:
     212           0 :                 return var_tmp_dir(ret);
     213             : 
     214           0 :         case SD_PATH_SYSTEM_BINARIES:
     215           0 :                 *ret = "/usr/bin";
     216           0 :                 return 0;
     217             : 
     218           0 :         case SD_PATH_SYSTEM_INCLUDE:
     219           0 :                 *ret = "/usr/include";
     220           0 :                 return 0;
     221             : 
     222           0 :         case SD_PATH_SYSTEM_LIBRARY_PRIVATE:
     223           0 :                 *ret = "/usr/lib";
     224           0 :                 return 0;
     225             : 
     226           0 :         case SD_PATH_SYSTEM_LIBRARY_ARCH:
     227           0 :                 *ret = LIBDIR;
     228           0 :                 return 0;
     229             : 
     230           0 :         case SD_PATH_SYSTEM_SHARED:
     231           0 :                 *ret = "/usr/share";
     232           0 :                 return 0;
     233             : 
     234           0 :         case SD_PATH_SYSTEM_CONFIGURATION_FACTORY:
     235           0 :                 *ret = "/usr/share/factory/etc";
     236           0 :                 return 0;
     237             : 
     238           0 :         case SD_PATH_SYSTEM_STATE_FACTORY:
     239           0 :                 *ret = "/usr/share/factory/var";
     240           0 :                 return 0;
     241             : 
     242           0 :         case SD_PATH_SYSTEM_CONFIGURATION:
     243           0 :                 *ret = "/etc";
     244           0 :                 return 0;
     245             : 
     246           1 :         case SD_PATH_SYSTEM_RUNTIME:
     247           1 :                 *ret = "/run";
     248           1 :                 return 0;
     249             : 
     250           0 :         case SD_PATH_SYSTEM_RUNTIME_LOGS:
     251           0 :                 *ret = "/run/log";
     252           0 :                 return 0;
     253             : 
     254           1 :         case SD_PATH_SYSTEM_STATE_PRIVATE:
     255           1 :                 *ret = "/var/lib";
     256           1 :                 return 0;
     257             : 
     258           1 :         case SD_PATH_SYSTEM_STATE_LOGS:
     259           1 :                 *ret = "/var/log";
     260           1 :                 return 0;
     261             : 
     262           1 :         case SD_PATH_SYSTEM_STATE_CACHE:
     263           1 :                 *ret = "/var/cache";
     264           1 :                 return 0;
     265             : 
     266           0 :         case SD_PATH_SYSTEM_STATE_SPOOL:
     267           0 :                 *ret = "/var/spool";
     268           0 :                 return 0;
     269             : 
     270           0 :         case SD_PATH_USER_BINARIES:
     271           0 :                 return from_home_dir(NULL, ".local/bin", buffer, ret);
     272             : 
     273           0 :         case SD_PATH_USER_LIBRARY_PRIVATE:
     274           0 :                 return from_home_dir(NULL, ".local/lib", buffer, ret);
     275             : 
     276           0 :         case SD_PATH_USER_LIBRARY_ARCH:
     277           0 :                 return from_home_dir(NULL, ".local/lib/" LIB_ARCH_TUPLE, buffer, ret);
     278             : 
     279           0 :         case SD_PATH_USER_SHARED:
     280           0 :                 return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret);
     281             : 
     282          42 :         case SD_PATH_USER_CONFIGURATION:
     283          42 :                 return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret);
     284             : 
     285          16 :         case SD_PATH_USER_RUNTIME:
     286          16 :                 return from_environment("XDG_RUNTIME_DIR", NULL, ret);
     287             : 
     288          14 :         case SD_PATH_USER_STATE_CACHE:
     289          14 :                 return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret);
     290             : 
     291           0 :         case SD_PATH_USER:
     292           0 :                 r = get_home_dir(buffer);
     293           0 :                 if (r < 0)
     294           0 :                         return r;
     295             : 
     296           0 :                 *ret = *buffer;
     297           0 :                 return 0;
     298             : 
     299           0 :         case SD_PATH_USER_DOCUMENTS:
     300           0 :                 return from_user_dir("XDG_DOCUMENTS_DIR", buffer, ret);
     301             : 
     302           0 :         case SD_PATH_USER_MUSIC:
     303           0 :                 return from_user_dir("XDG_MUSIC_DIR", buffer, ret);
     304             : 
     305           0 :         case SD_PATH_USER_PICTURES:
     306           0 :                 return from_user_dir("XDG_PICTURES_DIR", buffer, ret);
     307             : 
     308           0 :         case SD_PATH_USER_VIDEOS:
     309           0 :                 return from_user_dir("XDG_VIDEOS_DIR", buffer, ret);
     310             : 
     311           0 :         case SD_PATH_USER_DOWNLOAD:
     312           0 :                 return from_user_dir("XDG_DOWNLOAD_DIR", buffer, ret);
     313             : 
     314           0 :         case SD_PATH_USER_PUBLIC:
     315           0 :                 return from_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret);
     316             : 
     317           0 :         case SD_PATH_USER_TEMPLATES:
     318           0 :                 return from_user_dir("XDG_TEMPLATES_DIR", buffer, ret);
     319             : 
     320           0 :         case SD_PATH_USER_DESKTOP:
     321           0 :                 return from_user_dir("XDG_DESKTOP_DIR", buffer, ret);
     322             :         }
     323             : 
     324           0 :         return -EOPNOTSUPP;
     325             : }
     326             : 
     327          76 : _public_ int sd_path_home(uint64_t type, const char *suffix, char **path) {
     328          76 :         _cleanup_free_ char *buffer = NULL;
     329             :         const char *ret;
     330             :         char *cc;
     331             :         int r;
     332             : 
     333          76 :         assert_return(path, -EINVAL);
     334             : 
     335          76 :         if (IN_SET(type,
     336             :                    SD_PATH_SEARCH_BINARIES,
     337             :                    SD_PATH_SEARCH_BINARIES_DEFAULT,
     338             :                    SD_PATH_SEARCH_LIBRARY_PRIVATE,
     339             :                    SD_PATH_SEARCH_LIBRARY_ARCH,
     340             :                    SD_PATH_SEARCH_SHARED,
     341             :                    SD_PATH_SEARCH_CONFIGURATION_FACTORY,
     342             :                    SD_PATH_SEARCH_STATE_FACTORY,
     343             :                    SD_PATH_SEARCH_CONFIGURATION)) {
     344             : 
     345           0 :                 _cleanup_strv_free_ char **l = NULL;
     346             : 
     347           0 :                 r = sd_path_search(type, suffix, &l);
     348           0 :                 if (r < 0)
     349           0 :                         return r;
     350             : 
     351           0 :                 buffer = strv_join(l, ":");
     352           0 :                 if (!buffer)
     353           0 :                         return -ENOMEM;
     354             : 
     355           0 :                 *path = TAKE_PTR(buffer);
     356           0 :                 return 0;
     357             :         }
     358             : 
     359          76 :         r = get_path(type, &buffer, &ret);
     360          76 :         if (r < 0)
     361           1 :                 return r;
     362             : 
     363          75 :         if (!suffix) {
     364          61 :                 if (!buffer) {
     365          19 :                         buffer = strdup(ret);
     366          19 :                         if (!buffer)
     367           0 :                                 return -ENOMEM;
     368             :                 }
     369             : 
     370          61 :                 *path = TAKE_PTR(buffer);
     371          61 :                 return 0;
     372             :         }
     373             : 
     374          14 :         suffix += strspn(suffix, "/");
     375          14 :         cc = path_join(ret, suffix);
     376          14 :         if (!cc)
     377           0 :                 return -ENOMEM;
     378             : 
     379          14 :         *path = TAKE_PTR(cc);
     380          14 :         return 0;
     381             : }
     382             : 
     383           0 : static int search_from_environment(
     384             :                 char ***list,
     385             :                 const char *env_home,
     386             :                 const char *home_suffix,
     387             :                 const char *env_search,
     388             :                 bool env_search_sufficient,
     389             :                 const char *first, ...) {
     390             : 
     391           0 :         _cleanup_strv_free_ char **l = NULL;
     392             :         const char *e;
     393           0 :         char *h = NULL;
     394             :         int r;
     395             : 
     396           0 :         assert(list);
     397             : 
     398           0 :         if (env_search) {
     399           0 :                 e = secure_getenv(env_search);
     400           0 :                 if (e) {
     401           0 :                         l = strv_split(e, ":");
     402           0 :                         if (!l)
     403           0 :                                 return -ENOMEM;
     404             : 
     405           0 :                         if (env_search_sufficient) {
     406           0 :                                 *list = TAKE_PTR(l);
     407           0 :                                 return 0;
     408             :                         }
     409             :                 }
     410             :         }
     411             : 
     412           0 :         if (!l && first) {
     413             :                 va_list ap;
     414             : 
     415           0 :                 va_start(ap, first);
     416           0 :                 l = strv_new_ap(first, ap);
     417           0 :                 va_end(ap);
     418             : 
     419           0 :                 if (!l)
     420           0 :                         return -ENOMEM;
     421             :         }
     422             : 
     423           0 :         if (env_home) {
     424           0 :                 e = secure_getenv(env_home);
     425           0 :                 if (e && path_is_absolute(e)) {
     426           0 :                         h = strdup(e);
     427           0 :                         if (!h)
     428           0 :                                 return -ENOMEM;
     429             :                 }
     430             :         }
     431             : 
     432           0 :         if (!h && home_suffix) {
     433           0 :                 e = secure_getenv("HOME");
     434           0 :                 if (e && path_is_absolute(e)) {
     435           0 :                         h = path_join(e, home_suffix);
     436           0 :                         if (!h)
     437           0 :                                 return -ENOMEM;
     438             :                 }
     439             :         }
     440             : 
     441           0 :         if (h) {
     442           0 :                 r = strv_consume_prepend(&l, h);
     443           0 :                 if (r < 0)
     444           0 :                         return -ENOMEM;
     445             :         }
     446             : 
     447           0 :         *list = TAKE_PTR(l);
     448           0 :         return 0;
     449             : }
     450             : 
     451             : #if HAVE_SPLIT_BIN
     452             : #  define ARRAY_SBIN_BIN(x) x "sbin", x "bin"
     453             : #else
     454             : #  define ARRAY_SBIN_BIN(x) x "bin"
     455             : #endif
     456             : 
     457           0 : static int get_search(uint64_t type, char ***list) {
     458             : 
     459           0 :         assert(list);
     460             : 
     461           0 :         switch(type) {
     462             : 
     463           0 :         case SD_PATH_SEARCH_BINARIES:
     464           0 :                 return search_from_environment(list,
     465             :                                                NULL,
     466             :                                                ".local/bin",
     467             :                                                "PATH",
     468             :                                                true,
     469             :                                                ARRAY_SBIN_BIN("/usr/local/"),
     470             :                                                ARRAY_SBIN_BIN("/usr/"),
     471             : #if HAVE_SPLIT_USR
     472             :                                                ARRAY_SBIN_BIN("/"),
     473             : #endif
     474             :                                                NULL);
     475             : 
     476           0 :         case SD_PATH_SEARCH_LIBRARY_PRIVATE:
     477           0 :                 return search_from_environment(list,
     478             :                                                NULL,
     479             :                                                ".local/lib",
     480             :                                                NULL,
     481             :                                                false,
     482             :                                                "/usr/local/lib",
     483             :                                                "/usr/lib",
     484             : #if HAVE_SPLIT_USR
     485             :                                                "/lib",
     486             : #endif
     487             :                                                NULL);
     488             : 
     489           0 :         case SD_PATH_SEARCH_LIBRARY_ARCH:
     490           0 :                 return search_from_environment(list,
     491             :                                                NULL,
     492             :                                                ".local/lib/" LIB_ARCH_TUPLE,
     493             :                                                "LD_LIBRARY_PATH",
     494             :                                                true,
     495             :                                                LIBDIR,
     496             : #if HAVE_SPLIT_USR
     497             :                                                ROOTLIBDIR,
     498             : #endif
     499             :                                                NULL);
     500             : 
     501           0 :         case SD_PATH_SEARCH_SHARED:
     502           0 :                 return search_from_environment(list,
     503             :                                                "XDG_DATA_HOME",
     504             :                                                ".local/share",
     505             :                                                "XDG_DATA_DIRS",
     506             :                                                false,
     507             :                                                "/usr/local/share",
     508             :                                                "/usr/share",
     509             :                                                NULL);
     510             : 
     511           0 :         case SD_PATH_SEARCH_CONFIGURATION_FACTORY:
     512           0 :                 return search_from_environment(list,
     513             :                                                NULL,
     514             :                                                NULL,
     515             :                                                NULL,
     516             :                                                false,
     517             :                                                "/usr/local/share/factory/etc",
     518             :                                                "/usr/share/factory/etc",
     519             :                                                NULL);
     520             : 
     521           0 :         case SD_PATH_SEARCH_STATE_FACTORY:
     522           0 :                 return search_from_environment(list,
     523             :                                                NULL,
     524             :                                                NULL,
     525             :                                                NULL,
     526             :                                                false,
     527             :                                                "/usr/local/share/factory/var",
     528             :                                                "/usr/share/factory/var",
     529             :                                                NULL);
     530             : 
     531           0 :         case SD_PATH_SEARCH_CONFIGURATION:
     532           0 :                 return search_from_environment(list,
     533             :                                                "XDG_CONFIG_HOME",
     534             :                                                ".config",
     535             :                                                "XDG_CONFIG_DIRS",
     536             :                                                false,
     537             :                                                "/etc",
     538             :                                                NULL);
     539             : 
     540           0 :         case SD_PATH_SEARCH_BINARIES_DEFAULT: {
     541             :                 char **t;
     542             : 
     543           0 :                 t = strv_split_nulstr(DEFAULT_PATH_NULSTR);
     544           0 :                 if (!t)
     545           0 :                         return -ENOMEM;
     546             : 
     547           0 :                 *list = t;
     548           0 :                 return 0;
     549             :         }}
     550             : 
     551           0 :         return -EOPNOTSUPP;
     552             : }
     553             : 
     554           0 : _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
     555             :         char **i, **j;
     556           0 :         _cleanup_strv_free_ char **l = NULL, **n = NULL;
     557             :         int r;
     558             : 
     559           0 :         assert_return(paths, -EINVAL);
     560             : 
     561           0 :         if (!IN_SET(type,
     562             :                     SD_PATH_SEARCH_BINARIES,
     563             :                     SD_PATH_SEARCH_BINARIES_DEFAULT,
     564             :                     SD_PATH_SEARCH_LIBRARY_PRIVATE,
     565             :                     SD_PATH_SEARCH_LIBRARY_ARCH,
     566             :                     SD_PATH_SEARCH_SHARED,
     567             :                     SD_PATH_SEARCH_CONFIGURATION_FACTORY,
     568             :                     SD_PATH_SEARCH_STATE_FACTORY,
     569             :                     SD_PATH_SEARCH_CONFIGURATION)) {
     570             : 
     571             :                 char *p;
     572             : 
     573           0 :                 r = sd_path_home(type, suffix, &p);
     574           0 :                 if (r < 0)
     575           0 :                         return r;
     576             : 
     577           0 :                 l = new(char*, 2);
     578           0 :                 if (!l) {
     579           0 :                         free(p);
     580           0 :                         return -ENOMEM;
     581             :                 }
     582             : 
     583           0 :                 l[0] = p;
     584           0 :                 l[1] = NULL;
     585             : 
     586           0 :                 *paths = TAKE_PTR(l);
     587           0 :                 return 0;
     588             :         }
     589             : 
     590           0 :         r = get_search(type, &l);
     591           0 :         if (r < 0)
     592           0 :                 return r;
     593             : 
     594           0 :         if (!suffix) {
     595           0 :                 *paths = TAKE_PTR(l);
     596           0 :                 return 0;
     597             :         }
     598             : 
     599           0 :         n = new(char*, strv_length(l)+1);
     600           0 :         if (!n)
     601           0 :                 return -ENOMEM;
     602             : 
     603           0 :         j = n;
     604           0 :         STRV_FOREACH(i, l) {
     605           0 :                 *j = path_join(*i, suffix);
     606           0 :                 if (!*j)
     607           0 :                         return -ENOMEM;
     608             : 
     609           0 :                 j++;
     610             :         }
     611             : 
     612           0 :         *j = NULL;
     613           0 :         *paths = TAKE_PTR(n);
     614           0 :         return 0;
     615             : }

Generated by: LCOV version 1.14