tarheader.cs

来自「全功能c#编译器」· CS 代码 · 共 769 行 · 第 1/2 页

CS
769
字号
			hdr.version   = (this.version == null)   ? null : new StringBuilder(this.version.ToString());
			hdr.userName  = (this.userName == null)  ? null : new StringBuilder(this.userName.ToString());
			hdr.groupName = (this.groupName == null) ? null : new StringBuilder(this.groupName.ToString());
			hdr.devMajor  = this.devMajor;
			hdr.devMinor  = this.devMinor;
			
			return hdr;
		}
		
		/// <summary>
		/// Get the name of this entry.
		/// </summary>
		/// <returns>
		/// The entry's name.
		/// </returns>
		public string GetName()
		{
			return this.name.ToString();
		}
		
		/// <summary>
		/// Parse an octal string from a header buffer. This is used for the
		/// file permission mode value.
		/// </summary>
		/// <param name = "header">
		/// The header buffer from which to parse.
		/// </param>
		/// <param name = "offset">
		/// The offset into the buffer from which to parse.
		/// </param>
		/// <param name = "length">
		/// The number of header bytes to parse.
		/// </param>
		/// <returns>
		/// The long value of the octal string.
		/// </returns>
		public static long ParseOctal(byte[] header, int offset, int length)
		{
			long result = 0;
			bool stillPadding = true;
			
			int end = offset + length;
			for (int i = offset; i < end ; ++i) {
				if (header[i] == 0) {
					break;
				}
				
				if (header[i] == (byte)' ' || header[i] == '0') {
					if (stillPadding) {
						continue;
					}
					
					if (header[i] == (byte)' ') {
						break;
					}
				}
				
				stillPadding = false;
				
				result = (result << 3) + (header[i] - '0');
			}
			
			return result;
		}
		
		/// <summary>
		/// Parse an entry name from a header buffer.
		/// </summary>
		/// <param name="header">
		/// The header buffer from which to parse.
		/// </param>
		/// <param name="offset">
		/// The offset into the buffer from which to parse.
		/// </param>
		/// <param name="length">
		/// The number of header bytes to parse.
		/// </param>
		/// <returns>
		/// The header's entry name.
		/// </returns>
		public static StringBuilder ParseName(byte[] header, int offset, int length)
		{
			StringBuilder result = new StringBuilder(length);
			
			for (int i = offset; i < offset + length; ++i) {
				if (header[i] == 0) {
					break;
				}
				result.Append((char)header[i]);
			}
			
			return result;
		}
		
		/// <summary>
		/// Add <paramref name="name">name</paramref> to the buffer as a collection of bytes
		/// </summary>
		/// <param name="name">the name to add</param>
		/// <param name="nameOffset">the offset of the first character</param>
		/// <param name="buf">the buffer to add to</param>
		/// <param name="bufferOffset">the index of the first byte to add</param>
		/// <param name="length">the number of characters/bytes to add</param>
		/// <returns>the next free index in the <paramref name="buf">buffer</paramref></returns>
		public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buf, int bufferOffset, int length)
		{
			int i;
			
			for (i = 0 ; i < length && nameOffset + i < name.Length; ++i) {
				buf[bufferOffset + i] = (byte)name[nameOffset + i];
			}
			
			for (; i < length ; ++i) {
				buf[bufferOffset + i] = 0;
			}
			
			return bufferOffset + length;
		}

		/// <summary>
		/// Add an entry name to the buffer
		/// </summary>
		/// <param name="name">
		/// The name to add
		/// </param>
		/// <param name="buf">
		/// The buffer to add to
		/// </param>
		/// <param name="offset">
		/// The offset into the buffer from which to start adding
		/// </param>
		/// <param name="length">
		/// The number of header bytes to add
		/// </param>
		/// <returns>
		/// The index of the next free byte in the buffer
		/// </returns>
		public static int GetNameBytes(StringBuilder name, byte[] buf, int offset, int length)
		{
			return GetNameBytes(name, 0, buf, offset, length);
		}
		
		/// <summary>
		/// Put an octal representation of a value into a buffer
		/// </summary>
		/// <param name = "val">
		/// the value to be converted to octal
		/// </param>
		/// <param name = "buf">
		/// buffer to store the octal string
		/// </param>
		/// <param name = "offset">
		/// The offset into the buffer where the value starts
		/// </param>
		/// <param name = "length">
		/// The length of the octal string to create
		/// </param>
		/// <returns>
		/// The offset of the character next byte after the octal string
		/// </returns>
		public static int GetOctalBytes(long val, byte[] buf, int offset, int length)
		{
			int idx = length - 1;

			// Either a space or null is valid here.  We use NULL as per GNUTar
			buf[offset + idx] = 0;
			--idx;

			if (val > 0) {
				for (long v = val; idx >= 0 && v > 0; --idx) {
					buf[offset + idx] = (byte)((byte)'0' + (byte)(v & 7));
					v >>= 3;
				}
			}
				
			for (; idx >= 0; --idx) {
				buf[offset + idx] = (byte)'0';
			}
			
			return offset + length;
		}
		
		/// <summary>
		/// Put an octal representation of a value into a buffer
		/// </summary>
		/// <param name = "val">
		/// Value to be convert to octal
		/// </param>
		/// <param name = "buf">
		/// The buffer to update
		/// </param>
		/// <param name = "offset">
		/// The offset into the buffer to store the value
		/// </param>
		/// <param name = "length">
		/// The length of the octal string
		/// </param>
		/// <returns>
		/// Index of next byte
		/// </returns>
		public static int GetLongOctalBytes(long val, byte[] buf, int offset, int length)
		{
			return GetOctalBytes(val, buf, offset, length);
		}
		
		/// <summary>
		/// Add the checksum octal integer to header buffer.
		/// </summary>
		/// <param name = "val">
		/// </param>
		/// <param name = "buf">
		/// The header buffer to set the checksum for
		/// </param>
		/// <param name = "offset">
		/// The offset into the buffer for the checksum
		/// </param>
		/// <param name = "length">
		/// The number of header bytes to update.
		/// It's formatted differently from the other fields: it has 6 digits, a
		/// null, then a space -- rather than digits, a space, then a null.
		/// The final space is already there, from checksumming
		/// </param>
		/// <returns>
		/// The modified buffer offset
		/// </returns>
		private static int GetCheckSumOctalBytes(long val, byte[] buf, int offset, int length)
		{
			TarHeader.GetOctalBytes(val, buf, offset, length - 1);
//			buf[offset + length - 1] = (byte)' ';  -jr- 23-Jan-2004 this causes failure!!!
//			buf[offset + length - 2] = 0;
			return offset + length;
		}
		
		/// <summary>
		/// Compute the checksum for a tar entry header.  
		/// The checksum field must be all spaces prior to this happening
		/// </summary>
		/// <param name = "buf">
		/// The tar entry's header buffer.
		/// </param>
		/// <returns>
		/// The computed checksum.
		/// </returns>
		private static long ComputeCheckSum(byte[] buf)
		{
			long sum = 0;
			for (int i = 0; i < buf.Length; ++i) {
				sum += buf[i];
			}
			return sum;
		}

		readonly static long     timeConversionFactor = 10000000L;                                    // -jr- 1 tick == 100 nanoseconds
		readonly static DateTime datetTime1970        = new DateTime(1970, 1, 1, 0, 0, 0, 0); 
//		readonly static DateTime datetTime1970        = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToUniversalTime(); // -jr- Should be UTC?  doesnt match Gnutar if this is so though, why?
		
		static int GetCTime(System.DateTime dateTime)
		{
			return (int)((dateTime.Ticks - datetTime1970.Ticks) / timeConversionFactor);
		}
		
		static DateTime GetDateTimeFromCTime(long ticks)
		{
			return new DateTime(datetTime1970.Ticks + ticks * timeConversionFactor);
		}

		/// <summary>
		/// Parse TarHeader information from a header buffer.
		/// </summary>
		/// <param name = "header">
		/// The tar entry header buffer to get information from.
		/// </param>
		public void ParseBuffer(byte[] header)
		{
			int offset = 0;
			
			name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN);
			offset += TarHeader.NAMELEN;
			
			mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN);
			offset += TarHeader.MODELEN;
			
			userId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN);
			offset += TarHeader.UIDLEN;
			
			groupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN);
			offset += TarHeader.GIDLEN;
			
			size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN);
			offset += TarHeader.SIZELEN;
			
			modTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN));
			offset += TarHeader.MODTIMELEN;
			
			checkSum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN);
			offset += TarHeader.CHKSUMLEN;
			
			typeFlag = header[ offset++ ];

			linkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN);
			offset += TarHeader.NAMELEN;
			
			magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN);
			offset += TarHeader.MAGICLEN;
			
			version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN);
			offset += TarHeader.VERSIONLEN;
			
			userName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN);
			offset += TarHeader.UNAMELEN;
			
			groupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN);
			offset += TarHeader.GNAMELEN;
			
			devMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);
			offset += TarHeader.DEVLEN;
			
			devMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);
			
			// Fields past this point not currently parsed or used...
		}

		/// <summary>
		/// 'Write' header information to buffer provided
		/// </summary>
		/// <param name="outbuf">output buffer for header information</param>
		public void WriteHeader(byte[] outbuf)
		{
			int offset = 0;
			
			offset = GetNameBytes(this.name, outbuf, offset, TarHeader.NAMELEN);
			offset = GetOctalBytes(this.mode, outbuf, offset, TarHeader.MODELEN);
			offset = GetOctalBytes(this.userId, outbuf, offset, TarHeader.UIDLEN);
			offset = GetOctalBytes(this.groupId, outbuf, offset, TarHeader.GIDLEN);
			
			long size = this.size;
			
			offset = GetLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);
			offset = GetLongOctalBytes(GetCTime(this.modTime), outbuf, offset, TarHeader.MODTIMELEN);
			
			int csOffset = offset;
			for (int c = 0; c < TarHeader.CHKSUMLEN; ++c) {
				outbuf[offset++] = (byte)' ';
			}
			
			outbuf[offset++] = this.typeFlag;
			
			offset = GetNameBytes(this.linkName, outbuf, offset, NAMELEN);
			offset = GetNameBytes(this.magic, outbuf, offset, MAGICLEN);
			offset = GetNameBytes(this.version, outbuf, offset, VERSIONLEN);
			offset = GetNameBytes(this.userName, outbuf, offset, UNAMELEN);
			offset = GetNameBytes(this.groupName, outbuf, offset, GNAMELEN);
			
			if (this.typeFlag == LF_CHR || this.typeFlag == LF_BLK) {
				offset = GetOctalBytes(this.devMajor, outbuf, offset, DEVLEN);
				offset = GetOctalBytes(this.devMinor, outbuf, offset, DEVLEN);
			}
			
			for ( ; offset < outbuf.Length; ) {
				outbuf[offset++] = 0;
			}
			
			long checkSum = ComputeCheckSum(outbuf);
			
			GetCheckSumOctalBytes(checkSum, outbuf, csOffset, CHKSUMLEN);
		}
	}
}

/* The original Java file had this header:
 * 
** Authored by Timothy Gerard Endres
** <mailto:time@gjt.org>  <http://www.trustice.com>
** 
** This work has been placed into the public domain.
** You may use this work in any way and for any purpose you wish.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE. 
** 
*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?