闲着没事,写了个操作百度pcs的例子,实现了上传,下载,删除等基本功能,百度pcs实现起来比较简单,只有在实现上传的时候遇到点麻烦,upload 中file的描述不够明确。
下面是主要代码,使用了cJSON和libcurl。
main.c
#include <time.h>
#include <stdio.h>#include <string.h>
#include <stdlib.h>
#include "trans_inf.h"
#include "cJSON.h"
#define ROOT_DIR "/apps/zztpcs" //这是我应用的目录名,需要改成自己的
#define PCS_DEBUG printf
char* access_token = "xxxx"; //access token,我固定了
struct pcs_stat
{
int isdir;
long long size;
int ctime;
int mtime;
};
char curdir[512] = ROOT_DIR;
int parse_pcs_stat(char* msg, struct pcs_stat* buf)
{
int ret = -1;
int i;
cJSON *root = NULL;
cJSON *list = NULL;
cJSON *item = NULL;
cJSON *node = NULL;
memset(buf, 0, sizeof(struct pcs_stat));
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
list = cJSON_GetObjectItem(root,"list");
if(NULL == list)
{
goto END;
}
for(i=0;i<cJSON_GetArraySize(list);i++)
{
item=cJSON_GetArrayItem(list,i);
if(item)
{
node = cJSON_GetObjectItem(item,"isdir");
if(node)
{
buf->isdir = node->valueint;
}
node = cJSON_GetObjectItem(item,"ctime");
if(node)
{
buf->ctime = node->valueint;
}
node = cJSON_GetObjectItem(item,"mtime");
if(node)
{
buf->mtime = node->valueint;
}
node = cJSON_GetObjectItem(item,"size");
if(node)
{
buf->size = node->valueint;
}
}
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_stat(char* path, struct pcs_stat* buf)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=meta&access_token=%s&path=%s",
access_token,
path);
getcmd(cmdbuf, &msg);
{
if(msg)
{
if(parse_pcs_stat(msg, buf) == 0)
{
ret = 0;
}
free(msg);
msg = NULL;
}
}
return ret;
}
int parse_mkdir(char* msg)
{
int ret = -1;
cJSON *root = NULL;
cJSON *node = NULL;
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
node = cJSON_GetObjectItem(root,"fs_id");
if(NULL == node)
{
goto END;
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_mkdir(char* path)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=mkdir&access_token=%s&path=%s",
access_token,
path);
postcmd(cmdbuf, "a", &msg);
{
if(msg)
{
if(parse_mkdir(msg) == 0)
{
ret = 0;
}
free(msg);
msg = NULL;
}
}
return ret;
}
int parse_ls(char* msg)
{
int ret = -1;
int i;
cJSON *root = NULL;
cJSON *list = NULL;
cJSON *item = NULL;
cJSON *node = NULL;
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
list = cJSON_GetObjectItem(root,"list");
if(NULL == list)
{
goto END;
}
printf("num path isdir ctime mtime size\n");
for(i=0;i<cJSON_GetArraySize(list);i++)
{
item=cJSON_GetArrayItem(list,i);
if(item)
{
printf("%d ", i);
node = cJSON_GetObjectItem(item,"path");
if(node)
{
printf("%s ", node->valuestring);
}
node = cJSON_GetObjectItem(item,"isdir");
if(node)
{
printf("%d ", node->valueint);
}
else
{
printf(" ");
}
node = cJSON_GetObjectItem(item,"ctime");
if(node)
{
printf("%d ", node->valueint);
}
else
{
printf(" ");
}
node = cJSON_GetObjectItem(item,"mtime");
if(node)
{
printf("%d ", node->valueint);
}
else
{
printf(" ");
}
node = cJSON_GetObjectItem(item,"size");
if(node)
{
printf("%d", node->valueint);
}
printf("\n");
}
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_ls(char* path)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=list&access_token=%s&path=%s",
access_token,
path);
getcmd(cmdbuf, &msg);
{
if(msg)
{
if(parse_ls(msg) == 0)
{
strcpy(curdir, path);
ret = 0;
}
free(msg);
msg = NULL;
}
}
return ret;
}
int parse_get(char* msg)
{
int ret = -1;
cJSON *root = NULL;
cJSON *node = NULL;
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_get(char* path, char* file)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=download&access_token=%s&path=%s",
access_token,
path);
ret = download(cmdbuf, file, &msg);
{
if(msg)
{
parse_get(msg);
free(msg);
msg = NULL;
}
}
return ret;
}
int parse_rm(char* msg)
{
int ret = -1;
cJSON *root = NULL;
cJSON *node = NULL;
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_rm(char* path)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=delete&access_token=%s&path=%s",
access_token,
path);
postcmd(cmdbuf, "a", &msg);
{
if(msg)
{
if(parse_rm(msg) == 0)
{
ret = 0;
}
free(msg);
msg = NULL;
}
}
return ret;
}
int parse_put(char* msg)
{
int ret = -1;
cJSON *root = NULL;
cJSON *node = NULL;
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
node = cJSON_GetObjectItem(root,"fs_id");
if(NULL == node)
{
goto END;
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_put(char* path, char* file)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=upload&access_token=%s&path=%s",
access_token,
path);
upload(cmdbuf, file, &msg);
{
if(msg)
{
if(parse_put(msg) == 0)
{
ret = 0;
}
free(msg);
msg = NULL;
}
}
return ret;
}
int parse_find(char* msg)
{
int ret = -1;
int i;
cJSON *root = NULL;
cJSON *list = NULL;
cJSON *item = NULL;
cJSON *node = NULL;
root = cJSON_Parse(msg);
if(NULL == root)
{
return;
}
node = cJSON_GetObjectItem(root,"request_id");
if(NULL == node)
{
goto END;
}
node = cJSON_GetObjectItem(root,"error_msg");
if(node)
{
printf("err:%s\n", node->valuestring);
goto END;
}
list = cJSON_GetObjectItem(root,"list");
if(NULL == list)
{
goto END;
}
printf("num: path, isdir, ctime, mtime, size\n");
for(i=0;i<cJSON_GetArraySize(list);i++)
{
item=cJSON_GetArrayItem(list,i);
if(item)
{
printf("%d: ", i);
node = cJSON_GetObjectItem(item,"path");
if(node)
{
printf("%s, ", node->valuestring);
}
node = cJSON_GetObjectItem(item,"isdir");
if(node)
{
printf("%d, ", node->valueint);
}
else
{
printf(", ");
}
node = cJSON_GetObjectItem(item,"ctime");
if(node)
{
printf("%d, ", node->valueint);
}
else
{
printf(", ");
}
node = cJSON_GetObjectItem(item,"mtime");
if(node)
{
printf("%d, ", node->valueint);
}
else
{
printf(", ");
}
node = cJSON_GetObjectItem(item,"size");
if(node)
{
printf("%d", node->valueint);
}
printf("\n");
}
}
ret = 0;
END:
if(root)
{
cJSON_Delete(root);
}
return ret;
}
int pcs_find(char* path, char* key)
{
int ret = -1;
char cmdbuf[1024];
char* msg = NULL;
sprintf(cmdbuf, "https://pcs.baidu.com/rest/2.0/pcs/file?method=search&access_token=%s&path=%s&re=1&wd=%s",
access_token,
path,
key);
getcmd(cmdbuf, &msg);
{
if(msg)
{
if(parse_find(msg) == 0)
{
ret = 0;
}
free(msg);
msg = NULL;
}
}
return ret;
}
char* trim_space(char* str)
{
if(NULL == str)
{
return NULL;
}
while(isspace(*str))
{
str++;
}
return str;
}
int parse_opt(char* input, char** largv, int max)
{
int count = 0;
if(NULL == input|| NULL == largv || 0 == max)
{
return 0;
}
do
{
if(*input == ' ')
{
*input = '\0';
input++;
}
input = trim_space(input);
largv[count] = input;
count++;
if(count == max)
{
return count;
}
} while((input = strchr(input, ' ')));
return count;
}
void usage()
{
printf("\n\
ls remotedirpath\n\
mkdir remotedirpath\n\
get remotefilepath localfilename\n\
put remotefilepath localfilename\n\
rm remotefilepath\n\
find remotedirpath keyword\n\
exit\n");
}
int main(int argc, char** argv)
{
int ret;
struct pcs_stat buf;
char inputbuf[1024];
char* ptr = NULL;
int largc;
char* largv[10];
trans_init();
ret = pcs_stat(ROOT_DIR, &buf);
if(ret == 0 && buf.isdir == 0)
{
PCS_DEBUG("not a dir\n");
return 0;
}
if(ret != 0)
{
if(pcs_mkdir(ROOT_DIR) < 0)
{
PCS_DEBUG("create dir failed\n");
return 0;
}
}
if(pcs_ls(ROOT_DIR) < 0)
{
PCS_DEBUG("get root dir info failed\n");
return 0;
}
while(1)
{
memset(inputbuf, 0, sizeof(inputbuf));
fgets(inputbuf, sizeof(inputbuf), stdin);
ptr = strchr(inputbuf, '\n');
if(ptr)
{
*ptr = '\0';
}
largc = parse_opt(inputbuf, largv, 10);
if(largc <= 0)
{
continue;
}
else if(strcmp(largv[0], "exit") == 0)
{
break;
}
else if(strcmp(largv[0], "help") == 0)
{
usage();
continue;
}
else if(strcmp(largv[0], "get") == 0)
{
if(largc != 3)
{
PCS_DEBUG("arg err\n");
continue;
}
if(pcs_get(largv[1], largv[2]) < 0)
{
PCS_DEBUG("get failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
else if(strcmp(largv[0], "ls") == 0)
{
if(largc == 2)
{
if(pcs_ls(largv[1]) < 0)
{
PCS_DEBUG("ls failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
else if(largc == 1)
{
if(pcs_ls(curdir) < 0)
{
PCS_DEBUG("ls failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
}
else if(strcmp(largv[0], "rm") == 0)
{
if(largc != 2)
{
PCS_DEBUG("arg err\n");
continue;
}
if(pcs_rm(largv[1]) < 0)
{
PCS_DEBUG("rm failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
else if(strcmp(largv[0], "put") == 0)
{
if(largc != 3)
{
PCS_DEBUG("arg err\n");
continue;
}
if(pcs_put(largv[1], largv[2]) < 0)
{
PCS_DEBUG("put failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
else if(strcmp(largv[0], "mkdir") == 0)
{
if(largc != 2)
{
PCS_DEBUG("arg err\n");
continue;
}
if(pcs_mkdir(largv[1]) < 0)
{
PCS_DEBUG("mkdir failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
else if(strcmp(largv[0], "find") == 0)
{
if(largc == 2)
{
if(pcs_find(curdir, largv[1]) < 0)
{
PCS_DEBUG("find failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
if(largc == 3)
{
if(pcs_find(largv[1], largv[2]) < 0)
{
PCS_DEBUG("find failed\n");
}
else
{
PCS_DEBUG("\nok\n");
}
}
}
}
return 0;
}
trans_inf.c
#define _GNU_SOURCE
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static size_t reveived_callback( char *ptr, size_t size, size_t nmemb, char** userdata)
{
char *c;
if(*userdata)
{
if (asprintf(&c, "%s%.*s", *userdata, size * nmemb, ptr) == -1)
{
free(*userdata);
return -1;
}
free(*userdata);
}
else
{
if (asprintf(&c, "%.*s", size * nmemb, ptr) == -1)
{
return -1;
}
}
*userdata = c;
return size*nmemb;
}
void trans_init()
{
curl_global_init(CURL_GLOBAL_ALL);
}
int postcmd(char* remote, char* postdata, char** received_data)
{
CURL *curl;
CURLcode res;
long code = 0;
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, remote);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, received_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, reveived_callback);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
if(code == 200)
{
return 0;
}
else
{
return -1;
}
}
return -1;
}
int getcmd(char* remote, char** received_data)
{
CURL *curl;
CURLcode res;
long code = 0;
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, remote);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, received_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, reveived_callback);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
if(code == 200)
{
return 0;
}
else
{
return -1;
}
}
return -1;
}
int download(char* remote, char* file, char** received_data)
{
CURL *curl;
CURLcode res;
FILE* fp = NULL;
long code = 0;
struct stat buf;
curl = curl_easy_init();
if(curl)
{
fp = fopen(file, "w");
if(fp)
{
curl_easy_setopt(curl, CURLOPT_URL, remote);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
fclose(fp);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
}
curl_easy_cleanup(curl);
if(code == 200)
{
return 0;
}
else
{
if(stat(file, &buf) == 0)
{
fp = fopen(file, "r");
if(fp)
{
*received_data = malloc(buf.st_size);
if(*received_data)
{
if(fread(*received_data, 1, buf.st_size, fp) == buf.st_size)
{
fclose(fp);
remove(file);
return -1;
}
free(*received_data);
*received_data = NULL;
}
fclose(fp);
}
remove(file);
}
return -1;
}
}
return -1;
}
int upload(char* remote, char* file, char**received_data)
{
CURL *curl;
CURLcode res;
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
long code = 0;
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, remote);
curl_easy_setopt(curl, CURLOPT_POST, remote);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, file,
CURLFORM_END);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, received_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, reveived_callback);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
curl_formfree(formpost);
if(code == 200)
{
return 0;
}
else
{
return -1;
}
}
return -1;
}