24RCSID(
"$Id: ccf8734f8944bbe7524de86f6844f817c78a44ce $")
31#include <freeradius-devel/util/file.h>
32#include <freeradius-devel/util/syserror.h>
33#include <freeradius-devel/util/value.h>
42 if ((ctx->
uid == (uid_t) -1) && (ctx->
gid == (gid_t) -1))
return 0;
44 if (fchown(fd, ctx->
uid, ctx->
gid) < 0) {
70 ret = mkdir(path, 0700);
72 fd = open(path, O_DIRECTORY);
77 p = strrchr(path, FR_DIR_SEP);
78 if (!p)
return start - path;
83 if (fchmod(fd, mode) < 0) {
103 if (errno == EEXIST) {
104 fd = open(path, O_DIRECTORY);
110 return strlen(start);
118 if (errno != ENOENT) {
130 p = strrchr(path, FR_DIR_SEP);
131 if (!p || (p == path))
return start - path;
134 if (
_fr_mkdir(fd_out, start, path, mode, func, uctx) <= 0)
return start - p;
136 fr_assert_msg((*fd_out) >= 0,
"Logic error - Bad FD %i", *fd_out);
145 if (mkdirat(*fd_out, p + 1, 0700) < 0) {
151 if (errno == EEXIST) {
152 fd = openat(*fd_out, p + 1, O_DIRECTORY);
170 fd = openat(*fd_out, p + 1, O_DIRECTORY);
177 if (fchmod(fd, mode) < 0) {
188 if (func && (func(fd, path, uctx) < 0)) {
201 return strlen(start);
224 if (len < 0) len = strlen(path);
225 if (len == 0)
return 0;
233 fd = open(path, O_DIRECTORY);
234 if (fd >= 0)
goto done;
253 slen =
_fr_mkdir(&fd, our_path, our_path, mode, func, uctx);
255 if (slen <= 0)
return slen;
285 char *tmp_path = NULL, *abs_path, *talloc_abs_path;
287 if (len > 0) path = tmp_path =
talloc_bstrndup(NULL, path, (
size_t)len);
289 abs_path = realpath(path, NULL);
301 if (!talloc_abs_path) {
306 return talloc_abs_path;
325 fd = open(filename, O_WRONLY | O_CREAT, mode);
330 if (mkdir && (errno == ENOENT) && (q = strrchr(filename, FR_DIR_SEP))) {
333 slen =
fr_mkdir(&dir_fd, filename, q - filename, dir_mode, NULL, NULL);
334 if((slen <= 0) || (dir_fd < 0))
return slen;
336 fd = openat(dir_fd, q + 1, O_WRONLY | O_CREAT, mode);
340 return strlen(filename);
343 slen = -(q - filename);
355 return strlen(filename);
367 if (unlink(filename) == 0)
return 0;
369 if (errno == ENOENT)
return 1;
385 static char our_wd[MAXPATHLEN];
388 if (!getcwd(our_wd,
sizeof(our_wd)))
return filename;
390 found = strstr(filename, our_wd);
391 if (found && (found == our_wd)) {
392 filename += strlen(our_wd);
393 while (*filename ==
'/') filename++;
411int fr_dirfd(
int *dirfd,
char const **filename,
char const *pathname)
413 char const *last_slash = strrchr(pathname,
'/');
415 if (last_slash == NULL) {
416 *filename = pathname;
421 char dirpath[(last_slash - pathname) + 1];
423 memcpy(dirpath, pathname, last_slash - pathname);
424 dirpath[last_slash - pathname] =
'\0';
425 *filename = last_slash + 1;
426 *dirfd = open(dirpath, O_DIRECTORY);
427 return (*dirfd < 0) ? -1 : 0;
436 struct stat stat_buf;
441 if (
try[0] ==
'.')
return false;
452 if (!len)
return false;
482 if (!len)
return false;
487 if ((len > 10) && (strncmp(&
try[len - 10],
".dpkg-dist", 10) == 0))
return false;
488 if ((len > 9) && (strncmp(&
try[len - 9],
".dpkg-old", 9) == 0))
return false;
489 if ((len > 7) && (strncmp(&
try[len - 7],
".rpmnew", 7) == 0))
return false;
490 if ((len > 8) && (strncmp(&
try[len - 8],
".rpmsave", 8) == 0))
return false;
501 room = (iter->
path + PATH_MAX) - filename;
503 if (
strlcpy(filename,
try, room) >= room)
return false;
508 if (stat(iter->
path, &stat_buf) != 0) {
512 if (S_ISREG(stat_buf.st_mode)) {
513 if ((stat_buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) {
516 }
else if (!S_ISLNK(stat_buf.st_mode)) {
539 dp = readdir(iter->dir);
541 if (errno != 0)
return -1;
572 iter->
path = malloc(PATH_MAX);
592 while (*p ==
'/') p++;
598 if ((
size_t) (q - iter->
path) >= PATH_MAX) {
619 if ((
size_t) (q - iter->
path) >= PATH_MAX) {
638 if (!slash)
continue;
645 while (*p ==
'/') p++;
666 if ((p[1] ==
'.') && (p[2] ==
'/')) {
708 for (p = pattern; *p !=
'\0'; p++) {
716 iter->
type = FR_GLOBDIR_DIR;
734 if ((*p ==
'*') || (*p ==
'?') || (*p ==
'[')) {
739 if ((pattern[0] !=
'/') && (dir[0] !=
'/')) {
744 iter->
type = FR_GLOBDIR_GLOB;
756 if (pattern[0] ==
'/') {
779 to_open = iter->
path;
786 switch (iter->
type) {
793 *filename = iter->
path;
801 iter->dir = opendir(to_open);
807 if (fr_globdir_dir_next(filename, iter) < 0) {
815 case FR_GLOBDIR_GLOB:
816 if (glob(to_open, GLOB_NOESCAPE | GLOB_ERR, NULL, &iter->glob) < 0) {
821 if (iter->glob.gl_pathc == 0) {
824 iter->gl_current = 0;
829 *filename = iter->glob.gl_pathv[iter->gl_current];
835 return 0 + (*filename != NULL);
853 switch (iter->
type) {
863 if (fr_globdir_dir_next(filename, iter) < 0)
return -1;
865 return 0 + (*filename != NULL);
869 case FR_GLOBDIR_GLOB:
871 if (iter->gl_current >= iter->glob.gl_pathc) {
875 *filename = iter->glob.gl_pathv[iter->gl_current];
892 switch (iter->
type) {
901 if (!iter->dir)
return 0;
903 return closedir(iter->dir);
907 case FR_GLOBDIR_GLOB:
908 globfree(&iter->glob);
923 [ 0x00 ... 0x2d ] =
true,
925 [ 0x3A ... 0x3f ] =
true,
926 [ 0x5b ... 0x5e ] =
true,
928 [ 0x7b ... 0xff ] =
true,
939 [ 0x00 ... 0x2f ] =
true,
940 [ 0x3A ... 0x3f ] =
true,
941 [ 0x5b ... 0x5e ] =
true,
943 [ 0x7b ... 0xff ] =
true,
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
ssize_t fr_mkdir(int *fd_out, char const *path, ssize_t len, mode_t mode, fr_mkdir_func_t func, void *uctx)
Create directories that are missing in the specified path.
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
int fr_globdir_iter_init(char const **filename, char const *dir, char const *pattern, fr_globdir_iter_t *iter)
Initialize an iterator over filenames.
static int fr_globdir_get_path(char const *dir, char const *pattern, fr_globdir_iter_t *iter)
Create a full path from dir + pattern.
int fr_mkdir_chown(int fd, char const *path, void *uctx)
Callback for the common case of chown() of the directory.
static bool fr_globdir_file_ok(char const *try, fr_globdir_iter_t *iter)
const fr_sbuff_escape_rules_t fr_filename_escape
ssize_t fr_touch(int *fd_out, char const *filename, mode_t mode, bool mkdir, mode_t dir_mode)
Create an empty file.
const fr_sbuff_escape_rules_t fr_filename_escape_dots
int fr_globdir_iter_next(char const **filename, fr_globdir_iter_t *iter)
Get the next filename.
char const * fr_cwd_strip(char const *filename)
Intended to be used in logging functions to make output more readable.
int fr_dirfd(int *dirfd, char const **filename, char const *pathname)
From a pathname, return fd and filename needed for *at() functions.
char * fr_realpath(TALLOC_CTX *ctx, char const *path, ssize_t len)
Convenience wrapper around realpath.
int fr_globdir_iter_free(fr_globdir_iter_t *iter)
static ssize_t _fr_mkdir(int *fd_out, char *start, char *path, mode_t mode, fr_mkdir_func_t func, void *uctx)
int(* fr_mkdir_func_t)(int fd, char const *path, void *uctx)
Callback for allowing additional operations on newly created directories.
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
#define talloc_strdup(_ctx, _str)
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const(_msg)
#define fr_box_strvalue_buffer(_val)