@@ -50,14 +50,22 @@ using namespace v8;
50
50
51
51
class FSReqWrap: public ReqWrap<uv_fs_t> {
52
52
public:
53
+ void * operator new (size_t size, char * storage) { return storage; }
54
+
53
55
FSReqWrap (const char * syscall )
54
- : syscall_ (syscall ) {
56
+ : syscall_ (syscall ),
57
+ dest_len_ (0 ) {
55
58
}
56
59
57
- const char * syscall () { return syscall_; }
60
+ inline const char * syscall () const { return syscall_; }
61
+ inline const char * dest () const { return dest_; }
62
+ inline unsigned int dest_len () const { return dest_len_; }
63
+ inline void dest_len (unsigned int dest_len) { dest_len_ = dest_len; }
58
64
59
65
private:
60
66
const char * syscall_;
67
+ unsigned int dest_len_;
68
+ char dest_[1 ];
61
69
};
62
70
63
71
@@ -102,6 +110,14 @@ static void After(uv_fs_t *req) {
102
110
argv[0 ] = UVException (req->errorno ,
103
111
NULL ,
104
112
req_wrap->syscall ());
113
+ } else if ((req->errorno == UV_EEXIST ||
114
+ req->errorno == UV_ENOTEMPTY ||
115
+ req->errorno == UV_EPERM) &&
116
+ req_wrap->dest_len () > 0 ) {
117
+ argv[0 ] = UVException (req->errorno ,
118
+ NULL ,
119
+ req_wrap->syscall (),
120
+ req_wrap->dest ());
105
121
} else {
106
122
argv[0 ] = UVException (req->errorno ,
107
123
NULL ,
@@ -212,10 +228,22 @@ struct fs_req_wrap {
212
228
};
213
229
214
230
215
- #define ASYNC_CALL (func, callback, ...) \
216
- FSReqWrap* req_wrap = new FSReqWrap(#func); \
217
- int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
218
- __VA_ARGS__, After); \
231
+ #define ASYNC_DEST_CALL (func, callback, dest_path, ...) \
232
+ FSReqWrap* req_wrap; \
233
+ char * dest_str = (dest_path); \
234
+ int dest_len = dest_str == NULL ? 0 : strlen(dest_str); \
235
+ char * storage = new char [sizeof (*req_wrap) + dest_len]; \
236
+ req_wrap = new (storage) FSReqWrap(#func); \
237
+ req_wrap->dest_len (dest_len); \
238
+ if (dest_str != NULL ) { \
239
+ memcpy (const_cast <char *>(req_wrap->dest ()), \
240
+ dest_str, \
241
+ dest_len + 1 ); \
242
+ } \
243
+ int r = uv_fs_##func(uv_default_loop(), \
244
+ &req_wrap->req_, \
245
+ __VA_ARGS__, \
246
+ After); \
219
247
req_wrap->object_->Set (oncomplete_sym, callback); \
220
248
req_wrap->Dispatched (); \
221
249
if (r < 0 ) { \
@@ -227,13 +255,29 @@ struct fs_req_wrap {
227
255
} \
228
256
return scope.Close(req_wrap->object_);
229
257
230
- #define SYNC_CALL (func, path, ...) \
258
+ #define ASYNC_CALL (func, callback, ...) \
259
+ ASYNC_DEST_CALL (func, callback, NULL , __VA_ARGS__) \
260
+
261
+ #define SYNC_DEST_CALL (func, path, dest, ...) \
231
262
fs_req_wrap req_wrap; \
232
- int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL ); \
263
+ int result = uv_fs_##func(uv_default_loop(), \
264
+ &req_wrap.req, \
265
+ __VA_ARGS__, \
266
+ NULL ); \
233
267
if (result < 0 ) { \
234
268
int code = uv_last_error (uv_default_loop ()).code ; \
235
- return ThrowException (UVException (code, #func, " " , path)); \
236
- }
269
+ if (dest != NULL && \
270
+ (code == UV_EEXIST || \
271
+ code == UV_ENOTEMPTY || \
272
+ code == UV_EPERM)) { \
273
+ return ThrowException (UVException (code, #func, " " , dest)); \
274
+ } else { \
275
+ return ThrowException (UVException (code, #func, " " , path)); \
276
+ } \
277
+ } \
278
+
279
+ #define SYNC_CALL (func, path, ...) \
280
+ SYNC_DEST_CALL (func, path, NULL , __VA_ARGS__) \
237
281
238
282
#define SYNC_REQ req_wrap.req
239
283
@@ -431,9 +475,9 @@ static Handle<Value> Symlink(const Arguments& args) {
431
475
}
432
476
433
477
if (args[3 ]->IsFunction ()) {
434
- ASYNC_CALL (symlink , args[3 ], *dest, *path, flags)
478
+ ASYNC_DEST_CALL (symlink , args[3 ], *dest , *dest, *path, flags)
435
479
} else {
436
- SYNC_CALL (symlink , *path, *dest, *path, flags)
480
+ SYNC_DEST_CALL (symlink , *path, *dest , *dest, *path, flags)
437
481
return Undefined ();
438
482
}
439
483
}
@@ -451,9 +495,9 @@ static Handle<Value> Link(const Arguments& args) {
451
495
String::Utf8Value new_path (args[1 ]);
452
496
453
497
if (args[2 ]->IsFunction ()) {
454
- ASYNC_CALL (link , args[2 ], *orig_path, *new_path)
498
+ ASYNC_DEST_CALL (link , args[2 ], *new_path , *orig_path, *new_path)
455
499
} else {
456
- SYNC_CALL (link , *orig_path, *orig_path, *new_path)
500
+ SYNC_DEST_CALL (link , *orig_path, *new_path , *orig_path, *new_path)
457
501
return Undefined ();
458
502
}
459
503
}
@@ -482,14 +526,14 @@ static Handle<Value> Rename(const Arguments& args) {
482
526
if (len < 2 ) return TYPE_ERROR (" new path required" );
483
527
if (!args[0 ]->IsString ()) return TYPE_ERROR (" old path must be a string" );
484
528
if (!args[1 ]->IsString ()) return TYPE_ERROR (" new path must be a string" );
485
-
529
+
486
530
String::Utf8Value old_path (args[0 ]);
487
531
String::Utf8Value new_path (args[1 ]);
488
532
489
533
if (args[2 ]->IsFunction ()) {
490
- ASYNC_CALL (rename , args[2 ], *old_path, *new_path)
534
+ ASYNC_DEST_CALL (rename , args[2 ], *new_path , *old_path, *new_path)
491
535
} else {
492
- SYNC_CALL (rename , *old_path, *old_path, *new_path)
536
+ SYNC_DEST_CALL (rename , *old_path, *new_path , *old_path, *new_path)
493
537
return Undefined ();
494
538
}
495
539
}
0 commit comments