gboolean is_repo_id_valid (const char *id) { if (!id) return FALSE; return is_uuid_valid (id); }
void export_file (GList *repo_id_list, const char *seafile_dir, char *export_path) { struct stat dir_st; if (stat (export_path, &dir_st) < 0) { if (errno == ENOENT) { if (g_mkdir (export_path, 0777) < 0) { seaf_warning ("Mkdir %s failed: %s.\n", export_path, strerror (errno)); return; } } else { seaf_warning ("Stat path: %s failed: %s.\n", export_path, strerror (errno)); return; } } else { if (!S_ISDIR(dir_st.st_mode)) { seaf_warning ("%s already exist, but it is not a directory.\n", export_path); return; } } if (!repo_id_list) { repo_id_list = get_repo_ids (seafile_dir); if (!repo_id_list) return; } GList *iter = repo_id_list; char *repo_id; GHashTable *enc_repos = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (; iter; iter=iter->next) { repo_id = iter->data; if (!is_uuid_valid (repo_id)) { seaf_warning ("Invalid repo id: %s.\n", repo_id); continue; } export_repo_files (repo_id, export_path, enc_repos); } if (g_hash_table_size (enc_repos) > 0) { seaf_message ("The following repos are encrypted and are not exported:\n"); g_hash_table_foreach (enc_repos, print_enc_repo, NULL); } while (repo_id_list) { g_free (repo_id_list->data); repo_id_list = g_list_delete_link (repo_id_list, repo_id_list); } g_hash_table_destroy (enc_repos); g_free (export_path); }
void seaf_obj_store_delete_obj (struct SeafObjStore *obj_store, const char *repo_id, int version, const char *obj_id) { ObjBackend *bend = obj_store->bend; if (!is_uuid_valid(repo_id) || !is_object_id_valid(obj_id)) return; return bend->delete (bend, repo_id, version, obj_id); }
gboolean seaf_obj_store_obj_exists (struct SeafObjStore *obj_store, const char *repo_id, int version, const char *obj_id) { ObjBackend *bend = obj_store->bend; if (!is_uuid_valid(repo_id) || !is_object_id_valid(obj_id)) return FALSE; return bend->exists (bend, repo_id, version, obj_id); }
int seaf_obj_store_read_obj (struct SeafObjStore *obj_store, const char *repo_id, int version, const char *obj_id, void **data, int *len) { ObjBackend *bend = obj_store->bend; if (!is_uuid_valid(repo_id) || !is_object_id_valid(obj_id)) return -1; return bend->read (bend, repo_id, version, obj_id, data, len); }
int seaf_obj_store_write_obj (struct SeafObjStore *obj_store, const char *repo_id, int version, const char *obj_id, void *data, int len, gboolean need_sync) { ObjBackend *bend = obj_store->bend; if (!is_uuid_valid(repo_id) || !is_object_id_valid(obj_id)) return -1; return bend->write (bend, repo_id, version, obj_id, data, len, need_sync); }
static int start (CcnetProcessor *processor, int argc, char **argv) { USE_PRIV; char *session_token; if (argc != 4) { ccnet_processor_send_response (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } if (!is_uuid_valid(argv[0]) || strlen(argv[2]) != 40) { ccnet_processor_send_response (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } memcpy (priv->repo_id, argv[0], 36); memcpy (priv->new_head, argv[2], 40); priv->branch_name = g_strdup(argv[1]); session_token = argv[3]; if (seaf_token_manager_verify_token (seaf->token_mgr, NULL, processor->peer_id, session_token, NULL) < 0) { ccnet_processor_send_response (processor, SC_ACCESS_DENIED, SS_ACCESS_DENIED, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } ccnet_processor_thread_create (processor, seaf->job_mgr, update_repo, thread_done, processor); return 0; }
GList * seaf_repo_manager_list_dir_with_perm (SeafRepoManager *mgr, const char *repo_id, const char *dir_path, const char *dir_id, const char *user, int offset, int limit, GError **error) { SeafRepo *repo; char *perm = NULL; SeafDir *dir; SeafDirent *dent; SeafileDirent *d; GList *res = NULL; GList *p; if (!repo_id || !is_uuid_valid(repo_id) || dir_id == NULL || !user) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id"); return NULL; } perm = seaf_repo_manager_check_permission (mgr, repo_id, user, error); if (!perm) { if (*error == NULL) g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Access denied"); return NULL; } repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); if (!repo) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id"); g_free (perm); return NULL; } dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr, repo->store_id, repo->version, dir_id); if (!dir) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id"); seaf_repo_unref (repo); g_free (perm); return NULL; } dir->entries = g_list_sort (dir->entries, comp_dirent_func); if (offset < 0) { offset = 0; } int index = 0; for (p = dir->entries; p != NULL; p = p->next, index++) { if (index < offset) { continue; } if (limit > 0) { if (index >= offset + limit) break; } dent = p->data; d = g_object_new (SEAFILE_TYPE_DIRENT, "obj_id", dent->id, "obj_name", dent->name, "mode", dent->mode, "version", dent->version, "mtime", dent->mtime, "size", dent->size, "permission", perm, NULL); res = g_list_prepend (res, d); } seaf_dir_free (dir); seaf_repo_unref (repo); g_free (perm); res = g_list_reverse (res); return res; }
static int start (CcnetProcessor *processor, int argc, char **argv) { char *repo_id, *token; USE_PRIV; if (argc != 5) { ccnet_processor_send_response (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } if (strcmp (argv[0], "upload") == 0) { priv->type = CHECK_TX_TYPE_UPLOAD; } else if (strcmp (argv[0], "download") == 0) { priv->type = CHECK_TX_TYPE_DOWNLOAD; } else { ccnet_processor_send_response (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } int client_version = atoi(argv[1]); if (client_version < 5) { seaf_debug ("Client protocol version lower than 5, not supported.\n"); ccnet_processor_send_response (processor, SC_PROTOCOL_MISMATCH, SS_PROTOCOL_MISMATCH, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } repo_id = argv[2]; token = argv[4]; if (!is_uuid_valid(repo_id)) { ccnet_processor_send_response (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; } memcpy (priv->repo_id, repo_id, 37); priv->branch_name = g_strdup("master"); priv->token = g_strdup(token); priv->client_version = client_version; CcnetPeer *peer = ccnet_get_peer (seaf->ccnetrpc_client, processor->peer_id); if (!peer || !peer->session_key) { seaf_warning ("[check tx slave v3] session key of peer %.10s is null\n", processor->peer_id); ccnet_processor_send_response (processor, SC_BAD_PEER, SS_BAD_PEER, NULL, 0); ccnet_processor_done (processor, FALSE); if (peer) g_object_unref (peer); return -1; } priv->session_key = g_strdup(peer->session_key); priv->peer_addr = g_strdup(peer->addr_str); priv->peer_name = g_strdup(peer->name); if (!priv->peer_name) priv->peer_name = g_strdup("Unknown"); g_object_unref (peer); seaf_debug ("[check-tx] %s repo %.8s.\n", argv[0], repo_id); ccnet_processor_thread_create (processor, seaf->job_mgr, check_tx, thread_done, processor); return 0; }
static void repair_repos (GList *repo_id_list, gboolean repair) { GList *ptr; char *repo_id; SeafRepo *repo; gboolean exists; gboolean reset; gboolean io_error; for (ptr = repo_id_list; ptr; ptr = ptr->next) { reset = FALSE; repo_id = ptr->data; seaf_message ("Running fsck for repo %s.\n", repo_id); if (!is_uuid_valid (repo_id)) { seaf_warning ("Invalid repo id %s.\n", repo_id); goto next; } exists = seaf_repo_manager_repo_exists (seaf->repo_mgr, repo_id); if (!exists) { seaf_warning ("Repo %.8s doesn't exist.\n", repo_id); goto next; } repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); if (!repo) { seaf_message ("Repo %.8s HEAD commit is corrupted, " "need to restore to an old version.\n", repo_id); repo = get_available_repo (repo_id, repair); if (!repo) { goto next; } reset = TRUE; } else { SeafCommit *commit = seaf_commit_manager_get_commit (seaf->commit_mgr, repo->id, repo->version, repo->head->commit_id); if (!commit) { seaf_warning ("Failed to get head commit %s of repo %s\n", repo->head->commit_id, repo->id); seaf_repo_unref (repo); goto next; } io_error = FALSE; if (!fsck_verify_seafobj (repo->store_id, repo->version, commit->root_id, &io_error, VERIFY_DIR, repair)) { if (io_error) { seaf_commit_unref (commit); seaf_repo_unref (repo); goto next; } else { // root fs object is corrupted, get available commit seaf_message ("Repo %.8s HEAD commit is corrupted, " "need to restore to an old version.\n", repo_id); seaf_commit_unref (commit); seaf_repo_unref (repo); repo = get_available_repo (repo_id, repair); if (!repo) { goto next; } reset = TRUE; } } else { // head commit is available seaf_commit_unref (commit); } } check_and_recover_repo (repo, reset, repair); seaf_repo_unref (repo); next: seaf_message ("Fsck finished for repo %.8s.\n\n", repo_id); } }
static void enable_sync_repo (const char *repo_id) { SeafRepo *repo = NULL; SeafCommit *parent_commit = NULL; SeafCommit *new_commit = NULL; gboolean exists; if (!is_uuid_valid (repo_id)) { seaf_warning ("Invalid repo id %s.\n", repo_id); return; } exists = seaf_repo_manager_repo_exists (seaf->repo_mgr, repo_id); if (!exists) { seaf_warning ("Repo %.8s doesn't exist.\n", repo_id); return; } repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); if (!repo) return; if (!repo->repaired) { seaf_repo_unref (repo); return; } seaf_message ("Enabling sync repo %s.\n", repo_id); parent_commit = seaf_commit_manager_get_commit_compatible (seaf->commit_mgr, repo_id, repo->head->commit_id); if (!parent_commit) { seaf_warning ("Commit %s:%s is missing\n", repo_id, repo->head->commit_id); goto out; } new_commit = seaf_commit_new (NULL, repo_id, parent_commit->root_id, parent_commit->creator_name, parent_commit->creator_id, "Enable sync repo", 0); if (!new_commit) { seaf_warning ("Out of memory when create commit.\n"); goto out; } new_commit->parent_id = g_strdup (parent_commit->commit_id); seaf_repo_to_commit (repo, new_commit); new_commit->repaired = FALSE; if (seaf_commit_manager_add_commit (seaf->commit_mgr, new_commit) < 0) { seaf_warning ("Failed to save commit %.8s for repo %.8s.\n", new_commit->commit_id, repo_id); goto out; } seaf_branch_set_commit (repo->head, new_commit->commit_id); if (seaf_branch_manager_update_branch (seaf->branch_mgr, repo->head) < 0) { seaf_warning ("Failed to update head commit %.8s to repo %.8s.\n", new_commit->commit_id, repo_id); } else { seaf_message ("Enable sync repo %.8s success.\n", repo_id); } out: if (parent_commit) seaf_commit_unref (parent_commit); if (new_commit) seaf_commit_unref (new_commit); if (repo) seaf_repo_unref (repo); }
GList * seaf_repo_manager_list_dir_with_perm (SeafRepoManager *mgr, const char *repo_id, const char *dir_path, const char *dir_id, const char *user, int offset, int limit, GError **error) { SeafRepo *repo; char *perm = NULL; SeafDir *dir; SeafDirent *dent; SeafileDirent *d; GList *res = NULL; GList *p; if (!repo_id || !is_uuid_valid(repo_id) || dir_id == NULL || !user) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id"); return NULL; } perm = seaf_repo_manager_check_permission (mgr, repo_id, user, error); if (!perm) { if (*error == NULL) g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Access denied"); return NULL; } repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); if (!repo) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id"); g_free (perm); return NULL; } dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr, repo->store_id, repo->version, dir_id); if (!dir) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id"); seaf_repo_unref (repo); g_free (perm); return NULL; } dir->entries = g_list_sort (dir->entries, comp_dirent_func); if (offset < 0) { offset = 0; } int index = 0; gboolean is_shared; char *cur_path; GHashTable *shared_sub_dirs = NULL; if (!repo->virtual_info) { char *repo_owner = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, repo_id); if (repo_owner && strcmp (user, repo_owner) == 0) { shared_sub_dirs = seaf_share_manager_get_shared_sub_dirs (seaf->share_mgr, repo->store_id, dir_path); } g_free (repo_owner); } for (p = dir->entries; p != NULL; p = p->next, index++) { if (index < offset) { continue; } if (limit > 0) { if (index >= offset + limit) break; } dent = p->data; d = g_object_new (SEAFILE_TYPE_DIRENT, "obj_id", dent->id, "obj_name", dent->name, "mode", dent->mode, "version", dent->version, "mtime", dent->mtime, "size", dent->size, "permission", perm, NULL); if (shared_sub_dirs && S_ISDIR(dent->mode)) { if (strcmp (dir_path, "/") == 0) { cur_path = g_strconcat (dir_path, dent->name, NULL); } else { cur_path = g_strconcat (dir_path, "/", dent->name, NULL); } is_shared = g_hash_table_lookup (shared_sub_dirs, cur_path) ? TRUE : FALSE; g_free (cur_path); g_object_set (d, "is_shared", is_shared, NULL); } res = g_list_prepend (res, d); } if (shared_sub_dirs) g_hash_table_destroy (shared_sub_dirs); seaf_dir_free (dir); seaf_repo_unref (repo); g_free (perm); if (res) res = g_list_reverse (res); return res; }