// Sync readfile using libuv APIs as an API function. static duk_ret_t duv_loadfile(duk_context *ctx) { const char* path = duk_require_string(ctx, 0); uv_fs_t req; int fd = 0; uint64_t size; char* chunk; uv_buf_t buf; if (uv_fs_open(&loop, &req, path, O_RDONLY, 0644, NULL) < 0) goto fail; fd = req.result; if (uv_fs_fstat(&loop, &req, fd, NULL) < 0) goto fail; size = req.statbuf.st_size; chunk = duk_alloc(ctx, size); buf = uv_buf_init(chunk, size); if (uv_fs_read(&loop, &req, fd, &buf, 1, 0, NULL) < 0) goto fail; duk_push_lstring(ctx, chunk, size); duk_free(ctx, chunk); uv_fs_close(&loop, &req, fd, NULL); uv_fs_req_cleanup(&req); return 1; fail: if (fd) uv_fs_close(&loop, &req, fd, NULL); uv_fs_req_cleanup(&req); duk_error(ctx, DUK_ERR_ERROR, "%s: %s: %s", uv_err_name(req.result), uv_strerror(req.result), path); }
/* * fs.fstat */ static int fs_fstat(lua_State* L) { FSR__SETUP int fd = luaL_checkint(L, 1); FSR__SET_OPT_CB(2, on_fs_callback) uv_fs_fstat(loop, req, fd, cb); FSR__TEARDOWN }
/* Reads the file from the current position to the end into a string. */ static MVMString * slurp(MVMThreadContext *tc, MVMOSHandle *h) { MVMIOFileData *data = (MVMIOFileData *)h->body.data; uv_fs_t req; ensure_decode_stream(tc, data); /* Typically we're slurping an entire file, so just request the bytes * until the end; repeat to ensure we get 'em all. */ if (uv_fs_fstat(tc->loop, &req, data->fd, NULL) < 0) { MVM_exception_throw_adhoc(tc, "slurp from filehandle failed: %s", uv_strerror(req.result)); } /* Sometimes - usually for special files like those in /proc - the file * size comes up 0, even though the S_ISREG test succeeds. So in that case * we try a small read and switch to a "read chunks until EOF" impl. * Otherwise we just read the exact size of the file. */ if (req.statbuf.st_size == 0) { if (read_to_buffer(tc, data, 32) > 0) { while (read_to_buffer(tc, data, 4096) > 0) ; } } else { while (read_to_buffer(tc, data, req.statbuf.st_size) > 0) ; } return MVM_string_decodestream_get_all(tc, data->ds); }
int async_fs_fstat(uv_file file, uv_fs_t *const req) { async_pool_enter(NULL); uv_fs_t _req[1]; int const err = uv_fs_fstat(async_loop, req ? req : _req, file, NULL); uv_fs_req_cleanup(req ? req : _req); async_pool_leave(NULL); return err; }
void fileSize(WrenVM* vm) { uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 1)); int fd = *(int*)wrenGetSlotForeign(vm, 0); // TODO: Assert fd != -1. uv_fs_fstat(getLoop(), request, fd, fileSizeCallback); }
DLLEXPORT int32_t jl_fstat(int fd, char *statbuf) { uv_fs_t req; int ret; ret = uv_fs_fstat(uv_default_loop(), &req, fd, NULL); if (ret == 0) memcpy(statbuf, req.ptr, sizeof(struct stat)); uv_fs_req_cleanup(&req); return ret; }
/// Get the file information for a given file descriptor /// /// @param file_descriptor File descriptor of the file. /// @param[out] file_info Pointer to a FileInfo to put the information in. /// @return `true` on success, `false` for failure. bool os_get_file_info_fd(int file_descriptor, FileInfo *file_info) { uv_fs_t request; int result = uv_fs_fstat(uv_default_loop(), &request, file_descriptor, NULL); file_info->stat = request.statbuf; uv_fs_req_cleanup(&request); if (result == kLibuvSuccess) { return true; } return false; }
static int lluv_file_stat(lua_State *L){ const char *path = NULL; lluv_file_t *f = lluv_check_file(L, 1, LLUV_FLAG_OPEN); lluv_loop_t *loop = f->loop; int argc = 1; LLUV_PRE_FILE(); lua_pushvalue(L, 1); req->file_ref = luaL_ref(L, LLUV_LUA_REGISTRY); err = uv_fs_fstat(loop->handle, &req->req, f->handle, cb); LLUV_POST_FILE(); }
/* Checks if the end of file has been reached. */ static MVMint64 mvm_eof(MVMThreadContext *tc, MVMOSHandle *h) { MVMIOFileData *data = (MVMIOFileData *)h->body.data; MVMint64 seek_pos; uv_fs_t req; if (data->ds && !MVM_string_decodestream_is_empty(tc, data->ds)) return 0; if (uv_fs_fstat(tc->loop, &req, data->fd, NULL) == -1) { MVM_exception_throw_adhoc(tc, "Failed to stat file descriptor: %s", uv_strerror(req.result)); } if ((seek_pos = MVM_platform_lseek(data->fd, 0, SEEK_CUR)) == -1) MVM_exception_throw_adhoc(tc, "Failed to seek in filehandle: %d", errno); return req.statbuf.st_size == seek_pos; }
/* Reads the file from the current position to the end into a string. */ static MVMString * slurp(MVMThreadContext *tc, MVMOSHandle *h) { MVMIOFileData *data = (MVMIOFileData *)h->body.data; uv_fs_t req; ensure_decode_stream(tc, data); /* Typically we're slurping an entire file, so just request the bytes * until the end; repeat to ensure we get 'em all. */ if (uv_fs_fstat(tc->loop, &req, data->fd, NULL) < 0) { MVM_exception_throw_adhoc(tc, "slurp from filehandle failed: %s", uv_strerror(req.result)); } while (read_to_buffer(tc, data, req.statbuf.st_size) > 0) ; return MVM_string_decodestream_get_all(tc, data->ds); }
/* Checks if the end of file has been reached. */ static MVMint64 mvm_eof(MVMThreadContext *tc, MVMOSHandle *h) { MVMIOFileData *data = (MVMIOFileData *)h->body.data; MVMint64 seek_pos; uv_fs_t req; if (data->ds && !MVM_string_decodestream_is_empty(tc, data->ds)) return 0; if (uv_fs_fstat(tc->loop, &req, data->fd, NULL) == -1) { MVM_exception_throw_adhoc(tc, "Failed to stat file descriptor: %s", uv_strerror(req.result)); } if ((seek_pos = MVM_platform_lseek(data->fd, 0, SEEK_CUR)) == -1) MVM_exception_throw_adhoc(tc, "Failed to seek in filehandle: %d", errno); /* Comparison with seek_pos for some special files, like those in /proc, * which file size is 0 can be false. In that case, we fall back to check * file size to detect EOF. */ return req.statbuf.st_size == seek_pos || req.statbuf.st_size == 0; }
static int lmz_reader_init(lua_State* L) { const char* path = luaL_checkstring(L, 1); mz_uint32 flags = luaL_optint(L, 2, 0); mz_uint64 size; lmz_file_t* zip = lua_newuserdata(L, sizeof(*zip)); mz_zip_archive* archive = &(zip->archive); luaL_getmetatable(L, "miniz_reader"); lua_setmetatable(L, -2); memset(archive, 0, sizeof(*archive)); zip->loop = uv_default_loop(); zip->fd = uv_fs_open(zip->loop, &(zip->req), path, O_RDONLY, 0644, NULL); uv_fs_fstat(zip->loop, &(zip->req), zip->fd, NULL); size = zip->req.statbuf.st_size; archive->m_pRead = lmz_file_read; archive->m_pIO_opaque = zip; if (!mz_zip_reader_init(archive, size, flags)) { lua_pushnil(L); lua_pushfstring(L, "read %s fail because of %s", path, mz_zip_get_error_string(mz_zip_get_last_error(archive))); return 2; } return 1; }
void FileRequestBaton::file_opened(uv_fs_t *req) { FileRequestBaton *ptr = (FileRequestBaton *)req->data; assert(ptr->thread_id == std::this_thread::get_id()); if (req->result < 0) { // Opening failed or was canceled. There isn't much left we can do. notify_error(req); cleanup(req); } else { const uv_file fd = uv_file(req->result); // We're going to reuse this handle, so we need to cleanup first. uv_fs_req_cleanup(req); if (ptr->canceled || !ptr->request) { // Either the FileRequest object has been destructed, or the // request was canceled. uv_fs_close(req->loop, req, fd, file_closed); } else { ptr->fd = fd; uv_fs_fstat(req->loop, req, fd, file_stated); } } }
// Sync readfile using libuv APIs as an API function. static duk_ret_t duv_loadfile(duk_context *ctx) { const char* path = duk_require_string(ctx, 0); uv_fs_t req; int fd = 0; uint64_t size; char* chunk; uv_buf_t buf; duk_push_thread_stash(ctx, ctx); duk_bool_t rc = duk_get_prop_string(ctx, -1, "__duk_loop"); assert(rc); uv_loop_t *dukLoop = (uv_loop_t *)duk_get_pointer(ctx, -1); duk_pop(ctx); duk_pop(ctx); if (uv_fs_open(dukLoop, &req, path, O_RDONLY, 0644, NULL) < 0) goto fail; uv_fs_req_cleanup(&req); fd = req.result; if (uv_fs_fstat(dukLoop, &req, fd, NULL) < 0) goto fail; uv_fs_req_cleanup(&req); size = req.statbuf.st_size; chunk = (char*)duk_alloc(ctx, static_cast<duk_size_t>(size)); buf = uv_buf_init(chunk, static_cast<unsigned int>(size)); if (uv_fs_read(dukLoop, &req, fd, &buf, 1, 0, NULL) < 0) { duk_free(ctx, chunk); goto fail; } uv_fs_req_cleanup(&req); duk_push_lstring(ctx, chunk, static_cast<duk_size_t>(size)); duk_free(ctx, chunk); uv_fs_close(dukLoop, &req, fd, NULL); uv_fs_req_cleanup(&req); return 1; fail: uv_fs_req_cleanup(&req); if (fd) uv_fs_close(dukLoop, &req, fd, NULL); uv_fs_req_cleanup(&req); // TODO hacking in a fallback to look for modules in a directory called duk_modules // TODO what about windows... will this work? fd = 0; std::string path2 = "duk_modules/"; path2 += path; if (uv_fs_open(dukLoop, &req, path2.c_str(), O_RDONLY, 0644, NULL) < 0) goto fail; uv_fs_req_cleanup(&req); fd = req.result; if (uv_fs_fstat(dukLoop, &req, fd, NULL) < 0) goto fail; uv_fs_req_cleanup(&req); size = req.statbuf.st_size; chunk = (char*)duk_alloc(ctx, static_cast<duk_size_t>(size)); buf = uv_buf_init(chunk, static_cast<unsigned int>(size)); if (uv_fs_read(dukLoop, &req, fd, &buf, 1, 0, NULL) < 0) { duk_free(ctx, chunk); goto fail2; } uv_fs_req_cleanup(&req); duk_push_lstring(ctx, chunk, static_cast<duk_size_t>(size)); duk_free(ctx, chunk); uv_fs_close(dukLoop, &req, fd, NULL); uv_fs_req_cleanup(&req); return 1; fail2: uv_fs_req_cleanup(&req); if (fd) uv_fs_close(dukLoop, &req, fd, NULL); uv_fs_req_cleanup(&req); duk_error(ctx, DUK_ERR_ERROR, "%s: %s: %s", uv_err_name(req.result), uv_strerror(req.result), path2.c_str()); }
extern "C" int rust_uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { return uv_fs_fstat(loop, req, file, cb); }
static void on_fs_open(uv_fs_t* req) { http_request* request = (http_request*) req->data; int result = req->result; uv_fs_req_cleanup(req); free(req); if (result < 0) { fprintf(stderr, "Open error: %s: %s\n", uv_err_name(result), uv_strerror(result)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } uv_fs_t stat_req; int r = uv_fs_fstat(loop, &stat_req, result, NULL); if (r) { fprintf(stderr, "Stat error: %s: %s\n", uv_err_name(r), uv_strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } uint64_t response_size = stat_req.statbuf.st_size; uv_fs_req_cleanup(&stat_req); const static char* ctype = "application/octet-stream"; const char* dot = request->file_path; const char* ptr = dot; while (dot) { ptr = dot; dot = strchr(dot + 1, '.'); } khint_t k = kh_get(mime_type, mime_type, ptr); if (k != kh_end(mime_type)) { ctype = kh_value(mime_type, k); } http_response* response = calloc(1, sizeof(http_response)); if (response == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } response->response_size = response_size; response->fd = result; response->request = request; response->handle = request->handle; response->pbuf = malloc(WRITE_BUF_SIZE); if (response->pbuf == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_response(response, 1); return; } response->buf = uv_buf_init(response->pbuf, WRITE_BUF_SIZE); response->read_req.data = response; response->write_req.data = response; char bufline[1024]; int nbuf = snprintf(bufline, sizeof(bufline), "HTTP/1.1 200 OK\r\n" "Content-Length: %" PRId64 "\r\n" "Content-Type: %s\r\n" "Connection: %s\r\n" "\r\n", response_size, ctype, (request->keep_alive ? "keep-alive" : "close")); uv_buf_t buf = uv_buf_init(bufline, nbuf); #ifndef _WIN32 r = uv_try_write((uv_stream_t*) request->handle, &buf, 1); if (r == 0) { fprintf(stderr, "Write error\n"); destroy_response(response, 1); return; } #else r = uv_write(&response->write_req, (uv_stream_t*) request->handle, &buf, 1, NULL); if (r) { fprintf(stderr, "Write error: %s: %s\n", uv_err_name(r), uv_strerror(r)); destroy_response(response, 1); return; } #endif r = uv_fs_read(loop, &response->read_req, result, &response->buf, 1, -1, on_fs_read); if (r) { response_error(request->handle, 500, "Internal Server Error\n", NULL); destroy_response(response, 1); } }
/* Opens a file, returning a synchronous file handle. */ MVMObject * MVM_file_open_fh(MVMThreadContext *tc, MVMString *filename, MVMString *mode) { char * const fname = MVM_string_utf8_c8_encode_C_string(tc, filename); uv_fs_t req; uv_file fd; int flag; /* Resolve mode description to flags. */ { char * const fmode = MVM_string_utf8_encode_C_string(tc, mode); if (!resolve_open_mode(&flag, fmode)) { char *waste[] = { fname, fmode, NULL }; MVM_exception_throw_adhoc_free(tc, waste, "Invalid open mode for file %s: %s", fname, fmode); } MVM_free(fmode); } /* Try to open the file. */ if ((fd = uv_fs_open(tc->loop, &req, (const char *)fname, flag, DEFAULT_MODE, NULL)) < 0) { char *waste[] = { fname, NULL }; const char *err = uv_strerror(req.result); uv_fs_req_cleanup(&req); MVM_exception_throw_adhoc_free(tc, waste, "Failed to open file %s: %s", fname, err); } uv_fs_req_cleanup(&req); /* Check that we didn't open a directory by accident. If fstat fails, just move on: Most of the documented error cases should already have triggered when opening the file, and we can't do anything about the others; a failure also does not necessarily imply that the file descriptor cannot be used for reading/writing. */ if (uv_fs_fstat(tc->loop, &req, fd, NULL) == 0 && (req.statbuf.st_mode & S_IFMT) == S_IFDIR) { char *waste[] = { fname, NULL }; uv_fs_req_cleanup(&req); if (uv_fs_close(tc->loop, &req, fd, NULL) < 0) { const char *err = uv_strerror(req.result); uv_fs_req_cleanup(&req); MVM_exception_throw_adhoc_free(tc, waste, "Tried to open directory %s, which we failed to close: %s", fname, err); } uv_fs_req_cleanup(&req); MVM_exception_throw_adhoc_free(tc, waste, "Tried to open directory %s", fname); } uv_fs_req_cleanup(&req); /* Set up handle. */ { MVMIOFileData * const data = MVM_calloc(1, sizeof(MVMIOFileData)); MVMOSHandle * const result = (MVMOSHandle *)MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTIO); data->fd = fd; data->filename = fname; data->encoding = MVM_encoding_type_utf8; MVM_string_decode_stream_sep_default(tc, &(data->sep_spec)); result->body.ops = &op_table; result->body.data = data; return (MVMObject *)result; } }
void FileObject::getSize(gc<Fiber> fiber) { FSTask* task = new FSTask(fiber); uv_fs_fstat(task->loop(), task->request(), file_, getSizeCallback); }