12 #include <sys/param.h> 13 #include <sys/types.h> 15 #include <sys/resource.h> 43 int offset = 1, len = 0;
45 char *
path = strdup(path_c);
50 for (len = strlen(
path); offset < len; offset++) {
51 if (
path[offset] ==
'/') {
53 if ((mkdir(
path, mode) < 0) && (errno != EEXIST)) {
60 if ((mkdir(
path, mode) < 0) && (errno != EEXIST)) {
83 CRM_CHECK((
path != NULL) && (resolved_path != NULL),
return EINVAL);
85 #if _POSIX_VERSION >= 200809L 87 *resolved_path = realpath(
path, NULL);
88 return (*resolved_path == NULL)? errno :
pcmk_rc_ok;
90 #elif defined(PATH_MAX) 93 *resolved_path = malloc(PATH_MAX);
94 if ((*resolved_path == NULL) || (realpath(
path, *resolved_path) == NULL)) {
99 *resolved_path = NULL;
118 unsigned int sequence,
bool bzip)
122 (bzip?
"bz2" :
"raw"));
141 char *series_file = NULL;
143 if ((directory == NULL) || (series == NULL) || (seq == NULL)) {
148 fp = fopen(series_file,
"r");
151 crm_debug(
"Could not open series file %s: %s",
152 series_file, strerror(rc));
157 if (fscanf(fp,
"%u", seq) != 1) {
158 rc = (errno == 0)?
ENODATA : errno;
159 crm_debug(
"Could not read sequence number from series file %s: %s",
165 crm_trace(
"Found last sequence number %u in series file %s",
184 unsigned int sequence,
int max)
187 FILE *file_strm = NULL;
188 char *series_file = NULL;
196 if (max > 0 && sequence >= max) {
201 file_strm = fopen(series_file,
"w");
202 if (file_strm != NULL) {
203 rc = fprintf(file_strm,
"%u", sequence);
205 crm_perror(LOG_ERR,
"Cannot write to series file %s", series_file);
209 crm_err(
"Cannot open series file %s for writing", series_file);
212 if (file_strm != NULL) {
217 crm_trace(
"Wrote %d to %s", sequence, series_file);
235 uid_t uid, gid_t gid)
237 char *series_file = NULL;
240 if ((directory == NULL) || (series == NULL)) {
244 if (chown(series_file, uid, gid) < 0) {
252 pcmk__daemon_user_can_write(
const char *target_name,
struct stat *target_stat)
254 struct passwd *sys_user = NULL;
258 if (sys_user == NULL) {
263 if (target_stat->st_uid != sys_user->pw_uid) {
264 crm_notice(
"%s is not owned by user %s " QB_XS
" uid %d != %d",
266 target_stat->st_uid);
269 if ((target_stat->st_mode & (S_IRUSR | S_IWUSR)) == 0) {
270 crm_notice(
"%s is not readable and writable by user %s " 271 QB_XS
" st_mode=0%lo",
273 (
unsigned long) target_stat->st_mode);
280 pcmk__daemon_group_can_write(
const char *target_name,
struct stat *target_stat)
282 struct group *sys_grp = NULL;
286 if (sys_grp == NULL) {
292 if (target_stat->st_gid != sys_grp->gr_gid) {
293 crm_notice(
"%s is not owned by group %s " QB_XS
" uid %d != %d",
295 sys_grp->gr_gid, target_stat->st_gid);
299 if ((target_stat->st_mode & (S_IRGRP | S_IWGRP)) == 0) {
300 crm_notice(
"%s is not readable and writable by group %s " 301 QB_XS
" st_mode=0%lo",
303 (
unsigned long) target_stat->st_mode);
328 char *full_file = NULL;
329 const char *
target = NULL;
339 s_res = stat(full_file, &buf);
346 }
else if (S_ISREG(buf.st_mode) == FALSE) {
347 crm_err(
"%s must be a regular file " QB_XS
" st_mode=0%lo",
348 target, (
unsigned long) buf.st_mode);
357 s_res = stat(dir, &buf);
362 }
else if (S_ISDIR(buf.st_mode) == FALSE) {
363 crm_err(
"%s must be a directory " QB_XS
" st_mode=0%lo",
364 dir, (
unsigned long) buf.st_mode);
369 if (!pcmk__daemon_user_can_write(
target, &buf)
370 && !pcmk__daemon_group_can_write(
target, &buf)) {
372 crm_err(
"%s must be owned and writable by either user %s or group %s " 373 QB_XS
" st_mode=0%lo",
375 (
unsigned long) buf.st_mode);
397 directory = opendir(
name);
398 if (directory == NULL) {
403 fd = dirfd(directory);
405 crm_perror(LOG_ERR,
"Could not obtain file descriptor for %s",
name);
412 if (closedir(directory) < 0) {
431 int length, read_len;
434 if ((filename == NULL) || (contents == NULL)) {
438 fp = fopen(filename,
"r");
439 if ((fp == NULL) || (fseek(fp, 0L, SEEK_END) < 0)) {
453 *contents = calloc(length + 1,
sizeof(
char));
454 if (*contents == NULL) {
460 read_len = fread(*contents, 1, length, fp);
461 if (read_len != length) {
469 (*contents)[length] =
'\0';
493 FILE *fp = fdopen(fd,
"w");
498 if ((contents != NULL) && (fprintf(fp,
"%s", contents) < 0)) {
501 if (fflush(fp) != 0) {
504 if (fsync(fileno(fp)) < 0) {
522 int flag = fcntl(fd, F_GETFL);
527 if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) {
545 const char *dir = getenv(
"TMPDIR");
547 return (dir && (*dir ==
'/'))? dir :
"/tmp";
566 int min_fd = (all? 0 : (STDERR_FILENO + 1));
571 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
572 max_fd = rlim.rlim_cur - 1;
574 long conf_max = sysconf(_SC_OPEN_MAX);
576 max_fd = (conf_max > 0)? conf_max : 1024;
584 #if HAVE_LINUX_PROCFS 585 dir = opendir(
"/proc/self/fd");
587 dir = opendir(
"/dev/fd");
590 dir = opendir(
"/dev/fd");
591 #endif // HAVE_LINUX_PROCFS 593 struct dirent *entry;
594 int dir_fd = dirfd(dir);
596 while ((entry = readdir(dir)) != NULL) {
597 int lpc = atoi(entry->d_name);
605 if ((lpc >= min_fd) && (lpc <= max_fd) && (lpc != dir_fd)) {
616 for (
int lpc = max_fd; lpc >= min_fd; lpc--) {
634 if (filename[0] ==
'/') {
#define CRM_CHECK(expr, failure_action)
#define crm_notice(fmt, args...)
int pcmk__real_path(const char *path, char **resolved_path)
int pcmk__chown_series_sequence(const char *directory, const char *series, uid_t uid, gid_t gid)
void pcmk__write_series_sequence(const char *directory, const char *series, unsigned int sequence, int max)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
bool pcmk__daemon_can_write(const char *dir, const char *file)
const char * pcmk__get_tmpdir(void)
#define crm_debug(fmt, args...)
#define crm_trace(fmt, args...)
#define pcmk__str_copy(str)
int pcmk__build_path(const char *path_c, mode_t mode)
#define pcmk__assert(expr)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
char * pcmk__series_filename(const char *directory, const char *series, unsigned int sequence, bool bzip)
#define crm_err(fmt, args...)
int pcmk__read_series_sequence(const char *directory, const char *series, unsigned int *seq)
char * pcmk__full_path(const char *filename, const char *dirname)
Duplicate a file path, inserting a prefix if not absolute.
void pcmk__close_fds_in_child(bool all)
void pcmk__sync_directory(const char *name)
int pcmk__write_sync(int fd, const char *contents)
int pcmk__set_nonblocking(int fd)
int pcmk__file_contents(const char *filename, char **contents)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1