ruby-libstorj 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +111 -0
  7. data/Guardfile +21 -0
  8. data/LICENSE +502 -0
  9. data/README.md +262 -0
  10. data/Rakefile +76 -0
  11. data/ext/libstorj/.gitignore +47 -0
  12. data/ext/libstorj/.travis.yml +27 -0
  13. data/ext/libstorj/Doxyfile +2427 -0
  14. data/ext/libstorj/LICENSE +502 -0
  15. data/ext/libstorj/Makefile.am +6 -0
  16. data/ext/libstorj/README.md +198 -0
  17. data/ext/libstorj/autogen.sh +3 -0
  18. data/ext/libstorj/configure.ac +64 -0
  19. data/ext/libstorj/depends/Makefile +153 -0
  20. data/ext/libstorj/depends/config.guess +1462 -0
  21. data/ext/libstorj/depends/config.sub +1823 -0
  22. data/ext/libstorj/depends/extract-osx-sdk.sh +33 -0
  23. data/ext/libstorj/depends/packages/cctools.mk +7 -0
  24. data/ext/libstorj/depends/packages/clang.mk +7 -0
  25. data/ext/libstorj/depends/packages/gmp.mk +23 -0
  26. data/ext/libstorj/depends/packages/gnutls.mk +25 -0
  27. data/ext/libstorj/depends/packages/json-c.mk +7 -0
  28. data/ext/libstorj/depends/packages/libcurl.mk +39 -0
  29. data/ext/libstorj/depends/packages/libmicrohttpd.mk +7 -0
  30. data/ext/libstorj/depends/packages/libuv.mk +7 -0
  31. data/ext/libstorj/depends/packages/nettle.mk +30 -0
  32. data/ext/libstorj/libstorj.pc.in +11 -0
  33. data/ext/libstorj/src/Makefile.am +23 -0
  34. data/ext/libstorj/src/bip39.c +233 -0
  35. data/ext/libstorj/src/bip39.h +64 -0
  36. data/ext/libstorj/src/bip39_english.h +2074 -0
  37. data/ext/libstorj/src/cli.c +1494 -0
  38. data/ext/libstorj/src/crypto.c +525 -0
  39. data/ext/libstorj/src/crypto.h +178 -0
  40. data/ext/libstorj/src/downloader.c +1923 -0
  41. data/ext/libstorj/src/downloader.h +163 -0
  42. data/ext/libstorj/src/http.c +688 -0
  43. data/ext/libstorj/src/http.h +175 -0
  44. data/ext/libstorj/src/rs.c +962 -0
  45. data/ext/libstorj/src/rs.h +99 -0
  46. data/ext/libstorj/src/storj.c +1523 -0
  47. data/ext/libstorj/src/storj.h +1014 -0
  48. data/ext/libstorj/src/uploader.c +2736 -0
  49. data/ext/libstorj/src/uploader.h +181 -0
  50. data/ext/libstorj/src/utils.c +336 -0
  51. data/ext/libstorj/src/utils.h +65 -0
  52. data/ext/libstorj/test/Makefile.am +27 -0
  53. data/ext/libstorj/test/mockbridge.c +260 -0
  54. data/ext/libstorj/test/mockbridge.json +687 -0
  55. data/ext/libstorj/test/mockbridgeinfo.json +1836 -0
  56. data/ext/libstorj/test/mockfarmer.c +358 -0
  57. data/ext/libstorj/test/storjtests.h +41 -0
  58. data/ext/libstorj/test/tests.c +1617 -0
  59. data/ext/libstorj/test/tests_rs.c +869 -0
  60. data/ext/ruby-libstorj/extconf.rb +8 -0
  61. data/ext/ruby-libstorj/ruby-libstorj.cc +17 -0
  62. data/lib/ruby-libstorj.rb +1 -0
  63. data/lib/ruby-libstorj/arg_forwarding_task.rb +58 -0
  64. data/lib/ruby-libstorj/env.rb +178 -0
  65. data/lib/ruby-libstorj/ext/bucket.rb +71 -0
  66. data/lib/ruby-libstorj/ext/create_bucket_request.rb +53 -0
  67. data/lib/ruby-libstorj/ext/curl_code.rb +139 -0
  68. data/lib/ruby-libstorj/ext/ext.rb +71 -0
  69. data/lib/ruby-libstorj/ext/file.rb +84 -0
  70. data/lib/ruby-libstorj/ext/get_bucket_request.rb +45 -0
  71. data/lib/ruby-libstorj/ext/json_request.rb +51 -0
  72. data/lib/ruby-libstorj/ext/list_files_request.rb +63 -0
  73. data/lib/ruby-libstorj/ext/types.rb +226 -0
  74. data/lib/ruby-libstorj/ext/upload_options.rb +38 -0
  75. data/lib/ruby-libstorj/libstorj.rb +22 -0
  76. data/lib/ruby-libstorj/mixins/storj.rb +27 -0
  77. data/lib/ruby-libstorj/struct.rb +42 -0
  78. data/ruby-libstorj.gemspec +57 -0
  79. data/spec/helpers/options.yml.example +22 -0
  80. data/spec/helpers/shared_rake_examples.rb +132 -0
  81. data/spec/helpers/storj_options.rb +96 -0
  82. data/spec/helpers/upload.data +3 -0
  83. data/spec/helpers/upload.data.sha256 +1 -0
  84. data/spec/libstorj_spec.rb +0 -0
  85. data/spec/ruby-libstorj/arg_forwarding_task_spec.rb +311 -0
  86. data/spec/ruby-libstorj/env_spec.rb +353 -0
  87. data/spec/ruby-libstorj/ext_spec.rb +75 -0
  88. data/spec/ruby-libstorj/json_request_spec.rb +13 -0
  89. data/spec/ruby-libstorj/libstorj_spec.rb +81 -0
  90. data/spec/ruby-libstorj/struct_spec.rb +64 -0
  91. data/spec/spec_helper.rb +113 -0
  92. metadata +136 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @file uploader.h
3
+ * @brief Storj upload methods and definitions.
4
+ *
5
+ * Structures and functions useful for uploading files.
6
+ */
7
+ #ifndef STORJ_UPLOADER_H
8
+ #define STORJ_UPLOADER_H
9
+ #include "storj.h"
10
+ #include "http.h"
11
+ #include "utils.h"
12
+ #include "crypto.h"
13
+ #include "rs.h"
14
+
15
+ #define STORJ_NULL -1
16
+ #define STORJ_MAX_REPORT_TRIES 2
17
+ #define STORJ_MAX_PUSH_FRAME_COUNT 6
18
+
19
+ typedef enum {
20
+ CANCELED = 0,
21
+ AWAITING_PREPARE_FRAME = 1,
22
+ PREPARING_FRAME = 2,
23
+ AWAITING_PUSH_FRAME = 3,
24
+ PUSHING_FRAME = 4,
25
+ AWAITING_PUSH_SHARD = 5,
26
+ PUSHING_SHARD = 6,
27
+ COMPLETED_PUSH_SHARD = 7
28
+ } storj_state_progress_t;
29
+
30
+ typedef enum {
31
+ PREPARE_FRAME_LIMIT = 1,
32
+ PUSH_FRAME_LIMIT = 32,
33
+ PUSH_SHARD_LIMIT = 32
34
+ } storj_state_progress_limits_t;
35
+
36
+ typedef struct {
37
+ /* state should not be modified in worker threads */
38
+ storj_upload_state_t *upload_state;
39
+ int status_code;
40
+ int error_status;
41
+ shard_meta_t *shard_meta;
42
+ // Position in shard meta array
43
+ int shard_meta_index;
44
+ // Either parity file pointer or original file
45
+ FILE *shard_file;
46
+ storj_log_levels_t *log;
47
+ } frame_builder_t;
48
+
49
+ typedef struct {
50
+ int error_status;
51
+ /* state should not be modified in worker threads */
52
+ storj_upload_state_t *upload_state;
53
+ } parity_shard_req_t;
54
+
55
+ typedef struct {
56
+ int error_status;
57
+ /* state should not be modified in worker threads */
58
+ storj_upload_state_t *upload_state;
59
+ } encrypt_file_req_t;
60
+
61
+ typedef struct {
62
+ storj_http_options_t *http_options;
63
+ storj_bridge_options_t *options;
64
+ int status_code;
65
+ int error_status;
66
+ storj_log_levels_t *log;
67
+ int shard_index;
68
+ int shard_meta_index;
69
+ FILE *shard_file;
70
+ uv_async_t progress_handle;
71
+ uint64_t start;
72
+ uint64_t end;
73
+
74
+ /* state should not be modified in worker threads */
75
+ storj_upload_state_t *upload_state;
76
+ bool *canceled;
77
+ } push_shard_request_t;
78
+
79
+ typedef struct {
80
+ storj_http_options_t *http_options;
81
+ storj_bridge_options_t *options;
82
+ char *token;
83
+ const char *bucket_id;
84
+ char *bucket_op;
85
+ /* state should not be modified in worker threads */
86
+ storj_upload_state_t *upload_state;
87
+ int status_code;
88
+ int error_status;
89
+ storj_log_levels_t *log;
90
+ } request_token_t;
91
+
92
+ typedef struct {
93
+ storj_http_options_t *http_options;
94
+ storj_bridge_options_t *options;
95
+ /* state should not be modified in worker threads */
96
+ storj_upload_state_t *upload_state;
97
+ char *frame_id;
98
+ int status_code;
99
+ int error_status;
100
+
101
+ // Add shard to frame
102
+ int shard_meta_index;
103
+ farmer_pointer_t *farmer_pointer;
104
+
105
+ storj_log_levels_t *log;
106
+ } frame_request_t;
107
+
108
+ typedef struct {
109
+ storj_http_options_t *http_options;
110
+ storj_bridge_options_t *options;
111
+ /* state should not be modified in worker threads */
112
+ storj_upload_state_t *upload_state;
113
+ int status_code;
114
+ int error_status;
115
+ struct json_object *response;
116
+ storj_log_levels_t *log;
117
+ } post_to_bucket_request_t;
118
+
119
+ typedef struct {
120
+ uint32_t pointer_index;
121
+ storj_http_options_t *http_options;
122
+ storj_bridge_options_t *options;
123
+ int status_code;
124
+ storj_exchange_report_t *report;
125
+ /* state should not be modified in worker threads */
126
+ storj_upload_state_t *state;
127
+ } shard_send_report_t;
128
+
129
+ static farmer_pointer_t *farmer_pointer_new();
130
+ static shard_meta_t *shard_meta_new();
131
+ static uv_work_t *shard_meta_work_new(int index, storj_upload_state_t *state);
132
+ static uv_work_t *frame_work_new(int *index, storj_upload_state_t *state);
133
+ static uv_work_t *uv_work_new();
134
+ static int prepare_encryption_key(storj_upload_state_t *state,
135
+ char *pre_pass,
136
+ int pre_pass_size,
137
+ char *pre_salt,
138
+ int pre_salt_size);
139
+
140
+ static int check_in_progress(storj_upload_state_t *state, int status);
141
+ char *create_tmp_name(storj_upload_state_t *state, char *extension);
142
+
143
+ static void shard_meta_cleanup(shard_meta_t *shard_meta);
144
+ static void pointer_cleanup(farmer_pointer_t *farmer_pointer);
145
+ static void cleanup_state(storj_upload_state_t *state);
146
+ static void free_encryption_ctx(storj_encryption_ctx_t *ctx);
147
+
148
+ static void queue_next_work(storj_upload_state_t *state);
149
+
150
+ static void queue_request_frame_id(storj_upload_state_t *state);
151
+ static void queue_prepare_frame(storj_upload_state_t *state, int index);
152
+ static void queue_push_frame(storj_upload_state_t *state, int index);
153
+ static void queue_push_shard(storj_upload_state_t *state, int index);
154
+ static void queue_create_bucket_entry(storj_upload_state_t *state);
155
+ static void queue_send_exchange_report(storj_upload_state_t *state, int index);
156
+ static void queue_create_encrypted_file(storj_upload_state_t *state);
157
+
158
+ static void request_token(uv_work_t *work);
159
+ static void request_frame_id(uv_work_t *work);
160
+ static void prepare_frame(uv_work_t *work);
161
+ static void push_frame(uv_work_t *work);
162
+ static void push_shard(uv_work_t *work);
163
+ static void create_bucket_entry(uv_work_t *work);
164
+ static void send_exchange_report(uv_work_t *work);
165
+ static void create_encrypted_file(uv_work_t *work);
166
+
167
+ static void after_request_token(uv_work_t *work, int status);
168
+ static void after_request_frame_id(uv_work_t *work, int status);
169
+ static void after_prepare_frame(uv_work_t *work, int status);
170
+ static void after_push_frame(uv_work_t *work, int status);
171
+ static void after_push_shard(uv_work_t *work, int status);
172
+ static void after_create_bucket_entry(uv_work_t *work, int status);
173
+ static void after_send_exchange_report(uv_work_t *work, int status);
174
+ static void after_create_encrypted_file(uv_work_t *work, int status);
175
+
176
+ static void queue_verify_bucket_id(storj_upload_state_t *state);
177
+ static void queue_verify_file_id(storj_upload_state_t *state);
178
+ static void verify_bucket_id_callback(uv_work_t *work_req, int status);
179
+ static void verify_file_id_callback(uv_work_t *work_req, int status);
180
+
181
+ #endif /* STORJ_UPLOADER_H */
@@ -0,0 +1,336 @@
1
+ #include "utils.h"
2
+
3
+ char *hex2str(size_t length, uint8_t *data)
4
+ {
5
+ size_t encode_len = BASE16_ENCODE_LENGTH(length);
6
+ uint8_t *result = calloc(encode_len + 1, sizeof(uint8_t));
7
+ if (!result) {
8
+ return NULL;
9
+ }
10
+
11
+ base16_encode_update(result, length, data);
12
+
13
+ return (char *)result;
14
+ }
15
+
16
+ void print_int_array(uint8_t *array, unsigned length)
17
+ {
18
+ printf("{");
19
+ for (int i = 0; i < length; i++) {
20
+ printf("%i", array[i]);
21
+ if (i != length - 1) {
22
+ printf(",");
23
+ }
24
+ }
25
+ printf("}\n");
26
+ }
27
+
28
+ uint8_t *str2hex(size_t length, char *data)
29
+ {
30
+ char *result = calloc(BASE16_DECODE_LENGTH(length) + 1, sizeof(char));
31
+ if (!result) {
32
+ return NULL;
33
+ }
34
+
35
+ struct base16_decode_ctx *ctx = malloc(sizeof(struct base16_decode_ctx));
36
+ base16_decode_init(ctx);
37
+
38
+ size_t decode_len = 0;
39
+ if (!base16_decode_update(ctx, &decode_len, (uint8_t *)result,
40
+ length, (uint8_t *)data)) {
41
+ free(result);
42
+ free(ctx);
43
+ return NULL;
44
+ }
45
+
46
+ if (!base16_decode_final(ctx)) {
47
+ free(result);
48
+ free(ctx);
49
+ return NULL;
50
+ }
51
+
52
+ free(ctx);
53
+ return (uint8_t *)result;
54
+ }
55
+
56
+ char *str_concat_many(int count, ...)
57
+ {
58
+ int length = 1;
59
+
60
+ va_list args;
61
+ va_start(args, count);
62
+ for (int i = 0; i < count; i++) {
63
+ char *item = va_arg(args, char *);
64
+ length += strlen(item);
65
+ }
66
+ va_end(args);
67
+
68
+ char *combined = calloc(length, sizeof(char));
69
+ if (!combined) {
70
+ return NULL;
71
+ }
72
+
73
+ va_start(args, count);
74
+ for (int i = 0; i < count; i++) {
75
+ char *item = va_arg(args, char *);
76
+ strcat(combined, item);
77
+ }
78
+ va_end(args);
79
+
80
+ return combined;
81
+ }
82
+
83
+ void random_buffer(uint8_t *buf, size_t len)
84
+ {
85
+ static FILE *frand = NULL;
86
+ #ifdef _WIN32
87
+ HCRYPTPROV hProvider;
88
+ int ret = CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
89
+ assert(ret);
90
+ ret = CryptGenRandom(hProvider, len, buf);
91
+ assert(ret);
92
+ CryptReleaseContext(hProvider, 0);
93
+ #else
94
+ if (!frand) {
95
+ frand = fopen("/dev/urandom", "r");
96
+ }
97
+ size_t len_read = fread(buf, 1, len, frand);
98
+ (void)len_read;
99
+ assert(len_read == len);
100
+ #endif
101
+ }
102
+
103
+ uint64_t shard_size(int hops)
104
+ {
105
+ return MIN_SHARD_SIZE * pow(2, hops);
106
+ };
107
+
108
+ uint64_t get_time_milliseconds() {
109
+ #ifdef _WIN32
110
+
111
+ // Time between windows epoch and standard epoch
112
+ const int64_t time_to_epoch = 116444736000000000LL;
113
+
114
+ FILETIME ft;
115
+
116
+ GetSystemTimeAsFileTime(&ft);
117
+
118
+ LARGE_INTEGER li;
119
+ li.LowPart = ft.dwLowDateTime;
120
+ li.HighPart = ft.dwHighDateTime;
121
+ li.QuadPart -= time_to_epoch;
122
+ li.QuadPart /= 10000;
123
+
124
+ uint64_t milliseconds = li.QuadPart;
125
+ #else
126
+ struct timeval t;
127
+ gettimeofday(&t, NULL);
128
+ uint64_t milliseconds = t.tv_sec * 1000LL + t.tv_usec / 1000;
129
+ #endif
130
+
131
+ return milliseconds;
132
+ }
133
+
134
+ void memset_zero(void *v, size_t n)
135
+ {
136
+ #ifdef _WIN32
137
+ SecureZeroMemory(v, n);
138
+ #else
139
+ volatile unsigned char *p = v;
140
+ while (n--) {
141
+ *p++ = 0;
142
+ }
143
+ #endif
144
+ }
145
+
146
+ uint64_t determine_shard_size(uint64_t file_size, int accumulator)
147
+ {
148
+ if (file_size <= 0) {
149
+ return 0;
150
+ }
151
+
152
+ accumulator = accumulator ? accumulator : 0;
153
+
154
+ // Determine hops back by accumulator
155
+ int hops = ((accumulator - SHARD_MULTIPLES_BACK) < 0 ) ?
156
+ 0 : accumulator - SHARD_MULTIPLES_BACK;
157
+
158
+ uint64_t byte_multiple = shard_size(accumulator);
159
+ double check = (double) file_size / byte_multiple;
160
+
161
+ // Determine if bytemultiple is highest bytemultiple that is still <= size
162
+ if (check > 0 && check <= 1) {
163
+ while (hops > 0 && shard_size(hops) > MAX_SHARD_SIZE) {
164
+ hops = hops - 1 <= 0 ? 0 : hops - 1;
165
+ }
166
+
167
+ return shard_size(hops);
168
+ }
169
+
170
+ // Maximum of 2 ^ 41 * 8 * 1024 * 1024
171
+ if (accumulator > 41) {
172
+ return 0;
173
+ }
174
+
175
+ return determine_shard_size(file_size, ++accumulator);
176
+ }
177
+
178
+ #ifdef _WIN32
179
+ ssize_t pread(int fd, void *buf, size_t count, uint64_t offset)
180
+ {
181
+ long unsigned int read_bytes = 0;
182
+
183
+ OVERLAPPED overlapped;
184
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
185
+
186
+ overlapped.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 32);
187
+ overlapped.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
188
+
189
+ HANDLE file = (HANDLE)_get_osfhandle(fd);
190
+ SetLastError(0);
191
+ bool RF = ReadFile(file, buf, count, &read_bytes, &overlapped);
192
+
193
+ // For some reason it errors when it hits end of file so we don't want to check that
194
+ if ((RF == 0) && GetLastError() != ERROR_HANDLE_EOF) {
195
+ errno = GetLastError();
196
+ // printf ("Error reading file : %d\n", GetLastError());
197
+ return -1;
198
+ }
199
+
200
+ return read_bytes;
201
+ }
202
+
203
+ ssize_t pwrite(int fd, const void *buf, size_t count, uint64_t offset)
204
+ {
205
+ long unsigned int written_bytes = 0;
206
+
207
+ OVERLAPPED overlapped;
208
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
209
+
210
+ overlapped.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 32);
211
+ overlapped.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
212
+
213
+ HANDLE file = (HANDLE)_get_osfhandle(fd);
214
+ SetLastError(0);
215
+ bool RF = WriteFile(file, buf, count, &written_bytes, &overlapped);
216
+ if ((RF == 0)) {
217
+ errno = GetLastError();
218
+ // printf ("Error reading file :%d\n", GetLastError());
219
+ return -1;
220
+ }
221
+
222
+ return written_bytes;
223
+ }
224
+ #endif
225
+
226
+ int allocatefile(int fd, uint64_t length)
227
+ {
228
+ #ifdef _WIN32
229
+ HANDLE file = (HANDLE)_get_osfhandle(fd);
230
+ if (file == INVALID_HANDLE_VALUE) {
231
+ return EBADF;
232
+ }
233
+
234
+ int status = 0;
235
+
236
+ LARGE_INTEGER size;
237
+ size.HighPart = (uint32_t)((length & 0xFFFFFFFF00000000LL) >> 32);
238
+ size.LowPart = (uint32_t)(length & 0xFFFFFFFFLL);
239
+
240
+ if (!SetFilePointerEx(file, size, 0, FILE_BEGIN)) {
241
+ status = GetLastError();
242
+ goto win_finished;
243
+ }
244
+
245
+ if (!SetEndOfFile(file)) {
246
+ status = GetLastError();
247
+ goto win_finished;
248
+ }
249
+
250
+ win_finished:
251
+
252
+ return status;
253
+ #elif HAVE_POSIX_FALLOCATE
254
+ return posix_fallocate(fd, 0, length);
255
+ #elif __unix__
256
+ if (fallocate(fd, 0, 0, length)) {
257
+ return errno;
258
+ }
259
+ return 0;
260
+ #elif __linux__
261
+ if (fallocate(fd, 0, 0, length)) {
262
+ return errno;
263
+ }
264
+ return 0;
265
+ #elif __APPLE__
266
+ fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, length, 0};
267
+ // Try to get a continous chunk of disk space
268
+ int ret = fcntl(fd, F_PREALLOCATE, &store);
269
+ if (-1 == ret) {
270
+ // OK, perhaps we are too fragmented, allocate non-continuous
271
+ store.fst_flags = F_ALLOCATEALL;
272
+ ret = fcntl(fd, F_PREALLOCATE, &store);
273
+ if ( -1 == ret) {
274
+ return -1;
275
+ }
276
+ }
277
+ return ftruncate(fd, length);
278
+ #else
279
+ return -1;
280
+ #endif
281
+ }
282
+
283
+
284
+ int unmap_file(uint8_t *map, uint64_t filesize)
285
+ {
286
+ #ifdef _WIN32
287
+ if (!FlushViewOfFile(map, filesize)) {
288
+ return GetLastError();
289
+ }
290
+ if (!UnmapViewOfFile(map)) {
291
+ return GetLastError();
292
+ }
293
+ #else
294
+ if (munmap(map, filesize)) {
295
+ return errno;
296
+ }
297
+ #endif
298
+ return 0;
299
+ }
300
+
301
+ int map_file(int fd, uint64_t filesize, uint8_t **map, bool read_only)
302
+ {
303
+ int status = 0;
304
+ #ifdef _WIN32
305
+ HANDLE fh = (HANDLE)_get_osfhandle(fd);
306
+ if (fh == INVALID_HANDLE_VALUE) {
307
+ return EBADF;
308
+ }
309
+
310
+ int prot = read_only ? PAGE_READONLY : PAGE_READWRITE;
311
+
312
+ HANDLE mh = CreateFileMapping(fh, NULL, prot, 0, 0, NULL);
313
+ if (!mh) {
314
+ status = GetLastError();
315
+ goto win_finished;
316
+ }
317
+
318
+ prot = read_only ? FILE_MAP_READ : FILE_MAP_WRITE;
319
+
320
+ *map = MapViewOfFileEx(mh, prot, 0, 0, filesize, NULL);
321
+ if (!*map) {
322
+ status = GetLastError();
323
+ goto win_finished;
324
+ }
325
+
326
+ win_finished:
327
+ CloseHandle(mh);
328
+ #else
329
+ int prot = read_only ? PROT_READ : PROT_READ | PROT_WRITE;
330
+ *map = (uint8_t *)mmap(NULL, filesize, prot, MAP_SHARED, fd, 0);
331
+ if (*map == MAP_FAILED) {
332
+ status = errno;
333
+ }
334
+ #endif
335
+ return status;
336
+ }