static ERL_NIF_TERM open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_data_t *d; ErlNifPid controlling_process; enum efile_modes_t modes; ERL_NIF_TERM result; efile_path_t path; if(argc != 2 || !enif_is_list(env, argv[1])) { return enif_make_badarg(env); } modes = efile_translate_modelist(env, argv[1]); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_open(&path, modes, efile_resource_type, &d))) { return posix_error_to_tuple(env, posix_errno); } result = enif_make_resource(env, d); enif_release_resource(d); enif_self(env, &controlling_process); if(enif_monitor_process(env, d, &controlling_process, &d->monitor)) { return posix_error_to_tuple(env, EINVAL); } return enif_make_tuple2(env, am_ok, result); }
static ERL_NIF_TERM read_info_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_fileinfo_t info = {0}; efile_path_t path; int follow_links; if(argc != 2 || !enif_get_int(env, argv[1], &follow_links)) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_read_info(&path, follow_links, &info))) { return posix_error_to_tuple(env, posix_errno); } /* #file_info as declared in file.hrl */ return enif_make_tuple(env, 14, am_file_info, enif_make_uint64(env, info.size), efile_filetype_to_atom(info.type), efile_access_to_atom(info.access), enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.a_time)), enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.m_time)), enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.c_time)), enif_make_uint(env, info.mode), enif_make_uint(env, info.links), enif_make_uint(env, info.major_device), enif_make_uint(env, info.minor_device), enif_make_uint(env, info.inode), enif_make_uint(env, info.uid), enif_make_uint(env, info.gid) ); }
static ERL_NIF_TERM read_file_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno, ignored; efile_fileinfo_t info = {0}; efile_path_t path; efile_data_t *d; ErlNifBinary result; ASSERT(argc == 1); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_read_info(&path, 1, &info))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_open(&path, EFILE_MODE_READ, efile_resource_type, &d))) { return posix_error_to_tuple(env, posix_errno); } posix_errno = read_file(d, info.size, &result); erts_atomic32_set_acqb(&d->state, EFILE_STATE_CLOSED); efile_close(d, &ignored); if(posix_errno) { return posix_error_to_tuple(env, posix_errno); } return enif_make_tuple2(env, am_ok, enif_make_binary(env, &result)); }
static ERL_NIF_TERM read_file_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_fileinfo_t info = {0}; efile_path_t path; efile_data_t *d; ErlNifBinary result; if(argc != 1) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_read_info(&path, 1, &info))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_open(&path, EFILE_MODE_READ, efile_resource_type, &d))) { return posix_error_to_tuple(env, posix_errno); } posix_errno = read_file(d, info.size, &result); enif_release_resource(d); if(posix_errno) { return posix_error_to_tuple(env, posix_errno); } return enif_make_tuple2(env, am_ok, enif_make_binary(env, &result)); }
static ERL_NIF_TERM make_soft_link_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t existing_path, new_path; ASSERT(argc == 2); if((posix_errno = efile_marshal_path(env, argv[0], &existing_path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_marshal_path(env, argv[1], &new_path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_make_soft_link(&existing_path, &new_path))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM rename_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t existing_path, new_path; if(argc != 2) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &existing_path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_marshal_path(env, argv[1], &new_path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_rename(&existing_path, &new_path))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM set_cwd_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t path; ASSERT(argc == 1); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_set_cwd(&path))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_data_t *d; ErlNifPid controlling_process; enum efile_modes_t modes; ERL_NIF_TERM result; efile_path_t path; ASSERT(argc == 2); if(!enif_is_list(env, argv[1])) { return enif_make_badarg(env); } modes = efile_translate_modelist(env, argv[1]); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_open(&path, modes, efile_resource_type, &d))) { return posix_error_to_tuple(env, posix_errno); } enif_self(env, &controlling_process); if(enif_monitor_process(env, d, &controlling_process, &d->monitor)) { /* We need to close the file manually as we haven't registered a * destructor. */ posix_errno_t ignored; erts_atomic32_set_acqb(&d->state, EFILE_STATE_CLOSED); efile_close(d, &ignored); return posix_error_to_tuple(env, EINVAL); } /* Note that we do not call enif_release_resource at this point. While it's * normally safe to leave resource management to the GC, efile_close is a * blocking operation which must not be done in the GC callback, and we * can't defer it as the resource is gone as soon as it returns. * * We instead keep the resource alive until efile_close is called, after * which it's safe to leave things to the GC. If the controlling process * were to die before the user had a chance to close their file, the above * monitor will tell the erts_prim_file process to close it for them. */ result = enif_make_resource(env, d); return enif_make_tuple2(env, am_ok, result); }
static ERL_NIF_TERM read_link_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t path; ERL_NIF_TERM result; ASSERT(argc == 1); if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_read_link(env, &path, &result))) { return posix_error_to_tuple(env, posix_errno); } return enif_make_tuple2(env, am_ok, result); }
static ERL_NIF_TERM del_dir_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t path; if(argc != 1) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_del_dir(&path))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM list_dir_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t path; ERL_NIF_TERM result; if(argc != 1) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_list_dir(env, &path, &result))) { return posix_error_to_tuple(env, posix_errno); } return enif_make_tuple2(env, am_ok, result); }
static ERL_NIF_TERM set_permissions_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t path; Uint32 permissions; if(argc != 2 || !enif_get_uint(env, argv[1], &permissions)) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_set_permissions(&path, permissions))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM set_owner_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; efile_path_t path; Sint32 uid, gid; if(argc != 3 || !enif_get_int(env, argv[1], &uid) || !enif_get_int(env, argv[2], &gid)) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_set_owner(&path, uid, gid))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM set_time_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; Sint64 accessed, modified, created; efile_path_t path; if(argc != 4 || !enif_get_int64(env, argv[1], &accessed) || !enif_get_int64(env, argv[2], &modified) || !enif_get_int64(env, argv[3], &created)) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_set_time(&path, accessed, modified, created))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }