Пример #1
0
int do_download(const char *remote_path,
const char *local_path,  
int overwrite,             /* 是否覆盖 */ 
int create_new             /* 是否新建 */ 
) { 
//{{{
    int ret                 = 0;
    int stdout_output       = 0;
    PCSFile *file           = NULL;  /* 需要释放 */
    PCSFile *t_file         = NULL; 
    const char *error       = NULL;

    int remote_root_offset  = 0;
    char *tmp;
    char t_local_root[PATH_MAX + 1];
    char t_local_file[PATH_MAX + 1];

    PCSFileList *stack      = NULL; /* 需要释放 */
    PCSFileList *list       = NULL; /* 需要释放 */

    /* 获取远程路径信息 */
    file = BaiduPCS_NewRemoteFile(api, remote_path);
    error = BaiduPCS_GetError(api);
    if (error != NULL || file == NULL) {
        color_log(COLOR_LOG_ERROR, "%s 获取文件信息失败:%s\n", remote_path, error);
        ret = 1;
        goto free;
    }

    stdout_output = strcmp(local_path, "-") == 0;

    sprintf(t_local_file, "%s", local_path);

    /* 保存路径修正 */
    if (!stdout_output) {
        /* 远端为目录 */
        if (file->is_dir) {
            sprintf(t_local_root, "%s", local_path);
            remote_root_offset = strlen(file->path);
            if (stat(local_path, &(api->file_st)) != -1) {
                if (S_ISDIR(api->file_st.st_mode)){
                    t_local_root[0] = '\0';
                    strcat(t_local_root, local_path);
                    strcat(t_local_root, "/");
                    strcat(t_local_root, basename(file->path));
#ifdef DEBUG
                    fprintf(stderr, "本地根目录修正为:%s\n", t_local_root);
#endif
                } else {
                    color_log(COLOR_LOG_ERROR, "%s -> %s 本地已存与目录同名的文件\n", file->path, local_path);
                    ret = 1;
                    goto free;
                }
            }
        } else {
            if (stat(local_path, &(api->file_st)) != -1) {
                if (S_ISDIR(api->file_st.st_mode)){
                    sprintf(t_local_file, "%s/%s", local_path, basename(file->path));
                }
            }
        }
    } 

    /* 下载单个文件 */
    if (!file->is_dir) {
        ret = _do_download(remote_path, t_local_file, overwrite, create_new);
    } else {
        stack = PCSFileList_New();
        while(file != NULL) {
            tmp = file->path + remote_root_offset;
            sprintf(t_local_file, "%s%s", t_local_root, tmp);

            /* 如果是普通文件 */
            if (!file->is_dir) {
#ifdef DEBUG
                PCSFile_Dump(file);
#endif
                _do_download(file->path, t_local_file, overwrite, create_new);
                PCSFile_Free(file);
                file = PCSFileList_Shift(stack);
            /* 如果是目录 */
            } else {
                /* 创建本地目录 */
                if (stat(t_local_file, &(api->file_st)) != -1) {
                    if (!S_ISDIR(api->file_st.st_mode)){
                        color_log(COLOR_LOG_ERROR, "%s -> %s 本地已存与目录同名的文件\n", file->path, t_local_file);
                        ret = 1;
                        goto free;
                    }
                } else {
                    if (0 != mkdir(t_local_file, 0755)) {
                        color_log(COLOR_LOG_ERROR, "%s -> %s 本地目录创建失败\n", file->path, t_local_file);
                        ret = 1;
                        goto free;
                    }
                }

                list = BaiduPCS_ListRemoteDir(api, file->path);
                error = BaiduPCS_GetError(api);
                if (error != NULL || list == NULL) {
                    color_log(COLOR_LOG_ERROR, "%s 获取目录列表失败:%s\n", file->path, error);
                }
                /* 列出目录 */
                if (list != NULL) {
                    t_file  = PCSFileList_Shift(list);
                    while(t_file != NULL) {
                        PCSFileList_Prepend(stack, t_file);
                        t_file = PCSFileList_Shift(list);
                    }
                    PCSFileList_Free(list);
                    list = NULL;
                }
                PCSFile_Free(file);
                file = PCSFileList_Shift(stack);
            }
        }
    }
free:
    if (file != NULL) {
        PCSFile_Free(file);
    }

    if (stack != NULL) {
        PCSFileList_Free(stack);
    }

    if (list != NULL) {
        PCSFileList_Free(list);
    }
    return ret;
}
Пример #2
0
/* 递归列表 */
int do_recursion_ls(const char *remote_path, int option_show_detail) {
//{{{
    int ret                 = 0;
    PCSFileList *stack      = NULL;
    PCSFileList *list       = NULL;
    PCSFile *c_file         = NULL;
    PCSFile *t_file         = NULL;
    const char *error       = NULL;
    
    /* 遍历栈 */
    stack = PCSFileList_New();

    c_file = BaiduPCS_NewRemoteFile(api, remote_path);
    error = BaiduPCS_GetError(api);
    if (error != NULL || c_file == NULL) {
        color_log(COLOR_LOG_ERROR, "%s 获取文件信息失败:%s\n", remote_path, error);
        ret = 1;
        goto free;
    }

    while(c_file != NULL) {
        /* 如果是普通文件 */
        if (!c_file->is_dir) {
            print_file(c_file, option_show_detail);
            PCSFile_Free(c_file);
            c_file = PCSFileList_Shift(stack);
        /* 如果是目录 */
        } else {
            print_file(c_file, option_show_detail);
            list = BaiduPCS_ListRemoteDir(api, c_file->path);
            error = BaiduPCS_GetError(api);
            if (error != NULL || list == NULL) {
                color_log(COLOR_LOG_ERROR, "%s 获取文件信息失败:%s\n", c_file->path, error);
            }
            /* 列出目录 */
            if (list != NULL) {
                t_file  = PCSFileList_Shift(list);
                while(t_file != NULL) {
                    if (t_file->is_dir) {
                        PCSFileList_Prepend(stack, t_file);
                    } else {
                        print_file(t_file, option_show_detail);
                        PCSFile_Free(t_file);
                    }
                    t_file = PCSFileList_Shift(list);
                }
                PCSFileList_Free(list);
                list = NULL;
            }
            PCSFile_Free(c_file);
            c_file = PCSFileList_Shift(stack);
        }
    }
free:
    if (stack != NULL) {
        PCSFileList_Free(stack);
    }
    if (c_file != NULL) {
        PCSFile_Free(c_file);
    }
    return ret;
}
Пример #3
0
int do_upload(const char *local_path,
const char *remote_path,  
int overwrite,              /* 是否覆盖 */ 
int create_new,             /* 是否新建 */ 
int follow_link,            /* 跟随软链 */
int split_size              /* 分片大小 */
) { 
//{{{
    int ret                 = 0;
    int is_first            = 1;
    PCSFile *new_file       = NULL;
    PCSFile *t_file         = NULL;
    struct dirent *item     = NULL;
    const char *error       = NULL;
    const char *ondup       = NULL;

    char t_path[PATH_MAX + 1];         /* 临时路径       */
    char t_remote_path[PATH_MAX + 1];  /* 临时路径       */

    /* 需要释放 */
    PCSFile *c_file         = NULL;
    PCSFileList *stack      = NULL;
    PCSFile *remote_file    = NULL;
    PCSFileList *r_list     = NULL;
    DIR *dir                = NULL;
    
    /* 遍历栈 */
    stack           = PCSFileList_New();
    c_file          = BaiduPCS_NewLocalFile(api, local_path);

    error = BaiduPCS_GetError(api);
    if (error != NULL || c_file == NULL) {
        color_log(COLOR_LOG_ERROR, "文件对象创建失败 %s\n", error);
        ret = 1;
        goto free;
    }

    /* 当前要上传的远程路径 */
    c_file->userdata = strdup(remote_path);
    
    if (create_new) {
        ondup = "newcopy";
    } else {
        ondup = "overwrite";
    }

    while(c_file != NULL) {
        remote_path = (char *)c_file->userdata;
        /* 普通文件 */
        if (!c_file->is_dir && !c_file->is_link) {

            if (is_first) {
                remote_file = BaiduPCS_NewRemoteFile(api, remote_path); 
                if (remote_file != NULL) {
                    /*  upload xx.txt /apps/xx/ 
                     *  对于这种情况,远端路径修正为/apps/xx/xx.txt
                     */
                    if (remote_file->is_dir) {
                        t_remote_path[0] = '\0';
                        strcat(t_remote_path, remote_path);
                        strcat(t_remote_path, "/");
                        strcat(t_remote_path, basename(c_file->path));
#ifdef DEBUG
                        fprintf(stderr, "上传路径 %s 修正为 %s\n", remote_path, t_remote_path);
#endif

                        free(c_file->userdata);
                        c_file->userdata = strdup(t_remote_path);
                        remote_path = c_file->userdata;
                        PCSFile_Free(remote_file);
                        remote_file = NULL;
                        continue;
                    /* upload xx.txt /apps/xx/xx.txt */
                    } else if (!overwrite && !create_new) {
                        color_log(COLOR_LOG_IGNORE, "%s -> %s 远端已存在同名文件\n", c_file->path, remote_file->path);
                        goto free; 
                    }
                    PCSFile_Free(remote_file);
                    remote_file = NULL;
                }
            }

            remote_file = BaiduPCS_Upload(api, c_file, remote_path, 0, ondup);
            error = BaiduPCS_GetError(api);
            /* 上传失败 */
            if (error != NULL || remote_file == NULL) {
                color_log(COLOR_LOG_ERROR, "%s -> %s %s\n", c_file->path, remote_path, error);
                /* 如果上传单个文件,失败后会返回error code */
                if (is_first) {
                    ret = 1;
                    goto free;
                }
            /* 上传成功 */
            } else {
                color_log(COLOR_LOG_OK, "%s -> %s\n", c_file->path, remote_file->path);
                PCSFile_Free(remote_file);
                remote_file = NULL;
            }

            free(c_file->userdata);
            PCSFile_Free(c_file);

            c_file = PCSFileList_Shift(stack);
            is_first = 0;
        //如果是目录
        } else if (c_file->is_dir) {
            /* 遍历目录 */
            dir = opendir(c_file->path);  
            /* 读取目录失败 */
            if (dir == NULL) {
                color_log(COLOR_LOG_ERROR, "%s -> %s 目录读取失败\n", c_file->path, remote_path);
                /* 如果当前为用户指定的根目录,直接返回错误 */
                if (is_first) {
                    ret = 1;
                    goto free;
                }
            } else {
                /* 进行目录修正 */
                if (is_first) {
                    remote_file = BaiduPCS_NewRemoteFile(api, remote_path); 
                    if (remote_file != NULL) {
                        /*  upload ./dir/ /apps/xx/ 
                         *  对于这种情况,远端路径修正为/apps/xx/dir
                         */
                        if (remote_file->is_dir) {
                            t_remote_path[0] = '\0';
                            strcat(t_remote_path, remote_file->path);
                            strcat(t_remote_path, "/");
                            strcat(t_remote_path, basename(c_file->path));
#ifdef DEBUG
                            fprintf(stderr, "上传目录 %s 修正为 %s\n", remote_path, t_remote_path);
#endif
                            free(c_file->userdata);
                            c_file->userdata = strdup(t_remote_path);
                            remote_path = c_file->userdata;

                        } else if (!remote_file->is_dir) {
                            color_log(COLOR_LOG_ERROR, "%s -> %s 远端路径不是目录\n", c_file->path, remote_file->path);
                            ret = 1;
                            goto free;
                        }

                        PCSFile_Free(remote_file);
                        remote_file = NULL;
                    }
                }

                /* 获取远程目录列表,用于排除远端已存在的文件 */
                remote_file = BaiduPCS_NewRemoteFile(api, remote_path);
                if (remote_file != NULL) {
                    /* 远端已存在同名文件 */
                    if (!remote_file->is_dir) {
                        color_log(COLOR_LOG_ERROR, "%s -> %s 远端已存与目录同名的文件\n", c_file->path, remote_file->path);
                        if (is_first) {
                            ret = 1;
                            goto free;
                        }
                    } else {
                        /* 获取远端目录文件列表,用于对比本地目录列表 */
                        r_list = BaiduPCS_ListRemoteDir(api, remote_path);
                    }
                    PCSFile_Free(remote_file);
                    remote_file = NULL;
                }
                
                while ((item = readdir(dir)) != NULL) {
                    if (strcmp(item->d_name, ".") == 0
                        || strcmp(item->d_name, "..") == 0) {
                        continue;
                    }

                    /* 构建本地文件完整路径 */
                    t_path[0] = '\0';
                    strcat(t_path, c_file->path);
                    strcat(t_path, "/");
                    strcat(t_path, item->d_name);

                    /* 构建上传路径 */
                    t_remote_path[0] = '\0';
                    strcat(t_remote_path, remote_path);
                    strcat(t_remote_path, "/");
                    strcat(t_remote_path, item->d_name);

                    new_file = BaiduPCS_NewLocalFile(api, t_path);
                    error = BaiduPCS_GetError(api);
                    if (error != NULL || new_file == NULL) {
                        color_log(COLOR_LOG_ERROR, "%s -> %s %s\n", t_path, t_remote_path, error);
                    } else {
                        if (r_list != NULL) {
                            t_file = PCSFileList_Find(r_list, t_remote_path);
                            /* 远程已存在同名文件 */
                            if (t_file != NULL) {
                                if (new_file->is_dir && !t_file->is_dir) {
                                    color_log(COLOR_LOG_ERROR, "%s -> %s 远程已存在与目录同名的文件\n", t_path, t_remote_path);
                                    PCSFile_Free(new_file);
                                    new_file = NULL;
                                    continue;
                                } else if (!new_file->is_dir && t_file->is_dir) {
                                    color_log(COLOR_LOG_ERROR, "%s -> %s 远程已存在与文件同名的目录\n", t_path, t_remote_path);
                                    PCSFile_Free(new_file);
                                    new_file = NULL;
                                    continue;
                                } else if (!new_file->is_dir && !new_file->is_link && !overwrite && !create_new) {
                                    color_log(COLOR_LOG_IGNORE, "%s -> %s 远程已存在同名文件\n", t_path, t_remote_path);
                                    PCSFile_Free(new_file);
                                    new_file = NULL;
                                    continue;
                                }
                            }
                        }
                       
                        new_file->userdata = strdup(t_remote_path);
                        //放入栈中
                        PCSFileList_Prepend(stack, new_file);
                        new_file = NULL;
                    }
                }
                if (r_list != NULL) {
                    PCSFileList_Free(r_list);
                    r_list = NULL;
                }

                closedir(dir);
                dir = NULL;
            }

            free(c_file->userdata);
            PCSFile_Free(c_file);
            c_file = PCSFileList_Shift(stack);
            is_first = 0;
        /* 软链接 */
        } else if (c_file->is_link) { 
            if (follow_link) {
                realpath(c_file->path, t_path);
#ifdef DEBUG
                fprintf(stderr, "跟随软链 %s -> %s\n", c_file->path, t_path);
#endif
                new_file = BaiduPCS_NewLocalFile(api, t_path);
                new_file->userdata = c_file->userdata;
                PCSFile_Free(c_file);
                c_file = new_file;
            } else {
                color_log(COLOR_LOG_IGNORE, "忽略软链接 %s\n", c_file->path);
                free(c_file->userdata);
                PCSFile_Free(c_file);
                c_file = PCSFileList_Shift(stack);
                is_first = 0;
            }
        /* 忽略其他类型 */
        } else {
            color_log(COLOR_LOG_ERROR, "不支持的文件类型 %s\n", c_file->path);
            free(c_file->userdata);
            PCSFile_Free(c_file);
            c_file = PCSFileList_Shift(stack);
            is_first = 0;
        }
    }

free:
    PCSFileList_Free(stack);

    if (dir != NULL) {
        closedir(dir);
    }

    if (c_file != NULL) {
        free(c_file->userdata);
        PCSFile_Free(c_file);
    }

    if (remote_file != NULL) {
        PCSFile_Free(remote_file);
    }

    if (r_list != NULL) {
        PCSFileList_Free(r_list);
    }
    return ret;
}
Пример #4
0
PCSFileList *BaiduPCS_ListRemoteDir(BaiduPCS *api, const char *path) {
//{{{
    PCSFileList *list       = NULL;
    PCSFile *file           = NULL;
    HttpClient *client      = api->client;
    char *url_buffer        = api->util_buffer0;
    const char *token       = api->token;
    const char *error       = NULL;
    const char *response    = NULL;
    char *path_encode       = NULL;
    cJSON *json             = NULL;
    cJSON *array            = NULL;
    cJSON *item             = NULL;
    int i                   = 0;
    int length              = 0;

    BaiduPCS_ResetError(api); 

    list          = PCSFileList_New();

    path_encode = curl_easy_escape(client->curl, path, 0);
    sprintf(url_buffer, "https://pcs.baidu.com/rest/2.0/pcs/file?"
           "access_token=%s"
           "&method=list"
           "&path=%s", token, path_encode);
    curl_free(path_encode);

#ifdef DEBUG
    fprintf(stderr, "request %s\n", url_buffer);
#endif

    HttpClient_Init(client);
    HttpClient_Get(client, url_buffer);

    MAKE_JSON();

    item = cJSON_GetObjectItem(json, "list");
    if (item == NULL || item->type != cJSON_Array) {
        BaiduPCS_ThrowError(api, "can't find json.list");
        goto free;
    }

    array = item;
    length = cJSON_GetArraySize(array);
    
    for (i = 0; i < length; i ++) {
        item = cJSON_GetArrayItem(array, i);
        if (item == NULL || item->type != cJSON_Object) {
            BaiduPCS_ThrowError(api, "json.list.item is not object");
            goto free;
        }

        file = PCSFile_New();
        PCSFileList_Prepend(list, file);
        _BaiduPCS_Json2File(api, file, item);
        if (BaiduPCS_GetError(api) != NULL) {
        }
    }
       
free:

    if (json != NULL) {
        cJSON_Delete(json);
    }

    return list;
}