chiark / gitweb /
nspawn: support ephemeral boots from images
[elogind.git] / src / basic / path-util.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010-2012 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 <errno.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27
28 /* When we include libgen.h because we need dirname() we immediately
29  * undefine basename() since libgen.h defines it as a macro to the
30  * POSIX version which is really broken. We prefer GNU basename(). */
31 #include <libgen.h>
32 #undef basename
33
34 #include "alloc-util.h"
35 #include "extract-word.h"
36 #include "fs-util.h"
37 #include "log.h"
38 #include "macro.h"
39 #include "missing.h"
40 #include "path-util.h"
41 #include "stat-util.h"
42 #include "string-util.h"
43 #include "strv.h"
44 #include "time-util.h"
45
46 bool path_is_absolute(const char *p) {
47         return p[0] == '/';
48 }
49
50 bool is_path(const char *p) {
51         return !!strchr(p, '/');
52 }
53
54 #if 0 /// UNNEEDED by elogind
55 int path_split_and_make_absolute(const char *p, char ***ret) {
56         char **l;
57         int r;
58
59         assert(p);
60         assert(ret);
61
62         l = strv_split(p, ":");
63         if (!l)
64                 return -ENOMEM;
65
66         r = path_strv_make_absolute_cwd(l);
67         if (r < 0) {
68                 strv_free(l);
69                 return r;
70         }
71
72         *ret = l;
73         return r;
74 }
75
76 char *path_make_absolute(const char *p, const char *prefix) {
77         assert(p);
78
79         /* Makes every item in the list an absolute path by prepending
80          * the prefix, if specified and necessary */
81
82         if (path_is_absolute(p) || !prefix)
83                 return strdup(p);
84
85         return strjoin(prefix, "/", p);
86 }
87 #endif // 0
88
89 int path_make_absolute_cwd(const char *p, char **ret) {
90         char *c;
91
92         assert(p);
93         assert(ret);
94
95         /* Similar to path_make_absolute(), but prefixes with the
96          * current working directory. */
97
98         if (path_is_absolute(p))
99                 c = strdup(p);
100         else {
101                 _cleanup_free_ char *cwd = NULL;
102
103                 cwd = get_current_dir_name();
104                 if (!cwd)
105                         return negative_errno();
106
107                 c = strjoin(cwd, "/", p);
108         }
109         if (!c)
110                 return -ENOMEM;
111
112         *ret = c;
113         return 0;
114 }
115
116 #if 0 /// UNNEEDED by elogind
117 int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
118         char *r, *p;
119         unsigned n_parents;
120
121         assert(from_dir);
122         assert(to_path);
123         assert(_r);
124
125         /* Strips the common part, and adds ".." elements as necessary. */
126
127         if (!path_is_absolute(from_dir))
128                 return -EINVAL;
129
130         if (!path_is_absolute(to_path))
131                 return -EINVAL;
132
133         /* Skip the common part. */
134         for (;;) {
135                 size_t a;
136                 size_t b;
137
138                 from_dir += strspn(from_dir, "/");
139                 to_path += strspn(to_path, "/");
140
141                 if (!*from_dir) {
142                         if (!*to_path)
143                                 /* from_dir equals to_path. */
144                                 r = strdup(".");
145                         else
146                                 /* from_dir is a parent directory of to_path. */
147                                 r = strdup(to_path);
148
149                         if (!r)
150                                 return -ENOMEM;
151
152                         path_kill_slashes(r);
153
154                         *_r = r;
155                         return 0;
156                 }
157
158                 if (!*to_path)
159                         break;
160
161                 a = strcspn(from_dir, "/");
162                 b = strcspn(to_path, "/");
163
164                 if (a != b)
165                         break;
166
167                 if (memcmp(from_dir, to_path, a) != 0)
168                         break;
169
170                 from_dir += a;
171                 to_path += b;
172         }
173
174         /* If we're here, then "from_dir" has one or more elements that need to
175          * be replaced with "..". */
176
177         /* Count the number of necessary ".." elements. */
178         for (n_parents = 0;;) {
179                 from_dir += strspn(from_dir, "/");
180
181                 if (!*from_dir)
182                         break;
183
184                 from_dir += strcspn(from_dir, "/");
185                 n_parents++;
186         }
187
188         r = malloc(n_parents * 3 + strlen(to_path) + 1);
189         if (!r)
190                 return -ENOMEM;
191
192         for (p = r; n_parents > 0; n_parents--, p += 3)
193                 memcpy(p, "../", 3);
194
195         strcpy(p, to_path);
196         path_kill_slashes(r);
197
198         *_r = r;
199         return 0;
200 }
201
202 int path_strv_make_absolute_cwd(char **l) {
203         char **s;
204         int r;
205
206         /* Goes through every item in the string list and makes it
207          * absolute. This works in place and won't rollback any
208          * changes on failure. */
209
210         STRV_FOREACH(s, l) {
211                 char *t;
212
213                 r = path_make_absolute_cwd(*s, &t);
214                 if (r < 0)
215                         return r;
216
217                 free(*s);
218                 *s = t;
219         }
220
221         return 0;
222 }
223 #endif // 0
224
225 char **path_strv_resolve(char **l, const char *prefix) {
226         char **s;
227         unsigned k = 0;
228         bool enomem = false;
229
230         if (strv_isempty(l))
231                 return l;
232
233         /* Goes through every item in the string list and canonicalize
234          * the path. This works in place and won't rollback any
235          * changes on failure. */
236
237         STRV_FOREACH(s, l) {
238                 char *t, *u;
239                 _cleanup_free_ char *orig = NULL;
240
241                 if (!path_is_absolute(*s)) {
242                         free(*s);
243                         continue;
244                 }
245
246                 if (prefix) {
247                         orig = *s;
248                         t = strappend(prefix, orig);
249                         if (!t) {
250                                 enomem = true;
251                                 continue;
252                         }
253                 } else
254                         t = *s;
255
256                 errno = 0;
257                 u = canonicalize_file_name(t);
258                 if (!u) {
259                         if (errno == ENOENT) {
260                                 if (prefix) {
261                                         u = orig;
262                                         orig = NULL;
263                                         free(t);
264                                 } else
265                                         u = t;
266                         } else {
267                                 free(t);
268                                 if (errno == ENOMEM || errno == 0)
269                                         enomem = true;
270
271                                 continue;
272                         }
273                 } else if (prefix) {
274                         char *x;
275
276                         free(t);
277                         x = path_startswith(u, prefix);
278                         if (x) {
279                                 /* restore the slash if it was lost */
280                                 if (!startswith(x, "/"))
281                                         *(--x) = '/';
282
283                                 t = strdup(x);
284                                 free(u);
285                                 if (!t) {
286                                         enomem = true;
287                                         continue;
288                                 }
289                                 u = t;
290                         } else {
291                                 /* canonicalized path goes outside of
292                                  * prefix, keep the original path instead */
293                                 free_and_replace(u, orig);
294                         }
295                 } else
296                         free(t);
297
298                 l[k++] = u;
299         }
300
301         l[k] = NULL;
302
303         if (enomem)
304                 return NULL;
305
306         return l;
307 }
308
309 char **path_strv_resolve_uniq(char **l, const char *prefix) {
310
311         if (strv_isempty(l))
312                 return l;
313
314         if (!path_strv_resolve(l, prefix))
315                 return NULL;
316
317         return strv_uniq(l);
318 }
319
320 char *path_kill_slashes(char *path) {
321         char *f, *t;
322         bool slash = false;
323
324         /* Removes redundant inner and trailing slashes. Modifies the
325          * passed string in-place.
326          *
327          * ///foo///bar/ becomes /foo/bar
328          */
329
330         for (f = path, t = path; *f; f++) {
331
332                 if (*f == '/') {
333                         slash = true;
334                         continue;
335                 }
336
337                 if (slash) {
338                         slash = false;
339                         *(t++) = '/';
340                 }
341
342                 *(t++) = *f;
343         }
344
345         /* Special rule, if we are talking of the root directory, a
346         trailing slash is good */
347
348         if (t == path && slash)
349                 *(t++) = '/';
350
351         *t = 0;
352         return path;
353 }
354
355 char* path_startswith(const char *path, const char *prefix) {
356         assert(path);
357         assert(prefix);
358
359         if ((path[0] == '/') != (prefix[0] == '/'))
360                 return NULL;
361
362         for (;;) {
363                 size_t a, b;
364
365                 path += strspn(path, "/");
366                 prefix += strspn(prefix, "/");
367
368                 if (*prefix == 0)
369                         return (char*) path;
370
371                 if (*path == 0)
372                         return NULL;
373
374                 a = strcspn(path, "/");
375                 b = strcspn(prefix, "/");
376
377                 if (a != b)
378                         return NULL;
379
380                 if (memcmp(path, prefix, a) != 0)
381                         return NULL;
382
383                 path += a;
384                 prefix += b;
385         }
386 }
387
388 int path_compare(const char *a, const char *b) {
389         int d;
390
391         assert(a);
392         assert(b);
393
394         /* A relative path and an abolute path must not compare as equal.
395          * Which one is sorted before the other does not really matter.
396          * Here a relative path is ordered before an absolute path. */
397         d = (a[0] == '/') - (b[0] == '/');
398         if (d != 0)
399                 return d;
400
401         for (;;) {
402                 size_t j, k;
403
404                 a += strspn(a, "/");
405                 b += strspn(b, "/");
406
407                 if (*a == 0 && *b == 0)
408                         return 0;
409
410                 /* Order prefixes first: "/foo" before "/foo/bar" */
411                 if (*a == 0)
412                         return -1;
413                 if (*b == 0)
414                         return 1;
415
416                 j = strcspn(a, "/");
417                 k = strcspn(b, "/");
418
419                 /* Alphabetical sort: "/foo/aaa" before "/foo/b" */
420                 d = memcmp(a, b, MIN(j, k));
421                 if (d != 0)
422                         return (d > 0) - (d < 0); /* sign of d */
423
424                 /* Sort "/foo/a" before "/foo/aaa" */
425                 d = (j > k) - (j < k);  /* sign of (j - k) */
426                 if (d != 0)
427                         return d;
428
429                 a += j;
430                 b += k;
431         }
432 }
433
434 bool path_equal(const char *a, const char *b) {
435         return path_compare(a, b) == 0;
436 }
437
438 bool path_equal_or_files_same(const char *a, const char *b) {
439         return path_equal(a, b) || files_same(a, b) > 0;
440 }
441
442 #if 0 /// UNNEEDED by elogind
443 char* path_join(const char *root, const char *path, const char *rest) {
444         assert(path);
445
446         if (!isempty(root))
447                 return strjoin(root, endswith(root, "/") ? "" : "/",
448                                path[0] == '/' ? path+1 : path,
449                                rest ? (endswith(path, "/") ? "" : "/") : NULL,
450                                rest && rest[0] == '/' ? rest+1 : rest);
451         else
452                 return strjoin(path,
453                                rest ? (endswith(path, "/") ? "" : "/") : NULL,
454                                rest && rest[0] == '/' ? rest+1 : rest);
455 }
456
457 int find_binary(const char *name, char **ret) {
458         int last_error, r;
459         const char *p;
460
461         assert(name);
462
463         if (is_path(name)) {
464                 if (access(name, X_OK) < 0)
465                         return -errno;
466
467                 if (ret) {
468                         r = path_make_absolute_cwd(name, ret);
469                         if (r < 0)
470                                 return r;
471                 }
472
473                 return 0;
474         }
475
476         /**
477          * Plain getenv, not secure_getenv, because we want
478          * to actually allow the user to pick the binary.
479          */
480         p = getenv("PATH");
481         if (!p)
482                 p = DEFAULT_PATH;
483
484         last_error = -ENOENT;
485
486         for (;;) {
487                 _cleanup_free_ char *j = NULL, *element = NULL;
488
489                 r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS);
490                 if (r < 0)
491                         return r;
492                 if (r == 0)
493                         break;
494
495                 if (!path_is_absolute(element))
496                         continue;
497
498                 j = strjoin(element, "/", name);
499                 if (!j)
500                         return -ENOMEM;
501
502                 if (access(j, X_OK) >= 0) {
503                         /* Found it! */
504
505                         if (ret) {
506                                 *ret = path_kill_slashes(j);
507                                 j = NULL;
508                         }
509
510                         return 0;
511                 }
512
513                 last_error = -errno;
514         }
515
516         return last_error;
517 }
518
519 bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) {
520         bool changed = false;
521         const char* const* i;
522
523         assert(timestamp);
524
525         if (paths == NULL)
526                 return false;
527
528         STRV_FOREACH(i, paths) {
529                 struct stat stats;
530                 usec_t u;
531
532                 if (stat(*i, &stats) < 0)
533                         continue;
534
535                 u = timespec_load(&stats.st_mtim);
536
537                 /* first check */
538                 if (*timestamp >= u)
539                         continue;
540
541                 log_debug("timestamp of '%s' changed", *i);
542
543                 /* update timestamp */
544                 if (update) {
545                         *timestamp = u;
546                         changed = true;
547                 } else
548                         return true;
549         }
550
551         return changed;
552 }
553
554 static int binary_is_good(const char *binary) {
555         _cleanup_free_ char *p = NULL, *d = NULL;
556         int r;
557
558         r = find_binary(binary, &p);
559         if (r == -ENOENT)
560                 return 0;
561         if (r < 0)
562                 return r;
563
564         /* An fsck that is linked to /bin/true is a non-existent
565          * fsck */
566
567         r = readlink_malloc(p, &d);
568         if (r == -EINVAL) /* not a symlink */
569                 return 1;
570         if (r < 0)
571                 return r;
572
573         return !PATH_IN_SET(d, "true"
574                                "/bin/true",
575                                "/usr/bin/true",
576                                "/dev/null");
577 }
578
579 int fsck_exists(const char *fstype) {
580         const char *checker;
581
582         assert(fstype);
583
584         if (streq(fstype, "auto"))
585                 return -EINVAL;
586
587         checker = strjoina("fsck.", fstype);
588         return binary_is_good(checker);
589 }
590
591 int mkfs_exists(const char *fstype) {
592         const char *mkfs;
593
594         assert(fstype);
595
596         if (streq(fstype, "auto"))
597                 return -EINVAL;
598
599         mkfs = strjoina("mkfs.", fstype);
600         return binary_is_good(mkfs);
601 }
602
603 char *prefix_root(const char *root, const char *path) {
604         char *n, *p;
605         size_t l;
606
607         /* If root is passed, prefixes path with it. Otherwise returns
608          * it as is. */
609
610         assert(path);
611
612         /* First, drop duplicate prefixing slashes from the path */
613         while (path[0] == '/' && path[1] == '/')
614                 path++;
615
616         if (isempty(root) || path_equal(root, "/"))
617                 return strdup(path);
618
619         l = strlen(root) + 1 + strlen(path) + 1;
620
621         n = new(char, l);
622         if (!n)
623                 return NULL;
624
625         p = stpcpy(n, root);
626
627         while (p > n && p[-1] == '/')
628                 p--;
629
630         if (path[0] != '/')
631                 *(p++) = '/';
632
633         strcpy(p, path);
634         return n;
635 }
636
637 int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) {
638         char *p;
639         int r;
640
641         /*
642          * This function is intended to be used in command line
643          * parsers, to handle paths that are passed in. It makes the
644          * path absolute, and reduces it to NULL if omitted or
645          * root (the latter optionally).
646          *
647          * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON
648          * SUCCESS! Hence, do not pass in uninitialized pointers.
649          */
650
651         if (isempty(path)) {
652                 *arg = mfree(*arg);
653                 return 0;
654         }
655
656         r = path_make_absolute_cwd(path, &p);
657         if (r < 0)
658                 return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
659
660         path_kill_slashes(p);
661         if (suppress_root && path_equal(p, "/"))
662                 p = mfree(p);
663
664         free(*arg);
665         *arg = p;
666         return 0;
667 }
668 #endif // 0
669
670 char* dirname_malloc(const char *path) {
671         char *d, *dir, *dir2;
672
673         assert(path);
674
675         d = strdup(path);
676         if (!d)
677                 return NULL;
678
679         dir = dirname(d);
680         assert(dir);
681
682         if (dir == d)
683                 return d;
684
685         dir2 = strdup(dir);
686         free(d);
687
688         return dir2;
689 }
690
691 bool filename_is_valid(const char *p) {
692         const char *e;
693
694         if (isempty(p))
695                 return false;
696
697         if (streq(p, "."))
698                 return false;
699
700         if (streq(p, ".."))
701                 return false;
702
703         e = strchrnul(p, '/');
704         if (*e != 0)
705                 return false;
706
707         if (e - p > FILENAME_MAX)
708                 return false;
709
710         return true;
711 }
712
713 bool path_is_safe(const char *p) {
714
715         if (isempty(p))
716                 return false;
717
718         if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
719                 return false;
720
721         if (strlen(p)+1 > PATH_MAX)
722                 return false;
723
724         /* The following two checks are not really dangerous, but hey, they still are confusing */
725         if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
726                 return false;
727
728         if (strstr(p, "//"))
729                 return false;
730
731         return true;
732 }
733
734 char *file_in_same_dir(const char *path, const char *filename) {
735         char *e, *ret;
736         size_t k;
737
738         assert(path);
739         assert(filename);
740
741         /* This removes the last component of path and appends
742          * filename, unless the latter is absolute anyway or the
743          * former isn't */
744
745         if (path_is_absolute(filename))
746                 return strdup(filename);
747
748         e = strrchr(path, '/');
749         if (!e)
750                 return strdup(filename);
751
752         k = strlen(filename);
753         ret = new(char, (e + 1 - path) + k + 1);
754         if (!ret)
755                 return NULL;
756
757         memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
758         return ret;
759 }
760
761 bool hidden_or_backup_file(const char *filename) {
762         const char *p;
763
764         assert(filename);
765
766         if (filename[0] == '.' ||
767             streq(filename, "lost+found") ||
768             streq(filename, "aquota.user") ||
769             streq(filename, "aquota.group") ||
770             endswith(filename, "~"))
771                 return true;
772
773         p = strrchr(filename, '.');
774         if (!p)
775                 return false;
776
777         /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
778          * with always new suffixes and that everybody else should just adjust to that, then it really should be on
779          * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
780          * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
781          * string. Specifically: there's now:
782          *
783          *    The generic suffixes "~" and ".bak" for backup files
784          *    The generic prefix "." for hidden files
785          *
786          * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
787          * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
788          */
789
790         return STR_IN_SET(p + 1,
791                           "rpmnew",
792                           "rpmsave",
793                           "rpmorig",
794                           "dpkg-old",
795                           "dpkg-new",
796                           "dpkg-tmp",
797                           "dpkg-dist",
798                           "dpkg-bak",
799                           "dpkg-backup",
800                           "dpkg-remove",
801                           "ucf-new",
802                           "ucf-old",
803                           "ucf-dist",
804                           "swp",
805                           "bak",
806                           "old",
807                           "new");
808 }
809
810 #if 0 /// UNNEEDED by elogind
811 bool is_device_path(const char *path) {
812
813         /* Returns true on paths that refer to a device, either in
814          * sysfs or in /dev */
815
816         return path_startswith(path, "/dev/") ||
817                path_startswith(path, "/sys/");
818 }
819
820 bool is_deviceallow_pattern(const char *path) {
821         return path_startswith(path, "/dev/") ||
822                startswith(path, "block-") ||
823                startswith(path, "char-");
824 }
825
826 int systemd_installation_has_version(const char *root, unsigned minimal_version) {
827         const char *pattern;
828         int r;
829
830         /* Try to guess if systemd installation is later than the specified version. This
831          * is hacky and likely to yield false negatives, particularly if the installation
832          * is non-standard. False positives should be relatively rare.
833          */
834
835         NULSTR_FOREACH(pattern,
836                        /* /lib works for systems without usr-merge, and for systems with a sane
837                         * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
838                         * for Gentoo which does a merge without making /lib a symlink.
839                         */
840                        "lib/systemd/libsystemd-shared-*.so\0"
841                        "usr/lib/systemd/libsystemd-shared-*.so\0") {
842
843                 _cleanup_strv_free_ char **names = NULL;
844                 _cleanup_free_ char *path = NULL;
845                 char *c, **name;
846
847                 path = prefix_root(root, pattern);
848                 if (!path)
849                         return -ENOMEM;
850
851                 r = glob_extend(&names, path);
852                 if (r == -ENOENT)
853                         continue;
854                 if (r < 0)
855                         return r;
856
857                 assert_se((c = endswith(path, "*.so")));
858                 *c = '\0'; /* truncate the glob part */
859
860                 STRV_FOREACH(name, names) {
861                         /* This is most likely to run only once, hence let's not optimize anything. */
862                         char *t, *t2;
863                         unsigned version;
864
865                         t = startswith(*name, path);
866                         if (!t)
867                                 continue;
868
869                         t2 = endswith(t, ".so");
870                         if (!t2)
871                                 continue;
872
873                         t2[0] = '\0'; /* truncate the suffix */
874
875                         r = safe_atou(t, &version);
876                         if (r < 0) {
877                                 log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
878                                 continue;
879                         }
880
881                         log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
882                                   *name, version,
883                                   version >= minimal_version ? "OK" : "too old");
884                         if (version >= minimal_version)
885                                 return true;
886                 }
887         }
888
889         return false;
890 }
891 #endif // 0