diff --git a/docs/docs/standard-lib/io.md b/docs/docs/standard-lib/io.md index f3a81781..1dad57b7 100644 --- a/docs/docs/standard-lib/io.md +++ b/docs/docs/standard-lib/io.md @@ -41,3 +41,13 @@ Prints a given list of values to stdout with an appended newline character. IO.println("Dictu!"); // Dictu! ``` + +### IO.copyFile(String: src, String: dst) -> Result + +Copies the contents from the source file to the destination file. + +Returns a Result type and on success will unwrap to nil. + +```cs +IO.copyFile(src, dst); +``` diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index 05238970..9306457a 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -280,13 +280,3 @@ Note: This is not available on Windows systems. System.mkdirTemp().unwrap(); // "VOO16s" System.mkdirTemp("test_XXXXXX").unwrap(); // "test_0bL2qS" ``` - -### System.copyFile(String: src, String: dst) -> Result - -Copies the contents from the source file to the destination file. - -Returns a Result type and on success will unwrap to nil. - -```cs -System.copyFile(src, dst); -``` diff --git a/examples/copyFile.du b/examples/copyFile.du index 9f8ec5db..76c47da1 100644 --- a/examples/copyFile.du +++ b/examples/copyFile.du @@ -1,3 +1,4 @@ +import IO; import Path; import System; @@ -36,7 +37,7 @@ def cleanup(tmpDir) { print(file.read()); } - System.copyFile(Path.join(tmpDir, srcFile), Path.join(tmpDir, dstFile)).match( + IO.copyFile(Path.join(tmpDir, srcFile), Path.join(tmpDir, dstFile)).match( def(result) => result, def(error) => { print(error); diff --git a/src/optionals/io.c b/src/optionals/io.c index 5ef8ad48..267f5f6c 100644 --- a/src/optionals/io.c +++ b/src/optionals/io.c @@ -1,3 +1,11 @@ +#include +#include +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#else +#include +#endif + #include "io.h" @@ -28,6 +36,52 @@ static Value printlnIO(DictuVM *vm, int argCount, Value *args) { return NIL_VAL; } +//#ifndef _WIN32 +static Value copyFileIO(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "copyFile() takes 2 arguments (%d given)", argCount); + return EMPTY_VAL; + } + + if (!IS_STRING(args[0])) { + runtimeError(vm, "src argument needs to be a string"); + return EMPTY_VAL; + } + + if (!IS_STRING(args[1])) { + runtimeError(vm, "dst argument needs to be a string"); + return EMPTY_VAL; + } + + char *src = AS_STRING(args[0])->chars; + char *dst = AS_STRING(args[1])->chars; + + int in = 0; + int out = 0; + + if ((in = open(src, O_RDONLY)) == -1) { + return newResultError(vm, "failed to open src file"); + } + if ((out = creat(dst, 0660)) == -1) { + close(in); + return newResultError(vm, "failed to create/open dst file"); + } + +#if defined(__APPLE__) || defined(__FreeBSD__) + fcopyfile(in, out, 0, COPYFILE_ALL); +#else + off_t bytes = 0; + struct stat fileinfo = {0}; + fstat(in, &fileinfo); + sendfile(out, in, &bytes, fileinfo.st_size); +#endif + close(in); + close(out); + + return newResultSuccess(vm, NIL_VAL); +} +//#endif + Value createIOModule(DictuVM *vm) { ObjString *name = copyString(vm, "IO", 2); push(vm, OBJ_VAL(name)); @@ -43,6 +97,9 @@ Value createIOModule(DictuVM *vm) { */ defineNative(vm, &module->values, "print", printIO); defineNative(vm, &module->values, "println", printlnIO); +//#ifndef _WIN32 + defineNative(vm, &module->values, "copyFile", copyFileIO); +//#endif pop(vm); pop(vm); diff --git a/src/optionals/system.c b/src/optionals/system.c index f8ac6f95..da7ed6e6 100644 --- a/src/optionals/system.c +++ b/src/optionals/system.c @@ -490,43 +490,6 @@ static Value chmodNative(DictuVM *vm, int argCount, Value *args) { return newResultSuccess(vm, NIL_VAL); } -static Value copyFileNative(DictuVM *vm, int argCount, Value *args) { - if (argCount != 2) { - runtimeError(vm, "copyFile() takes 2 arguments (%d given).", argCount); - return EMPTY_VAL; - } - - if (!IS_STRING(args[0]) || !IS_STRING(args[1])) { - runtimeError(vm, "copyFile() arguments must be strings."); - return EMPTY_VAL; - } - - char *srcFile = AS_STRING(args[0])->chars; - char *dstFile = AS_STRING(args[1])->chars; - - FILE *sf = fopen(srcFile, "r"); - if (sf == NULL) { - return newResultError(vm, "cannot open src file"); - } - - FILE *df = fopen(dstFile, "w"); - if (df == NULL) { - fclose(sf); - return newResultError(vm, "cannot open dst file"); - } - - int buffer = fgetc(sf); - while (buffer != EOF) { - fputc(buffer, df); - buffer = fgetc(sf); - } - - fclose(sf); - fclose(df); - - return newResultSuccess(vm, NIL_VAL); -} - void initArgv(DictuVM *vm, Table *table, int argc, char **argv) { ObjList *list = newList(vm); push(vm, OBJ_VAL(list)); @@ -627,7 +590,6 @@ Value createSystemModule(DictuVM *vm) { defineNative(vm, &module->values, "sleep", sleepNative); defineNative(vm, &module->values, "exit", exitNative); defineNative(vm, &module->values, "chmod", chmodNative); - defineNative(vm, &module->values, "copyFile", copyFileNative); /** * Define System properties diff --git a/tests/io/copyFile.du b/tests/io/copyFile.du new file mode 100644 index 00000000..5b306ba6 --- /dev/null +++ b/tests/io/copyFile.du @@ -0,0 +1,34 @@ +/** + * copyFile.du + * + * Testing the IO.copyFile() method + */ +from UnitTest import UnitTest; + +import IO; +import System; + +class TestIOCopyFile < UnitTest { + const testFile1 = "tests/io/test1"; + const testFile2 = "tests/io/test2"; + + setUp() { + with(this.testFile1, "w") { + this.written = file.write("Dictu!"); + } + } + + tearDown() { + System.remove(this.testFile1); + System.remove(this.testFile2); + } + + testIOCopyFile() { + const res = IO.copyFile(this.testFile1, this.testFile2); + this.assertSuccess(res); + } +} + +//if (System.platform != "windows") { + TestIOCopyFile().run(); +//} diff --git a/tests/io/import.du b/tests/io/import.du new file mode 100644 index 00000000..5324db54 --- /dev/null +++ b/tests/io/import.du @@ -0,0 +1,7 @@ +/** + * import.du + * + * General import file for the IO module tests + */ + +import "copyFile.du"; diff --git a/tests/runTests.du b/tests/runTests.du index 75b366b3..77e3e641 100644 --- a/tests/runTests.du +++ b/tests/runTests.du @@ -35,6 +35,7 @@ import "base64/import.du"; import "sqlite/import.du"; import "process/import.du"; import "inspect/import.du"; +import "io/import.du"; import "unittest/import.du"; if (isDefined("HTTP")) {