bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenmkdir_chown_full(const char *path, mode_t mode, uid_t uid,
a6bb10d402b5f28af4c31a4daa07e47146a3f897Timo Sirainen unsigned int i;
a6bb10d402b5f28af4c31a4daa07e47146a3f897Timo Sirainen for (i = 0;; i++) {
a6bb10d402b5f28af4c31a4daa07e47146a3f897Timo Sirainen /* it was just rmdir()ed by someone else? retry */
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainen /* EISDIR check is for BSD/OS which returns it if path
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainen contains '/' at the end and it exists.
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainen ENOSYS check is for NFS mount points. */
a6bb10d402b5f28af4c31a4daa07e47146a3f897Timo Sirainen i_error("%s", eperm_error_get_chgrp("fchown", path, gid,
a3e3650e98d326e8cc89e2a58061714af3214953Timo Sirainen if (gid != (gid_t)-1 && (mode & S_ISGID) == 0) {
a3e3650e98d326e8cc89e2a58061714af3214953Timo Sirainen /* make sure the directory doesn't have setgid bit enabled
a3e3650e98d326e8cc89e2a58061714af3214953Timo Sirainen (in case its parent had) */
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenint mkdir_chown(const char *path, mode_t mode, uid_t uid, gid_t gid)
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen return mkdir_chown_full(path, mode, uid, gid, NULL);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen return mkdir_chown_full(path, mode, (uid_t)-1, gid, gid_origin);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenmkdir_parents_chown_full(const char *path, mode_t mode, uid_t uid, gid_t gid,
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainen const char *p;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen if (mkdir_chown_full(path, mode, uid, gid, gid_origin) < 0) {
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainen /* doesn't exist, try recursively creating our parent dir */
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen ret = mkdir_parents_chown_full(t_strdup_until(path, p),
53b32ab10cd22d7e762db4d813298ff72bff4b3dTimo Sirainen /* should work now */
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen if (mkdir_chown_full(path, mode, uid, gid, gid_origin) < 0)
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenint mkdir_parents_chown(const char *path, mode_t mode, uid_t uid, gid_t gid)
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen return mkdir_parents_chown_full(path, mode, uid, gid, NULL);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenint mkdir_parents_chgrp(const char *path, mode_t mode,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen return mkdir_parents_chown_full(path, mode, (uid_t)-1, gid, gid_origin);
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainenint mkdir_parents(const char *path, mode_t mode)
6f9560d31a6fffeed234dc3b841169c40db1c5e1Timo Sirainen return mkdir_parents_chown(path, mode, (uid_t)-1, (gid_t)-1);
766814de3fbfeb8ca7c4d6b592f6ca09f14d5690Timo Sirainenint stat_first_parent(const char *path, const char **root_dir_r,
766814de3fbfeb8ca7c4d6b592f6ca09f14d5690Timo Sirainen const char *p;
766814de3fbfeb8ca7c4d6b592f6ca09f14d5690Timo Sirainen if (errno != ENOENT || strcmp(path, "/") == 0) {