66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering/***
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering This file is part of systemd.
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering Copyright 2010-2012 Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering systemd is free software; you can redistribute it and/or modify it
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering under the terms of the GNU Lesser General Public License as published by
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering (at your option) any later version.
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering systemd is distributed in the hope that it will be useful, but
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering Lesser General Public License for more details.
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering You should have received a copy of the GNU Lesser General Public License
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering***/
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <dirent.h>
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen#include <errno.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <fcntl.h>
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen#include <sys/stat.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/types.h>
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen#include <linux/magic.h>
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen#include <sys/statvfs.h>
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen#include <unistd.h>
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering#include "dirent-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fd-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "macro.h"
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering#include "missing.h"
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen#include "stat-util.h"
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering#include "string-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersenint is_symlink(const char *path) {
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering struct stat info;
0d39fa9c69b97a2ceb156053deef69c0866c2b97Lennart Poettering
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier assert(path);
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen
a8fbdf5424be099ba1b2b1ec261c02b8759d6b0cThomas Hindoe Paaboel Andersen if (lstat(path, &info) < 0)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return !!S_ISLNK(info.st_mode);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint is_dir(const char* path, bool follow) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct stat st;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering int r;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(path);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (follow)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering r = stat(path, &st);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering else
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt r = lstat(path, &st);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (r < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return !!S_ISDIR(st.st_mode);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint is_device_node(const char *path) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct stat info;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(path);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (lstat(path, &info) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint dir_is_empty(const char *path) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering _cleanup_closedir_ DIR *d;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct dirent *de;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering d = opendir(path);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (!d)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering FOREACH_DIRENT(de, d, return -errno)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return 0;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return 1;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringbool null_or_empty(struct stat *st) {
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering assert(st);
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering if (S_ISREG(st->st_mode) && st->st_size <= 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return true;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering /* We don't want to hardcode the major/minor of /dev/null,
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering * hence we do a simpler "is this a device node?" check. */
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt return true;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return false;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint null_or_empty_path(const char *fn) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct stat st;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(fn);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (stat(fn, &st) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return null_or_empty(&st);
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint null_or_empty_fd(int fd) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct stat st;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(fd >= 0);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (fstat(fd, &st) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return null_or_empty(&st);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint path_is_read_only_fs(const char *path) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct statvfs st;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(path);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (statvfs(path, &st) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (st.f_flag & ST_RDONLY)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return true;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering /* On NFS, statvfs() might not reflect whether we can actually
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering * write to the remote share. Let's try again with
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering * access(W_OK) which is more reliable, at least sometimes. */
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (access(path, W_OK) < 0 && errno == EROFS)
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering return true;
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering return false;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint path_is_os_tree(const char *path) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering char *p;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering int r;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt assert(path);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering /* We use /usr/lib/os-release as flag file if something is an OS */
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering p = strjoina(path, "/usr/lib/os-release");
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering r = access(p, F_OK);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (r >= 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return 1;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering /* Also check for the old location in /etc, just in case. */
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering p = strjoina(path, "/etc/os-release");
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering r = access(p, F_OK);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return r >= 0;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint files_same(const char *filea, const char *fileb) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct stat a, b;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(filea);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(fileb);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (stat(filea, &a) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (stat(fileb, &b) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return a.st_dev == b.st_dev &&
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering a.st_ino == b.st_ino;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringbool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert(s);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return F_TYPE_EQUAL(s->f_type, magic_value);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint fd_check_fstype(int fd, statfs_f_type_t magic_value) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct statfs s;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (fstatfs(fd, &s) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering return is_fs_type(&s, magic_value);
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint path_check_fstype(const char *path, statfs_f_type_t magic_value) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering _cleanup_close_ int fd = -1;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering fd = open(path, O_RDONLY);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (fd < 0)
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return fd_check_fstype(fd, magic_value);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringbool is_temporary_fs(const struct statfs *s) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return is_fs_type(s, TMPFS_MAGIC) ||
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering is_fs_type(s, RAMFS_MAGIC);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poetteringint fd_is_temporary_fs(int fd) {
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering struct statfs s;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering if (fstatfs(fd, &s) < 0)
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return -errno;
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering return is_temporary_fs(&s);
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering}
66cdd0f2d0670b054bd27dad16fcb5838b11dde3Lennart Poettering