fs-util.c revision 06eeacb6fe029804f296b065b3ce91e796e1cd0e
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dirent.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "alloc-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "user-util.h"
#include "util.h"
int unlink_noerrno(const char *path) {
int r;
if (r < 0)
return -errno;
return 0;
}
size_t l;
int r = 0;
/* Skip trailing slashes */
l--;
while (l > 0) {
char *t;
/* Skip last component */
l--;
/* Skip trailing slashes */
l--;
if (l <= 0)
break;
if (!t)
return -ENOMEM;
if (path_startswith(stop, t)) {
free(t);
return 0;
}
r = rmdir(t);
free(t);
if (r < 0)
return -errno;
}
return 0;
}
int ret;
if (ret >= 0)
return 0;
/* renameat2() exists since Linux 3.15, btrfs added support for it later.
* If it is not implemented, fallback to another method. */
return -errno;
/* The link()/unlink() fallback does not work on directories. But
* renameat() without RENAME_NOREPLACE gives the same semantics on
* directories, except when newpath is an *empty* directory. This is
* good enough. */
}
/* If it is not a directory, use the link()/unlink() fallback. */
if (ret < 0)
return -errno;
if (ret < 0) {
/* backup errno before the following unlinkat() alters it */
return -errno;
}
return 0;
}
size_t l = 100;
int r;
assert(p);
for (;;) {
char *c;
ssize_t n;
c = new(char, l);
if (!c)
return -ENOMEM;
if (n < 0) {
r = -errno;
free(c);
return r;
}
if ((size_t) n < l-1) {
c[n] = 0;
*ret = c;
return 0;
}
free(c);
l *= 2;
}
}
int readlink_malloc(const char *p, char **ret) {
}
int readlink_value(const char *p, char **ret) {
char *value;
int r;
r = readlink_malloc(p, &link);
if (r < 0)
return r;
if (!value)
return -ENOENT;
if (!value)
return -ENOMEM;
return 0;
}
int readlink_and_make_absolute(const char *p, char **r) {
char *k;
int j;
assert(p);
assert(r);
j = readlink_malloc(p, &target);
if (j < 0)
return j;
k = file_in_same_dir(p, target);
if (!k)
return -ENOMEM;
*r = k;
return 0;
}
int readlink_and_canonicalize(const char *p, char **r) {
char *t, *s;
int j;
assert(p);
assert(r);
j = readlink_and_make_absolute(p, &t);
if (j < 0)
return j;
s = canonicalize_file_name(t);
if (s) {
free(t);
*r = s;
} else
*r = t;
path_kill_slashes(*r);
return 0;
}
const char *full;
int r;
if (r < 0)
return r;
if (!t)
return -ENOMEM;
*ret = t;
t = NULL;
return 0;
}
/* Under the assumption that we are running privileged we
* first change the access mode and only then hand out
* ownership to avoid a window where access is too open. */
if (mode != MODE_INVALID)
return -errno;
return -errno;
return 0;
}
/* Under the assumption that we are running privileged we
* first change the access mode and only then hand out
* ownership to avoid a window where access is too open. */
if (mode != MODE_INVALID)
return -errno;
return -errno;
return 0;
}
mode_t u;
int r;
u = umask(0777);
umask(u);
return r;
}
return -errno;
log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
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);
return 0;
}
_cleanup_close_ int fd;
int r;
if (parents)
if (fd < 0)
return -errno;
if (mode != MODE_INVALID) {
if (r < 0)
return -errno;
}
if (r < 0)
return -errno;
}
if (stamp != USEC_INFINITY) {
} else
if (r < 0)
return -errno;
return 0;
}
}
_cleanup_free_ char *p = NULL;
int r;
return -errno;
r = readlink_malloc(to, &p);
if (r < 0)
return r;
return -EINVAL;
}
return 0;
}
_cleanup_free_ char *t = NULL;
int r;
if (r < 0)
return r;
return -errno;
unlink_noerrno(t);
return -errno;
}
return 0;
}
_cleanup_free_ char *t = NULL;
int r;
if (r < 0)
return r;
return -errno;
unlink_noerrno(t);
return -errno;
}
return 0;
}
_cleanup_free_ char *t = NULL;
int r;
if (r < 0)
return r;
return -errno;
unlink_noerrno(t);
return -errno;
}
return 0;
}
_cleanup_strv_free_ char **l = NULL;
/* Returns all files in a directory in *list, and the number
* of files as return value. If list is NULL returns only the
* number. */
if (!d)
return -errno;
for (;;) {
errno = 0;
return -errno;
if (!de)
break;
dirent_ensure_type(d, de);
if (!dirent_is_file(de))
continue;
if (list) {
/* one extra slot is needed for the terminating NULL */
return -ENOMEM;
if (!l[n])
return -ENOMEM;
l[++n] = NULL;
} else
n++;
}
if (list) {
*list = l;
l = NULL; /* avoid freeing */
}
return n;
}