diff --git a/.gitignore b/.gitignore index 0331bbb..9b03041 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ *.exe *.out *.app +*bin \ No newline at end of file diff --git a/Makefile b/Makefile index b2ff53d..715c85d 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,13 @@ PREFIX?=/usr/local INSTALL_BIN= $(PREFIX)/bin #CFLAGS=-DDEBUG -g +#CFLAGS=-I/home/brook/openwrt/openwrt/staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/include +#LDFLAGS=-L/home/brook/openwrt/openwrt/staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib + all:baidu_pcs baidu_pcs: - gcc $(CFLAGS) -Wall -O2 baidu_pcs.c pcs.c pcs_file.c cJSON.c http_client.c -o ./baidu_pcs -lcurl -lm + $(CC) $(CFLAGS) $(LDFLAGS) -Wall -O2 baidu_pcs.c pcs.c pcs_file.c cJSON.c http_client.c -o ./bin/baidu_pcs -lcurl -lm install:baidu_pcs mkdir -p $(INSTALL_BIN) diff --git a/README.md b/README.md index fe22b8c..1bca8e0 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,6 @@ #依赖 libcurl >= 7.18, centos/redhat 5自带curl版本较低,编译前请升级 #安装 -编译前请修改`baidu_pcs.c`中的两个全局变量为自己的API Key和Secret Key -~~~ -/* pcs api key */ -static const char *option_api_key = ""; -/* pcs api secret */ -static const char *option_api_secret = ""; -~~~ -然后 ~~~ make make install #这一步可以省略咯,就一个可行行文件,可以自己随便copy到哪里。。 @@ -19,6 +11,9 @@ make install #这一步可以省略咯,就一个可行行文件,可以自己 ~~~ 使用方法: baidu_pcs 命令 [选项] +说明: + 配置文件必须放在 /etc/baidupcs.conf 或者 ~/baidupcs.conf + 命令列表: info 查看云盘信息 @@ -42,9 +37,16 @@ download [选项] [远程路径] [本地路径] 下载文件或目录 选项: -o 覆盖本地同名文件 -n 如果存在同名文件,创建以日期结尾的新文件 + cp [远程路径] [目的远程路径] 复制远程文件或目录 mv [远程路径] [目的远程路径] 移动远程文件或目录 rm [远程路径] 删除远程文件或目录 + +sync [选项] [远程路径] [本地路径] 同步文件或者目录 + 选项: + 默认:略过已存在同名文件 + -o 覆盖同名文件 + -n 如果存在同名文件,创建以日期结尾的新文件 ~~~ #你可能需要知道 1. pcs api只能操作/apps/xxx下的文件 @@ -55,3 +57,19 @@ rm [远程路径] 删除远程文件或目录 4. 非上传请求,5秒连接超时,20秒请求超时 5. 上传请求,5秒连接超时,文件尺寸/(10K/s)的上传超时 6. 上面你都可以自己改了重新编译。。。 + +#更新的内容 +###2013-11-25: +1. 增加一个sync命令,daemon方式每15秒调用一次download命令 +2. 增加配置文件功能,用于保存API Key 和 API Secret,方便没有条件编译的朋友 +3. 此版本主要是为了方便嵌入系统使用的,比如dd-wrt, openWRT +4. 在osx10.9 ubuntu mips环境下编译通过 + +#关于 +本人Linux、C方面是小白,周末在家配置路由器`BUFFALO WZR-HP-G300NH2`的远程下载时想到这个好工具, +无奈没有可以在dd-wrt上运行的版本,于是想自己动手编译,不料掉入cross compile深坑, +费半天时间在OS X下尝试失败,因为教程几乎一水Linux下于是转战Ubuntu。 +还好功夫不负有心人搭近周末编译出了MIPS版。 + +在此感谢原作者 [@emptyhua](https://github.com/emptyhua) 无私分享的优秀代码,我后来添加的那些代码已经无法直视了。 + diff --git a/baidu_pcs.c b/baidu_pcs.c old mode 100644 new mode 100755 index 80eb28c..312c31c --- a/baidu_pcs.c +++ b/baidu_pcs.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013 emptyhua@gmail.com + * Copyright (c) 2013 brook.qin@gmail.com */ @@ -15,20 +16,24 @@ #include #include #include +#include #include "pcs.h" #define COLOR_LOG_OK 1 #define COLOR_LOG_ERROR 2 #define COLOR_LOG_IGNORE 3 +#define MAX_LINE_LEN 512 /* pcs api key */ -static const char *option_api_key = ""; +static char option_api_key[32]; /* pcs api secret */ -static const char *option_api_secret = ""; +static char option_api_secret[32]; static BaiduPCS *api = NULL; +static int sync_running = 0; + void color_log(int type, const char *format, ...) { //{{{ va_list args; @@ -124,6 +129,9 @@ void usage() { fprintf(stderr, "使用方法: baidu_pcs 命令 [选项]\n" "\n" +"说明:\n" +" 配置文件必须放在 /etc/baidupcs.conf 或者 ~/baidupcs.conf \n" +"\n" "命令列表:\n" "\n" "info 查看云盘信息\n" @@ -147,13 +155,40 @@ void usage() { " 选项:\n" " -o 覆盖本地同名文件\n" " -n 如果存在同名文件,创建以日期结尾的新文件\n" +"\n" "cp [远程路径] [目的远程路径] 复制远程文件或目录\n" "mv [远程路径] [目的远程路径] 移动远程文件或目录\n" "rm [远程路径] 删除远程文件或目录\n" +"\n" +"sync [选项] [远程路径] [本地路径] 同步文件或者目录\n" +" 选项:\n" +" 默认:略过已存在同名文件\n" +" -o 覆盖同名文件\n" +" -n 如果存在同名文件,创建以日期结尾的新文件\n" ); } //}}} +/* deamon method */ +void init_daemon() +{ + pid_t pid; + if ((pid = fork()) != 0) + exit(0); + setsid(); + if ((pid = fork()) != 0) + exit(0); + chdir("/"); + umask(0); +} + +void handle_term_signal (int sig) +{ + sync_running = 0; + sleep(10); + exit(0); +} + /* 初始化API */ int init_api() { //{{{ @@ -934,13 +969,15 @@ int create_new /* 是否新建 */ 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 +#endif +*/ } else { color_log(COLOR_LOG_ERROR, "%s -> %s 本地已存与目录同名的文件\n", file->path, local_path); ret = 1; @@ -1026,7 +1063,6 @@ int create_new /* 是否新建 */ } //}}} - /* 下载文件或目录 */ int command_download(int argc, char **argv) { //{{{ @@ -1057,6 +1093,10 @@ int command_download(int argc, char **argv) { goto free; } +#ifdef DEBUG + fprintf(stderr, "optind: %d,argc %d\n", optind, argc); +#endif + if (optind < argc - 2) { color_log(COLOR_LOG_ERROR, "请指定路径\n"); usage(); @@ -1093,6 +1133,78 @@ int command_download(int argc, char **argv) { //}}} +/* 同步文件,实际只是循环调用 do_download */ +int command_sync(int argc, char **argv) { +//{{{ + int option_overwrite = 0; /* 覆盖同名文件 */ + int option_new = 0; /* 创建新文件 */ + + int ret = 0; + char c; + + char *remote_path; + char *local_path; + + opterr = 0; + while ((c = getopt(argc, argv, "on")) != -1) { + switch (c) { + case 'o': + option_overwrite = 1; + break; + case 'n': + option_new = 1; + break; + } + } + + if (option_overwrite && option_new) { + color_log(COLOR_LOG_ERROR, "请不要同时指定-n -o\n"); + ret = 1; + goto free; + } + + if (optind < argc - 2) { + color_log(COLOR_LOG_ERROR, "请指定路径\n"); + usage(); + ret = 1; + goto free; + } + + local_path = argv[argc - 1]; + if (local_path[strlen(local_path) - 1] == '/') { + local_path[strlen(local_path) - 1] = '\0'; + } + + remote_path = argv[argc - 2]; + if (remote_path[strlen(remote_path) - 1] == '/') { + remote_path[strlen(remote_path) - 1] = '\0'; + } + + if (!init_api()) { + ret = 1; + goto free; + } + + init_daemon(); + + sync_running = 1; + while (sync_running == 1) { + + ret = do_download(remote_path, + local_path, + option_overwrite, + option_new); + + color_log(COLOR_LOG_OK, "15 秒后开始下次同步.\n"); + + sleep(15); + } + +free: + return ret; +//}}} +} + /* 移动,复制 */ int command_move_or_copy(int argc, char **argv, const char *type) { //{{{ @@ -1168,14 +1280,70 @@ int command_remove(int argc, char **argv) { } //}}} +int read_config() { + + struct passwd *pw; + const char *homedir; + char config[1024]; + + FILE *config_fp; + char line[MAX_LINE_LEN + 1]; + char *token ; + int ret = 0; + + config_fp = fopen("/etc/baidupcs.conf", "r") ; + if(config_fp == NULL) { + pw = getpwuid(getuid()); + homedir = pw->pw_dir; + snprintf(config, 1023, "%s/baidupcs.conf", homedir); + + config_fp = fopen(config, "r"); + } + + if(config_fp != NULL) { + while(fgets(line, MAX_LINE_LEN, config_fp) != NULL) + { + token = strtok(line, "\t =\n\r") ; + if(token != NULL && token[0] != '#') + { + if(strcmp(token, "apikey") == 0) { + token = strtok(NULL, "\t =\n\r"); + sprintf(option_api_key, "%s", token); + } + else if(strcmp(token, "apisecret") == 0) { + token = strtok(NULL, "\t =\n\r"); + sprintf(option_api_secret, "%s", token); + } + } + } + + if(*option_api_key == '\0' || *option_api_secret == '\0') ret = 1; + + fclose(config_fp); + config_fp = NULL; + } + else { + ret = 1; + color_log(COLOR_LOG_ERROR, "%s\n", "没有找到配置文件!"); + } + +#ifdef DEBUG + fprintf(stderr, "key: %s \nsec: %s\n", option_api_key, option_api_secret); +#endif + + return ret; +} + int main(int argc, char **argv) { //{{{ int ret = 0; - if (argc < 2) { + if (argc < 2 || read_config() > 0) { usage(); return 1; } + + signal(SIGTERM, handle_term_signal); char *command = argv[1]; @@ -1198,6 +1366,8 @@ int main(int argc, char **argv) { ret = command_move_or_copy(argc, argv, "cp"); } else if (strcmp(command, "rm") == 0) { ret = command_remove(argc, argv); + } else if (strcmp(command, "sync") == 0) { + ret = command_sync(argc, argv); } else { color_log(COLOR_LOG_ERROR, "未知命令!\n"); usage(); diff --git a/baidupcs.conf b/baidupcs.conf new file mode 100644 index 0000000..d2b63c9 --- /dev/null +++ b/baidupcs.conf @@ -0,0 +1,7 @@ +# +# 配置文件 +# 必须置于 /etc/baidupcs.conf 或 ~/baidupcs.conf +# + +apikey= +apisecret= \ No newline at end of file