ruby-libstorj 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![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
|
-
|
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
|
+
[![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
|
-
|
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
|
}
|