chiark / gitweb /
tree-wide: make bus_map_all_properties return a proper sd_bus_error
[elogind.git] / src / basic / fs-util.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010 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 <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <unistd.h>
28
29 #include "alloc-util.h"
30 #include "dirent-util.h"
31 #include "fd-util.h"
32 #include "fileio.h"
33 #include "fs-util.h"
34 //#include "log.h"
35 //#include "macro.h"
36 //#include "missing.h"
37 #include "mkdir.h"
38 #include "parse-util.h"
39 #include "path-util.h"
40 #include "string-util.h"
41 #include "strv.h"
42 //#include "time-util.h"
43 #include "user-util.h"
44 #include "util.h"
45
46 int unlink_noerrno(const char *path) {
47         PROTECT_ERRNO;
48         int r;
49
50         r = unlink(path);
51         if (r < 0)
52                 return -errno;
53
54         return 0;
55 }
56
57 #if 0 /// UNNEEDED by elogind
58 int rmdir_parents(const char *path, const char *stop) {
59         size_t l;
60         int r = 0;
61
62         assert(path);
63         assert(stop);
64
65         l = strlen(path);
66
67         /* Skip trailing slashes */
68         while (l > 0 && path[l-1] == '/')
69                 l--;
70
71         while (l > 0) {
72                 char *t;
73
74                 /* Skip last component */
75                 while (l > 0 && path[l-1] != '/')
76                         l--;
77
78                 /* Skip trailing slashes */
79                 while (l > 0 && path[l-1] == '/')
80                         l--;
81
82                 if (l <= 0)
83                         break;
84
85                 t = strndup(path, l);
86                 if (!t)
87                         return -ENOMEM;
88
89                 if (path_startswith(stop, t)) {
90                         free(t);
91                         return 0;
92                 }
93
94                 r = rmdir(t);
95                 free(t);
96
97                 if (r < 0)
98                         if (errno != ENOENT)
99                                 return -errno;
100         }
101
102         return 0;
103 }
104
105
106 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
107         struct stat buf;
108         int ret;
109
110         ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
111         if (ret >= 0)
112                 return 0;
113
114         /* renameat2() exists since Linux 3.15, btrfs added support for it later.
115          * If it is not implemented, fallback to another method. */
116         if (!IN_SET(errno, EINVAL, ENOSYS))
117                 return -errno;
118
119         /* The link()/unlink() fallback does not work on directories. But
120          * renameat() without RENAME_NOREPLACE gives the same semantics on
121          * directories, except when newpath is an *empty* directory. This is
122          * good enough. */
123         ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
124         if (ret >= 0 && S_ISDIR(buf.st_mode)) {
125                 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
126                 return ret >= 0 ? 0 : -errno;
127         }
128
129         /* If it is not a directory, use the link()/unlink() fallback. */
130         ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
131         if (ret < 0)
132                 return -errno;
133
134         ret = unlinkat(olddirfd, oldpath, 0);
135         if (ret < 0) {
136                 /* backup errno before the following unlinkat() alters it */
137                 ret = errno;
138                 (void) unlinkat(newdirfd, newpath, 0);
139                 errno = ret;
140                 return -errno;
141         }
142
143         return 0;
144 }
145 #endif // 0
146
147 int readlinkat_malloc(int fd, const char *p, char **ret) {
148         size_t l = 100;
149         int r;
150
151         assert(p);
152         assert(ret);
153
154         for (;;) {
155                 char *c;
156                 ssize_t n;
157
158                 c = new(char, l);
159                 if (!c)
160                         return -ENOMEM;
161
162                 n = readlinkat(fd, p, c, l-1);
163                 if (n < 0) {
164                         r = -errno;
165                         free(c);
166                         return r;
167                 }
168
169                 if ((size_t) n < l-1) {
170                         c[n] = 0;
171                         *ret = c;
172                         return 0;
173                 }
174
175                 free(c);
176                 l *= 2;
177         }
178 }
179
180 int readlink_malloc(const char *p, char **ret) {
181         return readlinkat_malloc(AT_FDCWD, p, ret);
182 }
183
184 #if 0 /// UNNEEDED by elogind
185 int readlink_value(const char *p, char **ret) {
186         _cleanup_free_ char *link = NULL;
187         char *value;
188         int r;
189
190         r = readlink_malloc(p, &link);
191         if (r < 0)
192                 return r;
193
194         value = basename(link);
195         if (!value)
196                 return -ENOENT;
197
198         value = strdup(value);
199         if (!value)
200                 return -ENOMEM;
201
202         *ret = value;
203
204         return 0;
205 }
206
207 int readlink_and_make_absolute(const char *p, char **r) {
208         _cleanup_free_ char *target = NULL;
209         char *k;
210         int j;
211
212         assert(p);
213         assert(r);
214
215         j = readlink_malloc(p, &target);
216         if (j < 0)
217                 return j;
218
219         k = file_in_same_dir(p, target);
220         if (!k)
221                 return -ENOMEM;
222
223         *r = k;
224         return 0;
225 }
226
227 int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
228         char *t, *s;
229         int r;
230
231         assert(p);
232         assert(ret);
233
234         r = readlink_and_make_absolute(p, &t);
235         if (r < 0)
236                 return r;
237
238         r = chase_symlinks(t, root, 0, &s);
239         if (r < 0)
240                 /* If we can't follow up, then let's return the original string, slightly cleaned up. */
241                 *ret = path_kill_slashes(t);
242         else {
243                 *ret = s;
244                 free(t);
245         }
246
247         return 0;
248 }
249
250 int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
251         _cleanup_free_ char *target = NULL, *t = NULL;
252         const char *full;
253         int r;
254
255         full = prefix_roota(root, path);
256         r = readlink_malloc(full, &target);
257         if (r < 0)
258                 return r;
259
260         t = file_in_same_dir(path, target);
261         if (!t)
262                 return -ENOMEM;
263
264         *ret = t;
265         t = NULL;
266
267         return 0;
268 }
269 #endif // 0
270
271 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
272         assert(path);
273
274         /* Under the assumption that we are running privileged we
275          * first change the access mode and only then hand out
276          * ownership to avoid a window where access is too open. */
277
278         if (mode != MODE_INVALID)
279                 if (chmod(path, mode) < 0)
280                         return -errno;
281
282         if (uid != UID_INVALID || gid != GID_INVALID)
283                 if (chown(path, uid, gid) < 0)
284                         return -errno;
285
286         return 0;
287 }
288
289 int fchmod_umask(int fd, mode_t m) {
290         mode_t u;
291         int r;
292
293         u = umask(0777);
294         r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
295         umask(u);
296
297         return r;
298 }
299
300 int fd_warn_permissions(const char *path, int fd) {
301         struct stat st;
302
303         if (fstat(fd, &st) < 0)
304                 return -errno;
305
306         if (st.st_mode & 0111)
307                 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
308
309         if (st.st_mode & 0002)
310                 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
311
312         if (getpid() == 1 && (st.st_mode & 0044) != 0044)
313                 log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
314
315         return 0;
316 }
317
318 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
319         _cleanup_close_ int fd;
320         int r;
321
322         assert(path);
323
324         if (parents)
325                 mkdir_parents(path, 0755);
326
327         fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
328                         (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
329         if (fd < 0)
330                 return -errno;
331
332         if (mode != MODE_INVALID) {
333                 r = fchmod(fd, mode);
334                 if (r < 0)
335                         return -errno;
336         }
337
338         if (uid != UID_INVALID || gid != GID_INVALID) {
339                 r = fchown(fd, uid, gid);
340                 if (r < 0)
341                         return -errno;
342         }
343
344         if (stamp != USEC_INFINITY) {
345                 struct timespec ts[2];
346
347                 timespec_store(&ts[0], stamp);
348                 ts[1] = ts[0];
349                 r = futimens(fd, ts);
350         } else
351                 r = futimens(fd, NULL);
352         if (r < 0)
353                 return -errno;
354
355         return 0;
356 }
357
358 int touch(const char *path) {
359         return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
360 }
361
362 #if 0 /// UNNEEDED by elogind
363 int symlink_idempotent(const char *from, const char *to) {
364         _cleanup_free_ char *p = NULL;
365         int r;
366
367         assert(from);
368         assert(to);
369
370         if (symlink(from, to) < 0) {
371                 if (errno != EEXIST)
372                         return -errno;
373
374                 r = readlink_malloc(to, &p);
375                 if (r < 0)
376                         return r;
377
378                 if (!streq(p, from))
379                         return -EINVAL;
380         }
381
382         return 0;
383 }
384
385 int symlink_atomic(const char *from, const char *to) {
386         _cleanup_free_ char *t = NULL;
387         int r;
388
389         assert(from);
390         assert(to);
391
392         r = tempfn_random(to, NULL, &t);
393         if (r < 0)
394                 return r;
395
396         if (symlink(from, t) < 0)
397                 return -errno;
398
399         if (rename(t, to) < 0) {
400                 unlink_noerrno(t);
401                 return -errno;
402         }
403
404         return 0;
405 }
406
407 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
408         _cleanup_free_ char *t = NULL;
409         int r;
410
411         assert(path);
412
413         r = tempfn_random(path, NULL, &t);
414         if (r < 0)
415                 return r;
416
417         if (mknod(t, mode, dev) < 0)
418                 return -errno;
419
420         if (rename(t, path) < 0) {
421                 unlink_noerrno(t);
422                 return -errno;
423         }
424
425         return 0;
426 }
427
428 int mkfifo_atomic(const char *path, mode_t mode) {
429         _cleanup_free_ char *t = NULL;
430         int r;
431
432         assert(path);
433
434         r = tempfn_random(path, NULL, &t);
435         if (r < 0)
436                 return r;
437
438         if (mkfifo(t, mode) < 0)
439                 return -errno;
440
441         if (rename(t, path) < 0) {
442                 unlink_noerrno(t);
443                 return -errno;
444         }
445
446         return 0;
447 }
448 #endif // 0
449
450 int get_files_in_directory(const char *path, char ***list) {
451         _cleanup_closedir_ DIR *d = NULL;
452         struct dirent *de;
453         size_t bufsize = 0, n = 0;
454         _cleanup_strv_free_ char **l = NULL;
455
456         assert(path);
457
458         /* Returns all files in a directory in *list, and the number
459          * of files as return value. If list is NULL returns only the
460          * number. */
461
462         d = opendir(path);
463         if (!d)
464                 return -errno;
465
466         FOREACH_DIRENT_ALL(de, d, return -errno) {
467                 dirent_ensure_type(d, de);
468
469                 if (!dirent_is_file(de))
470                         continue;
471
472                 if (list) {
473                         /* one extra slot is needed for the terminating NULL */
474                         if (!GREEDY_REALLOC(l, bufsize, n + 2))
475                                 return -ENOMEM;
476
477                         l[n] = strdup(de->d_name);
478                         if (!l[n])
479                                 return -ENOMEM;
480
481                         l[++n] = NULL;
482                 } else
483                         n++;
484         }
485
486         if (list) {
487                 *list = l;
488                 l = NULL; /* avoid freeing */
489         }
490
491         return n;
492 }
493
494 #if 0 /// UNNEEDED by elogind
495 static int getenv_tmp_dir(const char **ret_path) {
496         const char *n;
497         int r, ret = 0;
498
499         assert(ret_path);
500
501         /* We use the same order of environment variables python uses in tempfile.gettempdir():
502          * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
503         FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
504                 const char *e;
505
506                 e = secure_getenv(n);
507                 if (!e)
508                         continue;
509                 if (!path_is_absolute(e)) {
510                         r = -ENOTDIR;
511                         goto next;
512                 }
513                 if (!path_is_safe(e)) {
514                         r = -EPERM;
515                         goto next;
516                 }
517
518                 r = is_dir(e, true);
519                 if (r < 0)
520                         goto next;
521                 if (r == 0) {
522                         r = -ENOTDIR;
523                         goto next;
524                 }
525
526                 *ret_path = e;
527                 return 1;
528
529         next:
530                 /* Remember first error, to make this more debuggable */
531                 if (ret >= 0)
532                         ret = r;
533         }
534
535         if (ret < 0)
536                 return ret;
537
538         *ret_path = NULL;
539         return ret;
540 }
541
542 static int tmp_dir_internal(const char *def, const char **ret) {
543         const char *e;
544         int r, k;
545
546         assert(def);
547         assert(ret);
548
549         r = getenv_tmp_dir(&e);
550         if (r > 0) {
551                 *ret = e;
552                 return 0;
553         }
554
555         k = is_dir(def, true);
556         if (k == 0)
557                 k = -ENOTDIR;
558         if (k < 0)
559                 return r < 0 ? r : k;
560
561         *ret = def;
562         return 0;
563 }
564
565 int var_tmp_dir(const char **ret) {
566
567         /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
568          * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
569          * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
570          * making it a variable that overrides all temporary file storage locations. */
571
572         return tmp_dir_internal("/var/tmp", ret);
573 }
574
575 int tmp_dir(const char **ret) {
576
577         /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
578          * backed by an in-memory file system: /tmp. */
579
580         return tmp_dir_internal("/tmp", ret);
581 }
582
583 int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
584         char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
585         int r;
586
587         /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
588         xsprintf(path, "/proc/self/fd/%i", what);
589
590         r = inotify_add_watch(fd, path, mask);
591         if (r < 0)
592                 return -errno;
593
594         return r;
595 }
596
597 int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
598         _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
599         _cleanup_close_ int fd = -1;
600         unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
601         bool exists = true;
602         char *todo;
603         int r;
604
605         assert(path);
606
607         /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
608          * symlinks relative to a root directory, instead of the root of the host.
609          *
610          * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
611          * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
612          * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
613          * prefixed accordingly.
614          *
615          * Algorithmically this operates on two path buffers: "done" are the components of the path we already
616          * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
617          * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
618          * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
619          * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
620          * at a minimum.
621          *
622          * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
623          * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
624          * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
625          * specified path.
626          *
627          * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the
628          * passed root. */
629
630         if (original_root) {
631                 r = path_make_absolute_cwd(original_root, &root);
632                 if (r < 0)
633                         return r;
634
635                 if (flags & CHASE_PREFIX_ROOT)
636                         path = prefix_roota(root, path);
637         }
638
639         r = path_make_absolute_cwd(path, &buffer);
640         if (r < 0)
641                 return r;
642
643         fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
644         if (fd < 0)
645                 return -errno;
646
647         todo = buffer;
648         for (;;) {
649                 _cleanup_free_ char *first = NULL;
650                 _cleanup_close_ int child = -1;
651                 struct stat st;
652                 size_t n, m;
653
654                 /* Determine length of first component in the path */
655                 n = strspn(todo, "/");                  /* The slashes */
656                 m = n + strcspn(todo + n, "/");         /* The entire length of the component */
657
658                 /* Extract the first component. */
659                 first = strndup(todo, m);
660                 if (!first)
661                         return -ENOMEM;
662
663                 todo += m;
664
665                 /* Just a single slash? Then we reached the end. */
666                 if (isempty(first) || path_equal(first, "/"))
667                         break;
668
669                 /* Just a dot? Then let's eat this up. */
670                 if (path_equal(first, "/."))
671                         continue;
672
673                 /* Two dots? Then chop off the last bit of what we already found out. */
674                 if (path_equal(first, "/..")) {
675                         _cleanup_free_ char *parent = NULL;
676                         int fd_parent = -1;
677
678                         /* If we already are at the top, then going up will not change anything. This is in-line with
679                          * how the kernel handles this. */
680                         if (isempty(done) || path_equal(done, "/"))
681                                 continue;
682
683                         parent = dirname_malloc(done);
684                         if (!parent)
685                                 return -ENOMEM;
686
687                         /* Don't allow this to leave the root dir.  */
688                         if (root &&
689                             path_startswith(done, root) &&
690                             !path_startswith(parent, root))
691                                 continue;
692
693                         free_and_replace(done, parent);
694
695                         fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
696                         if (fd_parent < 0)
697                                 return -errno;
698
699                         safe_close(fd);
700                         fd = fd_parent;
701
702                         continue;
703                 }
704
705                 /* Otherwise let's see what this is. */
706                 child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH);
707                 if (child < 0) {
708
709                         if (errno == ENOENT &&
710                             (flags & CHASE_NONEXISTENT) &&
711                             (isempty(todo) || path_is_safe(todo))) {
712
713                                 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
714                                  * what we got so far. But don't allow this if the remaining path contains "../ or "./"
715                                  * or something else weird. */
716
717                                 if (!strextend(&done, first, todo, NULL))
718                                         return -ENOMEM;
719
720                                 exists = false;
721                                 break;
722                         }
723
724                         return -errno;
725                 }
726
727                 if (fstat(child, &st) < 0)
728                         return -errno;
729
730                 if (S_ISLNK(st.st_mode)) {
731                         char *joined;
732
733                         _cleanup_free_ char *destination = NULL;
734
735                         /* This is a symlink, in this case read the destination. But let's make sure we don't follow
736                          * symlinks without bounds. */
737                         if (--max_follow <= 0)
738                                 return -ELOOP;
739
740                         r = readlinkat_malloc(fd, first + n, &destination);
741                         if (r < 0)
742                                 return r;
743                         if (isempty(destination))
744                                 return -EINVAL;
745
746                         if (path_is_absolute(destination)) {
747
748                                 /* An absolute destination. Start the loop from the beginning, but use the root
749                                  * directory as base. */
750
751                                 safe_close(fd);
752                                 fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
753                                 if (fd < 0)
754                                         return -errno;
755
756                                 free(done);
757
758                                 /* Note that we do not revalidate the root, we take it as is. */
759                                 if (isempty(root))
760                                         done = NULL;
761                                 else {
762                                         done = strdup(root);
763                                         if (!done)
764                                                 return -ENOMEM;
765                                 }
766
767                         }
768
769                         /* Prefix what's left to do with what we just read, and start the loop again,
770                          * but remain in the current directory. */
771
772                         joined = strjoin("/", destination, todo);
773                         if (!joined)
774                                 return -ENOMEM;
775
776                         free(buffer);
777                         todo = buffer = joined;
778
779                         continue;
780                 }
781
782                 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
783                 if (!done) {
784                         done = first;
785                         first = NULL;
786                 } else {
787                         if (!strextend(&done, first, NULL))
788                                 return -ENOMEM;
789                 }
790
791                 /* And iterate again, but go one directory further down. */
792                 safe_close(fd);
793                 fd = child;
794                 child = -1;
795         }
796
797         if (!done) {
798                 /* Special case, turn the empty string into "/", to indicate the root directory. */
799                 done = strdup("/");
800                 if (!done)
801                         return -ENOMEM;
802         }
803
804         *ret = done;
805         done = NULL;
806
807         return exists;
808 }
809 #endif // 0