You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							191 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
	
	
							191 lines
						
					
					
						
							5.2 KiB
						
					
					
				
 | 
						|
module.exports = ExtendedHeaderWriter | 
						|
 | 
						|
var inherits = require("inherits") | 
						|
  , EntryWriter = require("./entry-writer.js") | 
						|
 | 
						|
inherits(ExtendedHeaderWriter, EntryWriter) | 
						|
 | 
						|
var tar = require("../tar.js") | 
						|
  , path = require("path") | 
						|
  , TarHeader = require("./header.js") | 
						|
 | 
						|
// props is the props of the thing we need to write an | 
						|
// extended header for. | 
						|
// Don't be shy with it.  Just encode everything. | 
						|
function ExtendedHeaderWriter (props) { | 
						|
  // console.error(">> ehw ctor") | 
						|
  var me = this | 
						|
 | 
						|
  if (!(me instanceof ExtendedHeaderWriter)) { | 
						|
    return new ExtendedHeaderWriter(props) | 
						|
  } | 
						|
 | 
						|
  me.fields = props | 
						|
 | 
						|
  var p = | 
						|
    { path : ("PaxHeader" + path.join("/", props.path || "")) | 
						|
             .replace(/\\/g, "/").substr(0, 100) | 
						|
    , mode : props.mode || 0666 | 
						|
    , uid : props.uid || 0 | 
						|
    , gid : props.gid || 0 | 
						|
    , size : 0 // will be set later | 
						|
    , mtime : props.mtime || Date.now() / 1000 | 
						|
    , type : "x" | 
						|
    , linkpath : "" | 
						|
    , ustar : "ustar\0" | 
						|
    , ustarver : "00" | 
						|
    , uname : props.uname || "" | 
						|
    , gname : props.gname || "" | 
						|
    , devmaj : props.devmaj || 0 | 
						|
    , devmin : props.devmin || 0 | 
						|
    } | 
						|
 | 
						|
 | 
						|
  EntryWriter.call(me, p) | 
						|
  // console.error(">> ehw props", me.props) | 
						|
  me.props = p | 
						|
 | 
						|
  me._meta = true | 
						|
} | 
						|
 | 
						|
ExtendedHeaderWriter.prototype.end = function () { | 
						|
  // console.error(">> ehw end") | 
						|
  var me = this | 
						|
 | 
						|
  if (me._ended) return | 
						|
  me._ended = true | 
						|
 | 
						|
  me._encodeFields() | 
						|
 | 
						|
  if (me.props.size === 0) { | 
						|
    // nothing to write! | 
						|
    me._ready = true | 
						|
    me._stream.end() | 
						|
    return | 
						|
  } | 
						|
 | 
						|
  me._stream.write(TarHeader.encode(me.props)) | 
						|
  me.body.forEach(function (l) { | 
						|
    me._stream.write(l) | 
						|
  }) | 
						|
  me._ready = true | 
						|
 | 
						|
  // console.error(">> ehw _process calling end()", me.props) | 
						|
  this._stream.end() | 
						|
} | 
						|
 | 
						|
ExtendedHeaderWriter.prototype._encodeFields = function () { | 
						|
  // console.error(">> ehw _encodeFields") | 
						|
  this.body = [] | 
						|
  if (this.fields.prefix) { | 
						|
    this.fields.path = this.fields.prefix + "/" + this.fields.path | 
						|
    this.fields.prefix = "" | 
						|
  } | 
						|
  encodeFields(this.fields, "", this.body, this.fields.noProprietary) | 
						|
  var me = this | 
						|
  this.body.forEach(function (l) { | 
						|
    me.props.size += l.length | 
						|
  }) | 
						|
} | 
						|
 | 
						|
function encodeFields (fields, prefix, body, nop) { | 
						|
  // console.error(">> >> ehw encodeFields") | 
						|
  // "%d %s=%s\n", <length>, <keyword>, <value> | 
						|
  // The length is a decimal number, and includes itself and the \n | 
						|
  // Numeric values are decimal strings. | 
						|
 | 
						|
  Object.keys(fields).forEach(function (k) { | 
						|
    var val = fields[k] | 
						|
      , numeric = tar.numeric[k] | 
						|
 | 
						|
    if (prefix) k = prefix + "." + k | 
						|
 | 
						|
    // already including NODETAR.type, don't need File=true also | 
						|
    if (k === fields.type && val === true) return | 
						|
 | 
						|
    switch (k) { | 
						|
      // don't include anything that's always handled just fine | 
						|
      // in the normal header, or only meaningful in the context | 
						|
      // of nodetar | 
						|
      case "mode": | 
						|
      case "cksum": | 
						|
      case "ustar": | 
						|
      case "ustarver": | 
						|
      case "prefix": | 
						|
      case "basename": | 
						|
      case "dirname": | 
						|
      case "needExtended": | 
						|
      case "block": | 
						|
      case "filter": | 
						|
        return | 
						|
 | 
						|
      case "rdev": | 
						|
        if (val === 0) return | 
						|
        break | 
						|
 | 
						|
      case "nlink": | 
						|
      case "dev": // Truly a hero among men, Creator of Star! | 
						|
      case "ino": // Speak his name with reverent awe!  It is: | 
						|
        k = "SCHILY." + k | 
						|
        break | 
						|
 | 
						|
      default: break | 
						|
    } | 
						|
 | 
						|
    if (val && typeof val === "object" && | 
						|
        !Buffer.isBuffer(val)) encodeFields(val, k, body, nop) | 
						|
    else if (val === null || val === undefined) return | 
						|
    else body.push.apply(body, encodeField(k, val, nop)) | 
						|
  }) | 
						|
 | 
						|
  return body | 
						|
} | 
						|
 | 
						|
function encodeField (k, v, nop) { | 
						|
  // lowercase keys must be valid, otherwise prefix with | 
						|
  // "NODETAR." | 
						|
  if (k.charAt(0) === k.charAt(0).toLowerCase()) { | 
						|
    var m = k.split(".")[0] | 
						|
    if (!tar.knownExtended[m]) k = "NODETAR." + k | 
						|
  } | 
						|
 | 
						|
  // no proprietary | 
						|
  if (nop && k.charAt(0) !== k.charAt(0).toLowerCase()) { | 
						|
    return [] | 
						|
  } | 
						|
 | 
						|
  if (typeof val === "number") val = val.toString(10) | 
						|
 | 
						|
  var s = new Buffer(" " + k + "=" + v + "\n") | 
						|
    , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1 | 
						|
 | 
						|
  // console.error("1 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) | 
						|
 | 
						|
  // if adding that many digits will make it go over that length, | 
						|
  // then add one to it. For example, if the string is: | 
						|
  // " foo=bar\n" | 
						|
  // then that's 9 characters.  With the "9", that bumps the length | 
						|
  // up to 10.  However, this is invalid: | 
						|
  // "10 foo=bar\n" | 
						|
  // but, since that's actually 11 characters, since 10 adds another | 
						|
  // character to the length, and the length includes the number | 
						|
  // itself.  In that case, just bump it up again. | 
						|
  if (s.length + digits >= Math.pow(10, digits)) digits += 1 | 
						|
  // console.error("2 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) | 
						|
 | 
						|
  var len = digits + s.length | 
						|
  // console.error("3 s=%j digits=%j s.length=%d len=%d", s.toString(), digits, s.length, len) | 
						|
  var lenBuf = new Buffer("" + len) | 
						|
  if (lenBuf.length + s.length !== len) { | 
						|
    throw new Error("Bad length calculation\n"+ | 
						|
                    "len="+len+"\n"+ | 
						|
                    "lenBuf="+JSON.stringify(lenBuf.toString())+"\n"+ | 
						|
                    "lenBuf.length="+lenBuf.length+"\n"+ | 
						|
                    "digits="+digits+"\n"+ | 
						|
                    "s="+JSON.stringify(s.toString())+"\n"+ | 
						|
                    "s.length="+s.length) | 
						|
  } | 
						|
 | 
						|
  return [lenBuf, s] | 
						|
}
 | 
						|
 |