UNPKG

2.47 kBJavaScriptView Raw
1'use strict';
2
3const Fs = require('fs');
4const Util = require('util');
5
6const Boom = require('@hapi/boom');
7const Bounce = require('@hapi/bounce');
8const Hoek = require('@hapi/hoek');
9
10
11const internals = {
12 methods: {
13 promised: ['open', 'close', 'fstat', 'readdir'],
14 raw: ['createReadStream']
15 }
16};
17
18
19exports.File = function (path) {
20
21 this.path = path;
22 this.fd = null;
23};
24
25
26exports.File.prototype.open = async function (mode) {
27
28 Hoek.assert(this.fd === null);
29
30 try {
31 this.fd = await exports.open(this.path, mode);
32 }
33 catch (err) {
34 const data = { path: this.path };
35
36 if (this.path.indexOf('\u0000') !== -1 || err.code === 'ENOENT') {
37 throw Boom.notFound(null, data);
38 }
39
40 if (err.code === 'EACCES' || err.code === 'EPERM') {
41 data.code = err.code;
42 throw Boom.forbidden(null, data);
43 }
44
45 throw Boom.boomify(err, { message: 'Failed to open file', data });
46 }
47};
48
49
50exports.File.prototype.close = function () {
51
52 if (this.fd !== null) {
53 Bounce.background(exports.close(this.fd));
54 this.fd = null;
55 }
56};
57
58
59exports.File.prototype.stat = async function () {
60
61 Hoek.assert(this.fd !== null);
62
63 try {
64 const stat = await exports.fstat(this.fd);
65
66 if (stat.isDirectory()) {
67 throw Boom.forbidden(null, { code: 'EISDIR', path: this.path });
68 }
69
70 return stat;
71 }
72 catch (err) {
73 this.close(this.fd);
74
75 Bounce.rethrow(err, ['boom', 'system']);
76 throw Boom.boomify(err, { message: 'Failed to stat file', data: { path: this.path } });
77 }
78};
79
80
81exports.File.prototype.openStat = async function (mode) {
82
83 await this.open(mode);
84 return this.stat();
85};
86
87
88exports.File.prototype.createReadStream = function (options) {
89
90 Hoek.assert(this.fd !== null);
91
92 options = Object.assign({ fd: this.fd, start: 0 }, options);
93
94 const stream = exports.createReadStream(this.path, options);
95
96 if (options.autoClose !== false) {
97 this.fd = null; // The stream now owns the fd
98 }
99
100 return stream;
101};
102
103
104// Export Fs methods
105
106for (let i = 0; i < internals.methods.raw.length; ++i) {
107 const method = internals.methods.raw[i];
108 exports[method] = Fs[method].bind(Fs);
109}
110
111for (let i = 0; i < internals.methods.promised.length; ++i) {
112 const method = internals.methods.promised[i];
113 exports[method] = Util.promisify(Fs[method]);
114}