ruby-libstorj 0.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52c2c5dd170de6905993f7a4c034102773de5cd1
4
- data.tar.gz: 599fcf11242ff3dad90f62f0771da0affa3cefc8
3
+ metadata.gz: 8de9d6c135ae3b5e58a34ce91f1ac731bc2e887a
4
+ data.tar.gz: f581db0c00bfcbbec33081df8034bcb17c8d7e18
5
5
  SHA512:
6
- metadata.gz: 60e028360df7c68c8686f2a4077f6799f1989b6049310b3a0a0e33e33c7ed29a456d95520fffdc658c5c2e3ccb5cd1bcc4caa0ea5ccd4c23f749ce80fbc6183b
7
- data.tar.gz: 0a92e395b4a2cbd29d2f53351dc7a6afe2f2bab22fd86c21adad27e57adea0fbff4cb9ceeb234642d33fad3462646e9da8c49acc9a5a6828cbe9a29474aeedce
6
+ metadata.gz: d7d9eef9134284db52495f95e1fbf73f7827380e180e6da2ffff75ae8ff6db1a204f3f3e646670ca7c664c74613dbd2e3e028ef945abf531a940c670fd842f29
7
+ data.tar.gz: 0a58c196a68386fc3ca0fc8bf3caf0156f38d2526c374a551b4a7eb194121f733e22943fbf06e171cfd2283195e6cbb2f0581cbdf4b3ea8b76a7c47dbafbc1b1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-libstorj (0.0.0)
4
+ ruby-libstorj (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -108,4 +108,4 @@ DEPENDENCIES
108
108
  simplecov!
109
109
 
110
110
  BUNDLED WITH
111
- 1.15.4
111
+ 1.16.0
data/README.md CHANGED
@@ -1,10 +1,22 @@
1
1
  ruby-libstorj: Ruby bindings for libstorj
2
2
  ===
3
+ [![Gem Version](https://badge.fury.io/rb/ruby-libstorj.svg)](https://badge.fury.io/rb/ruby-libstorj)
3
4
 
4
5
  ## Using ruby-libstorj
5
6
 
6
7
  ### Install gem:
7
- _(until initial release installing from source is necessary)_
8
+ + using bundler:
9
+ ```
10
+ # in your Gemfile
11
+ gem 'ruby-libstorj'
12
+ ```
13
+ ```bash
14
+ bundle install
15
+ ```
16
+ + using rubygems (`gem`):
17
+ ```bash
18
+ gem install ruby-libstorj
19
+ ```
8
20
  + from source:
9
21
  ```bash
10
22
  git clone https://github.com/storj/ruby-libstorj && \
@@ -76,7 +88,7 @@ rake
76
88
  #### First create spec/helpers/options.yml !
77
89
  For the moment, the test suite doesn't start it's own mock backend but it does parse whatever's in the `spec/helpsers/options.yml` file to initialize `LibStorj::Ext::Storj::Env` to connect via http/https.
78
90
 
79
- You can copy [`spec/helpers/options.yml.example`](./spec/helpers/options.yml.example) and modify it for your use:
91
+ You can copy [`spec/helpers/options.yml.example`](spec/helpers/options.example.yml) and modify it for your use:
80
92
  ```bash
81
93
  cp spec/helpers/options.yml.example spec/helpers/options.yml && \
82
94
  vim spec/helpers/options.yml # or whatever
@@ -29,6 +29,7 @@ docs
29
29
  libstorj.pc
30
30
  libtool
31
31
  src/main
32
+ src/shard_size
32
33
  src/storj
33
34
  src/storj.dSYM/
34
35
  src/storj.exe
@@ -0,0 +1,66 @@
1
+ # Contributing
2
+
3
+ ## Required Skill-set
4
+ - An understanding of the Storj network and [SIP5](https://github.com/Storj/sips/blob/master/sip-0005.md)
5
+ - Practical understanding of cryptographic concepts
6
+ - Experience with some C-like language
7
+ - Understanding of asynchronous programming and event loops
8
+ - An understanding of networking protocols, such as TCP/HTTP
9
+ - Familiarity with unit, integration and e2e testing
10
+ - Familiarity with autotools
11
+ - An understanding of `git` for version control and collaboration
12
+ - Debugging experience
13
+
14
+ ## Share Early, Share Often
15
+
16
+ It's highly recommended to announce your plans before you start work. Once started, commit your changes in small, clear and atomic commits (see commit messages below). This has several benefits:
17
+ - Avoids duplicate work
18
+ - Get feedback and help to achieve your goals
19
+ - Requires less rebasing or merging from master
20
+ - Improves ability to rebase changes
21
+
22
+ ## Compiling, Debugging and Testing
23
+
24
+ We strive to do test driven development and cover all critical sections of code.
25
+
26
+ The test suite is composed of a mix of unit and integration tests. All dependent network components are mocked with reproducible behaviors.
27
+
28
+ There should not be any known leaks when running `valgrind --leak-check=full ./test/tests`, and there shouldn't be compile warnings with either `gcc` or `clang`.
29
+
30
+ Using `gdb` is recommended to be used to help identify issues, this can become more tricky on systems such as Windows. However it's possible to compile `gdb` for Windows using Cygwin. Almost all development for Windows can be done using Mingw and Wine, with results then verified on a Windows virtual machine. Please see the [README for details on cross compilation](README.md#cross-compiling-dependencies-from-ubuntu-1604).
31
+
32
+ ## Memory Ownership & Threads
33
+
34
+ To avoid issues with multi-threaded memory conflicts, it's necessary to make it clear where memory is allocated, free'd, and if it's safe to modify in a thread. This is handled by making it unnecessary to get locks before modifying variables. For an example of this, the `state` types for uploads and downloads can be modified in the main event loop, however should not be modified in the worker pool threads. There is a specific data type for work in the thread pool, that is for the purpose of moving memory between threads.
35
+
36
+ ## Coding Style
37
+
38
+ - Naming and comments are important, think about yourself after a few months away
39
+ - 4 spaces
40
+ - Always use brackets, and keep on the same line, except for functions
41
+ - The pointer `*` goes next to the name not the type
42
+ - Types are defined with a `_t` for example `storj_download_state_t`
43
+
44
+ ## Commit Messages
45
+
46
+ It's recommended to make atomic commits for each change. This improves the ability to rebase and review changes.
47
+
48
+ An example commit message:
49
+
50
+ ```
51
+ Short description of the changes
52
+
53
+ More detailed description of changes and potentially the
54
+ rational for the changes and any other information that
55
+ would help someone looking back at the history may want
56
+ to know.
57
+ ```
58
+
59
+ ## Contributor License Agreement
60
+
61
+ By submitting pull requests, you agree that your work may be licensed under one of:
62
+
63
+ GNU Affero General Public License Version 3 (or later)
64
+ GNU Lesser General Public License Version 2.1 (or later)
65
+
66
+ You also assert that you have completed the [Contributor License Agreement](https://docs.google.com/forms/d/e/1FAIpQLSdVzD5W8rx-J_jLaPuG31nbOzS8yhNIIu4yHvzonji6NeZ4ig/viewform)
@@ -827,7 +827,7 @@ EXCLUDE_SYMLINKS = NO
827
827
  # Note that the wildcards are matched against the file with absolute path, so to
828
828
  # exclude all test directories for example use the pattern */test/*
829
829
 
830
- EXCLUDE_PATTERNS =
830
+ EXCLUDE_PATTERNS = */depends/* */release/* */test/*
831
831
 
832
832
  # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
833
833
  # (namespaces, classes, functions, etc.) that should be excluded from the
@@ -1,6 +1,7 @@
1
1
  libstorj
2
2
  =======
3
3
 
4
+ [![Storj.io](https://storj.io/img/storj-badge.svg)](https://storj.io)
4
5
  [![Build Status](https://travis-ci.org/Storj/libstorj.svg?branch=master)](https://travis-ci.org/Storj/libstorj)
5
6
 
6
7
  Asynchronous multi-platform C library and CLI for encrypted file transfer on the Storj network.
@@ -66,7 +67,11 @@ Dependencies:
66
67
  brew install curl nettle json-c libuv
67
68
  ```
68
69
 
69
- ### Cross Compiling Dependencies from Ubuntu 16.04
70
+ ------
71
+
72
+ ## Cross Compiling Dependencies from Ubuntu 16.04
73
+
74
+ These notes are for cross compiling for various systems from a Debian based linux distribution, specifically Ubuntu 16.04. The mingw toolchain is used to build for Windows and clang and cctools for macOS builds.
70
75
 
71
76
  **Windows**
72
77
 
@@ -1,4 +1,4 @@
1
- AC_INIT([libstorj],[2.0.0-beta])
1
+ AC_INIT([libstorj],[2.0.0-beta2])
2
2
  AC_CONFIG_AUX_DIR([build-aux])
3
3
  AC_CONFIG_MACRO_DIR([build-aux/m4])
4
4
  AM_INIT_AUTOMAKE([foreign])
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+
3
+ # This file is to automate some of the release process.
4
+ # It will package up releases built and installed into
5
+ # a prefix directory of "release". The result will be
6
+ # signed tar and zip files in "release/packages".
7
+
8
+ set -e
9
+
10
+ basename="libstorj-2.0.0-beta2"
11
+
12
+ releases=(arm-linux-gnueabihf
13
+ i686-pc-linux-gnu
14
+ i686-w64-mingw32
15
+ x86_64-apple-darwin11
16
+ x86_64-pc-linux-gnu
17
+ x86_64-w64-mingw32)
18
+
19
+ short_releases=(linux-armv7
20
+ linux32
21
+ win32
22
+ macos
23
+ linux64
24
+ win64)
25
+
26
+ for i in "${!releases[@]}"; do
27
+ release="${releases[$i]}"
28
+ short="${short_releases[$i]}"
29
+
30
+ printf "Starting %s (%s)...\n" $release $short
31
+
32
+ echo "Copying documents..."
33
+ rel_dir="release/${release}"
34
+ cp -v "README.md" "${rel_dir}/"
35
+ cp -v "LICENSE" "${rel_dir}/"
36
+
37
+ echo "Preparing directory..."
38
+ new_dir="release/${release}/${basename}"
39
+ mkdir -p "${new_dir}"
40
+ mv -v $rel_dir/[^$basename]* $new_dir/
41
+
42
+ echo "Packaging..."
43
+ mkdir -p "release/packages"
44
+ pushd $rel_dir
45
+ if [[ "$release" =~ "w64" ]]; then
46
+ zip -r $basename-$short.zip $basename
47
+ mv $basename-$short.zip ../packages/
48
+ else
49
+ tar -cvzf $basename-$short.tar.gz $basename
50
+ mv $basename-$short.tar.gz ../packages/
51
+ fi
52
+ popd
53
+
54
+ printf "\n\n"
55
+ done
56
+
57
+ echo "Hashing and signing packages..."
58
+ pushd "release/packages"
59
+ sha256sum [!SHA256SUMS]* > SHA256SUMS
60
+ gpg --clearsign SHA256SUMS
61
+ popd
@@ -1,5 +1,5 @@
1
1
  lib_LTLIBRARIES = libstorj.la
2
- libstorj_la_SOURCES = storj.c utils.c utils.h http.c http.h uploader.c uploader.h downloader.c downloader.h bip39.c bip39.h bip39_english.h crypto.c crypto.h rs.c rs.h
2
+ libstorj_la_SOURCES = storj.c utils.c utils.h http.c http.h uploader.c uploader.h downloader.c downloader.h bip39.c bip39.h bip39_english.h crypto.c crypto.h rs.c rs.h cli_callback.c cli_callback.h
3
3
  libstorj_la_LIBADD = -lcurl -lnettle -ljson-c -luv -lm
4
4
  # The rules of thumb, when dealing with these values are:
5
5
  # - Always increase the revision value.
@@ -7,7 +7,7 @@ libstorj_la_LIBADD = -lcurl -lnettle -ljson-c -luv -lm
7
7
  # - Increase the age value only if the changes made to the ABI are backward compatible.
8
8
  # https://autotools.io/libtool/version.html
9
9
  # The order for version-info is <current>:<revision>:<age>
10
- libstorj_la_LDFLAGS = -Wall -version-info 1:1:0
10
+ libstorj_la_LDFLAGS = -Wall -version-info 2:2:0
11
11
  if BUILD_STORJ_DLL
12
12
  libstorj_la_LDFLAGS += -no-undefined
13
13
  endif
@@ -190,6 +190,11 @@ bool mnemonic_check(const char *mnemonic)
190
190
  int mnemonic_to_seed(const char *mnemonic, const char *passphrase,
191
191
  char **buffer)
192
192
  {
193
+ // If mnemonic is NULL, assume empty string
194
+ if (!mnemonic) {
195
+ mnemonic = "";
196
+ }
197
+
193
198
  int passphraselen = strlen(passphrase);
194
199
 
195
200
  // We can't exceed a password of 256 bytes
@@ -15,6 +15,9 @@
15
15
  #endif
16
16
 
17
17
  #include "storj.h"
18
+ #include "cli_callback.c"
19
+
20
+ //#define debug_enable
18
21
 
19
22
  #define STORJ_THREADPOOL_SIZE "64"
20
23
 
@@ -30,45 +33,153 @@ typedef struct {
30
33
  extern int errno;
31
34
  #endif
32
35
 
33
- static inline void noop() {};
34
36
 
35
37
  #define HELP_TEXT "usage: storj [<options>] <command> [<args>]\n\n" \
36
38
  "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 " \
39
+ "setting up user profiles:\n" \
40
+ " register setup a new storj bridge user\n" \
41
+ " import-keys import existing user\n" \
42
+ " export-keys export bridge user, password and " \
41
43
  "encryption keys\n\n" \
42
- "working with buckets and files\n" \
44
+ "unix style commands:\n" \
45
+ " ls lists the available buckets\n" \
46
+ " ls <bucket-name> lists the files in a bucket\n" \
47
+ " cp [-rR] <path> <uri> upload files to a bucket " \
48
+ "(e.g. storj cp -[rR] /<some-dir>/* storj://<bucket-name>/)\n" \
49
+ " cp [-rR] <uri> <path> download files from a bucket " \
50
+ "(e.g. storj cp -[rR] storj://<bucket-name>/ /<some-dir>/)\n" \
51
+ " mkbkt <bucket-name> make a bucket\n" \
52
+ " rm <bucket-name> <file-name> remove a file from a bucket\n" \
53
+ " rm <bucket-name> remove a bucket\n" \
54
+ " lm <bucket-name> <file-name> list mirrors\n\n" \
55
+ "working with buckets and files:\n" \
43
56
  " list-buckets\n" \
44
57
  " list-files <bucket-id>\n" \
45
58
  " remove-file <bucket-id> <file-id>\n" \
46
- " add-bucket <name> \n" \
47
59
  " 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" \
60
+ " add-bucket <name> \n" \
61
+ " list-mirrors <bucket-id> <file-id>\n" \
62
+ " get-bucket-id <bucket-name>\n\n" \
63
+ "uploading files:\n" \
64
+ " upload-file <bucket-id> <path>\n\n" \
65
+ "downloading files:\n" \
66
+ " download-file <bucket-id> <file-id> <path>\n\n" \
67
+ "bridge api information:\n" \
53
68
  " get-info\n\n" \
54
69
  "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 " \
70
+ " -h, --help output usage information\n" \
71
+ " -v, --version output the version number\n" \
72
+ " -u, --url <url> set the base url for the api\n" \
73
+ " -p, --proxy <url> set the socks proxy " \
59
74
  "(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" \
75
+ " -l, --log <level> set the log level (default 0)\n" \
76
+ " -d, --debug set the debug log level\n\n" \
62
77
  "environment variables:\n" \
63
- " STORJ_KEYPASS imported user settings passphrase\n" \
64
- " STORJ_BRIDGE the bridge host " \
78
+ " STORJ_KEYPASS imported user settings passphrase\n" \
79
+ " STORJ_BRIDGE the bridge host " \
65
80
  "(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"
81
+ " STORJ_BRIDGE_USER bridge username\n" \
82
+ " STORJ_BRIDGE_PASS bridge password\n" \
83
+ " STORJ_ENCRYPTION_KEY file encryption key\n\n"
84
+
85
+
86
+ #define CLI_VERSION "libstorj-2.0.0-beta2"
87
+
88
+ static int check_file_path(char *file_path)
89
+ {
90
+ struct stat sb;
91
+
92
+ if (stat(file_path, &sb) == -1) {
93
+ perror("stat");
94
+ return CLI_NO_SUCH_FILE_OR_DIR;
95
+ }
96
+
97
+ switch (sb.st_mode & S_IFMT) {
98
+ case S_IFBLK:
99
+ printf("block device\n");
100
+ break;
101
+ case S_IFCHR:
102
+ printf("character device\n");
103
+ break;
104
+ case S_IFDIR:
105
+ return CLI_VALID_DIR;
106
+ break;
107
+ case S_IFIFO:
108
+ printf("FIFO/pipe\n");
109
+ break;
110
+ case S_IFLNK:
111
+ printf("symlink\n");
112
+ break;
113
+ case S_IFREG:
114
+ return CLI_VALID_REGULAR_FILE;
115
+ break;
116
+ case S_IFSOCK:
117
+ printf("socket\n");
118
+ break;
119
+ default:
120
+ printf("unknown?\n");
121
+ break;
122
+ }
123
+
124
+ #if ENABLE_FILE_DETAILS
125
+ printf("I-node number: %ld\n", (long)sb.st_ino);
126
+
127
+ printf("Mode: %lo (octal)\n",
128
+ (unsigned long)sb.st_mode);
129
+
130
+ printf("Link count: %ld\n", (long)sb.st_nlink);
131
+ printf("Ownership: UID=%ld GID=%ld\n",
132
+ (long)sb.st_uid, (long)sb.st_gid);
133
+
134
+ printf("Preferred I/O block size: %ld bytes\n",
135
+ (long)sb.st_blksize);
136
+ printf("File size: %lld bytes\n",
137
+ (long long)sb.st_size);
138
+ printf("Blocks allocated: %lld\n",
139
+ (long long)sb.st_blocks);
140
+
141
+ printf("Last status change: %s", ctime(&sb.st_ctime));
142
+ printf("Last file access: %s", ctime(&sb.st_atime));
143
+ printf("Last file modification: %s", ctime(&sb.st_mtime));
144
+ #endif
145
+
146
+ return CLI_UNKNOWN_FILE_ATTR;
147
+ }
148
+
149
+
150
+ static int strpos(char *str, char *sub_str)
151
+ {
152
+ /* find first occurance of substring in string */
153
+ char *sub_str_pos=strstr(str,sub_str);
154
+
155
+ /* if null return -1 , otherwise return substring address - base address */
156
+ return sub_str_pos == NULL ? -1 : (sub_str_pos - str );
157
+ }
158
+
159
+ static int validate_cmd_tokenize(char *cmd_str, char *str_token[])
160
+ {
161
+ char sub_str[] = "storj://";
162
+ int i = 0x00; /* num of tokens */
163
+
164
+ int ret = strpos(cmd_str, sub_str);
165
+ if (ret == -1) {
166
+ printf("Invalid Command Entry (%d), \ntry ... storj://<bucket_name>/<file_name>\n", ret);
167
+ }
69
168
 
169
+ if (ret == 0x00) {
170
+ /* start tokenizing */
171
+ str_token[0] = strtok(cmd_str, "/");
172
+ while (str_token[i] != NULL) {
173
+ i++;
174
+ str_token[i] = strtok(NULL, "/");
175
+ }
176
+ } else {
177
+ i = ret;
178
+ }
179
+
180
+ return i;
181
+ }
70
182
 
71
- #define CLI_VERSION "libstorj-2.0.0-beta"
72
183
 
73
184
  static void json_logger(const char *message, int level, void *handle)
74
185
  {
@@ -109,37 +220,6 @@ static int make_user_directory(char *path)
109
220
  return 0;
110
221
  }
111
222
 
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
223
 
144
224
  static int get_user_auth_location(char *host, char **root_dir, char **user_file)
145
225
  {
@@ -170,24 +250,6 @@ static int get_user_auth_location(char *host, char **root_dir, char **user_file)
170
250
  return 0;
171
251
  }
172
252
 
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
253
 
192
254
  static int generate_mnemonic(char **mnemonic)
193
255
  {
@@ -318,274 +380,6 @@ static int get_password_verify(char *prompt, char *password, int count)
318
380
  }
319
381
  }
320
382
 
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
383
  static int import_keys(user_options_t *options)
590
384
  {
591
385
  int status = 0;
@@ -810,123 +604,20 @@ static void register_callback(uv_work_t *work_req, int status)
810
604
  free(work_req);
811
605
  }
812
606
 
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
607
  static void create_bucket_callback(uv_work_t *work_req, int status)
920
608
  {
921
609
  assert(status == 0);
922
610
  create_bucket_request_t *req = work_req->data;
923
611
 
924
- if (req->status_code == 404) {
925
- printf("Cannot create bucket [%s]. Name already exists \n", req->bucket->name);
612
+ if (req->status_code == 409) {
613
+ printf("Cannot create bucket [%s]. Name already exists.\n", req->bucket->name);
926
614
  goto clean_variables;
927
615
  } else if (req->status_code == 401) {
928
616
  printf("Invalid user credentials.\n");
929
617
  goto clean_variables;
618
+ } else if (req->status_code == 403) {
619
+ printf("Forbidden, user not active.\n");
620
+ goto clean_variables;
930
621
  }
931
622
 
932
623
  if (req->status_code != 201) {
@@ -1047,6 +738,7 @@ clear_variables:
1047
738
  int main(int argc, char **argv)
1048
739
  {
1049
740
  int status = 0;
741
+ char temp_buff[256] = {};
1050
742
 
1051
743
  static struct option cmd_options[] = {
1052
744
  {"url", required_argument, 0, 'u'},
@@ -1055,6 +747,7 @@ int main(int argc, char **argv)
1055
747
  {"log", required_argument, 0, 'l'},
1056
748
  {"debug", no_argument, 0, 'd'},
1057
749
  {"help", no_argument, 0, 'h'},
750
+ {"recursive", required_argument, 0, 'r'},
1058
751
  {0, 0, 0, 0}
1059
752
  };
1060
753
 
@@ -1073,10 +766,11 @@ int main(int argc, char **argv)
1073
766
  char *storj_bridge = getenv("STORJ_BRIDGE");
1074
767
  int c;
1075
768
  int log_level = 0;
769
+ char *local_file_path = NULL;
1076
770
 
1077
771
  char *proxy = getenv("STORJ_PROXY");
1078
772
 
1079
- while ((c = getopt_long_only(argc, argv, "hdl:p:vVu:",
773
+ while ((c = getopt_long_only(argc, argv, "hdl:p:vVu:r:R:",
1080
774
  cmd_options, &index)) != -1) {
1081
775
  switch (c) {
1082
776
  case 'u':
@@ -1096,10 +790,18 @@ int main(int argc, char **argv)
1096
790
  printf(CLI_VERSION "\n\n");
1097
791
  exit(0);
1098
792
  break;
793
+ case 'R':
794
+ case 'r':
795
+ local_file_path = optarg;
796
+ break;
1099
797
  case 'h':
1100
798
  printf(HELP_TEXT);
1101
799
  exit(0);
1102
800
  break;
801
+ default:
802
+ exit(0);
803
+ break;
804
+
1103
805
  }
1104
806
  }
1105
807
 
@@ -1172,6 +874,7 @@ int main(int argc, char **argv)
1172
874
  char *user = NULL;
1173
875
  char *pass = NULL;
1174
876
  char *mnemonic = NULL;
877
+ cli_api_t *cli_api = NULL;
1175
878
 
1176
879
  if (strcmp(command, "get-info") == 0) {
1177
880
  printf("Storj bridge: %s\n\n", storj_bridge);
@@ -1191,7 +894,7 @@ int main(int argc, char **argv)
1191
894
 
1192
895
  storj_bridge_get_info(env, NULL, get_info_callback);
1193
896
 
1194
- } else if(strcmp(command, "register") == 0) {
897
+ } else if (strcmp(command, "register") == 0) {
1195
898
  storj_bridge_options_t options = {
1196
899
  .proto = proto,
1197
900
  .host = host,
@@ -1303,7 +1006,6 @@ int main(int argc, char **argv)
1303
1006
  } else if (file_mnemonic) {
1304
1007
  free(file_mnemonic);
1305
1008
  }
1306
-
1307
1009
  }
1308
1010
 
1309
1011
  // Third, ask for authentication
@@ -1369,6 +1071,28 @@ int main(int argc, char **argv)
1369
1071
  goto end_program;
1370
1072
  }
1371
1073
 
1074
+ cli_api = malloc(sizeof(cli_api_t));
1075
+
1076
+ if (!cli_api) {
1077
+ status = 1;
1078
+ goto end_program;
1079
+ }
1080
+ memset(cli_api, 0x00, sizeof(*cli_api));
1081
+
1082
+ cli_api->env = env;
1083
+
1084
+ #ifdef debug_enable
1085
+ printf("command = %s; command_index = %d\n", command, command_index);
1086
+ printf("local_file_path (req arg_ = %s\n", local_file_path);
1087
+ for (int i = 0x00; i < argc; i++) {
1088
+ printf("argc = %d; argv[%d] = %s\n", argc, i, argv[i]);
1089
+ }
1090
+
1091
+ for (int i = 0x00; i < (argc - command_index); i++) {
1092
+ printf("argc = %d; argv[command_index+%d] = %s\n", argc, i, argv[command_index + i]);
1093
+ }
1094
+ #endif
1095
+
1372
1096
  if (strcmp(command, "download-file") == 0) {
1373
1097
  char *bucket_id = argv[command_index + 1];
1374
1098
  char *file_id = argv[command_index + 2];
@@ -1380,7 +1104,11 @@ int main(int argc, char **argv)
1380
1104
  goto end_program;
1381
1105
  }
1382
1106
 
1383
- if (download_file(env, bucket_id, file_id, path)) {
1107
+ memcpy(cli_api->bucket_id, bucket_id, strlen(bucket_id));
1108
+ memcpy(cli_api->file_id, file_id, strlen(file_id));
1109
+ cli_api->dst_file = path;
1110
+
1111
+ if (download_file(env, bucket_id, file_id, path, cli_api)) {
1384
1112
  status = 1;
1385
1113
  goto end_program;
1386
1114
  }
@@ -1394,7 +1122,10 @@ int main(int argc, char **argv)
1394
1122
  goto end_program;
1395
1123
  }
1396
1124
 
1397
- if (upload_file(env, bucket_id, path)) {
1125
+ memcpy(cli_api->bucket_id, bucket_id, strlen(bucket_id));
1126
+ cli_api->dst_file = path;
1127
+
1128
+ if (upload_file(env, bucket_id, path, cli_api)) {
1398
1129
  status = 1;
1399
1130
  goto end_program;
1400
1131
  }
@@ -1407,8 +1138,8 @@ int main(int argc, char **argv)
1407
1138
  goto end_program;
1408
1139
  }
1409
1140
 
1410
- storj_bridge_list_files(env, bucket_id, NULL, list_files_callback);
1411
- } else if (strcmp(command, "add-bucket") == 0) {
1141
+ storj_bridge_list_files(env, bucket_id, cli_api, list_files_callback);
1142
+ } else if ((strcmp(command, "add-bucket") == 0) || (strcmp(command, "mkbkt") == 0x00)) {
1412
1143
  char *bucket_name = argv[command_index + 1];
1413
1144
 
1414
1145
  if (!bucket_name) {
@@ -1429,7 +1160,7 @@ int main(int argc, char **argv)
1429
1160
  goto end_program;
1430
1161
  }
1431
1162
 
1432
- storj_bridge_delete_bucket(env, bucket_id, NULL,
1163
+ storj_bridge_delete_bucket(env, bucket_id, cli_api,
1433
1164
  delete_bucket_callback);
1434
1165
 
1435
1166
  } else if (strcmp(command, "remove-file") == 0) {
@@ -1442,7 +1173,7 @@ int main(int argc, char **argv)
1442
1173
  goto end_program;
1443
1174
  }
1444
1175
  storj_bridge_delete_file(env, bucket_id, file_id,
1445
- NULL, delete_file_callback);
1176
+ cli_api, delete_file_callback);
1446
1177
 
1447
1178
  } else if (strcmp(command, "list-buckets") == 0) {
1448
1179
  storj_bridge_get_buckets(env, NULL, get_buckets_callback);
@@ -1456,7 +1187,355 @@ int main(int argc, char **argv)
1456
1187
  goto end_program;
1457
1188
  }
1458
1189
  storj_bridge_list_mirrors(env, bucket_id, file_id,
1459
- NULL, list_mirrors_callback);
1190
+ cli_api, list_mirrors_callback);
1191
+ } else if (strcmp(command, "cp") == 0) {
1192
+ #define UPLOAD_CMD 0x00
1193
+ #define DOWNLOAD_CMD 0x01
1194
+ #define RECURSIVE_CMD 0x02
1195
+ #define NON_RECURSIVE_CMD 0x03
1196
+
1197
+ int ret = 0x00;
1198
+ char *src_path = NULL; /* holds the local path */
1199
+ char *dst_path = NULL; /* holds the storj:// path */
1200
+ char *bucket_name = NULL;
1201
+ int cmd_type = 0x00; /* 0-> upload and 1 -> download */
1202
+ char modified_src_path[256] = {}; /* use this buffer to store the loca-file-path, if modified */
1203
+ memset(modified_src_path, 0x00, sizeof(modified_src_path));
1204
+ char *upload_file_path = modified_src_path;
1205
+
1206
+ /* cp command wrt to upload-file */
1207
+ if (local_file_path == NULL) {/* without -r[R] */
1208
+ /* hold the local path */
1209
+ src_path = argv[command_index + 0x01];
1210
+
1211
+ /* Handle the dst argument (storj://<bucket-name>/ */
1212
+ dst_path = argv[argc - 0x01];
1213
+
1214
+ cmd_type = NON_RECURSIVE_CMD;
1215
+ } else { /* with -r[R] */
1216
+ if ((strcmp(argv[1],"-r") == 0x00) || (strcmp(argv[1],"-R") == 0x00)) {
1217
+ src_path = local_file_path;
1218
+
1219
+ /* Handle the dst argument (storj://<bucket-name>/ */
1220
+ dst_path = argv[argc - 0x01];
1221
+
1222
+ cmd_type = RECURSIVE_CMD;
1223
+ } else {
1224
+ printf("[%s][%d] Invalid command option '%s'\n",
1225
+ __FUNCTION__, __LINE__, argv[1]);
1226
+ goto end_program;
1227
+ }
1228
+ }
1229
+
1230
+ if ((strcmp(src_path, argv[command_index]) == 0x00) ||
1231
+ (strcmp(dst_path, argv[command_index]) == 0x00) ||
1232
+ (strcmp(dst_path, src_path) == 0x00)) {
1233
+ printf("[%s][%d] Invalid command option '%s'\n",
1234
+ __FUNCTION__, __LINE__, argv[1]);
1235
+ goto end_program;
1236
+ }
1237
+
1238
+ /* check for upload or download command */
1239
+ char sub_str[] = "storj://";
1240
+ ret = strpos(dst_path, sub_str);
1241
+
1242
+ if (ret == 0x00) { /* Handle upload command*/
1243
+ if (cmd_type == NON_RECURSIVE_CMD) {
1244
+ if (check_file_path(src_path) != CLI_VALID_DIR) {
1245
+ local_file_path = src_path;
1246
+
1247
+ bucket_name = dst_path;
1248
+ } else {
1249
+ printf("[%s][%d] Invalid command entry\n",
1250
+ __FUNCTION__, __LINE__);
1251
+ goto end_program;
1252
+ }
1253
+ } else if (cmd_type == RECURSIVE_CMD) {
1254
+ local_file_path = src_path;
1255
+
1256
+ bucket_name = dst_path;
1257
+ } else {
1258
+ printf("[%s][%d] Invalid command entry \n", __FUNCTION__, __LINE__);
1259
+ goto end_program;
1260
+ }
1261
+
1262
+ cmd_type = UPLOAD_CMD;
1263
+ } else if (ret == -1) { /* Handle download command*/
1264
+ ret = strpos(src_path, sub_str);
1265
+
1266
+ if (ret == 0x00) {
1267
+ if ((cmd_type == NON_RECURSIVE_CMD) || (cmd_type == RECURSIVE_CMD)) {
1268
+ local_file_path = dst_path;
1269
+ bucket_name = src_path;
1270
+
1271
+ char *dst_file_name = NULL;
1272
+ dst_file_name = (char *)get_filename_separator(local_file_path);
1273
+
1274
+ /* token[0]-> storj:; token[1]->bucket_name; token[2]->upload_file_name */
1275
+ char *token[0x03];
1276
+ memset(token, 0x00, sizeof(token));
1277
+ int num_of_tokens = validate_cmd_tokenize(bucket_name, token);
1278
+
1279
+ /* set the bucket name from which file(s) to be downloaded */
1280
+ cli_api->bucket_name = token[1];
1281
+
1282
+ /* initialize the local folder to copy the downloaded file into */
1283
+ cli_api->file_path = local_file_path;
1284
+
1285
+ /* initialize the filename to be downloaded as */
1286
+ cli_api->dst_file = dst_file_name;
1287
+
1288
+ if ((argc == 0x04) || (argc == 0x05)) { /* handle non recursive operations */
1289
+ if ((token[2] == NULL) || (strcmp(token[2], "*") == 0x00)) {
1290
+ if (check_file_path(local_file_path) == CLI_VALID_DIR) {
1291
+ cli_download_files(cli_api);
1292
+ } else {
1293
+ printf("[%s][%d] Invalid '%s' dst directory !!!!!\n",
1294
+ __FUNCTION__, __LINE__, local_file_path);
1295
+ goto end_program;
1296
+ }
1297
+ } else if (token[2] != NULL) {
1298
+ /* set the file to be downloaded */
1299
+ cli_api->file_name = token[2];
1300
+
1301
+ if ((check_file_path(local_file_path) == CLI_VALID_DIR) || (strcmp(dst_file_name, ".") == 0x00)) {
1302
+ memset(temp_buff, 0x00, sizeof(temp_buff));
1303
+ strcat(temp_buff, local_file_path);
1304
+ strcat(temp_buff, "/");
1305
+ strcat(temp_buff, token[2]);
1306
+ cli_api->dst_file = temp_buff;
1307
+ } else if (strlen(dst_file_name) > 0x00) {
1308
+ cli_api->dst_file = local_file_path;
1309
+ } else {
1310
+ printf("[%s][%d] Invalid '%s' dst directory !!!!!\n",
1311
+ __FUNCTION__, __LINE__, local_file_path);
1312
+ goto end_program;
1313
+ }
1314
+ printf("[%s][%d]file %s downloaded from bucketname = %s as file %s\n",
1315
+ __FUNCTION__, __LINE__, cli_api->file_name, cli_api->bucket_name, cli_api->dst_file);
1316
+ cli_download_file(cli_api);
1317
+ } else {
1318
+ printf("[%s][%d] Invalid '%s' dst directory !!!!!\n",
1319
+ __FUNCTION__, __LINE__, local_file_path);
1320
+ goto end_program;
1321
+ }
1322
+ } else {
1323
+ /* more args then needed wrong command */
1324
+ printf("[%s][%d] Valid dst filename missing !!!!!\n", __FUNCTION__, __LINE__);
1325
+ goto end_program;
1326
+ }
1327
+ } else {
1328
+ printf("[%s][%d] Invalid command entry \n", __FUNCTION__, __LINE__);
1329
+ goto end_program;
1330
+ }
1331
+ } else {
1332
+ printf("[%s][%d]Invalid Command Entry (%d) \n",
1333
+ __FUNCTION__, __LINE__, ret);
1334
+ goto end_program;
1335
+ }
1336
+ } else {
1337
+ printf("[%s][%d]Invalid Command Entry (%d) \n",
1338
+ __FUNCTION__, __LINE__, ret);
1339
+ goto end_program;
1340
+ }
1341
+
1342
+ if (cmd_type == UPLOAD_CMD) {
1343
+ /* handling single file copy with -r[R]: ./storj cp -r /home/kishore/libstorj/src/xxx.y storj://testbucket/yyy.x */
1344
+ /* Handle the src argument */
1345
+ /* single file to copy, make sure the files exits */
1346
+ if ((argc == 0x05) && (check_file_path(local_file_path) == CLI_VALID_REGULAR_FILE)) {
1347
+ cli_api->file_name = local_file_path;
1348
+
1349
+ /* Handle the dst argument (storj://<bucket-name>/<file-name> */
1350
+ /* token[0]-> storj:; token[1]->bucket_name; token[2]->upload_file_name */
1351
+ char *token[0x03];
1352
+ memset(token,0x00, sizeof(token));
1353
+ int num_of_tokens = validate_cmd_tokenize(bucket_name, token);
1354
+
1355
+ if ((num_of_tokens == 0x02) || (num_of_tokens == 0x03)) {
1356
+ char *dst_file_name = NULL;
1357
+
1358
+ cli_api->bucket_name = token[1];
1359
+ dst_file_name = (char *)get_filename_separator(local_file_path);
1360
+
1361
+ if ((token[2] == NULL) || (strcmp(dst_file_name, token[2]) == 0x00) ||
1362
+ (strcmp(token[2], ".") == 0x00)) {
1363
+ /* use the src list buff as temp memory to hold the dst filename */
1364
+ memset(cli_api->src_list, 0x00, sizeof(cli_api->src_list));
1365
+ strcpy(cli_api->src_list, dst_file_name);
1366
+ cli_api->dst_file = cli_api->src_list;
1367
+ } else {
1368
+ cli_api->dst_file = token[2];
1369
+ }
1370
+ cli_upload_file(cli_api);
1371
+ } else {
1372
+ printf("[%s][%d] Valid dst filename missing !!!!!\n", __FUNCTION__, __LINE__);
1373
+ goto end_program;
1374
+ }
1375
+ }
1376
+ else {
1377
+ /* directory is being used, store it in file_path */
1378
+ cli_api->file_path = local_file_path;
1379
+
1380
+ /* Handle wild character options for files selection */
1381
+ if (check_file_path(local_file_path) != CLI_VALID_DIR) {
1382
+ char pwd_path[256] = { };
1383
+ memset(pwd_path, 0x00, sizeof(pwd_path));
1384
+ char *upload_list_file = pwd_path;
1385
+
1386
+ /* create "/tmp/STORJ_upload_list_file.txt" upload files list based on the file path */
1387
+ if ((upload_list_file = getenv("TMPDIR")) != NULL) {
1388
+ if (upload_list_file[(strlen(upload_list_file) - 1)] == '/') {
1389
+ strcat(upload_list_file, "STORJ_output_list.txt");
1390
+ } else {
1391
+ strcat(upload_list_file, "/STORJ_output_list.txt");
1392
+ }
1393
+
1394
+ /* check the directory and create the path to upload list file */
1395
+ memset(cli_api->src_list, 0x00, sizeof(cli_api->src_list));
1396
+ memcpy(cli_api->src_list, upload_list_file, sizeof(pwd_path));
1397
+ cli_api->dst_file = cli_api->src_list;
1398
+ } else {
1399
+ printf("[%s][%d] Upload list file generation error!!! \n",
1400
+ __FUNCTION__, __LINE__);
1401
+ goto end_program;
1402
+ }
1403
+
1404
+ /* if local file path is a file, then just get the directory
1405
+ from that */
1406
+ char *ret = NULL;
1407
+ ret = strrchr(local_file_path, '/');
1408
+ memset(temp_buff, 0x00, sizeof(temp_buff));
1409
+ memcpy(temp_buff, local_file_path, ((ret - local_file_path)+1));
1410
+
1411
+ FILE *file = NULL;
1412
+ /* create the file and add the list of files to be uploaded */
1413
+ if ((file = fopen(cli_api->src_list, "w")) != NULL) {
1414
+ if ((strcmp(argv[1],"-r") == 0x00) || (strcmp(argv[1],"-R") == 0x00)) {
1415
+ fprintf(file, "%s\n", local_file_path);
1416
+ }
1417
+
1418
+ for (int i = 0x01; i < ((argc - command_index) - 1); i++) {
1419
+ fprintf(file, "%s\n", argv[command_index + i]);
1420
+ }
1421
+ } else {
1422
+ printf("[%s][%d] Invalid upload src path entered\n", __FUNCTION__, __LINE__);
1423
+ goto end_program;
1424
+ }
1425
+ fclose(file);
1426
+
1427
+ cli_api->file_path = temp_buff;
1428
+ } else {
1429
+ /* its a valid directory so let the list of files to be uploaded be handled in
1430
+ verify upload file () */
1431
+ cli_api->dst_file = NULL;
1432
+
1433
+ memcpy(upload_file_path, cli_api->file_path, strlen(cli_api->file_path));
1434
+ if (upload_file_path[(strlen(upload_file_path) - 1)] != '/') {
1435
+ strcat(upload_file_path, "/");
1436
+ cli_api->file_path = upload_file_path;
1437
+ }
1438
+ }
1439
+
1440
+ /* token[0]-> storj:; token[1]->bucket_name; token[2]->upload_file_name */
1441
+ char *token[0x03];
1442
+ memset(token, 0x00, sizeof(token));
1443
+ int num_of_tokens = validate_cmd_tokenize(bucket_name, token);
1444
+
1445
+ if ((num_of_tokens > 0x00) && ((num_of_tokens >= 0x02) || (num_of_tokens <= 0x03))) {
1446
+ char *dst_file_name = NULL;
1447
+
1448
+ cli_api->bucket_name = token[1];
1449
+
1450
+ if ((token[2] == NULL) ||
1451
+ (strcmp(token[2], ".") == 0x00)) {
1452
+ cli_upload_files(cli_api);
1453
+ } else {
1454
+ printf("[%s][%d] storj://<bucket-name>; storj://<bucket-name>/ storj://<bucket-name>/. !!!!!\n", __FUNCTION__, __LINE__);
1455
+ goto end_program;
1456
+ }
1457
+ } else {
1458
+ printf("[%s][%d] Valid dst filename missing !!!!!\n", __FUNCTION__, __LINE__);
1459
+ goto end_program;
1460
+ }
1461
+ }
1462
+ }
1463
+ } else if (strcmp(command, "upload-files") == 0) {
1464
+ /* get the corresponding bucket id from the bucket name */
1465
+ cli_api->bucket_name = argv[command_index + 1];
1466
+ cli_api->file_path = argv[command_index + 2];
1467
+ cli_api->dst_file = NULL;
1468
+
1469
+ if (!cli_api->bucket_name || !cli_api->file_name) {
1470
+ printf("Missing arguments: <bucket-name> <path>\n");
1471
+ status = 1;
1472
+ goto end_program;
1473
+ }
1474
+
1475
+ cli_upload_files(cli_api);
1476
+ } else if (strcmp(command, "download-files") == 0) {
1477
+ /* get the corresponding bucket id from the bucket name */
1478
+ cli_api->bucket_name = argv[command_index + 1];
1479
+ cli_api->file_path = argv[command_index + 2];
1480
+
1481
+ if (!cli_api->bucket_name || !cli_api->file_path) {
1482
+ printf("Missing arguments: <bucket-name> <path>\n");
1483
+ status = 1;
1484
+ goto end_program;
1485
+ }
1486
+
1487
+ cli_download_files(cli_api);
1488
+ } else if (strcmp(command, "mkbkt") == 0x00) {
1489
+ char *bucket_name = argv[command_index + 1];
1490
+
1491
+ if (!bucket_name) {
1492
+ printf("Missing first argument: <bucket-name>\n");
1493
+ status = 1;
1494
+ goto end_program;
1495
+ }
1496
+
1497
+ storj_bridge_create_bucket(env, bucket_name,
1498
+ NULL, create_bucket_callback);
1499
+ } else if (strcmp(command, "rm") == 0) {
1500
+ cli_api->bucket_name = argv[command_index + 1];
1501
+ cli_api->file_name = argv[command_index + 2];
1502
+
1503
+ if (cli_api->file_name != NULL) {
1504
+ if (!cli_api->bucket_name|| !cli_api->file_name) {
1505
+ printf("Missing arguments, expected: <bucket-name> <file-name>\n");
1506
+ status = 1;
1507
+ goto end_program;
1508
+ }
1509
+
1510
+ cli_remove_file(cli_api);
1511
+ }
1512
+ else {
1513
+ cli_remove_bucket(cli_api);
1514
+ }
1515
+ } else if (strcmp(command, "ls") == 0x00) {
1516
+ if (argv[command_index + 1] != NULL) {
1517
+ /* bucket-name , used to list files */
1518
+ cli_api->bucket_name = argv[command_index + 1];
1519
+
1520
+ cli_list_files(cli_api);
1521
+ }
1522
+ else {
1523
+ cli_list_buckets(cli_api);
1524
+ }
1525
+ } else if (strcmp(command, "get-bucket-id") == 0) {
1526
+ cli_api->bucket_name = argv[command_index + 1];
1527
+ cli_get_bucket_id(cli_api);
1528
+ } else if (strcmp(command, "lm") == 0) {
1529
+ cli_api->bucket_name = argv[command_index + 1];
1530
+ cli_api->file_name = argv[command_index + 2];
1531
+
1532
+ if (!cli_api->bucket_name|| !cli_api->file_name) {
1533
+ printf("Missing arguments, expected: <bucket-name> <file-name>\n");
1534
+ status = 1;
1535
+ goto end_program;
1536
+ }
1537
+
1538
+ cli_list_mirrors(cli_api);
1460
1539
  } else {
1461
1540
  printf("'%s' is not a storj command. See 'storj --help'\n\n",
1462
1541
  command);
@@ -1490,5 +1569,9 @@ end_program:
1490
1569
  if (mnemonic) {
1491
1570
  free(mnemonic);
1492
1571
  }
1572
+ if (cli_api){
1573
+ free(cli_api);
1574
+ }
1575
+
1493
1576
  return status;
1494
1577
  }