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