Пример #1
0
int
dirSetHierarchyPermissions(const char *path,
        int uid, int gid, int dirMode, int fileMode)
{
    struct stat st;
    if (lstat(path, &st)) {
        return -1;
    }

    /* ignore symlinks */
    if (S_ISLNK(st.st_mode)) {
        return 0;
    }

    /* directories and files get different permissions */
    if (chown(path, uid, gid) ||
        chmod(path, S_ISDIR(st.st_mode) ? dirMode : fileMode)) {
        return -1;
    }

    /* recurse over directory components */
    if (S_ISDIR(st.st_mode)) {
        DIR *dir = opendir(path);
        if (dir == NULL) {
            return -1;
        }

        errno = 0;
        const struct dirent *de;
        while (errno == 0 && (de = readdir(dir)) != NULL) {
            if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) {
                continue;
            }

            char dn[PATH_MAX];
            snprintf(dn, sizeof(dn), "%s/%s", path, de->d_name);
            if (!dirSetHierarchyPermissions(dn, uid, gid, dirMode, fileMode)) {
                errno = 0;
            } else if (errno == 0) {
                errno = -1;
            }
        }

        if (errno != 0) {
            int save = errno;
            closedir(dir);
            errno = save;
            return -1;
        }

        if (closedir(dir)) {
            return -1;
        }
    }

    return 0;
}
Пример #2
0
/* set_perm <uid> <gid> <mode> <path> [... <pathN>]
 * set_perm_recursive <uid> <gid> <dir-mode> <file-mode> <path> [... <pathN>]
 *
 * Like "chmod", "chown" and "chgrp" all in one, set ownership and permissions
 * of single files or entire directory trees.  Any error causes failure.
 * User, group, and modes must all be integer values (hex or octal OK).
 */
static int
cmd_set_perm(const char *name, void *cookie, int argc, const char *argv[],
        PermissionRequestList *permissions)
{
    UNUSED(cookie);
    CHECK_WORDS();
    bool recurse = !strcmp(name, "set_perm_recursive");

    int min_args = 4 + (recurse ? 1 : 0);
    if (argc < min_args) {
        LOGE("Command %s requires at least %d args\n", name, min_args);
        return 1;
    }

    // All the arguments except the path(s) are numeric.
    int i, n[min_args - 1];
    for (i = 0; i < min_args - 1; ++i) {
        char *end;
        n[i] = strtoul(argv[i], &end, 0);
        if (end[0] != '\0' || argv[i][0] == '\0') {
            LOGE("Command %s: invalid argument \"%s\"\n", name, argv[i]);
            return 1;
        }
    }

    for (i = min_args - 1; i < min_args; ++i) {
        char path[PATH_MAX];
        if (translate_root_path(argv[i], path, sizeof(path)) == NULL) {
            LOGE("Command %s: bad path \"%s\"\n", name, argv[i]);
            return 1;
        }

        if (ensure_root_path_mounted(argv[i])) {
            LOGE("Can't mount %s\n", argv[i]);
            return 1;
        }

        if (recurse
                ? dirSetHierarchyPermissions(path, n[0], n[1], n[2], n[3])
                : (chown(path, n[0], n[1]) || chmod(path, n[2]))) {
           LOGE("Can't chown/mod %s\n(%s)\n", path, strerror(errno));
           return 1;
        }
    }

    return 0;
}
Пример #3
0
Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) {
    char* result = NULL;
    bool recursive = (strcmp(name, "set_perm_recursive") == 0);

    int min_args = 4 + (recursive ? 1 : 0);
    if (argc < min_args) {
        return ErrorAbort(state, "%s() expects %d+ args, got %d", name, argc);
    }

    char** args = ReadVarArgs(state, argc, argv);
    if (args == NULL) return NULL;

    char* end;
    int i;
    int bad = 0;

    int uid = strtoul(args[0], &end, 0);
    if (*end != '\0' || args[0][0] == 0) {
        ErrorAbort(state, "%s: \"%s\" not a valid uid", name, args[0]);
        goto done;
    }

    int gid = strtoul(args[1], &end, 0);
    if (*end != '\0' || args[1][0] == 0) {
        ErrorAbort(state, "%s: \"%s\" not a valid gid", name, args[1]);
        goto done;
    }

    if (recursive) {
        int dir_mode = strtoul(args[2], &end, 0);
        if (*end != '\0' || args[2][0] == 0) {
            ErrorAbort(state, "%s: \"%s\" not a valid dirmode", name, args[2]);
            goto done;
        }

        int file_mode = strtoul(args[3], &end, 0);
        if (*end != '\0' || args[3][0] == 0) {
            ErrorAbort(state, "%s: \"%s\" not a valid filemode",
                       name, args[3]);
            goto done;
        }

        for (i = 4; i < argc; ++i) {
            dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode);
        }
    } else {
        int mode = strtoul(args[2], &end, 0);
        if (*end != '\0' || args[2][0] == 0) {
            ErrorAbort(state, "%s: \"%s\" not a valid mode", name, args[2]);
            goto done;
        }

        for (i = 3; i < argc; ++i) {
            if (chown(args[i], uid, gid) < 0) {
                fprintf(stderr, "%s: chown of %s to %d %d failed: %s\n",
                        name, args[i], uid, gid, strerror(errno));
                ++bad;
            }
            if (chmod(args[i], mode) < 0) {
                fprintf(stderr, "%s: chmod of %s to %o failed: %s\n",
                        name, args[i], mode, strerror(errno));
                ++bad;
            }
        }
    }
    result = strdup("");

done:
    for (i = 0; i < argc; ++i) {
        free(args[i]);
    }
    free(args);

    if (bad) {
        free(result);
        return ErrorAbort(state, "%s: some changes failed", name);
    }
    return StringValue(result);
}