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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +14 -2
- data/ext/libstorj/.gitignore +1 -0
- data/ext/libstorj/CONTRIBUTING.md +66 -0
- data/ext/libstorj/Doxyfile +1 -1
- data/ext/libstorj/README.md +6 -1
- data/ext/libstorj/configure.ac +1 -1
- data/ext/libstorj/release.sh +61 -0
- data/ext/libstorj/src/Makefile.am +2 -2
- data/ext/libstorj/src/bip39.c +5 -0
- data/ext/libstorj/src/cli.c +542 -459
- data/ext/libstorj/src/cli_callback.c +1173 -0
- data/ext/libstorj/src/cli_callback.h +175 -0
- data/ext/libstorj/src/crypto.c +98 -4
- data/ext/libstorj/src/crypto.h +51 -0
- data/ext/libstorj/src/downloader.c +2 -3
- data/ext/libstorj/src/storj.c +371 -123
- data/ext/libstorj/src/storj.h +96 -4
- data/ext/libstorj/src/uploader.c +46 -50
- data/ext/libstorj/src/utils.c +48 -0
- data/ext/libstorj/src/utils.h +12 -0
- data/ext/libstorj/test/mockbridge.c +11 -1
- data/ext/libstorj/test/mockbridge.json +3 -0
- data/ext/libstorj/test/tests.c +132 -20
- data/ruby-libstorj.gemspec +1 -1
- data/spec/helpers/{options.yml.example → options.example.yml} +6 -3
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8de9d6c135ae3b5e58a34ce91f1ac731bc2e887a
|
4
|
+
data.tar.gz: f581db0c00bfcbbec33081df8034bcb17c8d7e18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7d9eef9134284db52495f95e1fbf73f7827380e180e6da2ffff75ae8ff6db1a204f3f3e646670ca7c664c74613dbd2e3e028ef945abf531a940c670fd842f29
|
7
|
+
data.tar.gz: 0a58c196a68386fc3ca0fc8bf3caf0156f38d2526c374a551b4a7eb194121f733e22943fbf06e171cfd2283195e6cbb2f0581cbdf4b3ea8b76a7c47dbafbc1b1
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,22 @@
|
|
1
1
|
ruby-libstorj: Ruby bindings for libstorj
|
2
2
|
===
|
3
|
+
[](https://badge.fury.io/rb/ruby-libstorj)
|
3
4
|
|
4
5
|
## Using ruby-libstorj
|
5
6
|
|
6
7
|
### Install gem:
|
7
|
-
|
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`](
|
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
|
data/ext/libstorj/.gitignore
CHANGED
@@ -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)
|
data/ext/libstorj/Doxyfile
CHANGED
@@ -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
|
data/ext/libstorj/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
libstorj
|
2
2
|
=======
|
3
3
|
|
4
|
+
[](https://storj.io)
|
4
5
|
[](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
|
-
|
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
|
|
data/ext/libstorj/configure.ac
CHANGED
@@ -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
|
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
|
data/ext/libstorj/src/bip39.c
CHANGED
@@ -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
|
data/ext/libstorj/src/cli.c
CHANGED
@@ -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
|
38
|
-
" register
|
39
|
-
" import-keys
|
40
|
-
" export-keys
|
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
|
-
"
|
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
|
-
"
|
49
|
-
"
|
50
|
-
"
|
51
|
-
"
|
52
|
-
"
|
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
|
56
|
-
" -v, --version
|
57
|
-
" -u, --url <url>
|
58
|
-
" -p, --proxy <url>
|
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>
|
61
|
-
" -d, --debug
|
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
|
64
|
-
" STORJ_BRIDGE
|
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
|
67
|
-
" STORJ_BRIDGE_PASS
|
68
|
-
" STORJ_ENCRYPTION_KEY
|
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 ==
|
925
|
-
printf("Cannot create bucket [%s]. Name already exists
|
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
|
-
|
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
|
-
|
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,
|
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,
|
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
|
-
|
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
|
-
|
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
|
}
|