@@ -102,6 +102,9 @@ static ERL_NIF_TERM read_file_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM a
102
102
static ERL_NIF_TERM open_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []);
103
103
static ERL_NIF_TERM close_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []);
104
104
105
+ static ERL_NIF_TERM copy_file_available_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []);
106
+ static ERL_NIF_TERM copy_file_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []);
107
+
105
108
static ERL_NIF_TERM file_desc_to_ref_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []);
106
109
107
110
/* Internal ops */
@@ -185,6 +188,8 @@ static ErlNifFunc nif_funcs[] = {
185
188
{"allocate_nif" , 3 , allocate_nif , ERL_NIF_DIRTY_JOB_IO_BOUND },
186
189
{"advise_nif" , 4 , advise_nif , ERL_NIF_DIRTY_JOB_IO_BOUND },
187
190
{"read_handle_info_nif" , 1 , read_handle_info_nif , ERL_NIF_DIRTY_JOB_IO_BOUND },
191
+ {"copy_file_available_nif" , 0 , copy_file_available_nif , ERL_NIF_DIRTY_JOB_IO_BOUND },
192
+ {"copy_file_nif" , 3 , copy_file_nif , ERL_NIF_DIRTY_JOB_IO_BOUND },
188
193
189
194
/* Filesystem ops */
190
195
{"make_hard_link_nif" , 2 , make_hard_link_nif , ERL_NIF_DIRTY_JOB_IO_BOUND },
@@ -1399,3 +1404,76 @@ static ERL_NIF_TERM altname_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM arg
1399
1404
1400
1405
return enif_make_tuple2 (env , am_ok , result );
1401
1406
}
1407
+
1408
+ static ERL_NIF_TERM copy_file_available_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []) {
1409
+ off64_t ret ;
1410
+
1411
+ ret = syscall (SYS_copy_file_range , -1 , NULL , -1 , NULL , 0 , 0 );
1412
+
1413
+ if (ret == -1 && errno == ENOSYS ) {
1414
+ return enif_make_atom (env , "false" );
1415
+ } else {
1416
+ return enif_make_atom (env , "true" );
1417
+ }
1418
+ }
1419
+
1420
+ static ERL_NIF_TERM copy_file_nif (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv []) {
1421
+ posix_errno_t posix_errno , ignored ;
1422
+ efile_data_t * d_in , * d_out ;
1423
+ off64_t ret = 0 , len ;
1424
+ efile_fileinfo_t info = {0 };
1425
+ efile_path_t file_path_in , file_path_out ;
1426
+ char atom_name [256 ];
1427
+
1428
+ ASSERT (argc == 2 );
1429
+
1430
+ if ((posix_errno = efile_marshal_path (env , argv [0 ], & file_path_in ))) {
1431
+ return posix_error_to_tuple (env , posix_errno );
1432
+ }
1433
+
1434
+ if ((posix_errno = efile_marshal_path (env , argv [1 ], & file_path_out ))) {
1435
+ return posix_error_to_tuple (env , posix_errno );
1436
+ }
1437
+
1438
+ /* We need to open Source file in order to get file size*/
1439
+ if (posix_errno = efile_open (& file_path_in , EFILE_MODE_READ , efile_resource_type , & d_in )) {
1440
+ return posix_error_to_tuple (env , posix_errno );
1441
+ }
1442
+
1443
+ if ((posix_errno = efile_read_handle_info (d_in , & info ))) {
1444
+ /* In error case we should close Source file */
1445
+ erts_atomic32_set_acqb (& d_in -> state , EFILE_STATE_CLOSED );
1446
+ efile_close (d_in , & ignored );
1447
+ return posix_error_to_tuple (env , posix_errno );
1448
+ }
1449
+
1450
+ len = (off64_t )info .size ;
1451
+
1452
+ if (len < 0 ) {
1453
+ return enif_make_badarg (env );
1454
+ }
1455
+
1456
+ if ((posix_errno = efile_open (& file_path_out , EFILE_MODE_WRITE , efile_resource_type , & d_out ))) {
1457
+ erts_atomic32_set_acqb (& d_in -> state , EFILE_STATE_CLOSED );
1458
+ efile_close (d_in , & ignored );
1459
+ return posix_error_to_tuple (env , posix_errno );
1460
+ }
1461
+
1462
+ /* Copy file contents using SYS_copy_file_range syscall */
1463
+ if ((posix_errno = efile_copy_file_range (d_in , d_out , len , & ret ))) {
1464
+ erts_atomic32_set_acqb (& d_in -> state , EFILE_STATE_CLOSED );
1465
+ efile_close (d_in , & ignored );
1466
+ erts_atomic32_set_acqb (& d_out -> state , EFILE_STATE_CLOSED );
1467
+ efile_close (d_out , & ignored );
1468
+ return posix_error_to_tuple (env , posix_errno );
1469
+ }
1470
+
1471
+ /* Close file descriptors
1472
+ * Closing without moving the file into CLOSED state will crash the debug emulator.*/
1473
+ erts_atomic32_set_acqb (& d_in -> state , EFILE_STATE_CLOSED );
1474
+ efile_close (d_in , & ignored );
1475
+ erts_atomic32_set_acqb (& d_out -> state , EFILE_STATE_CLOSED );
1476
+ efile_close (d_out , & ignored );
1477
+
1478
+ return enif_make_tuple2 (env , enif_make_atom (env , "ok" ), enif_make_uint (env , (unsigned int )ret ));
1479
+ }
0 commit comments