diff options
Diffstat (limited to 'usr.sbin/smtpd/util.c')
-rw-r--r-- | usr.sbin/smtpd/util.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c index a627e5ae89d..e11307142dd 100644 --- a/usr.sbin/smtpd/util.c +++ b/usr.sbin/smtpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.49 2011/10/27 14:32:57 chl Exp $ */ +/* $OpenBSD: util.c,v 1.50 2011/11/14 11:53:10 eric Exp $ */ /* * Copyright (c) 2000,2001 Markus Friedl. All rights reserved. @@ -66,6 +66,71 @@ bsnprintf(char *str, size_t size, const char *format, ...) return 1; } +int +ckdir(const char *path, mode_t mode, uid_t owner, gid_t group, int create) +{ + char mode_str[12]; + int ret; + struct stat sb; + + if (stat(path, &sb) == -1) { + if (errno != ENOENT || create == 0) { + warn("stat: %s", path); + return (0); + } + + /* chmod is deferred to avoid umask effect */ + if (mkdir(path, 0) == -1) { + warn("mkdir: %s", path); + return (0); + } + + if (chown(path, owner, group) == -1) { + warn("chown: %s", path); + return (0); + } + + if (chmod(path, mode) == -1) { + warn("chmod: %s", path); + return (0); + } + + if (stat(path, &sb) == -1) { + warn("stat: %s", path); + return (0); + } + } + + ret = 1; + + /* check if it's a directory */ + if (!S_ISDIR(sb.st_mode)) { + ret = 0; + warnx("%s is not a directory", path); + } + + /* check that it is owned by owner/group */ + if (sb.st_uid != owner) { + ret = 0; + warnx("%s is not owned by uid %d", path, owner); + } + if (sb.st_gid != group) { + ret = 0; + warnx("%s is not owned by gid %d", path, group); + } + + /* check permission */ + if ((sb.st_mode & 07777) != mode) { + ret = 0; + strmode(mode, mode_str); + mode_str[10] = '\0'; + warnx("%s must be %s (%o)", path, mode_str + 1, mode); + } + + return ret; +} + + /* Close file, signifying temporary error condition (if any) to the caller. */ int safe_fclose(FILE *fp) |