15#include <sys/resource.h>
43 int offset = 1, len = 0;
45 char *
path = strdup(path_c);
48 for (len = strlen(
path); offset < len; offset++) {
49 if (
path[offset] ==
'/') {
51 if ((mkdir(
path, mode) < 0) && (errno != EEXIST)) {
58 if ((mkdir(
path, mode) < 0) && (errno != EEXIST)) {
81 CRM_CHECK((
path != NULL) && (resolved_path != NULL),
return EINVAL);
83#if _POSIX_VERSION >= 200809L
85 *resolved_path = realpath(
path, NULL);
86 return (*resolved_path == NULL)? errno :
pcmk_rc_ok;
88#elif defined(PATH_MAX)
91 *resolved_path = malloc(PATH_MAX);
92 if ((*resolved_path == NULL) || (realpath(
path, *resolved_path) == NULL)) {
97 *resolved_path = NULL;
116 unsigned int sequence,
bool bzip)
120 (bzip?
"bz2" :
"raw"));
139 char *series_file = NULL;
141 if ((directory == NULL) || (series == NULL) || (seq == NULL)) {
146 fp = fopen(series_file,
"r");
149 crm_debug(
"Could not open series file %s: %s",
150 series_file, strerror(rc));
155 if (fscanf(fp,
"%u", seq) != 1) {
156 rc = (errno == 0)?
ENODATA : errno;
157 crm_debug(
"Could not read sequence number from series file %s: %s",
163 crm_trace(
"Found last sequence number %u in series file %s",
182 unsigned int sequence,
int max)
185 FILE *file_strm = NULL;
186 char *series_file = NULL;
194 if (max > 0 && sequence >= max) {
199 file_strm = fopen(series_file,
"w");
200 if (file_strm != NULL) {
201 rc = fprintf(file_strm,
"%u", sequence);
203 crm_perror(LOG_ERR,
"Cannot write to series file %s", series_file);
207 crm_err(
"Cannot open series file %s for writing", series_file);
210 if (file_strm != NULL) {
215 crm_trace(
"Wrote %d to %s", sequence, series_file);
233 uid_t uid, gid_t gid)
235 char *series_file = NULL;
238 if ((directory == NULL) || (series == NULL)) {
242 if (chown(series_file, uid, gid) < 0) {
250pcmk__daemon_user_can_write(
const char *target_name,
struct stat *target_stat)
252 struct passwd *sys_user = NULL;
256 if (sys_user == NULL) {
261 if (target_stat->st_uid != sys_user->pw_uid) {
262 crm_notice(
"%s is not owned by user %s " QB_XS
" uid %d != %d",
264 target_stat->st_uid);
267 if ((target_stat->st_mode & (S_IRUSR | S_IWUSR)) == 0) {
268 crm_notice(
"%s is not readable and writable by user %s "
269 QB_XS
" st_mode=0%lo",
271 (
unsigned long) target_stat->st_mode);
278pcmk__daemon_group_can_write(
const char *target_name,
struct stat *target_stat)
280 struct group *sys_grp = NULL;
284 if (sys_grp == NULL) {
290 if (target_stat->st_gid != sys_grp->gr_gid) {
291 crm_notice(
"%s is not owned by group %s " QB_XS
" uid %d != %d",
293 sys_grp->gr_gid, target_stat->st_gid);
297 if ((target_stat->st_mode & (S_IRGRP | S_IWGRP)) == 0) {
298 crm_notice(
"%s is not readable and writable by group %s "
299 QB_XS
" st_mode=0%lo",
301 (
unsigned long) target_stat->st_mode);
326 char *full_file = NULL;
327 const char *
target = NULL;
337 s_res = stat(full_file, &buf);
344 }
else if (S_ISREG(buf.st_mode) == FALSE) {
345 crm_err(
"%s must be a regular file " QB_XS
" st_mode=0%lo",
346 target, (
unsigned long) buf.st_mode);
355 s_res = stat(dir, &buf);
360 }
else if (S_ISDIR(buf.st_mode) == FALSE) {
361 crm_err(
"%s must be a directory " QB_XS
" st_mode=0%lo",
362 dir, (
unsigned long) buf.st_mode);
367 if (!pcmk__daemon_user_can_write(
target, &buf)
368 && !pcmk__daemon_group_can_write(
target, &buf)) {
370 crm_err(
"%s must be owned and writable by either user %s or group %s "
371 QB_XS
" st_mode=0%lo",
373 (
unsigned long) buf.st_mode);
395 directory = opendir(
name);
396 if (directory == NULL) {
401 fd = dirfd(directory);
403 crm_perror(LOG_ERR,
"Could not obtain file descriptor for %s",
name);
410 if (closedir(directory) < 0) {
429 int length, read_len;
432 if ((filename == NULL) || (contents == NULL)) {
436 fp = fopen(filename,
"r");
437 if ((fp == NULL) || (fseek(fp, 0L, SEEK_END) < 0)) {
451 *contents = calloc(length + 1,
sizeof(
char));
452 if (*contents == NULL) {
465 read_len = fread(*contents, 1, length, fp);
466 if (read_len != length) {
474 (*contents)[length] =
'\0';
498 FILE *fp = fdopen(fd,
"w");
503 if ((contents != NULL) && (fprintf(fp,
"%s", contents) < 0)) {
506 if (fflush(fp) != 0) {
509 if (fsync(fileno(fp)) < 0) {
527 int flag = fcntl(fd, F_GETFL);
532 if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) {
550 const char *dir = getenv(
"TMPDIR");
552 return (dir && (*dir ==
'/'))? dir :
"/tmp";
571 int min_fd = (all? 0 : (STDERR_FILENO + 1));
576 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
577 max_fd = rlim.rlim_cur - 1;
579 long conf_max = sysconf(_SC_OPEN_MAX);
581 max_fd = (conf_max > 0)? conf_max : 1024;
590 dir = opendir(
"/dev/fd");
594 struct dirent *entry;
595 int dir_fd = dirfd(dir);
597 while ((entry = readdir(dir)) != NULL) {
598 int lpc = atoi(entry->d_name);
606 if ((lpc >= min_fd) && (lpc <= max_fd) && (lpc != dir_fd)) {
617 for (
int lpc = max_fd; lpc >= min_fd; lpc--) {
635 if (filename[0] ==
'/') {
DIR * pcmk__procfs_fd_dir(void)
void pcmk__write_series_sequence(const char *directory, const char *series, unsigned int sequence, int max)
int pcmk__real_path(const char *path, char **resolved_path)
char * pcmk__series_filename(const char *directory, const char *series, unsigned int sequence, bool bzip)
int pcmk__chown_series_sequence(const char *directory, const char *series, uid_t uid, gid_t gid)
void pcmk__sync_directory(const char *name)
char * pcmk__full_path(const char *filename, const char *dirname)
Duplicate a file path, inserting a prefix if not absolute.
bool pcmk__daemon_can_write(const char *dir, const char *file)
void pcmk__close_fds_in_child(bool all)
int pcmk__file_contents(const char *filename, char **contents)
int pcmk__read_series_sequence(const char *directory, const char *series, unsigned int *seq)
const char * pcmk__get_tmpdir(void)
int pcmk__write_sync(int fd, const char *contents)
int pcmk__build_path(const char *path_c, mode_t mode)
int pcmk__set_nonblocking(int fd)
#define crm_notice(fmt, args...)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
#define CRM_CHECK(expr, failure_action)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
#define pcmk__assert(expr)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk__str_copy(str)