LCOV - code coverage report
Current view: top level - libsystemd/sd-path - sd-path.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 284 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 8 0.0 %

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

Generated by: LCOV version 1.11