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