如何创建与现有目录具有相同访问权限的目录?

时间:2014-04-18 22:20:50

标签: c unix stat

我需要创建一个与另一个文件夹具有相同权限的新文件夹。 我的最终目标是完全复制目录及其内容。 这是我的第一步,我似乎无法让它发挥作用。

我的内容如下:

struct stat srcstat;
int srcstatus = stat(source, &srcstat);
if (chdir(dest))
    if (mkdir(dest, srcstat.st_mode)){
        printf("error: could not create <dest>\n");
        exit(1);
    }

source是一个cstring,其中包含我想要使用其权限的文​​件夹的路径。 dest是一个带有新文件夹路径的c字符串。

具有旧文件夹和新文件夹权限的ls位于

之下
drwxrwxrwx 2 kingacev CS-Majors 4096 Apr 18 17:03 test
drwxr-xr-x 2 kingacev CS-Majors 4096 Apr 18 18:12 test3

我的第一个想法是我不能像我尝试的那样使用srcstat.st_mode。如果是这样的话,是否有同样简单的方法来做我想做的事情?如果没有,我离这个标记有多远?

2 个答案:

答案 0 :(得分:11)

您正在违反&#34; umask&#34;,这是一个每个进程设置,屏蔽输出文件和目录创建操作中的权限位。

没有安全的方法来禁用umask。你应该做的是创建模式为零的目录(即所有访问被拒绝),然后使用chmod(系统调用,而不是同名的shell命令)来调整你想要的权限。 / p>

您的程序片段还有许多其他错误。如果你得到错误的,这很难成为一个安全漏洞,所以我会详细写出正确的代码:

int
make_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;
}

练习:

  1. 为什么这是抑制umask效果的唯一安全方法? (提示:线程。但这只是其中一个原因。)
  2. 为什么我使用lstat而不是stat
  3. 如果mkdirerrno == EEXIST失败,为什么有必要统计创建路径?
  4. 为什么使用chdir时不正确? (有两个原因。)
  5. 为什么安全在我们不知道是否已存在某些内容的情况下继续在创建路径上致电mkdir
  6. 为什么需要& ~S_IFMT这件事?

答案 1 :(得分:0)

您需要将umask设置为零。见http://man7.org/linux/man-pages/man2/umask.2.html

否则,一些位(通常是022,就像你看到的那样)将永远被清除。

umask(0);