@@ -50,14 +50,22 @@ using namespace v8;
5050
5151class FSReqWrap: public ReqWrap<uv_fs_t> {
5252 public:
53+ void * operator new (size_t size, char * storage) { return storage; }
54+
5355 FSReqWrap (const char * syscall)
54- : syscall_ (syscall) {
56+ : syscall_ (syscall),
57+ dest_len_ (0 ) {
5558 }
5659
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; }
5864
5965 private:
6066 const char * syscall_;
67+ unsigned int dest_len_;
68+ char dest_[1 ];
6169};
6270
6371
@@ -102,6 +110,14 @@ static void After(uv_fs_t *req) {
102110 argv[0 ] = UVException (req->errorno ,
103111 NULL ,
104112 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 ());
105121 } else {
106122 argv[0 ] = UVException (req->errorno ,
107123 NULL ,
@@ -212,10 +228,22 @@ struct fs_req_wrap {
212228};
213229
214230
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); \
219247 req_wrap->object_->Set (oncomplete_sym, callback); \
220248 req_wrap->Dispatched (); \
221249 if (r < 0 ) { \
@@ -227,13 +255,29 @@ struct fs_req_wrap {
227255 } \
228256 return scope.Close(req_wrap->object_);
229257
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, ...) \
231262 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 ); \
233267 if (result < 0 ) { \
234268 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__) \
237281
238282#define SYNC_REQ req_wrap.req
239283
@@ -431,9 +475,9 @@ static Handle<Value> Symlink(const Arguments& args) {
431475 }
432476
433477 if (args[3 ]->IsFunction ()) {
434- ASYNC_CALL (symlink, args[3 ], *dest, *path, flags)
478+ ASYNC_DEST_CALL (symlink, args[3 ], *dest , *dest, *path, flags)
435479 } else {
436- SYNC_CALL (symlink, *path, *dest, *path, flags)
480+ SYNC_DEST_CALL (symlink, *path, *dest , *dest, *path, flags)
437481 return Undefined ();
438482 }
439483}
@@ -451,9 +495,9 @@ static Handle<Value> Link(const Arguments& args) {
451495 String::Utf8Value new_path (args[1 ]);
452496
453497 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)
455499 } else {
456- SYNC_CALL (link, *orig_path, *orig_path, *new_path)
500+ SYNC_DEST_CALL (link, *orig_path, *new_path , *orig_path, *new_path)
457501 return Undefined ();
458502 }
459503}
@@ -482,14 +526,14 @@ static Handle<Value> Rename(const Arguments& args) {
482526 if (len < 2 ) return TYPE_ERROR (" new path required" );
483527 if (!args[0 ]->IsString ()) return TYPE_ERROR (" old path must be a string" );
484528 if (!args[1 ]->IsString ()) return TYPE_ERROR (" new path must be a string" );
485-
529+
486530 String::Utf8Value old_path (args[0 ]);
487531 String::Utf8Value new_path (args[1 ]);
488532
489533 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)
491535 } else {
492- SYNC_CALL (rename, *old_path, *old_path, *new_path)
536+ SYNC_DEST_CALL (rename, *old_path, *new_path , *old_path, *new_path)
493537 return Undefined ();
494538 }
495539}
0 commit comments