PCS_API PcsFileInfo *pcs_meta(Pcs handle, const char *path) { PcsFileInfoList *filist; PcsFileInfo *meta = NULL; char *dir, *key; PcsFileInfoListIterater iterater; pcs_clear_errmsg(handle); dir = pcs_utils_basedir(path); key = pcs_utils_filename(path); filist = pcs_search(handle, dir, key, PcsFalse); pcs_free(dir); pcs_free(key); if (!filist) return NULL; pcs_filist_iterater_init(filist, &iterater, PcsFalse); while(pcs_filist_iterater_next(&iterater)) { if (pcs_utils_strcmpi(path, iterater.current->path) == 0) { meta = iterater.current; break; } } if (meta) { meta = pcs_fileinfo_clone(meta); if (!meta) { pcs_set_errmsg(handle, "Can't clone the meta data."); } } else { pcs_set_errmsg(handle, "Can't find the file."); } pcs_filist_destroy(filist); return meta; }
static void exec_search(Pcs pcs, struct params *params) { PcsFileInfoList *list; printf("\n%sSearch %s in %s\n", params->is_recursion ? "Recursive " : "", params->args[1], params->args[0]); list = pcs_search(pcs, params->args[0], params->args[1], params->is_recursion); putchar('\n'); if (list) { print_filelist(list); pcs_filist_destroy(list); } else { print_filelist_head(4); } }
static void exec_list(Pcs pcs, struct params *params) { PcsFileInfoList *list; printf("\n%sList %s\n", params->is_recursion ? "Recursive " : "", params->args[0]); list = get_file_list(pcs, params->args[0], params->sort, params->is_desc, params->is_recursion); if (list) { printf("Got %d Files\n", list->count); fflush(stdout); print_filelist(list); pcs_filist_destroy(list); } else { printf("Got 0 Files\n"); fflush(stdout); print_filelist_head(4); } }
static int exec_download_dir(Pcs pcs, const char *remote_path, const char *local_path, int force, int recursion, int synch) { int ft; hashtable *ht; my_dirent *ents, *ent, *local_file; PcsFileInfoList *remote_files; PcsFileInfoListIterater iterater; PcsFileInfo *file; PcsRes dres; char *dest_path; struct download_state ddstat; FILE *pf; printf("\nDownload %s to %s\n", remote_path, local_path); ft = is_dir_or_file(local_path); if (ft == 1) { printf("Invalidate target: %s is not the directory.\n", local_path); return -1; } else if (ft == 2) { //if (!force) { // printf("execute upload command failed: The target %s exist.\n", remote_path); // return -1; //} } else { if (mkdir(local_path)) { printf("Cannot create the directory %s.\n", local_path); return -1; } } ents = list_dir(local_path, 0); ht = hashtable_create(100, 1, NULL); if (!ht) { printf("Cannot create hashtable.\n"); my_dirent_destroy(ents); return -1; } ent = ents; while(ent) { if (hashtable_add(ht, ent->path, ent)) { printf("Cannot add item into hashtable.\n"); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } ent = ent->next; } remote_files = get_file_list(pcs, remote_path, NULL, PcsFalse, PcsFalse); if (!remote_files) { hashtable_destroy(ht); my_dirent_destroy(ents); if (pcs_strerror(pcs)) { printf("Cannot list the remote files.\n"); return -1; } return 0; } pcs_filist_iterater_init(remote_files, &iterater, PcsFalse); while(pcs_filist_iterater_next(&iterater)) { file = iterater.current; dest_path = combin_local_path(local_path, file->server_filename); if (!dest_path) { printf("Cannot alloca memory. 0%s, %s\n", local_path, file->server_filename); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } if (file->isdir) { if (force || recursion) { local_file = (my_dirent *)hashtable_get(ht, dest_path); if (local_file) { local_file->user_flag = 1; printf("[SKIP] d %s\n", file->path); } else if (recursion) { if (mkdir(dest_path)) { printf("[FAIL] d %s Cannot create the folder %s\n", file->path, dest_path); pcs_free(dest_path); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } else { printf("[SUCC] d %s => %s\n", file->path, dest_path); } } } } else { local_file = (my_dirent *)hashtable_get(ht, dest_path); if (local_file) local_file->user_flag = 1; if (force || !local_file || my_dirent_get_mtime(local_file) < ((time_t)file->server_mtime)) { ddstat.msg = (char *) pcs_malloc(strlen(dest_path) + 12); if (!ddstat.msg) { printf("Cannot alloca memory. 1%s, %s\n", local_path, file->server_filename); pcs_free(dest_path); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } sprintf(ddstat.msg, "Download %s ", dest_path); pf = fopen(dest_path, "wb"); if (!pf) { printf("Cannot create the local file: %s\n", dest_path); pcs_free(dest_path); pcs_free(ddstat.msg); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } ddstat.pf = pf; ddstat.size = 0; pcs_setopt(pcs, PCS_OPTION_DOWNLOAD_WRITE_FUNCTION_DATA, &ddstat); dres = pcs_download(pcs, file->path); pcs_free(ddstat.msg); fclose(ddstat.pf); if (dres != PCS_OK) { printf("[FAIL] - %s => %s\n", file->path, dest_path); pcs_free(dest_path); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } my_dirent_utime(dest_path, file->server_mtime); printf("[SUCC] - %s => %s\n", file->path, dest_path); } else { printf("[SKIP] - %s\n", file->path); } } pcs_free(dest_path); } if (recursion) { pcs_filist_iterater_init(remote_files, &iterater, PcsFalse); while(pcs_filist_iterater_next(&iterater)) { file = iterater.current; dest_path = combin_local_path(local_path, file->server_filename); if (!dest_path) { printf("Cannot alloca memory. 2%s, %s\n", local_path, file->server_filename); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } if (file->isdir) { if (exec_download_dir(pcs, file->path, dest_path, force, recursion, synch)) { pcs_free(dest_path); pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return -1; } } pcs_free(dest_path); } } if (synch) { hashtable_iterater *iterater; iterater = hashtable_iterater_create(ht); hashtable_iterater_reset(iterater); while(hashtable_iterater_next(iterater)) { local_file = (my_dirent *)hashtable_iterater_current(iterater); if (!local_file->user_flag) { if (my_dirent_remove(local_file->path)) { printf("[DELETE] [FAIL] %s %s \n", local_file->is_dir ? "d" : "-", local_file->path); } else { printf("[DELETE] [SUCC] %s %s \n", local_file->is_dir ? "d" : "-", local_file->path); } } } hashtable_iterater_destroy(iterater); } pcs_filist_destroy(remote_files); hashtable_destroy(ht); my_dirent_destroy(ents); return 0; }
static PcsFileInfoList *get_file_list(Pcs pcs, const char *dir, const char *sort, PcsBool desc, PcsBool recursion) { PcsFileInfoList *reslist = NULL, *list = NULL, *sublist = NULL, *item = NULL; PcsFileInfo *info = NULL; int page_index = 1, page_size = 100; int cnt = 0, cnt_total = 0; while(1) { printf("List %s, Got %d Files \r", dir, cnt_total); fflush(stdout); list = pcs_list(pcs, dir, page_index, page_size, sort ? sort : "name", sort ? desc : PcsFalse); if (!list) { if (pcs_strerror(pcs)) printf("Cannot list %s: %s\n", dir, pcs_strerror(pcs)); return NULL; } cnt = list->count; cnt_total += cnt; if (recursion) { PcsFileInfoListItem *listitem; PcsFileInfoListIterater iterater; reslist = pcs_filist_create(); if (!reslist) { printf("Cannot create the PcsFileInfoList object for %s.\n", dir); pcs_filist_destroy(list); return NULL; } pcs_filist_iterater_init(list, &iterater, PcsFalse); while(pcs_filist_iterater_next(&iterater)) { info = iterater.current; listitem = iterater.cursor; pcs_filist_remove(list, listitem, &iterater); pcs_filist_add(reslist, listitem); if (info->isdir) { sublist = get_file_list(pcs, info->path, sort, desc, recursion); if (sublist) { pcs_filist_combin(reslist, sublist); pcs_filist_destroy(sublist); } } else { /* * 因为百度网盘返回的都是文件夹在前,文件在后, * 因此遇到第一个文件,则后边的都是文件。 * 所以可以跳过检查,直接合并 */ pcs_filist_combin(reslist, list); break; } } pcs_filist_destroy(list); } else { reslist = list; } if (cnt > 0) { printf("List %s, Got %d Files \r", dir, cnt_total); fflush(stdout); } if (cnt < page_size) { break; } page_index++; } return reslist; }
static int exec_upload_dir(Pcs pcs, const char *local_path, const char *remote_path, int force, int recursion, int synch) { int ft = 0, res = 0, ric = 0; char *dest_path = NULL; PcsFileInfo *meta = NULL, *remote_file = NULL; PcsFileInfoList *remote_filelist = NULL; PcsFileInfoListIterater iterater = {0}; PcsRes pcsres = PCS_NONE; PcsPanApiRes *pcsapires = NULL; hashtable *ht = NULL; my_dirent *ents = NULL, *ent = NULL; printf("\nUpload %s to %s\n", local_path, remote_path); exec_upload_dir_label_1: meta = pcs_meta(pcs, remote_path); if (meta) { if (meta->isdir) ft = 2; else ft = 1; pcs_fileinfo_destroy(meta); meta = NULL; } else if (pcs_strerror(pcs)) { printf("Cannot get the meta for %s: %s\n", remote_path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') goto exec_upload_dir_label_1; else return -1; } if (ft == 1) { if (force) { PcsSList slist = { (char *)remote_path, 0 }; printf("Delete the %s, since the target is not the directory and you specify -f.\n", remote_path); exec_upload_dir_label_2: pcsapires = pcs_delete(pcs, &slist); if (!pcsapires) { printf("[DELETE] [FAIL] - %s: %s\n", remote_path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') goto exec_upload_dir_label_2; else return -1; } else { printf("[DELETE] [SUCC] - %s \n", remote_path); pcs_pan_api_res_destroy(pcsapires); } exec_upload_dir_label_3: pcsres = pcs_mkdir(pcs, remote_path); if (pcsres != PCS_OK) { printf("[FAIL] Cannot create the directory %s: %s\n", remote_path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') goto exec_upload_dir_label_3; else return -1; } else { printf("[SUCC] Create directory %s\n", remote_path); goto exec_upload_dir_label_5; } } else { printf("The target %s is not the directory. You can use -f to force recreate the directory.\n", remote_path); } return -1; } else if (ft == 2) { } else { exec_upload_dir_label_4: pcsres = pcs_mkdir(pcs, remote_path); if (pcsres != PCS_OK) { printf("[FAIL] Cannot create the directory %s: %s\n", remote_path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') goto exec_upload_dir_label_4; else return -1; } else { printf("[SUCC] Create directory %s\n", remote_path); goto exec_upload_dir_label_5; } } exec_upload_dir_label_5: printf("Get remote file list %s.\n", remote_path); remote_filelist = get_file_list(pcs, remote_path, NULL, PcsFalse, PcsFalse); if (!remote_filelist && pcs_strerror(pcs)) { printf("[FAIL] Cannot list the directory %s: %s\n", remote_path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') goto exec_upload_dir_label_5; else return -1; } if (remote_filelist) { ht = hashtable_create(remote_filelist->count, 1, NULL); if (!ht) { printf("Cannot create hashtable.\n"); goto exec_upload_dir_label_00; } pcs_filist_iterater_init(remote_filelist, &iterater, PcsFalse); while(pcs_filist_iterater_next(&iterater)) { remote_file = iterater.current; if (hashtable_add(ht, remote_file->path, remote_file)) { printf("Cannot add object to hashtable.\n"); goto exec_upload_dir_label_00; } } } ents = list_dir(local_path, 0); if (!ents) { printf("[SKIP] d %s empty directory.\n", local_path); goto exec_upload_dir_label_0; } ent = ents; while(ent) { dest_path = combin_remote_path(remote_path, ent->filename); if (!dest_path) { printf("Cannot combin the path.\n"); goto exec_upload_dir_label_00; } if (ent->is_dir) { if (force || recursion) { remote_file = ht ? (PcsFileInfo *)hashtable_get(ht, dest_path) : NULL; if (remote_file) { remote_file->user_flag = 1; printf("[SKIP] d %s\n", ent->path); } else if (recursion) { exec_upload_dir_label_6: pcsres = pcs_mkdir(pcs, dest_path); if (pcsres != PCS_OK) { printf("[FAIL] d %s Cannot create the directory %s: %s\n", ent->path, dest_path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') { goto exec_upload_dir_label_6; } else { goto exec_upload_dir_label_00; } } else { printf("[SUCC] d %s => %s\n", ent->path, dest_path); } } } } else { remote_file = ht ? (PcsFileInfo *)hashtable_get(ht, dest_path) : NULL; if (remote_file) remote_file->user_flag = 1; if (force || !remote_file || ((time_t)remote_file->server_mtime) < my_dirent_get_mtime(ent)) { exec_upload_dir_label_7: pcs_setopt(pcs, PCS_OPTION_PROGRESS_FUNCTION_DATE, ent->path); pcs_setopt(pcs, PCS_OPTION_PROGRESS, (void *)PcsTrue); meta = pcs_upload(pcs, dest_path, PcsTrue, ent->path); pcs_setopt(pcs, PCS_OPTION_PROGRESS, (void *)PcsFalse); pcs_setopt(pcs, PCS_OPTION_PROGRESS_FUNCTION_DATE, NULL); if (!meta) { printf("[FAIL] - %s Cannot upload the file: %s\n", ent->path, pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') { goto exec_upload_dir_label_7; } else { goto exec_upload_dir_label_00; } } printf("[SUCC] - %s => %s\n", ent->path, meta->path); pcs_fileinfo_destroy(meta); meta = NULL; } else { printf("[SKIP] - %s\n", ent->path); } } ent = ent->next; pcs_free(dest_path); dest_path = NULL; } if (recursion) { ent = ents; while(ent) { dest_path = combin_remote_path(remote_path, ent->filename); if (!dest_path) { printf("Cannot combin the path.\n"); goto exec_upload_dir_label_00; } if (ent->is_dir) { if (exec_upload_dir(pcs, ent->path, dest_path, force, recursion, synch)) { goto exec_upload_dir_label_00; } } ent = ent->next; pcs_free(dest_path); dest_path = NULL; } } if (synch && ht) { hashtable_iterater *iterater; PcsSList slist = {0,0}; iterater = hashtable_iterater_create(ht); hashtable_iterater_reset(iterater); while(hashtable_iterater_next(iterater)) { remote_file = (PcsFileInfo *)hashtable_iterater_current(iterater); if (!remote_file->user_flag) { slist.string = remote_file->path; exec_upload_dir_label_8: pcsapires = pcs_delete(pcs, &slist); if (!pcsapires) { printf("[DELETE] [FAIL] %s %s Cannot delete the %s: %s\n", remote_file->isdir ? "d" : "-", remote_file->path, remote_file->isdir ? "directory" : "fire", pcs_strerror(pcs)); ric = retry_cancel(); if (ric == 'r') { goto exec_upload_dir_label_8; } else { goto exec_upload_dir_label_00; } } else { printf("[DELETE] [SUCC] %s %s \n", remote_file->isdir ? "d" : "-", remote_file->path); pcs_pan_api_res_destroy(pcsapires); } } } hashtable_iterater_destroy(iterater); } goto exec_upload_dir_label_0; exec_upload_dir_label_00: res = -1; exec_upload_dir_label_0: if (dest_path) pcs_free(dest_path); if (meta) pcs_fileinfo_destroy(meta); if (ht) hashtable_destroy(ht); if (remote_filelist) pcs_filist_destroy(remote_filelist); if (ents) my_dirent_destroy(ents); return res; }
/* 根据传入参数,执行api函数。参数传入方法,参考pcs_build_pan_api_url()函数 action: list, search */ static PcsFileInfoList *pcs_pan_api_1(Pcs handle, const char *action, ...) { struct pcs *pcs = (struct pcs *)handle; va_list args; cJSON *json, *item, *list; char *url, *html; int error, cnt, i; PcsFileInfoList *filist = NULL; PcsFileInfoListItem *filist_item; PcsFileInfo *fi; pcs_clear_errmsg(handle); va_start(args, action); url = pcs_build_pan_api_url_v(handle, action, args); va_end(args); if (!url) { pcs_set_errmsg(handle, "Can't build url."); return NULL; } html = pcs_http_get(pcs->http, url, PcsTrue); pcs_free(url); if (!html) { pcs_set_errmsg(handle, "Can't get response from the remote server."); return NULL; } json = cJSON_Parse(html); if (!json){ //printf("%s\n", html); pcs_set_errmsg(handle, "Can't parse the response as json: %s", html); return NULL; } item = cJSON_GetObjectItem(json, "errno"); if (!item) { //printf("%s\n", html); pcs_set_errmsg(handle, "Can't read res.errno: %s", html); cJSON_Delete(json); return NULL; } error = item->valueint; if (error != 0) { //printf("%s\n", html); pcs_set_errmsg(handle, "%s, Error:%d", get_errmsg_by_errno(error), error); cJSON_Delete(json); return NULL; } list = cJSON_GetObjectItem(json, "list"); if (!list) { pcs_set_errmsg(handle, "Can't read res.list: %s", html); cJSON_Delete(json); return NULL; } cnt = cJSON_GetArraySize(list); if (cnt <= 0) { cJSON_Delete(json); return NULL; } filist = pcs_filist_create(); if (!filist) { pcs_set_errmsg(handle, "Can't create object: PcsFileInfoList"); cJSON_Delete(json); return NULL; } for (i = 0; i < cnt; i++) { item = cJSON_GetArrayItem(list, i); filist_item = pcs_filistitem_create(); if (!filist_item) { pcs_set_errmsg(handle, "Can't create object: PcsFileInfoListItem"); cJSON_Delete(json); if (filist) pcs_filist_destroy(filist); return NULL; } fi = pcs_parse_fileinfo(item); if (!fi) { pcs_set_errmsg(handle, "Can't create object: PcsFileInfo"); cJSON_Delete(json); pcs_filistitem_destroy(filist_item); if (filist) pcs_filist_destroy(filist); return NULL; } filist_item->info = fi; pcs_filist_add(filist, filist_item); } cJSON_Delete(json); return filist; }