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