コード例 #1
0
ファイル: repo-perm.c プロジェクト: ferdynice/seafile
/*
 * Comprehensive repo access permission checker.
 *
 * Returns read/write permission.
 */
char *
seaf_repo_manager_check_permission (SeafRepoManager *mgr,
                                    const char *repo_id,
                                    const char *user,
                                    GError **error)
{
    SeafVirtRepo *vinfo;
    char *owner = NULL;
    char *permission = NULL;

    /* This is a virtual repo.*/
    vinfo = seaf_repo_manager_get_virtual_repo_info (mgr, repo_id);
    if (vinfo) {
        permission = check_virtual_repo_permission (mgr, repo_id,
                     vinfo->origin_repo_id,
                     user, error);
        goto out;
    }

    owner = seaf_repo_manager_get_repo_owner (mgr, repo_id);
    if (owner != NULL) {
        if (strcmp (owner, user) == 0)
            permission = g_strdup("rw");
        else
            permission = check_repo_share_permission (mgr, repo_id, user);
    }

out:
    seaf_virtual_repo_info_free (vinfo);
    g_free (owner);
    return permission;
}
コード例 #2
0
ファイル: repo-mgr.c プロジェクト: AlanForeverAi/seafile
static SeafRepo *
load_repo (SeafRepoManager *manager, const char *repo_id)
{
    SeafRepo *repo;
    SeafBranch *branch;
    SeafVirtRepo *vinfo = NULL;

    repo = seaf_repo_new(repo_id, NULL, NULL);
    if (!repo) {
        g_warning ("[repo mgr] failed to alloc repo.\n");
        return NULL;
    }

    repo->manager = manager;

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo_id, "master");
    if (!branch) {
        g_warning ("Failed to get master branch of repo %.8s.\n", repo_id);
        repo->is_corrupted = TRUE;
    } else {
        load_repo_commit (manager, repo, branch);
        seaf_branch_unref (branch);
    }

    if (repo->is_corrupted) {
        g_warning ("Repo %.8s is corrupted.\n", repo->id);
        seaf_repo_free (repo);
        return NULL;
    }

    vinfo = seaf_repo_manager_get_virtual_repo_info (manager, repo_id);
    if (vinfo) {
        repo->is_virtual = TRUE;
        memcpy (repo->store_id, vinfo->origin_repo_id, 36);
    } else {
        repo->is_virtual = FALSE;
        memcpy (repo->store_id, repo->id, 36);
    }
    seaf_virtual_repo_info_free (vinfo);

#if 0
    if (pthread_rwlock_wrlock (&manager->priv->lock) < 0) {
        g_warning ("[repo mgr] failed to lock repo cache.\n");
        seaf_repo_free (repo);
        return NULL;
    }
    avl_insert (manager->priv->repo_tree, repo);
    /* Don't need to increase ref count, since the ref count of
     * a new repo object is already 1.
     */
    pthread_rwlock_unlock (&manager->priv->lock);
#endif

    return repo;
}
コード例 #3
0
ファイル: quota-mgr.c プロジェクト: 285452612/seafile
int
seaf_quota_manager_check_quota_with_delta (SeafQuotaManager *mgr,
                                           const char *repo_id,
                                           gint64 delta)
{
    SeafVirtRepo *vinfo;
    const char *r_repo_id = repo_id;
    char *user = NULL;
    gint64 quota, usage;
    int ret = 0;

    /* If it's a virtual repo, check quota to origin repo. */
    vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id);
    if (vinfo)
        r_repo_id = vinfo->origin_repo_id;

    user = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, r_repo_id);
    if (user != NULL) {
        quota = seaf_quota_manager_get_user_quota (mgr, user);
    } else {
        seaf_warning ("Repo %s has no owner.\n", r_repo_id);
        ret = -1;
        goto out;
    }

    if (quota == INFINITE_QUOTA)
        goto out;

    usage = seaf_quota_manager_get_user_usage (mgr, user);
    if (usage < 0) {
        ret = -1;
        goto out;
    }

    if (delta != 0) {
        usage += delta;
    }
    if (usage >= quota) {
        ret = 1;
    }

out:
    seaf_virtual_repo_info_free (vinfo);
    g_free (user);
    return ret;
}
コード例 #4
0
ファイル: repo-mgr.c プロジェクト: Buzer/seafile
static SeafRepo *
load_repo (SeafRepoManager *manager, const char *repo_id, gboolean ret_corrupt)
{
    SeafRepo *repo;
    SeafBranch *branch;
    SeafVirtRepo *vinfo = NULL;

    repo = seaf_repo_new(repo_id, NULL, NULL);
    if (!repo) {
        seaf_warning ("[repo mgr] failed to alloc repo.\n");
        return NULL;
    }

    repo->manager = manager;

    branch = seaf_branch_manager_get_branch (seaf->branch_mgr, repo_id, "master");
    if (!branch) {
        g_warning ("Failed to get master branch of repo %.8s.\n", repo_id);
        repo->is_corrupted = TRUE;
    } else {
        load_repo_commit (manager, repo, branch);
        seaf_branch_unref (branch);
    }

    if (repo->is_corrupted) {
        if (!ret_corrupt) {
            seaf_repo_free (repo);
            return NULL;
        }
        return repo;
    }

    vinfo = seaf_repo_manager_get_virtual_repo_info (manager, repo_id);
    if (vinfo) {
        repo->is_virtual = TRUE;
        memcpy (repo->store_id, vinfo->origin_repo_id, 36);
    } else {
        repo->is_virtual = FALSE;
        memcpy (repo->store_id, repo->id, 36);
    }
    seaf_virtual_repo_info_free (vinfo);

    return repo;
}
コード例 #5
0
ファイル: repo-mgr.c プロジェクト: hram908/seafile
int
seaf_repo_manager_set_repo_history_limit (SeafRepoManager *mgr,
        const char *repo_id,
        int days)
{
    SeafVirtRepo *vinfo;
    SeafDB *db = mgr->seaf->db;
    char sql[256];

    vinfo = seaf_repo_manager_get_virtual_repo_info (mgr, repo_id);
    if (vinfo) {
        seaf_virtual_repo_info_free (vinfo);
        return 0;
    }

    if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
        gboolean err;
        snprintf(sql, sizeof(sql),
                 "SELECT repo_id FROM RepoHistoryLimit "
                 "WHERE repo_id='%s'", repo_id);
        if (seaf_db_check_for_existence(db, sql, &err))
            snprintf(sql, sizeof(sql),
                     "UPDATE RepoHistoryLimit SET days=%d"
                     "WHERE repo_id='%s'", days, repo_id);
        else
            snprintf(sql, sizeof(sql),
                     "INSERT INTO RepoHistoryLimit VALUES "
                     "('%s', %d)", repo_id, days);
        if (err)
            return -1;
        return seaf_db_query(db, sql);
    } else {
        snprintf (sql, sizeof(sql),
                  "REPLACE INTO RepoHistoryLimit VALUES ('%s', %d)",
                  repo_id, days);
        if (seaf_db_query (db, sql) < 0)
            return -1;
    }

    return 0;
}
コード例 #6
0
ファイル: repo-mgr.c プロジェクト: hram908/seafile
int
seaf_repo_manager_get_repo_history_limit (SeafRepoManager *mgr,
        const char *repo_id)
{
    SeafVirtRepo *vinfo;
    const char *r_repo_id = repo_id;
    char sql[256];
    int per_repo_days = -1;

    vinfo = seaf_repo_manager_get_virtual_repo_info (mgr, repo_id);
    if (vinfo)
        r_repo_id = vinfo->origin_repo_id;

    snprintf (sql, sizeof(sql),
              "SELECT days FROM RepoHistoryLimit WHERE repo_id='%s'",
              r_repo_id);
    seaf_virtual_repo_info_free (vinfo);

    /* We don't use seaf_db_get_int() because we need to differ DB error
     * from not exist.
     * We can't just return global config value if DB error occured,
     * since the global value may be smaller than per repo one.
     * This can lead to data lose in GC.
     */
    if (seaf_db_foreach_selected_row (mgr->seaf->db, sql,
                                      get_limit, &per_repo_days) < 0) {
        seaf_warning ("DB error.\n");
        return -1;
    }

    /* If per repo value is not set, return the global one. */
    if (per_repo_days < 0)
        return mgr->seaf->keep_history_days;

    return per_repo_days;
}
コード例 #7
0
ファイル: fsck.c プロジェクト: Danath/seafile
static int
recover_corrupted_repo_head (char *repo_id)
{
    GList *commit_list = NULL;
    GList *temp_list = NULL;
    SeafCommit *temp_commit = NULL;
    SeafBranch *branch = NULL;
    SeafRepo *repo = NULL;
    SeafVirtRepo *vinfo = NULL;
    FsckRes res;
    int rc = -1;

    seaf_message ("Recovering corrupt head commit for repo %.8s.\n", repo_id);

    seaf_obj_store_foreach_obj (seaf->commit_mgr->obj_store, repo_id,
                                1, fsck_get_repo_commit, &commit_list);

    if (commit_list == NULL)
        return rc;

    commit_list = g_list_sort (commit_list, compare_commit_by_ctime);
    memset (&res, 0, sizeof(res));
    res.existing_blocks = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                 g_free, NULL);


    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;

        branch = seaf_branch_new ("master", repo_id, temp_commit->commit_id);
        if (branch == NULL) {
            continue;
        }
        repo = seaf_repo_new (repo_id, NULL, NULL);
        if (repo == NULL) {
            seaf_branch_unref (branch);
            continue;
        }
        repo->head = branch;
        seaf_repo_from_commit (repo, temp_commit);
        vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id);
        if (vinfo) {
            repo->is_virtual = TRUE;
            memcpy (repo->store_id, vinfo->origin_repo_id, 36);
        } else {
            repo->is_virtual = FALSE;
            memcpy (repo->store_id, repo->id, 36);
        }
        seaf_virtual_repo_info_free (vinfo);

        res.repo = repo;
        rc = seaf_fs_manager_traverse_tree (seaf->fs_mgr,
                                            repo->store_id,
                                            repo->version,
                                            temp_commit->root_id,
                                            fs_callback,
                                            &res, FALSE);

        if (rc < 0) {
            seaf_repo_unref (repo);
        } else {
            break;
        }
    }

    if (rc < 0) {
        seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
    } else {
        // create new head commit, and set it's parent commit as latest avaliable commit
        temp_commit = cre_commit_from_parent (repo_id, temp_commit);
        if (temp_commit) {
            seaf_branch_set_commit (repo->head, temp_commit->commit_id);
            // in case of branch col miss, using add_branch instead of update_branch
            if (seaf_branch_manager_add_branch (seaf->branch_mgr, repo->head) < 0) {
                seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
                rc = -1;
            } else {
                seaf_commit_manager_add_commit (seaf->commit_mgr, temp_commit);
                seaf_message ("Head commit of repo %.8s has been fixed to commit %.8s.\n",
                              repo_id, temp_commit->commit_id);
            }
            seaf_commit_unref (temp_commit);
        } else {
            seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
            rc = -1;
        }
    }

    g_hash_table_destroy (res.existing_blocks);
    seaf_repo_unref (repo);
    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;
        seaf_commit_unref (temp_commit);
    }
    g_list_free (commit_list);

    return rc;
}
コード例 #8
0
int
seaf_quota_manager_check_quota (SeafQuotaManager *mgr,
                                const char *repo_id)
{
    SeafVirtRepo *vinfo;
    const char *r_repo_id = repo_id;
    char *user = NULL;
    int org_id;
    gint64 quota, usage;
    int ret = 0;

    /* If it's a virtual repo, check quota to origin repo. */
    vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id);
    if (vinfo)
        r_repo_id = vinfo->origin_repo_id;

    user = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, r_repo_id);
    if (user != NULL) {
        quota = seaf_quota_manager_get_user_quota (mgr, user);
    } else if (seaf->cloud_mode) {
        org_id = seaf_repo_manager_get_repo_org (seaf->repo_mgr, r_repo_id);
        if (org_id < 0) {
            seaf_warning ("Repo %s has no owner.\n", r_repo_id);
            ret = -1;
            goto out;
        }

        quota = seaf_quota_manager_get_org_quota (mgr, org_id);
    } else {
        seaf_warning ("Repo %s has no owner.\n", r_repo_id);
        ret = -1;
        goto out;
    }

    if (quota == INFINITE_QUOTA)
        goto out;

    if (user) {
        if (!mgr->calc_share_usage) {
            usage = seaf_quota_manager_get_user_usage (mgr, user);
        } else {
            gint64 my_usage, share_usage;
            share_usage = seaf_quota_manager_get_user_share_usage (mgr, user);
            if (share_usage < 0) {
                ret = -1;
                goto out;
            }
            my_usage = seaf_quota_manager_get_user_usage (mgr, user);
            if (my_usage < 0) {
                ret = -1;
                goto out;
            }
            usage = my_usage + share_usage;
        }
    } else
        usage = seaf_quota_manager_get_org_usage (mgr, org_id);

    if (usage < 0 || usage >= quota)
        ret = -1;

out:
    seaf_virtual_repo_info_free (vinfo);
    g_free (user);
    return ret;
}
コード例 #9
0
ファイル: fsck.c プロジェクト: rptec/seafile
static SeafRepo*
get_available_repo (char *repo_id, gboolean repair)
{
    GList *commit_list = NULL;
    GList *temp_list = NULL;
    SeafCommit *temp_commit = NULL;
    SeafBranch *branch = NULL;
    SeafRepo *repo = NULL;
    SeafVirtRepo *vinfo = NULL;
    gboolean io_error;

    seaf_message ("Scanning available commits...\n");

    seaf_obj_store_foreach_obj (seaf->commit_mgr->obj_store, repo_id,
                                1, fsck_get_repo_commit, &commit_list);

    if (commit_list == NULL) {
        seaf_warning ("No available commits for repo %.8s, can't be repaired.\n",
                      repo_id);
        return NULL;
    }

    commit_list = g_list_sort (commit_list, compare_commit_by_ctime);

    repo = seaf_repo_new (repo_id, NULL, NULL);
    if (repo == NULL) {
        seaf_warning ("Out of memory, stop to run fsck for repo %.8s.\n",
                      repo_id);
        goto out;
    }

    vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id);
    if (vinfo) {
        repo->is_virtual = TRUE;
        memcpy (repo->store_id, vinfo->origin_repo_id, 36);
        seaf_virtual_repo_info_free (vinfo);
    } else {
        repo->is_virtual = FALSE;
        memcpy (repo->store_id, repo->id, 36);
    }

    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;
        io_error = FALSE;

        if (!fsck_verify_seafobj (repo->store_id, 1, temp_commit->root_id,
                                  &io_error, VERIFY_DIR, repair)) {
            if (io_error) {
                seaf_repo_unref (repo);
                repo = NULL;
                goto out;
            }
            // fs object of this commit is corrupted,
            // continue to verify next
            continue;
        }

        branch = seaf_branch_new ("master", repo_id, temp_commit->commit_id);
        if (branch == NULL) {
            seaf_warning ("Out of memory, stop to run fsck for repo %.8s.\n",
                          repo_id);
            seaf_repo_unref (repo);
            repo = NULL;
            goto out;
        }
        repo->head = branch;
        seaf_repo_from_commit (repo, temp_commit);

        char time_buf[64];
        strftime (time_buf, 64, "%Y-%m-%d %H:%M:%S", localtime((time_t *)&temp_commit->ctime));
        seaf_message ("Find available commit %.8s(created at %s) for repo %.8s.\n",
                      temp_commit->commit_id, time_buf, repo_id);
        break;
    }

out:
    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;
        seaf_commit_unref (temp_commit);
    }
    g_list_free (commit_list);

    return repo;
}