92 static VSTREAM *safe_open_exist(
const char *path, 
int flags,
 
   95     struct stat local_statbuf;
 
  103     if ((fp = 
vstream_fopen(path, flags & ~(O_CREAT | O_EXCL), 0)) == 0) {
 
  116     fstat_st = &local_statbuf;
 
  118     msg_fatal(
"%s: bad open file status: %m", path);
 
  119     } 
else if (fstat_st->st_nlink != 1) {
 
  121             (
int) fstat_st->st_nlink);
 
  123     } 
else if (S_ISDIR(fstat_st->st_mode)) {
 
  149     else if (
lstat(path, &lstat_st) < 0) {
 
  152     } 
else if (S_ISLNK(lstat_st.st_mode)) {
 
  153     if (lstat_st.st_uid == 0) {
 
  155         const char *parent_path = 
sane_dirname(parent_buf, path);
 
  156         struct stat parent_st;
 
  159         parent_ok = (
stat(parent_path, &parent_st) == 0 
 
  160              && parent_st.st_uid == 0
 
  161              && (parent_st.st_mode & (S_IWGRP | S_IWOTH)) == 0);
 
  168     } 
else if (fstat_st->st_dev != lstat_st.st_dev
 
  169            || fstat_st->st_ino != lstat_st.st_ino
 
  171            || fstat_st->st_gen != lstat_st.st_gen
 
  173            || fstat_st->st_nlink != lstat_st.st_nlink
 
  174            || fstat_st->st_mode != lstat_st.st_mode) {
 
  195 static VSTREAM *safe_open_create(
const char *path, 
int flags, mode_t mode,
 
  196                 struct stat * st, uid_t user, gid_t group, 
VSTRING *why)
 
  204     if ((fp = 
vstream_fopen(path, flags | (O_CREAT | O_EXCL), mode)) == 0) {
 
  213     msg_fatal(
"%s: bad open file status: %m", path);
 
  220 #define CHANGE_OWNER(user, group) (user != (uid_t) -1 || group != (gid_t) -1) 
  224     msg_warn(
"%s: cannot change file ownership: %m", path);
 
  244                 struct stat * st, uid_t user, gid_t group, 
VSTRING *why)
 
  248     switch (flags & (O_CREAT | O_EXCL)) {
 
  254     return (safe_open_exist(path, flags, st, why));
 
  259     case O_CREAT | O_EXCL:
 
  260     return (safe_open_create(path, flags, mode, st, user, group, why));
 
  269     fp = safe_open_exist(path, flags, st, why);
 
  270     if (fp == 0 && errno == ENOENT) {
 
  271         fp = safe_open_create(path, flags, mode, st, user, group, why);
 
  272         if (fp == 0 && errno == EEXIST)
 
  273         fp = safe_open_exist(path, flags, st, why);
 
  281     msg_panic(
"safe_open: O_EXCL flag without O_CREAT flag");
 
NORETURN msg_panic(const char *fmt,...)
char * sane_dirname(VSTRING *bp, const char *path)
VSTREAM * vstream_fopen(const char *path, int flags, mode_t mode)
int vstream_fclose(VSTREAM *stream)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define CHANGE_OWNER(user, group)
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
NORETURN msg_fatal(const char *fmt,...)
VSTREAM * safe_open(const char *path, int flags, mode_t mode, struct stat *st, uid_t user, gid_t group, VSTRING *why)
VSTRING * vstring_free(VSTRING *vp)
#define vstream_fileno(vp)