thesidedoor-flock 0.2.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.
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining
2
+ a copy of this software and associated documentation files (the
3
+ "Software"), to deal in the Software without restriction, including
4
+ without limitation the rights to use, copy, modify, merge, publish,
5
+ distribute, sublicense, and/or sell copies of the Software, and to
6
+ permit persons to whom the Software is furnished to do so, subject to
7
+ the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be
10
+ included in all copies or substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # Sidedoor native file locking
2
+
3
+ This package builds the native source from fs-ext 2.1.1 by Matt Sergeant and
4
+ contributors under its original MIT license. It retains the OS flock behavior.
5
+ Sidedoor uses only the synchronous flock entry point.
6
+
7
+ The source removes nine process-global V8 persistent string handles used by
8
+ statvfs. Their property names are created in the current isolate instead.
9
+ This prevents concurrent Node worker initialization from resetting another
10
+ isolate's handles. No locking or filesystem operation has been replaced.
11
+
12
+ Installation requires the same native compiler toolchain as fs-ext. Build output
13
+ is produced locally by node-gyp and is not included in the package archive.
14
+
15
+ Next.js applications must list `thesidedoor-flock` in
16
+ `serverExternalPackages` so the server loads the installed native binary instead
17
+ of adding it to the application bundle.
package/binding.gyp ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "fs_ext",
5
+ "include_dirs" : [ "<!(node -e \"require('nan')\")" ],
6
+ "sources": [
7
+ "fs-ext.cc"
8
+ ]
9
+ }
10
+ ]
11
+ }
package/fs-ext.cc ADDED
@@ -0,0 +1,596 @@
1
+ // Permission is hereby granted, free of charge, to any person obtaining a
2
+ // copy of this software and associated documentation files (the
3
+ // "Software"), to deal in the Software without restriction, including
4
+ // without limitation the rights to use, copy, modify, merge, publish,
5
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
6
+ // persons to whom the Software is furnished to do so, subject to the
7
+ // following conditions:
8
+ //
9
+ // The above copyright notice and this permission notice shall be included
10
+ // in all copies or substantial portions of the Software.
11
+ //
12
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
13
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
15
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ #include <node.h>
21
+ #ifndef _WIN32
22
+ #include <fcntl.h>
23
+ #endif
24
+ #include <errno.h>
25
+ #include <stdio.h>
26
+ #include <sys/types.h>
27
+ #include <stdlib.h>
28
+ #include <string.h>
29
+ #include <nan.h>
30
+
31
+ #ifndef _WIN32
32
+ #include <sys/file.h>
33
+ #include <unistd.h>
34
+ #include <sys/statvfs.h>
35
+ #endif
36
+
37
+ #ifdef _WIN32
38
+ #include <io.h>
39
+ #include <windows.h>
40
+ #define off_t LONGLONG
41
+ #define _LARGEFILE_SOURCE
42
+ #endif
43
+
44
+ using namespace v8;
45
+ using namespace node;
46
+
47
+ #define THROW_BAD_ARGS Nan::ThrowTypeError("Bad argument")
48
+
49
+ struct store_data_t {
50
+ Nan::Callback *cb;
51
+ int fs_op; // operation type within this module
52
+ int fd;
53
+ int oper;
54
+ int arg;
55
+ off_t offset;
56
+ #ifndef _WIN32
57
+ struct statvfs statvfs_buf;
58
+ #endif
59
+ char *path;
60
+ int error;
61
+ int result;
62
+ };
63
+
64
+
65
+ #ifdef _WIN32
66
+ #define LOCK_SH 1
67
+ #define LOCK_EX 2
68
+ #define LOCK_NB 4
69
+ #define LOCK_UN 8
70
+ #endif
71
+
72
+ enum
73
+ {
74
+ FS_OP_FLOCK,
75
+ FS_OP_SEEK,
76
+ FS_OP_STATVFS,
77
+ #ifndef _WIN32
78
+ FS_OP_FCNTL,
79
+ #endif
80
+ };
81
+
82
+ static void EIO_After(uv_work_t *req) {
83
+ Nan::HandleScope scope;
84
+
85
+ store_data_t *store_data = static_cast<store_data_t *>(req->data);
86
+
87
+ // there is always at least one argument. "error"
88
+ int argc = 1;
89
+
90
+ // Allocate space for two args: error plus possible additional result
91
+ Local<Value> argv[2];
92
+ Local<Object> statvfs_result;
93
+ // NOTE: This may need to be changed if something returns a -1
94
+ // for a success, which is possible.
95
+ if (store_data->result == -1) {
96
+ // If the request doesn't have a path parameter set.
97
+ argv[0] = Nan::ErrnoException(store_data->error, "EIO_After", "");
98
+ } else {
99
+ // error value is empty or null for non-error.
100
+ argv[0] = Nan::Null();
101
+
102
+ switch (store_data->fs_op) {
103
+ // These operations have no data to pass other than "error".
104
+ case FS_OP_FLOCK:
105
+ argc = 1;
106
+ break;
107
+
108
+ case FS_OP_SEEK:
109
+ argc = 2;
110
+ argv[1] = Nan::New<Number>(static_cast<double>(store_data->offset));
111
+ break;
112
+ case FS_OP_STATVFS:
113
+ #ifndef _WIN32
114
+ argc = 2;
115
+ statvfs_result = Nan::New<Object>();
116
+ argv[1] = statvfs_result;
117
+ Nan::Set(statvfs_result, Nan::New<String>("f_namemax").ToLocalChecked(), Nan::New<Integer>(static_cast<uint32_t>(store_data->statvfs_buf.f_namemax)));
118
+ Nan::Set(statvfs_result, Nan::New<String>("f_bsize").ToLocalChecked(), Nan::New<Integer>(static_cast<uint32_t>(store_data->statvfs_buf.f_bsize)));
119
+ Nan::Set(statvfs_result, Nan::New<String>("f_frsize").ToLocalChecked(), Nan::New<Integer>(static_cast<uint32_t>(store_data->statvfs_buf.f_frsize)));
120
+ Nan::Set(statvfs_result, Nan::New<String>("f_blocks").ToLocalChecked(), Nan::New<Number>(store_data->statvfs_buf.f_blocks));
121
+ Nan::Set(statvfs_result, Nan::New<String>("f_bavail").ToLocalChecked(), Nan::New<Number>(store_data->statvfs_buf.f_bavail));
122
+ Nan::Set(statvfs_result, Nan::New<String>("f_bfree").ToLocalChecked(), Nan::New<Number>(store_data->statvfs_buf.f_bfree));
123
+ Nan::Set(statvfs_result, Nan::New<String>("f_files").ToLocalChecked(), Nan::New<Number>(store_data->statvfs_buf.f_files));
124
+ Nan::Set(statvfs_result, Nan::New<String>("f_favail").ToLocalChecked(), Nan::New<Number>(store_data->statvfs_buf.f_favail));
125
+ Nan::Set(statvfs_result, Nan::New<String>("f_ffree").ToLocalChecked(), Nan::New<Number>(store_data->statvfs_buf.f_ffree));
126
+ #else
127
+ argc = 1;
128
+ #endif
129
+ break;
130
+ #ifndef _WIN32
131
+ case FS_OP_FCNTL:
132
+ argc = 2;
133
+ argv[1] = Nan::New<Number>(store_data->result);
134
+ break;
135
+ #endif
136
+ default:
137
+ assert(0 && "Unhandled op type value");
138
+ }
139
+ }
140
+
141
+ Nan::TryCatch try_catch;
142
+
143
+ Nan::AsyncResource async_resource("fs-ext:EIO_After");
144
+ store_data->cb->Call(argc, argv, &async_resource);
145
+
146
+ if (try_catch.HasCaught()) {
147
+ Nan::FatalException(try_catch);
148
+ }
149
+
150
+ // Dispose of the persistent handle
151
+ delete store_data->cb;
152
+ delete store_data;
153
+ delete req;
154
+ }
155
+
156
+ static void EIO_StatVFS(uv_work_t *req) {
157
+ store_data_t* statvfs_data = static_cast<store_data_t *>(req->data);
158
+ statvfs_data->result = 0;
159
+ #ifndef _WIN32
160
+ struct statvfs *data = &(statvfs_data->statvfs_buf);
161
+ if (statvfs(statvfs_data->path, data)) {
162
+ statvfs_data->result = -1;
163
+ memset(data, 0, sizeof(struct statvfs));
164
+ };
165
+ #endif
166
+ free(statvfs_data->path);
167
+ ;
168
+ }
169
+
170
+ #ifdef _WIN32
171
+ static off_t _win32_lseek(int fd, off_t offset, int whence) {
172
+ HANDLE fh;
173
+ LARGE_INTEGER new_offset;
174
+
175
+ fh = (HANDLE)uv_get_osfhandle(fd);
176
+ if (fh == (HANDLE)-1) {
177
+ errno = EBADF;
178
+ return -1;
179
+ }
180
+
181
+ DWORD method;
182
+ switch (whence) {
183
+ case SEEK_SET:
184
+ method = FILE_BEGIN;
185
+ break;
186
+ case SEEK_CUR:
187
+ method = FILE_CURRENT;
188
+ break;
189
+ case SEEK_END:
190
+ method = FILE_END;
191
+ break;
192
+ default:
193
+ errno = EINVAL;
194
+ return -1;
195
+ }
196
+
197
+ LARGE_INTEGER distance;
198
+ distance.QuadPart = offset;
199
+
200
+ if (SetFilePointerEx(fh, distance, &new_offset, method)) {
201
+ return new_offset.QuadPart;
202
+ }
203
+
204
+ errno = EINVAL;
205
+ return -1;
206
+ }
207
+ #endif
208
+
209
+ static void EIO_Seek(uv_work_t *req) {
210
+ store_data_t* seek_data = static_cast<store_data_t *>(req->data);
211
+
212
+ #ifdef _WIN32
213
+ off_t offs = _win32_lseek(seek_data->fd, seek_data->offset, seek_data->oper);
214
+ #else
215
+ off_t offs = lseek(seek_data->fd, seek_data->offset, seek_data->oper);
216
+ #endif
217
+
218
+ if (offs == -1) {
219
+ seek_data->result = -1;
220
+ seek_data->error = errno;
221
+ } else {
222
+ seek_data->offset = offs;
223
+ }
224
+
225
+ }
226
+
227
+ #ifndef _WIN32
228
+ static void EIO_Fcntl(uv_work_t *req) {
229
+ store_data_t* data = static_cast<store_data_t *>(req->data);
230
+
231
+ struct flock lk;
232
+ lk.l_start = 0;
233
+ lk.l_len = 0;
234
+ lk.l_type = 0;
235
+ lk.l_whence = 0;
236
+ lk.l_pid = 0;
237
+
238
+ int result = -1;
239
+ if (data->oper == F_GETLK || data->oper == F_SETLK || data->oper == F_SETLKW) {
240
+ if (data->oper == F_SETLK || data->oper == F_SETLKW) {
241
+ lk.l_whence = SEEK_SET;
242
+ lk.l_type = data->arg;
243
+ }
244
+ data->result = result = fcntl(data->fd, data->oper, &lk);
245
+ } else {
246
+ data->result = result = fcntl(data->fd, data->oper, data->arg);
247
+ }
248
+ if (result == -1) {
249
+ data->error = errno;
250
+ }
251
+ }
252
+ #endif
253
+
254
+ #ifdef _WIN32
255
+
256
+ static void uv__crt_invalid_parameter_handler(const wchar_t* expression,
257
+ const wchar_t* function, const wchar_t * file, unsigned int line,
258
+ uintptr_t reserved) {
259
+ /* No-op. */
260
+ }
261
+
262
+ #define LK_LEN 0xffff0000
263
+
264
+ static int _win32_flock(int fd, int oper) {
265
+ OVERLAPPED o;
266
+ HANDLE fh;
267
+
268
+ int i = -1;
269
+
270
+ fh = (HANDLE)uv_get_osfhandle(fd);
271
+ if (fh == (HANDLE)-1) {
272
+ errno = EBADF;
273
+ return -1;
274
+ }
275
+
276
+ memset(&o, 0, sizeof(o));
277
+
278
+ switch(oper) {
279
+ case LOCK_SH: /* shared lock */
280
+ if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o))
281
+ i = 0;
282
+ break;
283
+ case LOCK_EX: /* exclusive lock */
284
+ if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o))
285
+ i = 0;
286
+ break;
287
+ case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
288
+ if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o))
289
+ i = 0;
290
+ break;
291
+ case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
292
+ if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
293
+ 0, LK_LEN, 0, &o))
294
+ i = 0;
295
+ break;
296
+ case LOCK_UN: /* unlock lock */
297
+ if (UnlockFileEx(fh, 0, LK_LEN, 0, &o) ||
298
+ GetLastError() == ERROR_NOT_LOCKED)
299
+ i = 0;
300
+ break;
301
+ default: /* unknown */
302
+ errno = EINVAL;
303
+ return -1;
304
+ }
305
+ if (i == -1) {
306
+ if (GetLastError() == ERROR_LOCK_VIOLATION)
307
+ errno = EWOULDBLOCK;
308
+ else
309
+ errno = EINVAL;
310
+ }
311
+ return i;
312
+ }
313
+ #endif
314
+
315
+ static void EIO_Flock(uv_work_t *req) {
316
+ store_data_t* flock_data = static_cast<store_data_t *>(req->data);
317
+
318
+ #ifdef _WIN32
319
+ int i = _win32_flock(flock_data->fd, flock_data->oper);
320
+ #else
321
+ int i = flock(flock_data->fd, flock_data->oper);
322
+ #endif
323
+
324
+ flock_data->result = i;
325
+ flock_data->error = errno;
326
+
327
+ }
328
+
329
+ static NAN_METHOD(Flock) {
330
+ if (info.Length() < 2 || !info[0]->IsInt32() || !info[1]->IsInt32()) {
331
+ return THROW_BAD_ARGS;
332
+ }
333
+
334
+ store_data_t* flock_data = new store_data_t();
335
+
336
+ flock_data->fs_op = FS_OP_FLOCK;
337
+ flock_data->fd = info[0].As<v8::Int32>()->Value();
338
+ flock_data->oper = info[1].As<v8::Int32>()->Value();
339
+
340
+ if (info[2]->IsFunction()) {
341
+ flock_data->cb = new Nan::Callback((Local<Function>) info[2].As<Function>());
342
+ uv_work_t *req = new uv_work_t;
343
+ req->data = flock_data;
344
+ uv_queue_work(uv_default_loop(), req, EIO_Flock, (uv_after_work_cb)EIO_After);
345
+ info.GetReturnValue().SetUndefined();
346
+ } else {
347
+ #ifdef _WIN32
348
+ int i = _win32_flock(flock_data->fd, flock_data->oper);
349
+ #else
350
+ int i = flock(flock_data->fd, flock_data->oper);
351
+ #endif
352
+ delete flock_data;
353
+ if (i != 0) return Nan::ThrowError(Nan::ErrnoException(errno, "Flock", ""));
354
+ info.GetReturnValue().SetUndefined();
355
+ }
356
+ }
357
+
358
+
359
+ #ifdef _LARGEFILE_SOURCE
360
+ static inline int IsInt64(double x) {
361
+ return x == static_cast<double>(static_cast<int64_t>(x));
362
+ }
363
+ #endif
364
+
365
+ #ifndef _LARGEFILE_SOURCE
366
+ #define ASSERT_OFFSET(a) \
367
+ if (!(a)->IsUndefined() && !(a)->IsNull() && !(a)->IsInt32()) { \
368
+ return Nan::ThrowTypeError("Not an integer"); \
369
+ }
370
+ #define GET_OFFSET(a) ((a)->IsInt32() ? (a).As<v8::Int32>()->Value() : -1)
371
+ #else
372
+ #define ASSERT_OFFSET(a) \
373
+ if (!(a)->IsUndefined() && !(a)->IsNull() && !((a)->IsNumber() && IsInt64((a).As<v8::Number>()->Value()))) { \
374
+ return Nan::ThrowTypeError("Not an integer"); \
375
+ }
376
+ #define GET_OFFSET(a) ((a)->IsNumber() ? static_cast<int64_t>((a).As<v8::Number>()->Value()) : -1)
377
+ #endif
378
+
379
+ // fs.seek(fd, position, whence [, callback] )
380
+
381
+ static NAN_METHOD(Seek) {
382
+ if (info.Length() < 3 ||
383
+ !info[0]->IsInt32() ||
384
+ !info[2]->IsInt32()) {
385
+ return THROW_BAD_ARGS;
386
+ }
387
+
388
+ int fd = info[0].As<v8::Int32>()->Value();
389
+ ASSERT_OFFSET(info[1]);
390
+ off_t offs = GET_OFFSET(info[1]);
391
+ int whence = info[2].As<v8::Int32>()->Value();
392
+
393
+ if ( ! info[3]->IsFunction()) {
394
+ #ifdef _WIN32
395
+ off_t offs_result = _win32_lseek(fd, offs, whence);
396
+ #else
397
+ off_t offs_result = lseek(fd, offs, whence);
398
+ #endif
399
+ if (offs_result == -1) return Nan::ThrowError(Nan::ErrnoException(errno, "Seek", ""));
400
+ info.GetReturnValue().Set(Nan::New<Number>(static_cast<double>(offs_result)));
401
+ return;
402
+ }
403
+
404
+ store_data_t* seek_data = new store_data_t();
405
+
406
+ seek_data->cb = new Nan::Callback((Local<Function>) info[3].As<Function>());
407
+ seek_data->fs_op = FS_OP_SEEK;
408
+ seek_data->fd = fd;
409
+ seek_data->offset = offs;
410
+ seek_data->oper = whence;
411
+
412
+ uv_work_t *req = new uv_work_t;
413
+ req->data = seek_data;
414
+ uv_queue_work(uv_default_loop(), req, EIO_Seek, (uv_after_work_cb)EIO_After);
415
+
416
+ info.GetReturnValue().SetUndefined();
417
+ }
418
+
419
+ // fs.fcntl(fd, cmd, [arg])
420
+
421
+ #ifndef _WIN32
422
+ static NAN_METHOD(Fcntl) {
423
+ if (info.Length() < 3 ||
424
+ !info[0]->IsInt32() ||
425
+ !info[1]->IsInt32() ||
426
+ !info[2]->IsInt32()) {
427
+ return THROW_BAD_ARGS;
428
+ }
429
+
430
+ int fd = info[0].As<v8::Int32>()->Value();
431
+ int cmd = info[1].As<v8::Int32>()->Value();
432
+ int arg = info[2].As<v8::Int32>()->Value();
433
+
434
+ if ( ! info[3]->IsFunction()) {
435
+ int result = fcntl(fd, cmd, arg);
436
+ if (result == -1) return Nan::ThrowError(Nan::ErrnoException(errno, "Fcntl", ""));
437
+ info.GetReturnValue().Set(Nan::New<Number>(result));
438
+ return;
439
+ }
440
+
441
+ store_data_t* data = new store_data_t();
442
+
443
+ data->cb = new Nan::Callback((Local<Function>) info[3].As<Function>());
444
+ data->fs_op = FS_OP_FCNTL;
445
+ data->fd = fd;
446
+ data->oper = cmd;
447
+ data->arg = arg;
448
+
449
+ uv_work_t *req = new uv_work_t;
450
+ req->data = data;
451
+ uv_queue_work(uv_default_loop(), req, EIO_Fcntl, (uv_after_work_cb)EIO_After);
452
+
453
+ info.GetReturnValue().SetUndefined();
454
+ }
455
+ #endif
456
+
457
+ // Wrapper for statvfs(2).
458
+ // fs.statVFS( path, [callback] )
459
+
460
+ static NAN_METHOD(StatVFS) {
461
+ if (info.Length() < 1 ||
462
+ !info[0]->IsString() ) {
463
+ return THROW_BAD_ARGS;
464
+ }
465
+
466
+ Nan::Utf8String path(info[0]);
467
+
468
+ // Synchronous call needs much less work
469
+ if (!info[1]->IsFunction()) {
470
+ #ifndef _WIN32
471
+ struct statvfs buf;
472
+ int ret = statvfs(*path, &buf);
473
+ if (ret != 0) return Nan::ThrowError(Nan::ErrnoException(errno, "statvfs", "", *path));
474
+ Local<Object> result = Nan::New<Object>();
475
+ Nan::Set(result, Nan::New<String>("f_namemax").ToLocalChecked(), Nan::New<Integer>(static_cast<uint32_t>(buf.f_namemax)));
476
+ Nan::Set(result, Nan::New<String>("f_bsize").ToLocalChecked(), Nan::New<Integer>(static_cast<uint32_t>(buf.f_bsize)));
477
+ Nan::Set(result, Nan::New<String>("f_frsize").ToLocalChecked(), Nan::New<Integer>(static_cast<uint32_t>(buf.f_frsize)));
478
+
479
+ Nan::Set(result, Nan::New<String>("f_blocks").ToLocalChecked(), Nan::New<Number>(buf.f_blocks));
480
+ Nan::Set(result, Nan::New<String>("f_bavail").ToLocalChecked(), Nan::New<Number>(buf.f_bavail));
481
+ Nan::Set(result, Nan::New<String>("f_bfree").ToLocalChecked(), Nan::New<Number>(buf.f_bfree));
482
+
483
+ Nan::Set(result, Nan::New<String>("f_files").ToLocalChecked(), Nan::New<Number>(buf.f_files));
484
+ Nan::Set(result, Nan::New<String>("f_favail").ToLocalChecked(), Nan::New<Number>(buf.f_favail));
485
+ Nan::Set(result, Nan::New<String>("f_ffree").ToLocalChecked(), Nan::New<Number>(buf.f_ffree));
486
+ info.GetReturnValue().Set(result);
487
+ #else
488
+ info.GetReturnValue().SetUndefined();
489
+ #endif
490
+ return;
491
+ }
492
+
493
+ store_data_t* statvfs_data = new store_data_t();
494
+
495
+ statvfs_data->cb = new Nan::Callback((Local<Function>) info[1].As<Function>());
496
+ statvfs_data->fs_op = FS_OP_STATVFS;
497
+ statvfs_data->path = strdup(*path);
498
+
499
+ uv_work_t *req = new uv_work_t;
500
+ req->data = statvfs_data;
501
+ uv_queue_work(uv_default_loop(), req, EIO_StatVFS,(uv_after_work_cb)EIO_After);
502
+
503
+ info.GetReturnValue().SetUndefined();
504
+ }
505
+
506
+ extern "C"
507
+ NAN_MODULE_INIT(init)
508
+ {
509
+ Nan::HandleScope scope;
510
+
511
+ #ifdef _WIN32
512
+ _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);
513
+ #endif
514
+
515
+ v8::Local<v8::Object> constants = Nan::New<v8::Object>();
516
+
517
+ #ifdef SEEK_SET
518
+ NODE_DEFINE_CONSTANT(constants, SEEK_SET);
519
+ #endif
520
+
521
+ #ifdef SEEK_CUR
522
+ NODE_DEFINE_CONSTANT(constants, SEEK_CUR);
523
+ #endif
524
+
525
+ #ifdef SEEK_END
526
+ NODE_DEFINE_CONSTANT(constants, SEEK_END);
527
+ #endif
528
+
529
+ #ifdef LOCK_SH
530
+ NODE_DEFINE_CONSTANT(constants, LOCK_SH);
531
+ #endif
532
+
533
+ #ifdef LOCK_EX
534
+ NODE_DEFINE_CONSTANT(constants, LOCK_EX);
535
+ #endif
536
+
537
+ #ifdef LOCK_NB
538
+ NODE_DEFINE_CONSTANT(constants, LOCK_NB);
539
+ #endif
540
+
541
+ #ifdef LOCK_UN
542
+ NODE_DEFINE_CONSTANT(constants, LOCK_UN);
543
+ #endif
544
+
545
+ #ifdef F_GETFD
546
+ NODE_DEFINE_CONSTANT(constants, F_GETFD);
547
+ #endif
548
+
549
+ #ifdef F_SETFD
550
+ NODE_DEFINE_CONSTANT(constants, F_SETFD);
551
+ #endif
552
+
553
+ #ifdef FD_CLOEXEC
554
+ NODE_DEFINE_CONSTANT(constants, FD_CLOEXEC);
555
+ #endif
556
+
557
+ #ifdef F_RDLCK
558
+ NODE_DEFINE_CONSTANT(constants, F_RDLCK);
559
+ #endif
560
+
561
+ #ifdef F_WRLCK
562
+ NODE_DEFINE_CONSTANT(constants, F_WRLCK);
563
+ #endif
564
+
565
+ #ifdef F_UNLCK
566
+ NODE_DEFINE_CONSTANT(constants, F_UNLCK);
567
+ #endif
568
+
569
+ #ifdef F_SETLK
570
+ NODE_DEFINE_CONSTANT(constants, F_SETLK);
571
+ #endif
572
+
573
+ #ifdef F_GETLK
574
+ NODE_DEFINE_CONSTANT(constants, F_GETLK);
575
+ #endif
576
+
577
+ #ifdef F_SETLKW
578
+ NODE_DEFINE_CONSTANT(constants, F_SETLKW);
579
+ #endif
580
+
581
+ Nan::Set(target, Nan::New("constants").ToLocalChecked(), constants);
582
+
583
+ Export(target, "seek", Seek);
584
+ #ifndef _WIN32
585
+ Export(target, "fcntl", Fcntl);
586
+ #endif
587
+ Export(target, "flock", Flock);
588
+ Export(target, "statVFS", StatVFS);
589
+
590
+ }
591
+
592
+ #if NODE_MODULE_VERSION > 1
593
+ NODE_MODULE_INIT() {
594
+ init(exports);
595
+ }
596
+ #endif
package/index.cjs ADDED
@@ -0,0 +1,4 @@
1
+ /* global module, process, __filename */
2
+ const { createRequire } = process.getBuiltinModule('node:module');
3
+
4
+ module.exports = createRequire(__filename)('./build/Release/fs_ext.node');
package/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export const constants: { readonly LOCK_SH: number; readonly LOCK_EX: number; readonly LOCK_NB: number };
2
+ export function flock(descriptor: number, flags: number): void;
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "thesidedoor-flock",
3
+ "version": "0.2.0",
4
+ "description": "Native operating-system file locking for Sidedoor file-backed state",
5
+ "author": "Andres Romero <me@afromero.co> (https://afromero.co)",
6
+ "homepage": "https://github.com/affromero/sidedoor#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/affromero/sidedoor/issues"
9
+ },
10
+ "keywords": [
11
+ "file-locking",
12
+ "flock",
13
+ "native-addon",
14
+ "self-hosted",
15
+ "nodejs"
16
+ ],
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/affromero/sidedoor.git",
21
+ "directory": "packages/flock"
22
+ },
23
+ "main": "index.cjs",
24
+ "types": "index.d.ts",
25
+ "engines": {
26
+ "node": ">=22"
27
+ },
28
+ "files": [
29
+ "fs-ext.cc",
30
+ "binding.gyp",
31
+ "index.cjs",
32
+ "index.d.ts",
33
+ "LICENSE",
34
+ "README.md"
35
+ ],
36
+ "scripts": {
37
+ "install": "node-gyp rebuild"
38
+ },
39
+ "dependencies": {
40
+ "nan": "2.28.0"
41
+ }
42
+ }