689 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			689 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
"use strict";
 | 
						|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
 | 
						|
    if (k2 === undefined) k2 = k;
 | 
						|
    var desc = Object.getOwnPropertyDescriptor(m, k);
 | 
						|
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
 | 
						|
      desc = { enumerable: true, get: function() { return m[k]; } };
 | 
						|
    }
 | 
						|
    Object.defineProperty(o, k2, desc);
 | 
						|
}) : (function(o, m, k, k2) {
 | 
						|
    if (k2 === undefined) k2 = k;
 | 
						|
    o[k2] = m[k];
 | 
						|
}));
 | 
						|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
 | 
						|
    Object.defineProperty(o, "default", { enumerable: true, value: v });
 | 
						|
}) : function(o, v) {
 | 
						|
    o["default"] = v;
 | 
						|
});
 | 
						|
var __importStar = (this && this.__importStar) || function (mod) {
 | 
						|
    if (mod && mod.__esModule) return mod;
 | 
						|
    var result = {};
 | 
						|
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
 | 
						|
    __setModuleDefault(result, mod);
 | 
						|
    return result;
 | 
						|
};
 | 
						|
var __importDefault = (this && this.__importDefault) || function (mod) {
 | 
						|
    return (mod && mod.__esModule) ? mod : { "default": mod };
 | 
						|
};
 | 
						|
Object.defineProperty(exports, "__esModule", { value: true });
 | 
						|
exports.WriteEntryTar = exports.WriteEntrySync = exports.WriteEntry = void 0;
 | 
						|
const fs_1 = __importDefault(require("fs"));
 | 
						|
const minipass_1 = require("minipass");
 | 
						|
const path_1 = __importDefault(require("path"));
 | 
						|
const header_js_1 = require("./header.js");
 | 
						|
const mode_fix_js_1 = require("./mode-fix.js");
 | 
						|
const normalize_windows_path_js_1 = require("./normalize-windows-path.js");
 | 
						|
const options_js_1 = require("./options.js");
 | 
						|
const pax_js_1 = require("./pax.js");
 | 
						|
const strip_absolute_path_js_1 = require("./strip-absolute-path.js");
 | 
						|
const strip_trailing_slashes_js_1 = require("./strip-trailing-slashes.js");
 | 
						|
const warn_method_js_1 = require("./warn-method.js");
 | 
						|
const winchars = __importStar(require("./winchars.js"));
 | 
						|
const prefixPath = (path, prefix) => {
 | 
						|
    if (!prefix) {
 | 
						|
        return (0, normalize_windows_path_js_1.normalizeWindowsPath)(path);
 | 
						|
    }
 | 
						|
    path = (0, normalize_windows_path_js_1.normalizeWindowsPath)(path).replace(/^\.(\/|$)/, '');
 | 
						|
    return (0, strip_trailing_slashes_js_1.stripTrailingSlashes)(prefix) + '/' + path;
 | 
						|
};
 | 
						|
const maxReadSize = 16 * 1024 * 1024;
 | 
						|
const PROCESS = Symbol('process');
 | 
						|
const FILE = Symbol('file');
 | 
						|
const DIRECTORY = Symbol('directory');
 | 
						|
const SYMLINK = Symbol('symlink');
 | 
						|
const HARDLINK = Symbol('hardlink');
 | 
						|
const HEADER = Symbol('header');
 | 
						|
const READ = Symbol('read');
 | 
						|
const LSTAT = Symbol('lstat');
 | 
						|
const ONLSTAT = Symbol('onlstat');
 | 
						|
const ONREAD = Symbol('onread');
 | 
						|
const ONREADLINK = Symbol('onreadlink');
 | 
						|
const OPENFILE = Symbol('openfile');
 | 
						|
const ONOPENFILE = Symbol('onopenfile');
 | 
						|
const CLOSE = Symbol('close');
 | 
						|
const MODE = Symbol('mode');
 | 
						|
const AWAITDRAIN = Symbol('awaitDrain');
 | 
						|
const ONDRAIN = Symbol('ondrain');
 | 
						|
const PREFIX = Symbol('prefix');
 | 
						|
class WriteEntry extends minipass_1.Minipass {
 | 
						|
    path;
 | 
						|
    portable;
 | 
						|
    myuid = (process.getuid && process.getuid()) || 0;
 | 
						|
    // until node has builtin pwnam functions, this'll have to do
 | 
						|
    myuser = process.env.USER || '';
 | 
						|
    maxReadSize;
 | 
						|
    linkCache;
 | 
						|
    statCache;
 | 
						|
    preservePaths;
 | 
						|
    cwd;
 | 
						|
    strict;
 | 
						|
    mtime;
 | 
						|
    noPax;
 | 
						|
    noMtime;
 | 
						|
    prefix;
 | 
						|
    fd;
 | 
						|
    blockLen = 0;
 | 
						|
    blockRemain = 0;
 | 
						|
    buf;
 | 
						|
    pos = 0;
 | 
						|
    remain = 0;
 | 
						|
    length = 0;
 | 
						|
    offset = 0;
 | 
						|
    win32;
 | 
						|
    absolute;
 | 
						|
    header;
 | 
						|
    type;
 | 
						|
    linkpath;
 | 
						|
    stat;
 | 
						|
    onWriteEntry;
 | 
						|
    #hadError = false;
 | 
						|
    constructor(p, opt_ = {}) {
 | 
						|
        const opt = (0, options_js_1.dealias)(opt_);
 | 
						|
        super();
 | 
						|
        this.path = (0, normalize_windows_path_js_1.normalizeWindowsPath)(p);
 | 
						|
        // suppress atime, ctime, uid, gid, uname, gname
 | 
						|
        this.portable = !!opt.portable;
 | 
						|
        this.maxReadSize = opt.maxReadSize || maxReadSize;
 | 
						|
        this.linkCache = opt.linkCache || new Map();
 | 
						|
        this.statCache = opt.statCache || new Map();
 | 
						|
        this.preservePaths = !!opt.preservePaths;
 | 
						|
        this.cwd = (0, normalize_windows_path_js_1.normalizeWindowsPath)(opt.cwd || process.cwd());
 | 
						|
        this.strict = !!opt.strict;
 | 
						|
        this.noPax = !!opt.noPax;
 | 
						|
        this.noMtime = !!opt.noMtime;
 | 
						|
        this.mtime = opt.mtime;
 | 
						|
        this.prefix =
 | 
						|
            opt.prefix ? (0, normalize_windows_path_js_1.normalizeWindowsPath)(opt.prefix) : undefined;
 | 
						|
        this.onWriteEntry = opt.onWriteEntry;
 | 
						|
        if (typeof opt.onwarn === 'function') {
 | 
						|
            this.on('warn', opt.onwarn);
 | 
						|
        }
 | 
						|
        let pathWarn = false;
 | 
						|
        if (!this.preservePaths) {
 | 
						|
            const [root, stripped] = (0, strip_absolute_path_js_1.stripAbsolutePath)(this.path);
 | 
						|
            if (root && typeof stripped === 'string') {
 | 
						|
                this.path = stripped;
 | 
						|
                pathWarn = root;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        this.win32 = !!opt.win32 || process.platform === 'win32';
 | 
						|
        if (this.win32) {
 | 
						|
            // force the \ to / normalization, since we might not *actually*
 | 
						|
            // be on windows, but want \ to be considered a path separator.
 | 
						|
            this.path = winchars.decode(this.path.replace(/\\/g, '/'));
 | 
						|
            p = p.replace(/\\/g, '/');
 | 
						|
        }
 | 
						|
        this.absolute = (0, normalize_windows_path_js_1.normalizeWindowsPath)(opt.absolute || path_1.default.resolve(this.cwd, p));
 | 
						|
        if (this.path === '') {
 | 
						|
            this.path = './';
 | 
						|
        }
 | 
						|
        if (pathWarn) {
 | 
						|
            this.warn('TAR_ENTRY_INFO', `stripping ${pathWarn} from absolute path`, {
 | 
						|
                entry: this,
 | 
						|
                path: pathWarn + this.path,
 | 
						|
            });
 | 
						|
        }
 | 
						|
        const cs = this.statCache.get(this.absolute);
 | 
						|
        if (cs) {
 | 
						|
            this[ONLSTAT](cs);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            this[LSTAT]();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    warn(code, message, data = {}) {
 | 
						|
        return (0, warn_method_js_1.warnMethod)(this, code, message, data);
 | 
						|
    }
 | 
						|
    emit(ev, ...data) {
 | 
						|
        if (ev === 'error') {
 | 
						|
            this.#hadError = true;
 | 
						|
        }
 | 
						|
        return super.emit(ev, ...data);
 | 
						|
    }
 | 
						|
    [LSTAT]() {
 | 
						|
        fs_1.default.lstat(this.absolute, (er, stat) => {
 | 
						|
            if (er) {
 | 
						|
                return this.emit('error', er);
 | 
						|
            }
 | 
						|
            this[ONLSTAT](stat);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    [ONLSTAT](stat) {
 | 
						|
        this.statCache.set(this.absolute, stat);
 | 
						|
        this.stat = stat;
 | 
						|
        if (!stat.isFile()) {
 | 
						|
            stat.size = 0;
 | 
						|
        }
 | 
						|
        this.type = getType(stat);
 | 
						|
        this.emit('stat', stat);
 | 
						|
        this[PROCESS]();
 | 
						|
    }
 | 
						|
    [PROCESS]() {
 | 
						|
        switch (this.type) {
 | 
						|
            case 'File':
 | 
						|
                return this[FILE]();
 | 
						|
            case 'Directory':
 | 
						|
                return this[DIRECTORY]();
 | 
						|
            case 'SymbolicLink':
 | 
						|
                return this[SYMLINK]();
 | 
						|
            // unsupported types are ignored.
 | 
						|
            default:
 | 
						|
                return this.end();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    [MODE](mode) {
 | 
						|
        return (0, mode_fix_js_1.modeFix)(mode, this.type === 'Directory', this.portable);
 | 
						|
    }
 | 
						|
    [PREFIX](path) {
 | 
						|
        return prefixPath(path, this.prefix);
 | 
						|
    }
 | 
						|
    [HEADER]() {
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.stat) {
 | 
						|
            throw new Error('cannot write header before stat');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.type === 'Directory' && this.portable) {
 | 
						|
            this.noMtime = true;
 | 
						|
        }
 | 
						|
        this.onWriteEntry?.(this);
 | 
						|
        this.header = new header_js_1.Header({
 | 
						|
            path: this[PREFIX](this.path),
 | 
						|
            // only apply the prefix to hard links.
 | 
						|
            linkpath: this.type === 'Link' && this.linkpath !== undefined ?
 | 
						|
                this[PREFIX](this.linkpath)
 | 
						|
                : this.linkpath,
 | 
						|
            // only the permissions and setuid/setgid/sticky bitflags
 | 
						|
            // not the higher-order bits that specify file type
 | 
						|
            mode: this[MODE](this.stat.mode),
 | 
						|
            uid: this.portable ? undefined : this.stat.uid,
 | 
						|
            gid: this.portable ? undefined : this.stat.gid,
 | 
						|
            size: this.stat.size,
 | 
						|
            mtime: this.noMtime ? undefined : this.mtime || this.stat.mtime,
 | 
						|
            /* c8 ignore next */
 | 
						|
            type: this.type === 'Unsupported' ? undefined : this.type,
 | 
						|
            uname: this.portable ? undefined
 | 
						|
                : this.stat.uid === this.myuid ? this.myuser
 | 
						|
                    : '',
 | 
						|
            atime: this.portable ? undefined : this.stat.atime,
 | 
						|
            ctime: this.portable ? undefined : this.stat.ctime,
 | 
						|
        });
 | 
						|
        if (this.header.encode() && !this.noPax) {
 | 
						|
            super.write(new pax_js_1.Pax({
 | 
						|
                atime: this.portable ? undefined : this.header.atime,
 | 
						|
                ctime: this.portable ? undefined : this.header.ctime,
 | 
						|
                gid: this.portable ? undefined : this.header.gid,
 | 
						|
                mtime: this.noMtime ? undefined : (this.mtime || this.header.mtime),
 | 
						|
                path: this[PREFIX](this.path),
 | 
						|
                linkpath: this.type === 'Link' && this.linkpath !== undefined ?
 | 
						|
                    this[PREFIX](this.linkpath)
 | 
						|
                    : this.linkpath,
 | 
						|
                size: this.header.size,
 | 
						|
                uid: this.portable ? undefined : this.header.uid,
 | 
						|
                uname: this.portable ? undefined : this.header.uname,
 | 
						|
                dev: this.portable ? undefined : this.stat.dev,
 | 
						|
                ino: this.portable ? undefined : this.stat.ino,
 | 
						|
                nlink: this.portable ? undefined : this.stat.nlink,
 | 
						|
            }).encode());
 | 
						|
        }
 | 
						|
        const block = this.header?.block;
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!block) {
 | 
						|
            throw new Error('failed to encode header');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        super.write(block);
 | 
						|
    }
 | 
						|
    [DIRECTORY]() {
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.stat) {
 | 
						|
            throw new Error('cannot create directory entry without stat');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.path.slice(-1) !== '/') {
 | 
						|
            this.path += '/';
 | 
						|
        }
 | 
						|
        this.stat.size = 0;
 | 
						|
        this[HEADER]();
 | 
						|
        this.end();
 | 
						|
    }
 | 
						|
    [SYMLINK]() {
 | 
						|
        fs_1.default.readlink(this.absolute, (er, linkpath) => {
 | 
						|
            if (er) {
 | 
						|
                return this.emit('error', er);
 | 
						|
            }
 | 
						|
            this[ONREADLINK](linkpath);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    [ONREADLINK](linkpath) {
 | 
						|
        this.linkpath = (0, normalize_windows_path_js_1.normalizeWindowsPath)(linkpath);
 | 
						|
        this[HEADER]();
 | 
						|
        this.end();
 | 
						|
    }
 | 
						|
    [HARDLINK](linkpath) {
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.stat) {
 | 
						|
            throw new Error('cannot create link entry without stat');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        this.type = 'Link';
 | 
						|
        this.linkpath = (0, normalize_windows_path_js_1.normalizeWindowsPath)(path_1.default.relative(this.cwd, linkpath));
 | 
						|
        this.stat.size = 0;
 | 
						|
        this[HEADER]();
 | 
						|
        this.end();
 | 
						|
    }
 | 
						|
    [FILE]() {
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.stat) {
 | 
						|
            throw new Error('cannot create file entry without stat');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.stat.nlink > 1) {
 | 
						|
            const linkKey = `${this.stat.dev}:${this.stat.ino}`;
 | 
						|
            const linkpath = this.linkCache.get(linkKey);
 | 
						|
            if (linkpath?.indexOf(this.cwd) === 0) {
 | 
						|
                return this[HARDLINK](linkpath);
 | 
						|
            }
 | 
						|
            this.linkCache.set(linkKey, this.absolute);
 | 
						|
        }
 | 
						|
        this[HEADER]();
 | 
						|
        if (this.stat.size === 0) {
 | 
						|
            return this.end();
 | 
						|
        }
 | 
						|
        this[OPENFILE]();
 | 
						|
    }
 | 
						|
    [OPENFILE]() {
 | 
						|
        fs_1.default.open(this.absolute, 'r', (er, fd) => {
 | 
						|
            if (er) {
 | 
						|
                return this.emit('error', er);
 | 
						|
            }
 | 
						|
            this[ONOPENFILE](fd);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    [ONOPENFILE](fd) {
 | 
						|
        this.fd = fd;
 | 
						|
        if (this.#hadError) {
 | 
						|
            return this[CLOSE]();
 | 
						|
        }
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.stat) {
 | 
						|
            throw new Error('should stat before calling onopenfile');
 | 
						|
        }
 | 
						|
        /* c8 ignore start */
 | 
						|
        this.blockLen = 512 * Math.ceil(this.stat.size / 512);
 | 
						|
        this.blockRemain = this.blockLen;
 | 
						|
        const bufLen = Math.min(this.blockLen, this.maxReadSize);
 | 
						|
        this.buf = Buffer.allocUnsafe(bufLen);
 | 
						|
        this.offset = 0;
 | 
						|
        this.pos = 0;
 | 
						|
        this.remain = this.stat.size;
 | 
						|
        this.length = this.buf.length;
 | 
						|
        this[READ]();
 | 
						|
    }
 | 
						|
    [READ]() {
 | 
						|
        const { fd, buf, offset, length, pos } = this;
 | 
						|
        if (fd === undefined || buf === undefined) {
 | 
						|
            throw new Error('cannot read file without first opening');
 | 
						|
        }
 | 
						|
        fs_1.default.read(fd, buf, offset, length, pos, (er, bytesRead) => {
 | 
						|
            if (er) {
 | 
						|
                // ignoring the error from close(2) is a bad practice, but at
 | 
						|
                // this point we already have an error, don't need another one
 | 
						|
                return this[CLOSE](() => this.emit('error', er));
 | 
						|
            }
 | 
						|
            this[ONREAD](bytesRead);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    /* c8 ignore start */
 | 
						|
    [CLOSE](cb = () => { }) {
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.fd !== undefined)
 | 
						|
            fs_1.default.close(this.fd, cb);
 | 
						|
    }
 | 
						|
    [ONREAD](bytesRead) {
 | 
						|
        if (bytesRead <= 0 && this.remain > 0) {
 | 
						|
            const er = Object.assign(new Error('encountered unexpected EOF'), {
 | 
						|
                path: this.absolute,
 | 
						|
                syscall: 'read',
 | 
						|
                code: 'EOF',
 | 
						|
            });
 | 
						|
            return this[CLOSE](() => this.emit('error', er));
 | 
						|
        }
 | 
						|
        if (bytesRead > this.remain) {
 | 
						|
            const er = Object.assign(new Error('did not encounter expected EOF'), {
 | 
						|
                path: this.absolute,
 | 
						|
                syscall: 'read',
 | 
						|
                code: 'EOF',
 | 
						|
            });
 | 
						|
            return this[CLOSE](() => this.emit('error', er));
 | 
						|
        }
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.buf) {
 | 
						|
            throw new Error('should have created buffer prior to reading');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        // null out the rest of the buffer, if we could fit the block padding
 | 
						|
        // at the end of this loop, we've incremented bytesRead and this.remain
 | 
						|
        // to be incremented up to the blockRemain level, as if we had expected
 | 
						|
        // to get a null-padded file, and read it until the end.  then we will
 | 
						|
        // decrement both remain and blockRemain by bytesRead, and know that we
 | 
						|
        // reached the expected EOF, without any null buffer to append.
 | 
						|
        if (bytesRead === this.remain) {
 | 
						|
            for (let i = bytesRead; i < this.length && bytesRead < this.blockRemain; i++) {
 | 
						|
                this.buf[i + this.offset] = 0;
 | 
						|
                bytesRead++;
 | 
						|
                this.remain++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        const chunk = this.offset === 0 && bytesRead === this.buf.length ?
 | 
						|
            this.buf
 | 
						|
            : this.buf.subarray(this.offset, this.offset + bytesRead);
 | 
						|
        const flushed = this.write(chunk);
 | 
						|
        if (!flushed) {
 | 
						|
            this[AWAITDRAIN](() => this[ONDRAIN]());
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            this[ONDRAIN]();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    [AWAITDRAIN](cb) {
 | 
						|
        this.once('drain', cb);
 | 
						|
    }
 | 
						|
    write(chunk, encoding, cb) {
 | 
						|
        /* c8 ignore start - just junk to comply with NodeJS.WritableStream */
 | 
						|
        if (typeof encoding === 'function') {
 | 
						|
            cb = encoding;
 | 
						|
            encoding = undefined;
 | 
						|
        }
 | 
						|
        if (typeof chunk === 'string') {
 | 
						|
            chunk = Buffer.from(chunk, typeof encoding === 'string' ? encoding : 'utf8');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.blockRemain < chunk.length) {
 | 
						|
            const er = Object.assign(new Error('writing more data than expected'), {
 | 
						|
                path: this.absolute,
 | 
						|
            });
 | 
						|
            return this.emit('error', er);
 | 
						|
        }
 | 
						|
        this.remain -= chunk.length;
 | 
						|
        this.blockRemain -= chunk.length;
 | 
						|
        this.pos += chunk.length;
 | 
						|
        this.offset += chunk.length;
 | 
						|
        return super.write(chunk, null, cb);
 | 
						|
    }
 | 
						|
    [ONDRAIN]() {
 | 
						|
        if (!this.remain) {
 | 
						|
            if (this.blockRemain) {
 | 
						|
                super.write(Buffer.alloc(this.blockRemain));
 | 
						|
            }
 | 
						|
            return this[CLOSE](er => er ? this.emit('error', er) : this.end());
 | 
						|
        }
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!this.buf) {
 | 
						|
            throw new Error('buffer lost somehow in ONDRAIN');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.offset >= this.length) {
 | 
						|
            // if we only have a smaller bit left to read, alloc a smaller buffer
 | 
						|
            // otherwise, keep it the same length it was before.
 | 
						|
            this.buf = Buffer.allocUnsafe(Math.min(this.blockRemain, this.buf.length));
 | 
						|
            this.offset = 0;
 | 
						|
        }
 | 
						|
        this.length = this.buf.length - this.offset;
 | 
						|
        this[READ]();
 | 
						|
    }
 | 
						|
}
 | 
						|
exports.WriteEntry = WriteEntry;
 | 
						|
class WriteEntrySync extends WriteEntry {
 | 
						|
    sync = true;
 | 
						|
    [LSTAT]() {
 | 
						|
        this[ONLSTAT](fs_1.default.lstatSync(this.absolute));
 | 
						|
    }
 | 
						|
    [SYMLINK]() {
 | 
						|
        this[ONREADLINK](fs_1.default.readlinkSync(this.absolute));
 | 
						|
    }
 | 
						|
    [OPENFILE]() {
 | 
						|
        this[ONOPENFILE](fs_1.default.openSync(this.absolute, 'r'));
 | 
						|
    }
 | 
						|
    [READ]() {
 | 
						|
        let threw = true;
 | 
						|
        try {
 | 
						|
            const { fd, buf, offset, length, pos } = this;
 | 
						|
            /* c8 ignore start */
 | 
						|
            if (fd === undefined || buf === undefined) {
 | 
						|
                throw new Error('fd and buf must be set in READ method');
 | 
						|
            }
 | 
						|
            /* c8 ignore stop */
 | 
						|
            const bytesRead = fs_1.default.readSync(fd, buf, offset, length, pos);
 | 
						|
            this[ONREAD](bytesRead);
 | 
						|
            threw = false;
 | 
						|
        }
 | 
						|
        finally {
 | 
						|
            // ignoring the error from close(2) is a bad practice, but at
 | 
						|
            // this point we already have an error, don't need another one
 | 
						|
            if (threw) {
 | 
						|
                try {
 | 
						|
                    this[CLOSE](() => { });
 | 
						|
                }
 | 
						|
                catch (er) { }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    [AWAITDRAIN](cb) {
 | 
						|
        cb();
 | 
						|
    }
 | 
						|
    /* c8 ignore start */
 | 
						|
    [CLOSE](cb = () => { }) {
 | 
						|
        /* c8 ignore stop */
 | 
						|
        if (this.fd !== undefined)
 | 
						|
            fs_1.default.closeSync(this.fd);
 | 
						|
        cb();
 | 
						|
    }
 | 
						|
}
 | 
						|
exports.WriteEntrySync = WriteEntrySync;
 | 
						|
class WriteEntryTar extends minipass_1.Minipass {
 | 
						|
    blockLen = 0;
 | 
						|
    blockRemain = 0;
 | 
						|
    buf = 0;
 | 
						|
    pos = 0;
 | 
						|
    remain = 0;
 | 
						|
    length = 0;
 | 
						|
    preservePaths;
 | 
						|
    portable;
 | 
						|
    strict;
 | 
						|
    noPax;
 | 
						|
    noMtime;
 | 
						|
    readEntry;
 | 
						|
    type;
 | 
						|
    prefix;
 | 
						|
    path;
 | 
						|
    mode;
 | 
						|
    uid;
 | 
						|
    gid;
 | 
						|
    uname;
 | 
						|
    gname;
 | 
						|
    header;
 | 
						|
    mtime;
 | 
						|
    atime;
 | 
						|
    ctime;
 | 
						|
    linkpath;
 | 
						|
    size;
 | 
						|
    onWriteEntry;
 | 
						|
    warn(code, message, data = {}) {
 | 
						|
        return (0, warn_method_js_1.warnMethod)(this, code, message, data);
 | 
						|
    }
 | 
						|
    constructor(readEntry, opt_ = {}) {
 | 
						|
        const opt = (0, options_js_1.dealias)(opt_);
 | 
						|
        super();
 | 
						|
        this.preservePaths = !!opt.preservePaths;
 | 
						|
        this.portable = !!opt.portable;
 | 
						|
        this.strict = !!opt.strict;
 | 
						|
        this.noPax = !!opt.noPax;
 | 
						|
        this.noMtime = !!opt.noMtime;
 | 
						|
        this.onWriteEntry = opt.onWriteEntry;
 | 
						|
        this.readEntry = readEntry;
 | 
						|
        const { type } = readEntry;
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (type === 'Unsupported') {
 | 
						|
            throw new Error('writing entry that should be ignored');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        this.type = type;
 | 
						|
        if (this.type === 'Directory' && this.portable) {
 | 
						|
            this.noMtime = true;
 | 
						|
        }
 | 
						|
        this.prefix = opt.prefix;
 | 
						|
        this.path = (0, normalize_windows_path_js_1.normalizeWindowsPath)(readEntry.path);
 | 
						|
        this.mode =
 | 
						|
            readEntry.mode !== undefined ?
 | 
						|
                this[MODE](readEntry.mode)
 | 
						|
                : undefined;
 | 
						|
        this.uid = this.portable ? undefined : readEntry.uid;
 | 
						|
        this.gid = this.portable ? undefined : readEntry.gid;
 | 
						|
        this.uname = this.portable ? undefined : readEntry.uname;
 | 
						|
        this.gname = this.portable ? undefined : readEntry.gname;
 | 
						|
        this.size = readEntry.size;
 | 
						|
        this.mtime =
 | 
						|
            this.noMtime ? undefined : opt.mtime || readEntry.mtime;
 | 
						|
        this.atime = this.portable ? undefined : readEntry.atime;
 | 
						|
        this.ctime = this.portable ? undefined : readEntry.ctime;
 | 
						|
        this.linkpath =
 | 
						|
            readEntry.linkpath !== undefined ?
 | 
						|
                (0, normalize_windows_path_js_1.normalizeWindowsPath)(readEntry.linkpath)
 | 
						|
                : undefined;
 | 
						|
        if (typeof opt.onwarn === 'function') {
 | 
						|
            this.on('warn', opt.onwarn);
 | 
						|
        }
 | 
						|
        let pathWarn = false;
 | 
						|
        if (!this.preservePaths) {
 | 
						|
            const [root, stripped] = (0, strip_absolute_path_js_1.stripAbsolutePath)(this.path);
 | 
						|
            if (root && typeof stripped === 'string') {
 | 
						|
                this.path = stripped;
 | 
						|
                pathWarn = root;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        this.remain = readEntry.size;
 | 
						|
        this.blockRemain = readEntry.startBlockSize;
 | 
						|
        this.onWriteEntry?.(this);
 | 
						|
        this.header = new header_js_1.Header({
 | 
						|
            path: this[PREFIX](this.path),
 | 
						|
            linkpath: this.type === 'Link' && this.linkpath !== undefined ?
 | 
						|
                this[PREFIX](this.linkpath)
 | 
						|
                : this.linkpath,
 | 
						|
            // only the permissions and setuid/setgid/sticky bitflags
 | 
						|
            // not the higher-order bits that specify file type
 | 
						|
            mode: this.mode,
 | 
						|
            uid: this.portable ? undefined : this.uid,
 | 
						|
            gid: this.portable ? undefined : this.gid,
 | 
						|
            size: this.size,
 | 
						|
            mtime: this.noMtime ? undefined : this.mtime,
 | 
						|
            type: this.type,
 | 
						|
            uname: this.portable ? undefined : this.uname,
 | 
						|
            atime: this.portable ? undefined : this.atime,
 | 
						|
            ctime: this.portable ? undefined : this.ctime,
 | 
						|
        });
 | 
						|
        if (pathWarn) {
 | 
						|
            this.warn('TAR_ENTRY_INFO', `stripping ${pathWarn} from absolute path`, {
 | 
						|
                entry: this,
 | 
						|
                path: pathWarn + this.path,
 | 
						|
            });
 | 
						|
        }
 | 
						|
        if (this.header.encode() && !this.noPax) {
 | 
						|
            super.write(new pax_js_1.Pax({
 | 
						|
                atime: this.portable ? undefined : this.atime,
 | 
						|
                ctime: this.portable ? undefined : this.ctime,
 | 
						|
                gid: this.portable ? undefined : this.gid,
 | 
						|
                mtime: this.noMtime ? undefined : this.mtime,
 | 
						|
                path: this[PREFIX](this.path),
 | 
						|
                linkpath: this.type === 'Link' && this.linkpath !== undefined ?
 | 
						|
                    this[PREFIX](this.linkpath)
 | 
						|
                    : this.linkpath,
 | 
						|
                size: this.size,
 | 
						|
                uid: this.portable ? undefined : this.uid,
 | 
						|
                uname: this.portable ? undefined : this.uname,
 | 
						|
                dev: this.portable ? undefined : this.readEntry.dev,
 | 
						|
                ino: this.portable ? undefined : this.readEntry.ino,
 | 
						|
                nlink: this.portable ? undefined : this.readEntry.nlink,
 | 
						|
            }).encode());
 | 
						|
        }
 | 
						|
        const b = this.header?.block;
 | 
						|
        /* c8 ignore start */
 | 
						|
        if (!b)
 | 
						|
            throw new Error('failed to encode header');
 | 
						|
        /* c8 ignore stop */
 | 
						|
        super.write(b);
 | 
						|
        readEntry.pipe(this);
 | 
						|
    }
 | 
						|
    [PREFIX](path) {
 | 
						|
        return prefixPath(path, this.prefix);
 | 
						|
    }
 | 
						|
    [MODE](mode) {
 | 
						|
        return (0, mode_fix_js_1.modeFix)(mode, this.type === 'Directory', this.portable);
 | 
						|
    }
 | 
						|
    write(chunk, encoding, cb) {
 | 
						|
        /* c8 ignore start - just junk to comply with NodeJS.WritableStream */
 | 
						|
        if (typeof encoding === 'function') {
 | 
						|
            cb = encoding;
 | 
						|
            encoding = undefined;
 | 
						|
        }
 | 
						|
        if (typeof chunk === 'string') {
 | 
						|
            chunk = Buffer.from(chunk, typeof encoding === 'string' ? encoding : 'utf8');
 | 
						|
        }
 | 
						|
        /* c8 ignore stop */
 | 
						|
        const writeLen = chunk.length;
 | 
						|
        if (writeLen > this.blockRemain) {
 | 
						|
            throw new Error('writing more to entry than is appropriate');
 | 
						|
        }
 | 
						|
        this.blockRemain -= writeLen;
 | 
						|
        return super.write(chunk, cb);
 | 
						|
    }
 | 
						|
    end(chunk, encoding, cb) {
 | 
						|
        if (this.blockRemain) {
 | 
						|
            super.write(Buffer.alloc(this.blockRemain));
 | 
						|
        }
 | 
						|
        /* c8 ignore start - just junk to comply with NodeJS.WritableStream */
 | 
						|
        if (typeof chunk === 'function') {
 | 
						|
            cb = chunk;
 | 
						|
            encoding = undefined;
 | 
						|
            chunk = undefined;
 | 
						|
        }
 | 
						|
        if (typeof encoding === 'function') {
 | 
						|
            cb = encoding;
 | 
						|
            encoding = undefined;
 | 
						|
        }
 | 
						|
        if (typeof chunk === 'string') {
 | 
						|
            chunk = Buffer.from(chunk, encoding ?? 'utf8');
 | 
						|
        }
 | 
						|
        if (cb)
 | 
						|
            this.once('finish', cb);
 | 
						|
        chunk ? super.end(chunk, cb) : super.end(cb);
 | 
						|
        /* c8 ignore stop */
 | 
						|
        return this;
 | 
						|
    }
 | 
						|
}
 | 
						|
exports.WriteEntryTar = WriteEntryTar;
 | 
						|
const getType = (stat) => stat.isFile() ? 'File'
 | 
						|
    : stat.isDirectory() ? 'Directory'
 | 
						|
        : stat.isSymbolicLink() ? 'SymbolicLink'
 | 
						|
            : 'Unsupported';
 | 
						|
//# sourceMappingURL=write-entry.js.map
 |