[macruby-changes] [1892] MacRuby/branches/experimental/io.c

source_changes at macosforge.org source_changes at macosforge.org
Fri Jun 19 16:50:20 PDT 2009


Revision: 1892
          http://trac.macosforge.org/projects/ruby/changeset/1892
Author:   lsansonetti at apple.com
Date:     2009-06-19 16:50:18 -0700 (Fri, 19 Jun 2009)
Log Message:
-----------
fixed IO.copy_streams to actually work (it was severily broken), added a fast path that uses copyfile(2) if both arguments are strings

Modified Paths:
--------------
    MacRuby/branches/experimental/io.c

Modified: MacRuby/branches/experimental/io.c
===================================================================
--- MacRuby/branches/experimental/io.c	2009-06-19 23:04:40 UTC (rev 1891)
+++ MacRuby/branches/experimental/io.c	2009-06-19 23:50:18 UTC (rev 1892)
@@ -20,6 +20,7 @@
 #include <paths.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <copyfile.h>
 
 #include <sys/select.h>
 #include <sys/ioctl.h>
@@ -3625,21 +3626,69 @@
  *
  */
 static VALUE
-rb_io_s_copy_stream(VALUE id, SEL sel, int argc, VALUE *argv)
+rb_io_s_copy_stream(VALUE rcv, SEL sel, int argc, VALUE *argv)
 {
-	VALUE src, dst, len, offset;
-	rb_scan_args(argc, argv, "22", &src, &dst, &len, &offset);
-	VALUE old_offset = rb_io_tell(src, 0); // save the old offset
-	if(!NIL_P(offset)) {
-		// seek if necessary
-		rb_io_seek(src, 0, offset);
+    VALUE src, dst, len, offset;
+    rb_scan_args(argc, argv, "22", &src, &dst, &len, &offset);
+
+    bool src_is_path = false, dst_is_path = false;
+
+    VALUE old_src_offset = Qnil;
+    if (TYPE(src) != T_FILE) {
+	FilePathValue(src);
+	src_is_path = true;
+    }
+    else {
+	old_src_offset = rb_io_tell(src, 0); // save the old offset
+	if (!NIL_P(offset)) {
+	    // seek if necessary
+	    rb_io_seek(src, 0, offset);
 	}
-	VALUE data_read = (NIL_P(len) ? io_read(src, 0, 0, NULL) : io_read(src, 0, 1, &len));
-	VALUE copied = io_write(dst, 0, data_read);
-	if(!NIL_P(offset)) {
-		rb_io_seek(src, 0, old_offset); // restore the old offset
+    }
+
+    if (TYPE(dst) != T_FILE) {
+	FilePathValue(dst);
+	dst_is_path = true;
+    }
+
+    if (src_is_path && dst_is_path) {
+	// Fast path!
+	copyfile_state_t s = copyfile_state_alloc();
+	if (copyfile(RSTRING_PTR(src), RSTRING_PTR(dst), s, COPYFILE_ALL)
+		!= 0) {
+	    copyfile_state_free(s);
+	    rb_sys_fail("copyfile() failed");
 	}
-	return copied;
+	int src_fd = -2; 
+	assert(copyfile_state_get(s, COPYFILE_STATE_SRC_FD, &src_fd) == 0);
+	struct stat st;
+	if (fstat(src_fd, &st) != 0) {
+	    rb_sys_fail("fstat() failed");
+	}
+	copyfile_state_free(s);
+	return LONG2NUM(st.st_size);
+    }
+    else {
+	if (src_is_path) {
+	    src = rb_f_open(rcv, 0, 1, &src);
+	}
+	if (dst_is_path) {
+	    VALUE args[2];
+	    args[0] = dst;
+	    args[1] = rb_str_new2("w");
+	    dst = rb_f_open(rcv, 0, 2, args);
+	}
+    }
+
+    VALUE data_read = NIL_P(len)
+	? io_read(src, 0, 0, NULL) : io_read(src, 0, 1, &len);
+
+    VALUE copied = io_write(dst, 0, data_read);
+
+    if (!NIL_P(old_src_offset)) {
+	rb_io_seek(src, 0, old_src_offset); // restore the old offset
+    }
+    return copied;
 }
 
 /*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090619/c032c03b/attachment.html>


More information about the macruby-changes mailing list