How do you create a directory with the same access permissions as an existing one? How do you create a directory with the same access permissions as an existing one? unix unix

How do you create a directory with the same access permissions as an existing one?


You are running foul of the "umask", a per-process setting which masks out permission bits in file and directory creation operations.

There is no safe way to disable the umask. What you should do instead is create the directory with mode zero (i.e. all access denied) and then use chmod (the system call, not the shell command of the same name) to adjust the permissions to what you want.

Your program fragment has many other bugs. This is tricky to get right, and might well be a security hole if you get it wrong, so I shall write out the correct code in detail:

intmake_directory_like(const char *to_create,                    const char *prototype)        {    struct stat st;    if (lstat(prototype, &st)) {        fprintf(stderr, "lstat: %s: %s\n", prototype, strerror(errno));        return -1;    }    if (!S_ISDIR(st.st_mode)) {        fprintf(stderr, "lstat: %s: %s\n", prototype, strerror(ENOTDIR));        return -1;    }    /* create directory initially with no perms at all - this is the only       safe way to suppress the effects of the umask.  */    if (mkdir(to_create, 0000)) {        if (errno != EEXIST) {            fprintf(stderr, "mkdir: %s: %s\n", to_create, strerror(errno));            return -1;        } else {            /* check whether the thing that exists is a directory */            struct stat st2;            if (lstat(to_create, &st2)) {                fprintf(stderr, "lstat: %s: %s\n", to_create, strerror(errno));                return -1;            }            if (!S_ISDIR(st2.st_mode)) {                fprintf(stderr, "mkdir: %s: %s\n", to_create, strerror(EEXIST));                return -1;            }        }    }    if (chmod(to_create, st.st_mode & ~S_IFMT)) {        fprintf(stderr, "chmod: %s: %s\n", to_create, strerror(errno));        return -1;    }    return 0;}

Exercises for you:

  1. Why is this the only safe way to suppress the effects of the umask? (Hint: threads. But that's only one of several reasons.)
  2. Why do I use lstat rather than stat?
  3. Why is it necessary to stat the to-create path if mkdir fails with errno == EEXIST?
  4. Why is it incorrect to use chdir as you were doing? (There are two reasons.)
  5. Why is it safe to go ahead and call mkdir on the to-create path when we don't know whether there is already something there?
  6. Why is that & ~S_IFMT thing necessary?


You'll want to set the umask to zero. See http://man7.org/linux/man-pages/man2/umask.2.html

Otherwise, some bits (often 022, like you're seeing) will always be cleared.

umask(0);