| // field paths that every tar file must have. |
| // header is padded to 512 bytes. |
| var f = 0 |
| , fields = {} |
| , path = fields.path = f++ |
| , mode = fields.mode = f++ |
| , uid = fields.uid = f++ |
| , gid = fields.gid = f++ |
| , size = fields.size = f++ |
| , mtime = fields.mtime = f++ |
| , cksum = fields.cksum = f++ |
| , type = fields.type = f++ |
| , linkpath = fields.linkpath = f++ |
| , headerSize = 512 |
| , blockSize = 512 |
| , fieldSize = [] |
| |
| fieldSize[path] = 100 |
| fieldSize[mode] = 8 |
| fieldSize[uid] = 8 |
| fieldSize[gid] = 8 |
| fieldSize[size] = 12 |
| fieldSize[mtime] = 12 |
| fieldSize[cksum] = 8 |
| fieldSize[type] = 1 |
| fieldSize[linkpath] = 100 |
| |
| // "ustar\0" may introduce another bunch of headers. |
| // these are optional, and will be nulled out if not present. |
| |
| var ustar = fields.ustar = f++ |
| , ustarver = fields.ustarver = f++ |
| , uname = fields.uname = f++ |
| , gname = fields.gname = f++ |
| , devmaj = fields.devmaj = f++ |
| , devmin = fields.devmin = f++ |
| , prefix = fields.prefix = f++ |
| , fill = fields.fill = f++ |
| |
| // terminate fields. |
| fields[f] = null |
| |
| fieldSize[ustar] = 6 |
| fieldSize[ustarver] = 2 |
| fieldSize[uname] = 32 |
| fieldSize[gname] = 32 |
| fieldSize[devmaj] = 8 |
| fieldSize[devmin] = 8 |
| fieldSize[prefix] = 155 |
| fieldSize[fill] = 12 |
| |
| // nb: prefix field may in fact be 130 bytes of prefix, |
| // a null char, 12 bytes for atime, 12 bytes for ctime. |
| // |
| // To recognize this format: |
| // 1. prefix[130] === ' ' or '\0' |
| // 2. atime and ctime are octal numeric values |
| // 3. atime and ctime have ' ' in their last byte |
| |
| var fieldEnds = {} |
| , fieldOffs = {} |
| , fe = 0 |
| for (var i = 0; i < f; i ++) { |
| fieldOffs[i] = fe |
| fieldEnds[i] = (fe += fieldSize[i]) |
| } |
| |
| // build a translation table of field paths. |
| Object.keys(fields).forEach(function (f) { |
| if (fields[f] !== null) fields[fields[f]] = f |
| }) |
| |
| // different values of the 'type' field |
| // paths match the values of Stats.isX() functions, where appropriate |
| var types = |
| { 0: "File" |
| , "\0": "OldFile" // like 0 |
| , "": "OldFile" |
| , 1: "Link" |
| , 2: "SymbolicLink" |
| , 3: "CharacterDevice" |
| , 4: "BlockDevice" |
| , 5: "Directory" |
| , 6: "FIFO" |
| , 7: "ContiguousFile" // like 0 |
| // posix headers |
| , g: "GlobalExtendedHeader" // k=v for the rest of the archive |
| , x: "ExtendedHeader" // k=v for the next file |
| // vendor-specific stuff |
| , A: "SolarisACL" // skip |
| , D: "GNUDumpDir" // like 5, but with data, which should be skipped |
| , I: "Inode" // metadata only, skip |
| , K: "NextFileHasLongLinkpath" // data = link path of next file |
| , L: "NextFileHasLongPath" // data = path of next file |
| , M: "ContinuationFile" // skip |
| , N: "OldGnuLongPath" // like L |
| , S: "SparseFile" // skip |
| , V: "TapeVolumeHeader" // skip |
| , X: "OldExtendedHeader" // like x |
| } |
| |
| Object.keys(types).forEach(function (t) { |
| types[types[t]] = types[types[t]] || t |
| }) |
| |
| // values for the mode field |
| var modes = |
| { suid: 04000 // set uid on extraction |
| , sgid: 02000 // set gid on extraction |
| , svtx: 01000 // set restricted deletion flag on dirs on extraction |
| , uread: 0400 |
| , uwrite: 0200 |
| , uexec: 0100 |
| , gread: 040 |
| , gwrite: 020 |
| , gexec: 010 |
| , oread: 4 |
| , owrite: 2 |
| , oexec: 1 |
| , all: 07777 |
| } |
| |
| var numeric = |
| { mode: true |
| , uid: true |
| , gid: true |
| , size: true |
| , mtime: true |
| , devmaj: true |
| , devmin: true |
| , cksum: true |
| , atime: true |
| , ctime: true |
| , dev: true |
| , ino: true |
| , nlink: true |
| } |
| |
| Object.keys(modes).forEach(function (t) { |
| modes[modes[t]] = modes[modes[t]] || t |
| }) |
| |
| var knownExtended = |
| { atime: true |
| , charset: true |
| , comment: true |
| , ctime: true |
| , gid: true |
| , gname: true |
| , linkpath: true |
| , mtime: true |
| , path: true |
| , realtime: true |
| , security: true |
| , size: true |
| , uid: true |
| , uname: true } |
| |
| |
| exports.fields = fields |
| exports.fieldSize = fieldSize |
| exports.fieldOffs = fieldOffs |
| exports.fieldEnds = fieldEnds |
| exports.types = types |
| exports.modes = modes |
| exports.numeric = numeric |
| exports.headerSize = headerSize |
| exports.blockSize = blockSize |
| exports.knownExtended = knownExtended |
| |
| exports.Pack = require("./lib/pack.js") |
| exports.Parse = require("./lib/parse.js") |
| exports.Extract = require("./lib/extract.js") |