ruby-libstorj 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +111 -0
- data/Guardfile +21 -0
- data/LICENSE +502 -0
- data/README.md +262 -0
- data/Rakefile +76 -0
- data/ext/libstorj/.gitignore +47 -0
- data/ext/libstorj/.travis.yml +27 -0
- data/ext/libstorj/Doxyfile +2427 -0
- data/ext/libstorj/LICENSE +502 -0
- data/ext/libstorj/Makefile.am +6 -0
- data/ext/libstorj/README.md +198 -0
- data/ext/libstorj/autogen.sh +3 -0
- data/ext/libstorj/configure.ac +64 -0
- data/ext/libstorj/depends/Makefile +153 -0
- data/ext/libstorj/depends/config.guess +1462 -0
- data/ext/libstorj/depends/config.sub +1823 -0
- data/ext/libstorj/depends/extract-osx-sdk.sh +33 -0
- data/ext/libstorj/depends/packages/cctools.mk +7 -0
- data/ext/libstorj/depends/packages/clang.mk +7 -0
- data/ext/libstorj/depends/packages/gmp.mk +23 -0
- data/ext/libstorj/depends/packages/gnutls.mk +25 -0
- data/ext/libstorj/depends/packages/json-c.mk +7 -0
- data/ext/libstorj/depends/packages/libcurl.mk +39 -0
- data/ext/libstorj/depends/packages/libmicrohttpd.mk +7 -0
- data/ext/libstorj/depends/packages/libuv.mk +7 -0
- data/ext/libstorj/depends/packages/nettle.mk +30 -0
- data/ext/libstorj/libstorj.pc.in +11 -0
- data/ext/libstorj/src/Makefile.am +23 -0
- data/ext/libstorj/src/bip39.c +233 -0
- data/ext/libstorj/src/bip39.h +64 -0
- data/ext/libstorj/src/bip39_english.h +2074 -0
- data/ext/libstorj/src/cli.c +1494 -0
- data/ext/libstorj/src/crypto.c +525 -0
- data/ext/libstorj/src/crypto.h +178 -0
- data/ext/libstorj/src/downloader.c +1923 -0
- data/ext/libstorj/src/downloader.h +163 -0
- data/ext/libstorj/src/http.c +688 -0
- data/ext/libstorj/src/http.h +175 -0
- data/ext/libstorj/src/rs.c +962 -0
- data/ext/libstorj/src/rs.h +99 -0
- data/ext/libstorj/src/storj.c +1523 -0
- data/ext/libstorj/src/storj.h +1014 -0
- data/ext/libstorj/src/uploader.c +2736 -0
- data/ext/libstorj/src/uploader.h +181 -0
- data/ext/libstorj/src/utils.c +336 -0
- data/ext/libstorj/src/utils.h +65 -0
- data/ext/libstorj/test/Makefile.am +27 -0
- data/ext/libstorj/test/mockbridge.c +260 -0
- data/ext/libstorj/test/mockbridge.json +687 -0
- data/ext/libstorj/test/mockbridgeinfo.json +1836 -0
- data/ext/libstorj/test/mockfarmer.c +358 -0
- data/ext/libstorj/test/storjtests.h +41 -0
- data/ext/libstorj/test/tests.c +1617 -0
- data/ext/libstorj/test/tests_rs.c +869 -0
- data/ext/ruby-libstorj/extconf.rb +8 -0
- data/ext/ruby-libstorj/ruby-libstorj.cc +17 -0
- data/lib/ruby-libstorj.rb +1 -0
- data/lib/ruby-libstorj/arg_forwarding_task.rb +58 -0
- data/lib/ruby-libstorj/env.rb +178 -0
- data/lib/ruby-libstorj/ext/bucket.rb +71 -0
- data/lib/ruby-libstorj/ext/create_bucket_request.rb +53 -0
- data/lib/ruby-libstorj/ext/curl_code.rb +139 -0
- data/lib/ruby-libstorj/ext/ext.rb +71 -0
- data/lib/ruby-libstorj/ext/file.rb +84 -0
- data/lib/ruby-libstorj/ext/get_bucket_request.rb +45 -0
- data/lib/ruby-libstorj/ext/json_request.rb +51 -0
- data/lib/ruby-libstorj/ext/list_files_request.rb +63 -0
- data/lib/ruby-libstorj/ext/types.rb +226 -0
- data/lib/ruby-libstorj/ext/upload_options.rb +38 -0
- data/lib/ruby-libstorj/libstorj.rb +22 -0
- data/lib/ruby-libstorj/mixins/storj.rb +27 -0
- data/lib/ruby-libstorj/struct.rb +42 -0
- data/ruby-libstorj.gemspec +57 -0
- data/spec/helpers/options.yml.example +22 -0
- data/spec/helpers/shared_rake_examples.rb +132 -0
- data/spec/helpers/storj_options.rb +96 -0
- data/spec/helpers/upload.data +3 -0
- data/spec/helpers/upload.data.sha256 +1 -0
- data/spec/libstorj_spec.rb +0 -0
- data/spec/ruby-libstorj/arg_forwarding_task_spec.rb +311 -0
- data/spec/ruby-libstorj/env_spec.rb +353 -0
- data/spec/ruby-libstorj/ext_spec.rb +75 -0
- data/spec/ruby-libstorj/json_request_spec.rb +13 -0
- data/spec/ruby-libstorj/libstorj_spec.rb +81 -0
- data/spec/ruby-libstorj/struct_spec.rb +64 -0
- data/spec/spec_helper.rb +113 -0
- metadata +136 -0
|
@@ -0,0 +1,1494 @@
|
|
|
1
|
+
#include <errno.h>
|
|
2
|
+
#include <getopt.h>
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
#include <sys/stat.h>
|
|
7
|
+
|
|
8
|
+
#ifdef _WIN32
|
|
9
|
+
#include <winsock2.h>
|
|
10
|
+
#include <windows.h>
|
|
11
|
+
#include <direct.h>
|
|
12
|
+
#else
|
|
13
|
+
#include <termios.h>
|
|
14
|
+
#include <unistd.h>
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
#include "storj.h"
|
|
18
|
+
|
|
19
|
+
#define STORJ_THREADPOOL_SIZE "64"
|
|
20
|
+
|
|
21
|
+
typedef struct {
|
|
22
|
+
char *user;
|
|
23
|
+
char *pass;
|
|
24
|
+
char *host;
|
|
25
|
+
char *mnemonic;
|
|
26
|
+
char *key;
|
|
27
|
+
} user_options_t;
|
|
28
|
+
|
|
29
|
+
#ifndef errno
|
|
30
|
+
extern int errno;
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
static inline void noop() {};
|
|
34
|
+
|
|
35
|
+
#define HELP_TEXT "usage: storj [<options>] <command> [<args>]\n\n" \
|
|
36
|
+
"These are common Storj commands for various situations:\n\n" \
|
|
37
|
+
"setting up users profiles\n" \
|
|
38
|
+
" register setup a new storj bridge user\n" \
|
|
39
|
+
" import-keys import existing user\n" \
|
|
40
|
+
" export-keys export bridge user, password and " \
|
|
41
|
+
"encryption keys\n\n" \
|
|
42
|
+
"working with buckets and files\n" \
|
|
43
|
+
" list-buckets\n" \
|
|
44
|
+
" list-files <bucket-id>\n" \
|
|
45
|
+
" remove-file <bucket-id> <file-id>\n" \
|
|
46
|
+
" add-bucket <name> \n" \
|
|
47
|
+
" remove-bucket <bucket-id>\n" \
|
|
48
|
+
" list-mirrors <bucket-id> <file-id>\n\n" \
|
|
49
|
+
"downloading and uploading files\n" \
|
|
50
|
+
" upload-file <bucket-id> <path>\n" \
|
|
51
|
+
" download-file <bucket-id> <file-id> <path>\n" \
|
|
52
|
+
"bridge api information\n" \
|
|
53
|
+
" get-info\n\n" \
|
|
54
|
+
"options:\n" \
|
|
55
|
+
" -h, --help output usage information\n" \
|
|
56
|
+
" -v, --version output the version number\n" \
|
|
57
|
+
" -u, --url <url> set the base url for the api\n" \
|
|
58
|
+
" -p, --proxy <url> set the socks proxy " \
|
|
59
|
+
"(e.g. <[protocol://][user:password@]proxyhost[:port]>)\n" \
|
|
60
|
+
" -l, --log <level> set the log level (default 0)\n" \
|
|
61
|
+
" -d, --debug set the debug log level\n\n" \
|
|
62
|
+
"environment variables:\n" \
|
|
63
|
+
" STORJ_KEYPASS imported user settings passphrase\n" \
|
|
64
|
+
" STORJ_BRIDGE the bridge host " \
|
|
65
|
+
"(e.g. https://api.storj.io)\n" \
|
|
66
|
+
" STORJ_BRIDGE_USER bridge username\n" \
|
|
67
|
+
" STORJ_BRIDGE_PASS bridge password\n" \
|
|
68
|
+
" STORJ_ENCRYPTION_KEY file encryption key\n\n"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#define CLI_VERSION "libstorj-2.0.0-beta"
|
|
72
|
+
|
|
73
|
+
static void json_logger(const char *message, int level, void *handle)
|
|
74
|
+
{
|
|
75
|
+
printf("{\"message\": \"%s\", \"level\": %i, \"timestamp\": %" PRIu64 "}\n",
|
|
76
|
+
message, level, storj_util_timestamp());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static char *get_home_dir()
|
|
80
|
+
{
|
|
81
|
+
#ifdef _WIN32
|
|
82
|
+
return getenv("USERPROFILE");
|
|
83
|
+
#else
|
|
84
|
+
return getenv("HOME");
|
|
85
|
+
#endif
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static int make_user_directory(char *path)
|
|
89
|
+
{
|
|
90
|
+
struct stat st = {0};
|
|
91
|
+
if (stat(path, &st) == -1) {
|
|
92
|
+
#if _WIN32
|
|
93
|
+
int mkdir_status = _mkdir(path);
|
|
94
|
+
if (mkdir_status) {
|
|
95
|
+
printf("Unable to create directory %s: code: %i.\n",
|
|
96
|
+
path,
|
|
97
|
+
mkdir_status);
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
#else
|
|
101
|
+
if (mkdir(path, 0700)) {
|
|
102
|
+
printf("Unable to create directory %s: reason: %s\n",
|
|
103
|
+
path,
|
|
104
|
+
strerror(errno));
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
#endif
|
|
108
|
+
}
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static const char *get_filename_separator(const char *file_path)
|
|
113
|
+
{
|
|
114
|
+
const char *file_name = NULL;
|
|
115
|
+
#ifdef _WIN32
|
|
116
|
+
file_name = strrchr(file_path, '\\');
|
|
117
|
+
if (!file_name) {
|
|
118
|
+
file_name = strrchr(file_path, '/');
|
|
119
|
+
}
|
|
120
|
+
if (!file_name && file_path) {
|
|
121
|
+
file_name = file_path;
|
|
122
|
+
}
|
|
123
|
+
if (!file_name) {
|
|
124
|
+
return NULL;
|
|
125
|
+
}
|
|
126
|
+
if (file_name[0] == '\\' || file_name[0] == '/') {
|
|
127
|
+
file_name++;
|
|
128
|
+
}
|
|
129
|
+
#else
|
|
130
|
+
file_name = strrchr(file_path, '/');
|
|
131
|
+
if (!file_name && file_path) {
|
|
132
|
+
file_name = file_path;
|
|
133
|
+
}
|
|
134
|
+
if (!file_name) {
|
|
135
|
+
return NULL;
|
|
136
|
+
}
|
|
137
|
+
if (file_name[0] == '/') {
|
|
138
|
+
file_name++;
|
|
139
|
+
}
|
|
140
|
+
#endif
|
|
141
|
+
return file_name;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static int get_user_auth_location(char *host, char **root_dir, char **user_file)
|
|
145
|
+
{
|
|
146
|
+
char *home_dir = get_home_dir();
|
|
147
|
+
if (home_dir == NULL) {
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
int len = strlen(home_dir) + strlen("/.storj/");
|
|
152
|
+
*root_dir = calloc(len + 1, sizeof(char));
|
|
153
|
+
if (!*root_dir) {
|
|
154
|
+
return 1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
strcpy(*root_dir, home_dir);
|
|
158
|
+
strcat(*root_dir, "/.storj/");
|
|
159
|
+
|
|
160
|
+
len = strlen(*root_dir) + strlen(host) + strlen(".json");
|
|
161
|
+
*user_file = calloc(len + 1, sizeof(char));
|
|
162
|
+
if (!*user_file) {
|
|
163
|
+
return 1;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
strcpy(*user_file, *root_dir);
|
|
167
|
+
strcat(*user_file, host);
|
|
168
|
+
strcat(*user_file, ".json");
|
|
169
|
+
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static void get_input(char *line)
|
|
174
|
+
{
|
|
175
|
+
if (fgets(line, BUFSIZ, stdin) == NULL) {
|
|
176
|
+
line[0] = '\0';
|
|
177
|
+
} else {
|
|
178
|
+
int len = strlen(line);
|
|
179
|
+
if (len > 0) {
|
|
180
|
+
char *last = strrchr(line, '\n');
|
|
181
|
+
if (last) {
|
|
182
|
+
last[0] = '\0';
|
|
183
|
+
}
|
|
184
|
+
last = strrchr(line, '\r');
|
|
185
|
+
if (last) {
|
|
186
|
+
last[0] = '\0';
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
static int generate_mnemonic(char **mnemonic)
|
|
193
|
+
{
|
|
194
|
+
char *strength_str = NULL;
|
|
195
|
+
int strength = 0;
|
|
196
|
+
int status = 0;
|
|
197
|
+
|
|
198
|
+
printf("We now need to create an secret key used for encrypting " \
|
|
199
|
+
"files.\nPlease choose strength from: 128, 160, 192, 224, 256\n\n");
|
|
200
|
+
|
|
201
|
+
while (strength % 32 || strength < 128 || strength > 256) {
|
|
202
|
+
strength_str = calloc(BUFSIZ, sizeof(char));
|
|
203
|
+
printf("Strength: ");
|
|
204
|
+
get_input(strength_str);
|
|
205
|
+
|
|
206
|
+
if (strength_str != NULL) {
|
|
207
|
+
strength = atoi(strength_str);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
free(strength_str);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (*mnemonic) {
|
|
214
|
+
free(*mnemonic);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
*mnemonic = NULL;
|
|
218
|
+
|
|
219
|
+
int generate_code = storj_mnemonic_generate(strength, mnemonic);
|
|
220
|
+
if (*mnemonic == NULL || generate_code == 0) {
|
|
221
|
+
printf("Failed to generate encryption key.\n");
|
|
222
|
+
status = 1;
|
|
223
|
+
status = generate_mnemonic(mnemonic);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return status;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
static int get_password(char *password, int mask)
|
|
230
|
+
{
|
|
231
|
+
int max_pass_len = 512;
|
|
232
|
+
|
|
233
|
+
#ifdef _WIN32
|
|
234
|
+
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
|
|
235
|
+
DWORD mode = 0;
|
|
236
|
+
DWORD prev_mode = 0;
|
|
237
|
+
GetConsoleMode(hstdin, &mode);
|
|
238
|
+
GetConsoleMode(hstdin, &prev_mode);
|
|
239
|
+
SetConsoleMode(hstdin, mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
|
|
240
|
+
#else
|
|
241
|
+
static struct termios prev_terminal;
|
|
242
|
+
static struct termios terminal;
|
|
243
|
+
|
|
244
|
+
tcgetattr(STDIN_FILENO, &prev_terminal);
|
|
245
|
+
|
|
246
|
+
memcpy (&terminal, &prev_terminal, sizeof(struct termios));
|
|
247
|
+
terminal.c_lflag &= ~(ICANON | ECHO);
|
|
248
|
+
terminal.c_cc[VTIME] = 0;
|
|
249
|
+
terminal.c_cc[VMIN] = 1;
|
|
250
|
+
tcsetattr(STDIN_FILENO, TCSANOW, &terminal);
|
|
251
|
+
#endif
|
|
252
|
+
|
|
253
|
+
size_t idx = 0; /* index, number of chars in read */
|
|
254
|
+
int c = 0;
|
|
255
|
+
|
|
256
|
+
const char BACKSPACE = 8;
|
|
257
|
+
const char RETURN = 13;
|
|
258
|
+
|
|
259
|
+
/* read chars from fp, mask if valid char specified */
|
|
260
|
+
#ifdef _WIN32
|
|
261
|
+
long unsigned int char_read = 0;
|
|
262
|
+
while ((ReadConsole(hstdin, &c, 1, &char_read, NULL) && c != '\n' && c != RETURN && c != EOF && idx < max_pass_len - 1) ||
|
|
263
|
+
(idx == max_pass_len - 1 && c == BACKSPACE))
|
|
264
|
+
#else
|
|
265
|
+
while (((c = fgetc(stdin)) != '\n' && c != EOF && idx < max_pass_len - 1) ||
|
|
266
|
+
(idx == max_pass_len - 1 && c == 127))
|
|
267
|
+
#endif
|
|
268
|
+
{
|
|
269
|
+
if (c != 127 && c != BACKSPACE) {
|
|
270
|
+
if (31 < mask && mask < 127) /* valid ascii char */
|
|
271
|
+
fputc(mask, stdout);
|
|
272
|
+
password[idx++] = c;
|
|
273
|
+
} else if (idx > 0) { /* handle backspace (del) */
|
|
274
|
+
if (31 < mask && mask < 127) {
|
|
275
|
+
fputc(0x8, stdout);
|
|
276
|
+
fputc(' ', stdout);
|
|
277
|
+
fputc(0x8, stdout);
|
|
278
|
+
}
|
|
279
|
+
password[--idx] = 0;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
password[idx] = 0; /* null-terminate */
|
|
283
|
+
|
|
284
|
+
// go back to the previous settings
|
|
285
|
+
#ifdef _WIN32
|
|
286
|
+
SetConsoleMode(hstdin, prev_mode);
|
|
287
|
+
#else
|
|
288
|
+
tcsetattr(STDIN_FILENO, TCSANOW, &prev_terminal);
|
|
289
|
+
#endif
|
|
290
|
+
|
|
291
|
+
return idx; /* number of chars in passwd */
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
static int get_password_verify(char *prompt, char *password, int count)
|
|
295
|
+
{
|
|
296
|
+
printf("%s", prompt);
|
|
297
|
+
char first_password[BUFSIZ];
|
|
298
|
+
get_password(first_password, '*');
|
|
299
|
+
|
|
300
|
+
printf("\nAgain to verify: ");
|
|
301
|
+
char second_password[BUFSIZ];
|
|
302
|
+
get_password(second_password, '*');
|
|
303
|
+
|
|
304
|
+
int match = strcmp(first_password, second_password);
|
|
305
|
+
strncpy(password, first_password, BUFSIZ);
|
|
306
|
+
|
|
307
|
+
if (match == 0) {
|
|
308
|
+
return 0;
|
|
309
|
+
} else {
|
|
310
|
+
printf("\nPassphrases did not match. ");
|
|
311
|
+
count++;
|
|
312
|
+
if (count > 3) {
|
|
313
|
+
printf("\n");
|
|
314
|
+
return 1;
|
|
315
|
+
}
|
|
316
|
+
printf("Try again...\n");
|
|
317
|
+
return get_password_verify(prompt, password, count);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
void close_signal(uv_handle_t *handle)
|
|
322
|
+
{
|
|
323
|
+
((void)0);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static void file_progress(double progress,
|
|
327
|
+
uint64_t downloaded_bytes,
|
|
328
|
+
uint64_t total_bytes,
|
|
329
|
+
void *handle)
|
|
330
|
+
{
|
|
331
|
+
int bar_width = 70;
|
|
332
|
+
|
|
333
|
+
if (progress == 0 && downloaded_bytes == 0) {
|
|
334
|
+
printf("Preparing File...");
|
|
335
|
+
fflush(stdout);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
printf("\r[");
|
|
340
|
+
int pos = bar_width * progress;
|
|
341
|
+
for (int i = 0; i < bar_width; ++i) {
|
|
342
|
+
if (i < pos) {
|
|
343
|
+
printf("=");
|
|
344
|
+
} else if (i == pos) {
|
|
345
|
+
printf(">");
|
|
346
|
+
} else {
|
|
347
|
+
printf(" ");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
printf("] %.*f%%", 2, progress * 100);
|
|
351
|
+
|
|
352
|
+
fflush(stdout);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
static void upload_file_complete(int status, char *file_id, void *handle)
|
|
356
|
+
{
|
|
357
|
+
printf("\n");
|
|
358
|
+
if (status != 0) {
|
|
359
|
+
printf("Upload failure: %s\n", storj_strerror(status));
|
|
360
|
+
exit(status);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
printf("Upload Success! File ID: %s\n", file_id);
|
|
364
|
+
|
|
365
|
+
free(file_id);
|
|
366
|
+
|
|
367
|
+
exit(0);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
void upload_signal_handler(uv_signal_t *req, int signum)
|
|
371
|
+
{
|
|
372
|
+
storj_upload_state_t *state = req->data;
|
|
373
|
+
storj_bridge_store_file_cancel(state);
|
|
374
|
+
if (uv_signal_stop(req)) {
|
|
375
|
+
printf("Unable to stop signal\n");
|
|
376
|
+
}
|
|
377
|
+
uv_close((uv_handle_t *)req, close_signal);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
static int upload_file(storj_env_t *env, char *bucket_id, const char *file_path)
|
|
381
|
+
{
|
|
382
|
+
bool using_stdin = false;
|
|
383
|
+
FILE *fd = fopen(file_path, "r");
|
|
384
|
+
|
|
385
|
+
if (!fd) {
|
|
386
|
+
printf("Invalid file path: %s\n", file_path);
|
|
387
|
+
fd = fdopen(0, "r");
|
|
388
|
+
using_stdin = true;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const char *file_name = get_filename_separator(file_path);
|
|
392
|
+
|
|
393
|
+
if (!file_name) {
|
|
394
|
+
file_name = file_path;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Upload opts env variables:
|
|
398
|
+
char *prepare_frame_limit;
|
|
399
|
+
char *push_frame_limit;
|
|
400
|
+
char *push_shard_limit;
|
|
401
|
+
char *rs = getenv("STORJ_REED_SOLOMON");
|
|
402
|
+
|
|
403
|
+
storj_upload_opts_t upload_opts = {
|
|
404
|
+
.prepare_frame_limit = (prepare_frame_limit) ? atoi(prepare_frame_limit) : 1,
|
|
405
|
+
.push_frame_limit = (push_frame_limit) ? atoi(push_frame_limit) : 64,
|
|
406
|
+
.push_shard_limit = (push_shard_limit) ? atoi(push_shard_limit) : 64,
|
|
407
|
+
.rs = (!rs) ? true : (strcmp(rs, "false") == 0) ? false : true,
|
|
408
|
+
.bucket_id = bucket_id,
|
|
409
|
+
.file_name = file_name,
|
|
410
|
+
.fd = fd
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
uv_signal_t *sig = malloc(sizeof(uv_signal_t));
|
|
414
|
+
if (!sig) {
|
|
415
|
+
return 1;
|
|
416
|
+
}
|
|
417
|
+
uv_signal_init(env->loop, sig);
|
|
418
|
+
uv_signal_start(sig, upload_signal_handler, SIGINT);
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
storj_progress_cb progress_cb = (storj_progress_cb)noop;
|
|
423
|
+
if (env->log_options->level == 0) {
|
|
424
|
+
progress_cb = file_progress;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
storj_upload_state_t *state = storj_bridge_store_file(env,
|
|
428
|
+
&upload_opts,
|
|
429
|
+
NULL,
|
|
430
|
+
progress_cb,
|
|
431
|
+
upload_file_complete);
|
|
432
|
+
|
|
433
|
+
if (!state) {
|
|
434
|
+
return 1;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
sig->data = state;
|
|
438
|
+
|
|
439
|
+
return state->error_status;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
static void download_file_complete(int status, FILE *fd, void *handle)
|
|
443
|
+
{
|
|
444
|
+
printf("\n");
|
|
445
|
+
fclose(fd);
|
|
446
|
+
if (status) {
|
|
447
|
+
// TODO send to stderr
|
|
448
|
+
switch(status) {
|
|
449
|
+
case STORJ_FILE_DECRYPTION_ERROR:
|
|
450
|
+
printf("Unable to properly decrypt file, please check " \
|
|
451
|
+
"that the correct encryption key was " \
|
|
452
|
+
"imported correctly.\n\n");
|
|
453
|
+
break;
|
|
454
|
+
default:
|
|
455
|
+
printf("Download failure: %s\n", storj_strerror(status));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
exit(status);
|
|
459
|
+
}
|
|
460
|
+
printf("Download Success!\n");
|
|
461
|
+
exit(0);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
void download_signal_handler(uv_signal_t *req, int signum)
|
|
465
|
+
{
|
|
466
|
+
storj_download_state_t *state = req->data;
|
|
467
|
+
storj_bridge_resolve_file_cancel(state);
|
|
468
|
+
if (uv_signal_stop(req)) {
|
|
469
|
+
printf("Unable to stop signal\n");
|
|
470
|
+
}
|
|
471
|
+
uv_close((uv_handle_t *)req, close_signal);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
static int download_file(storj_env_t *env, char *bucket_id,
|
|
475
|
+
char *file_id, char *path)
|
|
476
|
+
{
|
|
477
|
+
FILE *fd = NULL;
|
|
478
|
+
|
|
479
|
+
if (path) {
|
|
480
|
+
char user_input[BUFSIZ];
|
|
481
|
+
memset(user_input, '\0', BUFSIZ);
|
|
482
|
+
|
|
483
|
+
if(access(path, F_OK) != -1 ) {
|
|
484
|
+
printf("Warning: File already exists at path [%s].\n", path);
|
|
485
|
+
while (strcmp(user_input, "y") != 0 && strcmp(user_input, "n") != 0)
|
|
486
|
+
{
|
|
487
|
+
memset(user_input, '\0', BUFSIZ);
|
|
488
|
+
printf("Would you like to overwrite [%s]: [y/n] ", path);
|
|
489
|
+
get_input(user_input);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (strcmp(user_input, "n") == 0) {
|
|
493
|
+
printf("\nCanceled overwriting of [%s].\n", path);
|
|
494
|
+
return 1;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
unlink(path);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
fd = fopen(path, "w+");
|
|
501
|
+
} else {
|
|
502
|
+
fd = stdout;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (fd == NULL) {
|
|
506
|
+
// TODO send to stderr
|
|
507
|
+
printf("Unable to open %s: %s\n", path, strerror(errno));
|
|
508
|
+
return 1;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
uv_signal_t *sig = malloc(sizeof(uv_signal_t));
|
|
512
|
+
uv_signal_init(env->loop, sig);
|
|
513
|
+
uv_signal_start(sig, download_signal_handler, SIGINT);
|
|
514
|
+
|
|
515
|
+
storj_progress_cb progress_cb = (storj_progress_cb)noop;
|
|
516
|
+
if (path && env->log_options->level == 0) {
|
|
517
|
+
progress_cb = file_progress;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
storj_download_state_t *state = storj_bridge_resolve_file(env, bucket_id,
|
|
521
|
+
file_id, fd, NULL,
|
|
522
|
+
progress_cb,
|
|
523
|
+
download_file_complete);
|
|
524
|
+
if (!state) {
|
|
525
|
+
return 1;
|
|
526
|
+
}
|
|
527
|
+
sig->data = state;
|
|
528
|
+
|
|
529
|
+
return state->error_status;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
static void list_mirrors_callback(uv_work_t *work_req, int status)
|
|
533
|
+
{
|
|
534
|
+
assert(status == 0);
|
|
535
|
+
json_request_t *req = work_req->data;
|
|
536
|
+
|
|
537
|
+
if (req->status_code != 200) {
|
|
538
|
+
printf("Request failed with status code: %i\n",
|
|
539
|
+
req->status_code);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (req->response == NULL) {
|
|
543
|
+
free(req);
|
|
544
|
+
free(work_req);
|
|
545
|
+
printf("Failed to list mirrors.\n");
|
|
546
|
+
exit(1);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
int num_mirrors = json_object_array_length(req->response);
|
|
550
|
+
|
|
551
|
+
struct json_object *shard;
|
|
552
|
+
struct json_object *established;
|
|
553
|
+
struct json_object *available;
|
|
554
|
+
struct json_object *item;
|
|
555
|
+
struct json_object *hash;
|
|
556
|
+
struct json_object *contract;
|
|
557
|
+
struct json_object *address;
|
|
558
|
+
struct json_object *port;
|
|
559
|
+
struct json_object *node_id;
|
|
560
|
+
|
|
561
|
+
for (int i = 0; i < num_mirrors; i++) {
|
|
562
|
+
shard = json_object_array_get_idx(req->response, i);
|
|
563
|
+
json_object_object_get_ex(shard, "established",
|
|
564
|
+
&established);
|
|
565
|
+
int num_established =
|
|
566
|
+
json_object_array_length(established);
|
|
567
|
+
for (int j = 0; j < num_established; j++) {
|
|
568
|
+
item = json_object_array_get_idx(established, j);
|
|
569
|
+
if (j == 0) {
|
|
570
|
+
json_object_object_get_ex(item, "shardHash",
|
|
571
|
+
&hash);
|
|
572
|
+
printf("Shard %i: %s\n", i, json_object_get_string(hash));
|
|
573
|
+
}
|
|
574
|
+
json_object_object_get_ex(item, "contract", &contract);
|
|
575
|
+
json_object_object_get_ex(contract, "farmer_id", &node_id);
|
|
576
|
+
|
|
577
|
+
const char *node_id_str = json_object_get_string(node_id);
|
|
578
|
+
printf("\tnodeID: %s\n", node_id_str);
|
|
579
|
+
}
|
|
580
|
+
printf("\n\n");
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
json_object_put(req->response);
|
|
584
|
+
free(req->path);
|
|
585
|
+
free(req);
|
|
586
|
+
free(work_req);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
static int import_keys(user_options_t *options)
|
|
590
|
+
{
|
|
591
|
+
int status = 0;
|
|
592
|
+
char *host = options->host ? strdup(options->host) : NULL;
|
|
593
|
+
char *user = options->user ? strdup(options->user) : NULL;
|
|
594
|
+
char *pass = options->pass ? strdup(options->pass) : NULL;
|
|
595
|
+
char *key = options->key ? strdup(options->key) : NULL;
|
|
596
|
+
char *mnemonic = options->mnemonic ? strdup(options->mnemonic): NULL;
|
|
597
|
+
char *mnemonic_input = NULL;
|
|
598
|
+
char *user_file = NULL;
|
|
599
|
+
char *root_dir = NULL;
|
|
600
|
+
int num_chars;
|
|
601
|
+
|
|
602
|
+
char *user_input = calloc(BUFSIZ, sizeof(char));
|
|
603
|
+
if (user_input == NULL) {
|
|
604
|
+
printf("Unable to allocate buffer\n");
|
|
605
|
+
status = 1;
|
|
606
|
+
goto clear_variables;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (get_user_auth_location(host, &root_dir, &user_file)) {
|
|
610
|
+
printf("Unable to determine user auth filepath.\n");
|
|
611
|
+
status = 1;
|
|
612
|
+
goto clear_variables;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
struct stat st;
|
|
616
|
+
if (stat(user_file, &st) == 0) {
|
|
617
|
+
printf("Would you like to overwrite the current settings?: [y/n] ");
|
|
618
|
+
get_input(user_input);
|
|
619
|
+
while (strcmp(user_input, "y") != 0 && strcmp(user_input, "n") != 0)
|
|
620
|
+
{
|
|
621
|
+
printf("Would you like to overwrite the current settings?: [y/n] ");
|
|
622
|
+
get_input(user_input);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
if (strcmp(user_input, "n") == 0) {
|
|
626
|
+
printf("\nCanceled overwriting of stored credentials.\n");
|
|
627
|
+
status = 1;
|
|
628
|
+
goto clear_variables;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (!user) {
|
|
633
|
+
printf("Bridge username (email): ");
|
|
634
|
+
get_input(user_input);
|
|
635
|
+
num_chars = strlen(user_input);
|
|
636
|
+
user = calloc(num_chars + 1, sizeof(char));
|
|
637
|
+
if (!user) {
|
|
638
|
+
status = 1;
|
|
639
|
+
goto clear_variables;
|
|
640
|
+
}
|
|
641
|
+
memcpy(user, user_input, num_chars * sizeof(char));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (!pass) {
|
|
645
|
+
printf("Bridge password: ");
|
|
646
|
+
pass = calloc(BUFSIZ, sizeof(char));
|
|
647
|
+
if (!pass) {
|
|
648
|
+
status = 1;
|
|
649
|
+
goto clear_variables;
|
|
650
|
+
}
|
|
651
|
+
get_password(pass, '*');
|
|
652
|
+
printf("\n");
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
if (!mnemonic) {
|
|
656
|
+
mnemonic_input = calloc(BUFSIZ, sizeof(char));
|
|
657
|
+
if (!mnemonic_input) {
|
|
658
|
+
status = 1;
|
|
659
|
+
goto clear_variables;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
printf("\nIf you've previously uploaded files, please enter your" \
|
|
663
|
+
" existing encryption key (12 to 24 words). \nOtherwise leave" \
|
|
664
|
+
" the field blank to generate a new key.\n\n");
|
|
665
|
+
|
|
666
|
+
printf("Encryption key: ");
|
|
667
|
+
get_input(mnemonic_input);
|
|
668
|
+
num_chars = strlen(mnemonic_input);
|
|
669
|
+
|
|
670
|
+
if (num_chars == 0) {
|
|
671
|
+
printf("\n");
|
|
672
|
+
generate_mnemonic(&mnemonic);
|
|
673
|
+
printf("\n");
|
|
674
|
+
|
|
675
|
+
printf("Encryption key: %s\n", mnemonic);
|
|
676
|
+
printf("\n");
|
|
677
|
+
printf("Please make sure to backup this key in a safe location. " \
|
|
678
|
+
"If the key is lost, the data uploaded will also be lost.\n\n");
|
|
679
|
+
} else {
|
|
680
|
+
mnemonic = calloc(num_chars + 1, sizeof(char));
|
|
681
|
+
if (!mnemonic) {
|
|
682
|
+
status = 1;
|
|
683
|
+
goto clear_variables;
|
|
684
|
+
}
|
|
685
|
+
memcpy(mnemonic, mnemonic_input, num_chars * sizeof(char));
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if (!storj_mnemonic_check(mnemonic)) {
|
|
689
|
+
printf("Encryption key integrity check failed.\n");
|
|
690
|
+
status = 1;
|
|
691
|
+
goto clear_variables;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (!key) {
|
|
696
|
+
key = calloc(BUFSIZ, sizeof(char));
|
|
697
|
+
printf("We now need to save these settings. Please enter a passphrase" \
|
|
698
|
+
" to lock your settings.\n\n");
|
|
699
|
+
if (get_password_verify("Unlock passphrase: ", key, 0)) {
|
|
700
|
+
printf("Unable to store encrypted authentication.\n");
|
|
701
|
+
status = 1;
|
|
702
|
+
goto clear_variables;
|
|
703
|
+
}
|
|
704
|
+
printf("\n");
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (make_user_directory(root_dir)) {
|
|
708
|
+
status = 1;
|
|
709
|
+
goto clear_variables;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (storj_encrypt_write_auth(user_file, key, user, pass, mnemonic)) {
|
|
713
|
+
status = 1;
|
|
714
|
+
printf("Failed to write to disk\n");
|
|
715
|
+
goto clear_variables;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
printf("Successfully stored bridge username, password, and encryption "\
|
|
719
|
+
"key to %s\n\n",
|
|
720
|
+
user_file);
|
|
721
|
+
|
|
722
|
+
clear_variables:
|
|
723
|
+
if (user) {
|
|
724
|
+
free(user);
|
|
725
|
+
}
|
|
726
|
+
if (user_input) {
|
|
727
|
+
free(user_input);
|
|
728
|
+
}
|
|
729
|
+
if (pass) {
|
|
730
|
+
free(pass);
|
|
731
|
+
}
|
|
732
|
+
if (mnemonic) {
|
|
733
|
+
free(mnemonic);
|
|
734
|
+
}
|
|
735
|
+
if (mnemonic_input) {
|
|
736
|
+
free(mnemonic_input);
|
|
737
|
+
}
|
|
738
|
+
if (key) {
|
|
739
|
+
free(key);
|
|
740
|
+
}
|
|
741
|
+
if (root_dir) {
|
|
742
|
+
free(root_dir);
|
|
743
|
+
}
|
|
744
|
+
if (user_file) {
|
|
745
|
+
free(user_file);
|
|
746
|
+
}
|
|
747
|
+
if (host) {
|
|
748
|
+
free(host);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return status;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
static void register_callback(uv_work_t *work_req, int status)
|
|
755
|
+
{
|
|
756
|
+
assert(status == 0);
|
|
757
|
+
json_request_t *req = work_req->data;
|
|
758
|
+
|
|
759
|
+
if (req->status_code != 201) {
|
|
760
|
+
printf("Request failed with status code: %i\n",
|
|
761
|
+
req->status_code);
|
|
762
|
+
struct json_object *error;
|
|
763
|
+
json_object_object_get_ex(req->response, "error", &error);
|
|
764
|
+
printf("Error: %s\n", json_object_get_string(error));
|
|
765
|
+
|
|
766
|
+
user_options_t *handle = (user_options_t *) req->handle;
|
|
767
|
+
free(handle->user);
|
|
768
|
+
free(handle->host);
|
|
769
|
+
free(handle->pass);
|
|
770
|
+
} else {
|
|
771
|
+
struct json_object *email;
|
|
772
|
+
json_object_object_get_ex(req->response, "email", &email);
|
|
773
|
+
printf("\n");
|
|
774
|
+
printf("Successfully registered %s, please check your email "\
|
|
775
|
+
"to confirm.\n", json_object_get_string(email));
|
|
776
|
+
|
|
777
|
+
// save credentials
|
|
778
|
+
char *mnemonic = NULL;
|
|
779
|
+
printf("\n");
|
|
780
|
+
generate_mnemonic(&mnemonic);
|
|
781
|
+
printf("\n");
|
|
782
|
+
|
|
783
|
+
printf("Encryption key: %s\n", mnemonic);
|
|
784
|
+
printf("\n");
|
|
785
|
+
printf("Please make sure to backup this key in a safe location. " \
|
|
786
|
+
"If the key is lost, the data uploaded will also be lost.\n\n");
|
|
787
|
+
|
|
788
|
+
user_options_t *user_opts = req->handle;
|
|
789
|
+
|
|
790
|
+
user_opts->mnemonic = mnemonic;
|
|
791
|
+
import_keys(user_opts);
|
|
792
|
+
|
|
793
|
+
if (mnemonic) {
|
|
794
|
+
free(mnemonic);
|
|
795
|
+
}
|
|
796
|
+
if (user_opts->pass) {
|
|
797
|
+
free(user_opts->pass);
|
|
798
|
+
}
|
|
799
|
+
if (user_opts->user) {
|
|
800
|
+
free(user_opts->user);
|
|
801
|
+
}
|
|
802
|
+
if (user_opts->host) {
|
|
803
|
+
free(user_opts->host);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
json_object_put(req->response);
|
|
808
|
+
json_object_put(req->body);
|
|
809
|
+
free(req);
|
|
810
|
+
free(work_req);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
static void list_files_callback(uv_work_t *work_req, int status)
|
|
814
|
+
{
|
|
815
|
+
int ret_status = 0;
|
|
816
|
+
assert(status == 0);
|
|
817
|
+
list_files_request_t *req = work_req->data;
|
|
818
|
+
|
|
819
|
+
if (req->status_code == 404) {
|
|
820
|
+
printf("Bucket id [%s] does not exist\n", req->bucket_id);
|
|
821
|
+
goto cleanup;
|
|
822
|
+
} else if (req->status_code == 400) {
|
|
823
|
+
printf("Bucket id [%s] is invalid\n", req->bucket_id);
|
|
824
|
+
goto cleanup;
|
|
825
|
+
} else if (req->status_code == 401) {
|
|
826
|
+
printf("Invalid user credentials.\n");
|
|
827
|
+
goto cleanup;
|
|
828
|
+
} else if (req->status_code != 200) {
|
|
829
|
+
printf("Request failed with status code: %i\n", req->status_code);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
if (req->total_files == 0) {
|
|
833
|
+
printf("No files for bucket.\n");
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
for (int i = 0; i < req->total_files; i++) {
|
|
837
|
+
|
|
838
|
+
storj_file_meta_t *file = &req->files[i];
|
|
839
|
+
|
|
840
|
+
printf("ID: %s \tSize: %" PRIu64 " bytes \tDecrypted: %s \tType: %s \tCreated: %s \tName: %s\n",
|
|
841
|
+
file->id,
|
|
842
|
+
file->size,
|
|
843
|
+
file->decrypted ? "true" : "false",
|
|
844
|
+
file->mimetype,
|
|
845
|
+
file->created,
|
|
846
|
+
file->filename);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
cleanup:
|
|
850
|
+
json_object_put(req->response);
|
|
851
|
+
storj_free_list_files_request(req);
|
|
852
|
+
free(work_req);
|
|
853
|
+
exit(ret_status);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
static void delete_file_callback(uv_work_t *work_req, int status)
|
|
857
|
+
{
|
|
858
|
+
assert(status == 0);
|
|
859
|
+
json_request_t *req = work_req->data;
|
|
860
|
+
|
|
861
|
+
if (req->status_code == 200 || req->status_code == 204) {
|
|
862
|
+
printf("File was successfully removed from bucket.\n");
|
|
863
|
+
} else if (req->status_code == 401) {
|
|
864
|
+
printf("Invalid user credentials.\n");
|
|
865
|
+
} else {
|
|
866
|
+
printf("Failed to remove file from bucket. (%i)\n", req->status_code);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
json_object_put(req->response);
|
|
870
|
+
free(req->path);
|
|
871
|
+
free(req);
|
|
872
|
+
free(work_req);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
static void delete_bucket_callback(uv_work_t *work_req, int status)
|
|
876
|
+
{
|
|
877
|
+
assert(status == 0);
|
|
878
|
+
json_request_t *req = work_req->data;
|
|
879
|
+
|
|
880
|
+
if (req->status_code == 200 || req->status_code == 204) {
|
|
881
|
+
printf("Bucket was successfully removed.\n");
|
|
882
|
+
} else if (req->status_code == 401) {
|
|
883
|
+
printf("Invalid user credentials.\n");
|
|
884
|
+
} else {
|
|
885
|
+
printf("Failed to destroy bucket. (%i)\n", req->status_code);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
json_object_put(req->response);
|
|
889
|
+
free(req->path);
|
|
890
|
+
free(req);
|
|
891
|
+
free(work_req);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
static void get_buckets_callback(uv_work_t *work_req, int status)
|
|
895
|
+
{
|
|
896
|
+
assert(status == 0);
|
|
897
|
+
get_buckets_request_t *req = work_req->data;
|
|
898
|
+
|
|
899
|
+
if (req->status_code == 401) {
|
|
900
|
+
printf("Invalid user credentials.\n");
|
|
901
|
+
} else if (req->status_code != 200 && req->status_code != 304) {
|
|
902
|
+
printf("Request failed with status code: %i\n", req->status_code);
|
|
903
|
+
} else if (req->total_buckets == 0) {
|
|
904
|
+
printf("No buckets.\n");
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
for (int i = 0; i < req->total_buckets; i++) {
|
|
908
|
+
storj_bucket_meta_t *bucket = &req->buckets[i];
|
|
909
|
+
printf("ID: %s \tDecrypted: %s \tCreated: %s \tName: %s\n",
|
|
910
|
+
bucket->id, bucket->decrypted ? "true" : "false",
|
|
911
|
+
bucket->created, bucket->name);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
json_object_put(req->response);
|
|
915
|
+
storj_free_get_buckets_request(req);
|
|
916
|
+
free(work_req);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
static void create_bucket_callback(uv_work_t *work_req, int status)
|
|
920
|
+
{
|
|
921
|
+
assert(status == 0);
|
|
922
|
+
create_bucket_request_t *req = work_req->data;
|
|
923
|
+
|
|
924
|
+
if (req->status_code == 404) {
|
|
925
|
+
printf("Cannot create bucket [%s]. Name already exists \n", req->bucket->name);
|
|
926
|
+
goto clean_variables;
|
|
927
|
+
} else if (req->status_code == 401) {
|
|
928
|
+
printf("Invalid user credentials.\n");
|
|
929
|
+
goto clean_variables;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
if (req->status_code != 201) {
|
|
933
|
+
printf("Request failed with status code: %i\n", req->status_code);
|
|
934
|
+
goto clean_variables;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
if (req->bucket != NULL) {
|
|
938
|
+
printf("ID: %s \tDecrypted: %s \tName: %s\n",
|
|
939
|
+
req->bucket->id,
|
|
940
|
+
req->bucket->decrypted ? "true" : "false",
|
|
941
|
+
req->bucket->name);
|
|
942
|
+
} else {
|
|
943
|
+
printf("Failed to add bucket.\n");
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
clean_variables:
|
|
947
|
+
json_object_put(req->response);
|
|
948
|
+
free((char *)req->encrypted_bucket_name);
|
|
949
|
+
free(req->bucket);
|
|
950
|
+
free(req);
|
|
951
|
+
free(work_req);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
static void get_info_callback(uv_work_t *work_req, int status)
|
|
955
|
+
{
|
|
956
|
+
assert(status == 0);
|
|
957
|
+
json_request_t *req = work_req->data;
|
|
958
|
+
|
|
959
|
+
if (req->error_code || req->response == NULL) {
|
|
960
|
+
free(req);
|
|
961
|
+
free(work_req);
|
|
962
|
+
if (req->error_code) {
|
|
963
|
+
printf("Request failed, reason: %s\n",
|
|
964
|
+
curl_easy_strerror(req->error_code));
|
|
965
|
+
} else {
|
|
966
|
+
printf("Failed to get info.\n");
|
|
967
|
+
}
|
|
968
|
+
exit(1);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
struct json_object *info;
|
|
972
|
+
json_object_object_get_ex(req->response, "info", &info);
|
|
973
|
+
|
|
974
|
+
struct json_object *title;
|
|
975
|
+
json_object_object_get_ex(info, "title", &title);
|
|
976
|
+
struct json_object *description;
|
|
977
|
+
json_object_object_get_ex(info, "description", &description);
|
|
978
|
+
struct json_object *version;
|
|
979
|
+
json_object_object_get_ex(info, "version", &version);
|
|
980
|
+
struct json_object *host;
|
|
981
|
+
json_object_object_get_ex(req->response, "host", &host);
|
|
982
|
+
|
|
983
|
+
printf("Title: %s\n", json_object_get_string(title));
|
|
984
|
+
printf("Description: %s\n", json_object_get_string(description));
|
|
985
|
+
printf("Version: %s\n", json_object_get_string(version));
|
|
986
|
+
printf("Host: %s\n", json_object_get_string(host));
|
|
987
|
+
|
|
988
|
+
json_object_put(req->response);
|
|
989
|
+
free(req);
|
|
990
|
+
free(work_req);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
static int export_keys(char *host)
|
|
994
|
+
{
|
|
995
|
+
int status = 0;
|
|
996
|
+
char *user_file = NULL;
|
|
997
|
+
char *root_dir = NULL;
|
|
998
|
+
char *user = NULL;
|
|
999
|
+
char *pass = NULL;
|
|
1000
|
+
char *mnemonic = NULL;
|
|
1001
|
+
char *key = NULL;
|
|
1002
|
+
|
|
1003
|
+
if (get_user_auth_location(host, &root_dir, &user_file)) {
|
|
1004
|
+
printf("Unable to determine user auth filepath.\n");
|
|
1005
|
+
status = 1;
|
|
1006
|
+
goto clear_variables;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
if (access(user_file, F_OK) != -1) {
|
|
1010
|
+
key = calloc(BUFSIZ, sizeof(char));
|
|
1011
|
+
printf("Unlock passphrase: ");
|
|
1012
|
+
get_password(key, '*');
|
|
1013
|
+
printf("\n\n");
|
|
1014
|
+
|
|
1015
|
+
if (storj_decrypt_read_auth(user_file, key, &user, &pass, &mnemonic)) {
|
|
1016
|
+
printf("Unable to read user file.\n");
|
|
1017
|
+
status = 1;
|
|
1018
|
+
goto clear_variables;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
printf("Username:\t%s\nPassword:\t%s\nEncryption key:\t%s\n",
|
|
1022
|
+
user, pass, mnemonic);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
clear_variables:
|
|
1026
|
+
if (user) {
|
|
1027
|
+
free(user);
|
|
1028
|
+
}
|
|
1029
|
+
if (pass) {
|
|
1030
|
+
free(pass);
|
|
1031
|
+
}
|
|
1032
|
+
if (mnemonic) {
|
|
1033
|
+
free(mnemonic);
|
|
1034
|
+
}
|
|
1035
|
+
if (root_dir) {
|
|
1036
|
+
free(root_dir);
|
|
1037
|
+
}
|
|
1038
|
+
if (user_file) {
|
|
1039
|
+
free(user_file);
|
|
1040
|
+
}
|
|
1041
|
+
if (key) {
|
|
1042
|
+
free(key);
|
|
1043
|
+
}
|
|
1044
|
+
return status;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
int main(int argc, char **argv)
|
|
1048
|
+
{
|
|
1049
|
+
int status = 0;
|
|
1050
|
+
|
|
1051
|
+
static struct option cmd_options[] = {
|
|
1052
|
+
{"url", required_argument, 0, 'u'},
|
|
1053
|
+
{"version", no_argument, 0, 'v'},
|
|
1054
|
+
{"proxy", required_argument, 0, 'p'},
|
|
1055
|
+
{"log", required_argument, 0, 'l'},
|
|
1056
|
+
{"debug", no_argument, 0, 'd'},
|
|
1057
|
+
{"help", no_argument, 0, 'h'},
|
|
1058
|
+
{0, 0, 0, 0}
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1061
|
+
int index = 0;
|
|
1062
|
+
|
|
1063
|
+
// The default is usually 4 threads, we want to increase to the
|
|
1064
|
+
// locally set default value.
|
|
1065
|
+
#ifdef _WIN32
|
|
1066
|
+
if (!getenv("UV_THREADPOOL_SIZE")) {
|
|
1067
|
+
_putenv_s("UV_THREADPOOL_SIZE", STORJ_THREADPOOL_SIZE);
|
|
1068
|
+
}
|
|
1069
|
+
#else
|
|
1070
|
+
setenv("UV_THREADPOOL_SIZE", STORJ_THREADPOOL_SIZE, 0);
|
|
1071
|
+
#endif
|
|
1072
|
+
|
|
1073
|
+
char *storj_bridge = getenv("STORJ_BRIDGE");
|
|
1074
|
+
int c;
|
|
1075
|
+
int log_level = 0;
|
|
1076
|
+
|
|
1077
|
+
char *proxy = getenv("STORJ_PROXY");
|
|
1078
|
+
|
|
1079
|
+
while ((c = getopt_long_only(argc, argv, "hdl:p:vVu:",
|
|
1080
|
+
cmd_options, &index)) != -1) {
|
|
1081
|
+
switch (c) {
|
|
1082
|
+
case 'u':
|
|
1083
|
+
storj_bridge = optarg;
|
|
1084
|
+
break;
|
|
1085
|
+
case 'p':
|
|
1086
|
+
proxy = optarg;
|
|
1087
|
+
break;
|
|
1088
|
+
case 'l':
|
|
1089
|
+
log_level = atoi(optarg);
|
|
1090
|
+
break;
|
|
1091
|
+
case 'd':
|
|
1092
|
+
log_level = 4;
|
|
1093
|
+
break;
|
|
1094
|
+
case 'V':
|
|
1095
|
+
case 'v':
|
|
1096
|
+
printf(CLI_VERSION "\n\n");
|
|
1097
|
+
exit(0);
|
|
1098
|
+
break;
|
|
1099
|
+
case 'h':
|
|
1100
|
+
printf(HELP_TEXT);
|
|
1101
|
+
exit(0);
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
if (log_level > 4 || log_level < 0) {
|
|
1107
|
+
printf("Invalid log level\n");
|
|
1108
|
+
return 1;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
int command_index = optind;
|
|
1112
|
+
|
|
1113
|
+
char *command = argv[command_index];
|
|
1114
|
+
if (!command) {
|
|
1115
|
+
printf(HELP_TEXT);
|
|
1116
|
+
return 0;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
if (!storj_bridge) {
|
|
1120
|
+
storj_bridge = "https://api.storj.io:443/";
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// Parse the host, part and proto from the storj bridge url
|
|
1124
|
+
char proto[6];
|
|
1125
|
+
char host[100];
|
|
1126
|
+
int port = 0;
|
|
1127
|
+
sscanf(storj_bridge, "%5[^://]://%99[^:/]:%99d", proto, host, &port);
|
|
1128
|
+
|
|
1129
|
+
if (port == 0) {
|
|
1130
|
+
if (strcmp(proto, "https") == 0) {
|
|
1131
|
+
port = 443;
|
|
1132
|
+
} else {
|
|
1133
|
+
port = 80;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
if (strcmp(command, "login") == 0) {
|
|
1138
|
+
printf("'login' is not a storj command. Did you mean 'import-keys'?\n\n");
|
|
1139
|
+
return 1;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
if (strcmp(command, "import-keys") == 0) {
|
|
1143
|
+
user_options_t user_options = {NULL, NULL, host, NULL, NULL};
|
|
1144
|
+
return import_keys(&user_options);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (strcmp(command, "export-keys") == 0) {
|
|
1148
|
+
return export_keys(host);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// initialize event loop and environment
|
|
1152
|
+
storj_env_t *env = NULL;
|
|
1153
|
+
|
|
1154
|
+
storj_http_options_t http_options = {
|
|
1155
|
+
.user_agent = CLI_VERSION,
|
|
1156
|
+
.low_speed_limit = STORJ_LOW_SPEED_LIMIT,
|
|
1157
|
+
.low_speed_time = STORJ_LOW_SPEED_TIME,
|
|
1158
|
+
.timeout = STORJ_HTTP_TIMEOUT
|
|
1159
|
+
};
|
|
1160
|
+
|
|
1161
|
+
storj_log_options_t log_options = {
|
|
1162
|
+
.logger = json_logger,
|
|
1163
|
+
.level = log_level
|
|
1164
|
+
};
|
|
1165
|
+
|
|
1166
|
+
if (proxy) {
|
|
1167
|
+
http_options.proxy_url = proxy;
|
|
1168
|
+
} else {
|
|
1169
|
+
http_options.proxy_url = NULL;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
char *user = NULL;
|
|
1173
|
+
char *pass = NULL;
|
|
1174
|
+
char *mnemonic = NULL;
|
|
1175
|
+
|
|
1176
|
+
if (strcmp(command, "get-info") == 0) {
|
|
1177
|
+
printf("Storj bridge: %s\n\n", storj_bridge);
|
|
1178
|
+
|
|
1179
|
+
storj_bridge_options_t options = {
|
|
1180
|
+
.proto = proto,
|
|
1181
|
+
.host = host,
|
|
1182
|
+
.port = port,
|
|
1183
|
+
.user = NULL,
|
|
1184
|
+
.pass = NULL
|
|
1185
|
+
};
|
|
1186
|
+
|
|
1187
|
+
env = storj_init_env(&options, NULL, &http_options, &log_options);
|
|
1188
|
+
if (!env) {
|
|
1189
|
+
return 1;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
storj_bridge_get_info(env, NULL, get_info_callback);
|
|
1193
|
+
|
|
1194
|
+
} else if(strcmp(command, "register") == 0) {
|
|
1195
|
+
storj_bridge_options_t options = {
|
|
1196
|
+
.proto = proto,
|
|
1197
|
+
.host = host,
|
|
1198
|
+
.port = port,
|
|
1199
|
+
.user = NULL,
|
|
1200
|
+
.pass = NULL
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
env = storj_init_env(&options, NULL, &http_options, &log_options);
|
|
1204
|
+
if (!env) {
|
|
1205
|
+
return 1;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
user = calloc(BUFSIZ, sizeof(char));
|
|
1209
|
+
if (!user) {
|
|
1210
|
+
return 1;
|
|
1211
|
+
}
|
|
1212
|
+
printf("Bridge username (email): ");
|
|
1213
|
+
get_input(user);
|
|
1214
|
+
|
|
1215
|
+
printf("Bridge password: ");
|
|
1216
|
+
pass = calloc(BUFSIZ, sizeof(char));
|
|
1217
|
+
if (!pass) {
|
|
1218
|
+
return 1;
|
|
1219
|
+
}
|
|
1220
|
+
get_password(pass, '*');
|
|
1221
|
+
printf("\n");
|
|
1222
|
+
|
|
1223
|
+
user_options_t user_opts = {strdup(user), strdup(pass), strdup(host), NULL, NULL};
|
|
1224
|
+
|
|
1225
|
+
if (!user_opts.user || !user_opts.host || !user_opts.pass) {
|
|
1226
|
+
return 1;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
storj_bridge_register(env, user, pass, &user_opts, register_callback);
|
|
1230
|
+
} else {
|
|
1231
|
+
|
|
1232
|
+
char *user_file = NULL;
|
|
1233
|
+
char *root_dir = NULL;
|
|
1234
|
+
if (get_user_auth_location(host, &root_dir, &user_file)) {
|
|
1235
|
+
printf("Unable to determine user auth filepath.\n");
|
|
1236
|
+
return 1;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// We aren't using root dir so free it
|
|
1240
|
+
free(root_dir);
|
|
1241
|
+
|
|
1242
|
+
// First, get auth from environment variables
|
|
1243
|
+
user = getenv("STORJ_BRIDGE_USER") ?
|
|
1244
|
+
strdup(getenv("STORJ_BRIDGE_USER")) : NULL;
|
|
1245
|
+
|
|
1246
|
+
pass = getenv("STORJ_BRIDGE_PASS") ?
|
|
1247
|
+
strdup(getenv("STORJ_BRIDGE_PASS")) : NULL;
|
|
1248
|
+
|
|
1249
|
+
mnemonic = getenv("STORJ_ENCRYPTION_KEY") ?
|
|
1250
|
+
strdup(getenv("STORJ_ENCRYPTION_KEY")) : NULL;
|
|
1251
|
+
|
|
1252
|
+
char *keypass = getenv("STORJ_KEYPASS");
|
|
1253
|
+
|
|
1254
|
+
// Second, try to get from encrypted user file
|
|
1255
|
+
if ((!user || !pass || !mnemonic) && access(user_file, F_OK) != -1) {
|
|
1256
|
+
|
|
1257
|
+
char *key = NULL;
|
|
1258
|
+
if (keypass) {
|
|
1259
|
+
key = calloc(strlen(keypass) + 1, sizeof(char));
|
|
1260
|
+
if (!key) {
|
|
1261
|
+
return 1;
|
|
1262
|
+
}
|
|
1263
|
+
strcpy(key, keypass);
|
|
1264
|
+
} else {
|
|
1265
|
+
key = calloc(BUFSIZ, sizeof(char));
|
|
1266
|
+
if (!key) {
|
|
1267
|
+
return 1;
|
|
1268
|
+
}
|
|
1269
|
+
printf("Unlock passphrase: ");
|
|
1270
|
+
get_password(key, '*');
|
|
1271
|
+
printf("\n");
|
|
1272
|
+
}
|
|
1273
|
+
char *file_user = NULL;
|
|
1274
|
+
char *file_pass = NULL;
|
|
1275
|
+
char *file_mnemonic = NULL;
|
|
1276
|
+
if (storj_decrypt_read_auth(user_file, key, &file_user,
|
|
1277
|
+
&file_pass, &file_mnemonic)) {
|
|
1278
|
+
printf("Unable to read user file. Invalid keypass or path.\n");
|
|
1279
|
+
free(key);
|
|
1280
|
+
free(user_file);
|
|
1281
|
+
free(file_user);
|
|
1282
|
+
free(file_pass);
|
|
1283
|
+
free(file_mnemonic);
|
|
1284
|
+
goto end_program;
|
|
1285
|
+
}
|
|
1286
|
+
free(key);
|
|
1287
|
+
free(user_file);
|
|
1288
|
+
|
|
1289
|
+
if (!user && file_user) {
|
|
1290
|
+
user = file_user;
|
|
1291
|
+
} else if (file_user) {
|
|
1292
|
+
free(file_user);
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if (!pass && file_pass) {
|
|
1296
|
+
pass = file_pass;
|
|
1297
|
+
} else if (file_pass) {
|
|
1298
|
+
free(file_pass);
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
if (!mnemonic && file_mnemonic) {
|
|
1302
|
+
mnemonic = file_mnemonic;
|
|
1303
|
+
} else if (file_mnemonic) {
|
|
1304
|
+
free(file_mnemonic);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// Third, ask for authentication
|
|
1310
|
+
if (!user) {
|
|
1311
|
+
char *user_input = malloc(BUFSIZ);
|
|
1312
|
+
if (user_input == NULL) {
|
|
1313
|
+
return 1;
|
|
1314
|
+
}
|
|
1315
|
+
printf("Bridge username (email): ");
|
|
1316
|
+
get_input(user_input);
|
|
1317
|
+
int num_chars = strlen(user_input);
|
|
1318
|
+
user = calloc(num_chars + 1, sizeof(char));
|
|
1319
|
+
if (!user) {
|
|
1320
|
+
return 1;
|
|
1321
|
+
}
|
|
1322
|
+
memcpy(user, user_input, num_chars);
|
|
1323
|
+
free(user_input);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
if (!pass) {
|
|
1327
|
+
printf("Bridge password: ");
|
|
1328
|
+
pass = calloc(BUFSIZ, sizeof(char));
|
|
1329
|
+
if (!pass) {
|
|
1330
|
+
return 1;
|
|
1331
|
+
}
|
|
1332
|
+
get_password(pass, '*');
|
|
1333
|
+
printf("\n");
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
if (!mnemonic) {
|
|
1337
|
+
printf("Encryption key: ");
|
|
1338
|
+
char *mnemonic_input = malloc(BUFSIZ);
|
|
1339
|
+
if (mnemonic_input == NULL) {
|
|
1340
|
+
return 1;
|
|
1341
|
+
}
|
|
1342
|
+
get_input(mnemonic_input);
|
|
1343
|
+
int num_chars = strlen(mnemonic_input);
|
|
1344
|
+
mnemonic = calloc(num_chars + 1, sizeof(char));
|
|
1345
|
+
if (!mnemonic) {
|
|
1346
|
+
return 1;
|
|
1347
|
+
}
|
|
1348
|
+
memcpy(mnemonic, mnemonic_input, num_chars);
|
|
1349
|
+
free(mnemonic_input);
|
|
1350
|
+
printf("\n");
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
storj_bridge_options_t options = {
|
|
1354
|
+
.proto = proto,
|
|
1355
|
+
.host = host,
|
|
1356
|
+
.port = port,
|
|
1357
|
+
.user = user,
|
|
1358
|
+
.pass = pass
|
|
1359
|
+
};
|
|
1360
|
+
|
|
1361
|
+
storj_encrypt_options_t encrypt_options = {
|
|
1362
|
+
.mnemonic = mnemonic
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1365
|
+
env = storj_init_env(&options, &encrypt_options,
|
|
1366
|
+
&http_options, &log_options);
|
|
1367
|
+
if (!env) {
|
|
1368
|
+
status = 1;
|
|
1369
|
+
goto end_program;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
if (strcmp(command, "download-file") == 0) {
|
|
1373
|
+
char *bucket_id = argv[command_index + 1];
|
|
1374
|
+
char *file_id = argv[command_index + 2];
|
|
1375
|
+
char *path = argv[command_index + 3];
|
|
1376
|
+
|
|
1377
|
+
if (!bucket_id || !file_id || !path) {
|
|
1378
|
+
printf("Missing arguments: <bucket-id> <file-id> <path>\n");
|
|
1379
|
+
status = 1;
|
|
1380
|
+
goto end_program;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
if (download_file(env, bucket_id, file_id, path)) {
|
|
1384
|
+
status = 1;
|
|
1385
|
+
goto end_program;
|
|
1386
|
+
}
|
|
1387
|
+
} else if (strcmp(command, "upload-file") == 0) {
|
|
1388
|
+
char *bucket_id = argv[command_index + 1];
|
|
1389
|
+
char *path = argv[command_index + 2];
|
|
1390
|
+
|
|
1391
|
+
if (!bucket_id || !path) {
|
|
1392
|
+
printf("Missing arguments: <bucket-id> <path>\n");
|
|
1393
|
+
status = 1;
|
|
1394
|
+
goto end_program;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
if (upload_file(env, bucket_id, path)) {
|
|
1398
|
+
status = 1;
|
|
1399
|
+
goto end_program;
|
|
1400
|
+
}
|
|
1401
|
+
} else if (strcmp(command, "list-files") == 0) {
|
|
1402
|
+
char *bucket_id = argv[command_index + 1];
|
|
1403
|
+
|
|
1404
|
+
if (!bucket_id) {
|
|
1405
|
+
printf("Missing first argument: <bucket-id>\n");
|
|
1406
|
+
status = 1;
|
|
1407
|
+
goto end_program;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
storj_bridge_list_files(env, bucket_id, NULL, list_files_callback);
|
|
1411
|
+
} else if (strcmp(command, "add-bucket") == 0) {
|
|
1412
|
+
char *bucket_name = argv[command_index + 1];
|
|
1413
|
+
|
|
1414
|
+
if (!bucket_name) {
|
|
1415
|
+
printf("Missing first argument: <bucket-name>\n");
|
|
1416
|
+
status = 1;
|
|
1417
|
+
goto end_program;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
storj_bridge_create_bucket(env, bucket_name,
|
|
1421
|
+
NULL, create_bucket_callback);
|
|
1422
|
+
|
|
1423
|
+
} else if (strcmp(command, "remove-bucket") == 0) {
|
|
1424
|
+
char *bucket_id = argv[command_index + 1];
|
|
1425
|
+
|
|
1426
|
+
if (!bucket_id) {
|
|
1427
|
+
printf("Missing first argument: <bucket-id>\n");
|
|
1428
|
+
status = 1;
|
|
1429
|
+
goto end_program;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
storj_bridge_delete_bucket(env, bucket_id, NULL,
|
|
1433
|
+
delete_bucket_callback);
|
|
1434
|
+
|
|
1435
|
+
} else if (strcmp(command, "remove-file") == 0) {
|
|
1436
|
+
char *bucket_id = argv[command_index + 1];
|
|
1437
|
+
char *file_id = argv[command_index + 2];
|
|
1438
|
+
|
|
1439
|
+
if (!bucket_id || !file_id) {
|
|
1440
|
+
printf("Missing arguments, expected: <bucket-id> <file-id>\n");
|
|
1441
|
+
status = 1;
|
|
1442
|
+
goto end_program;
|
|
1443
|
+
}
|
|
1444
|
+
storj_bridge_delete_file(env, bucket_id, file_id,
|
|
1445
|
+
NULL, delete_file_callback);
|
|
1446
|
+
|
|
1447
|
+
} else if (strcmp(command, "list-buckets") == 0) {
|
|
1448
|
+
storj_bridge_get_buckets(env, NULL, get_buckets_callback);
|
|
1449
|
+
} else if (strcmp(command, "list-mirrors") == 0) {
|
|
1450
|
+
char *bucket_id = argv[command_index + 1];
|
|
1451
|
+
char *file_id = argv[command_index + 2];
|
|
1452
|
+
|
|
1453
|
+
if (!bucket_id || !file_id) {
|
|
1454
|
+
printf("Missing arguments, expected: <bucket-id> <file-id>\n");
|
|
1455
|
+
status = 1;
|
|
1456
|
+
goto end_program;
|
|
1457
|
+
}
|
|
1458
|
+
storj_bridge_list_mirrors(env, bucket_id, file_id,
|
|
1459
|
+
NULL, list_mirrors_callback);
|
|
1460
|
+
} else {
|
|
1461
|
+
printf("'%s' is not a storj command. See 'storj --help'\n\n",
|
|
1462
|
+
command);
|
|
1463
|
+
status = 1;
|
|
1464
|
+
goto end_program;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
// run all queued events
|
|
1470
|
+
if (uv_run(env->loop, UV_RUN_DEFAULT)) {
|
|
1471
|
+
uv_loop_close(env->loop);
|
|
1472
|
+
|
|
1473
|
+
// cleanup
|
|
1474
|
+
storj_destroy_env(env);
|
|
1475
|
+
|
|
1476
|
+
status = 1;
|
|
1477
|
+
goto end_program;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
end_program:
|
|
1481
|
+
if (env) {
|
|
1482
|
+
storj_destroy_env(env);
|
|
1483
|
+
}
|
|
1484
|
+
if (user) {
|
|
1485
|
+
free(user);
|
|
1486
|
+
}
|
|
1487
|
+
if (pass) {
|
|
1488
|
+
free(pass);
|
|
1489
|
+
}
|
|
1490
|
+
if (mnemonic) {
|
|
1491
|
+
free(mnemonic);
|
|
1492
|
+
}
|
|
1493
|
+
return status;
|
|
1494
|
+
}
|