| |
| /** |
| * Module dependencies. |
| */ |
| |
| var fs = require('fs'); |
| var uri2path = require('file-uri-to-path'); |
| var NotFoundError = require('./notfound'); |
| var NotModifiedError = require('./notmodified'); |
| var debug = require('debug')('get-uri:file'); |
| |
| /** |
| * Module exports. |
| */ |
| |
| module.exports = get; |
| |
| /** |
| * Returns a `fs.ReadStream` instance from a "file:" URI. |
| * |
| * @api protected |
| */ |
| |
| function get (parsed, opts, fn) { |
| |
| var fd; |
| var cache = opts.cache; |
| |
| // same as in fs.ReadStream's constructor |
| var flags = opts.hasOwnProperty('flags') ? options.flags : 'r'; |
| var mode = opts.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ |
| |
| // convert URI → Path |
| var uri = parsed.href; |
| var filepath = uri2path(uri); |
| debug('normalized pathname: %o', filepath); |
| |
| // open() first to get a fd and ensure that the file exists |
| fs.open(filepath, flags, mode, onopen); |
| |
| function onerror (err) { |
| if ('number' == typeof fd) { |
| fs.close(fd, onclose); |
| } |
| fn(err); |
| } |
| |
| function onclose () { |
| debug('closed fd %o', fd); |
| } |
| |
| function onopen (err, _fd) { |
| if (err) { |
| if ('ENOENT' == err.code) { |
| err = new NotFoundError(); |
| } |
| return onerror(err); |
| } |
| fd = _fd; |
| |
| // now fstat() to check the `mtime` and store the stat object for the cache |
| fs.fstat(fd, onstat); |
| } |
| |
| function onstat (err, stat) { |
| if (err) return onerror(err); |
| |
| // if a `cache` was provided, check if the file has not been modified |
| if (cache && cache.stat && stat && isNotModified(cache.stat, stat)) { |
| return onerror(new NotModifiedError()); |
| } |
| |
| // `fs.ReadStream` takes care of calling `fs.close()` on the |
| // fd after it's done reading |
| opts.fd = fd; |
| var rs = fs.createReadStream(null, opts); |
| rs.stat = stat; |
| |
| fn(null, rs); |
| } |
| |
| // returns `true` if the `mtime` of the 2 stat objects are equal |
| function isNotModified (prev, curr) { |
| return +prev.mtime == +curr.mtime; |
| } |
| } |