corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Collections.Generic;
29 using System.IO;
30 using System.Text;
31  
32 namespace OpenMetaverse.Assets
33 {
34 /// <summary>
35 /// Temporary code to produce a tar archive in tar v7 format
36 /// </summary>
37 public class TarArchiveWriter
38 {
39 protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding();
40  
41 /// <summary>
42 /// Binary writer for the underlying stream
43 /// </summary>
44 protected BinaryWriter m_bw;
45  
46 public TarArchiveWriter(Stream s)
47 {
48 m_bw = new BinaryWriter(s);
49 }
50  
51 /// <summary>
52 /// Write a directory entry to the tar archive. We can only handle one path level right now!
53 /// </summary>
54 /// <param name="dirName"></param>
55 public void WriteDir(string dirName)
56 {
57 // Directories are signalled by a final /
58 if (!dirName.EndsWith("/"))
59 dirName += "/";
60  
61 WriteFile(dirName, new byte[0]);
62 }
63  
64 /// <summary>
65 /// Write a file to the tar archive
66 /// </summary>
67 /// <param name="filePath"></param>
68 /// <param name="data"></param>
69 public void WriteFile(string filePath, string data)
70 {
71 WriteFile(filePath, m_asciiEncoding.GetBytes(data));
72 }
73  
74 /// <summary>
75 /// Write a file to the tar archive
76 /// </summary>
77 /// <param name="filePath"></param>
78 /// <param name="data"></param>
79 public void WriteFile(string filePath, byte[] data)
80 {
81 if (filePath.Length > 100)
82 WriteEntry("././@LongLink", m_asciiEncoding.GetBytes(filePath), 'L');
83  
84 char fileType;
85  
86 if (filePath.EndsWith("/"))
87 {
88 fileType = '5';
89 }
90 else
91 {
92 fileType = '0';
93 }
94  
95 WriteEntry(filePath, data, fileType);
96 }
97  
98 /// <summary>
99 /// Finish writing the raw tar archive data to a stream. The stream will be closed on completion.
100 /// </summary>
101 public void Close()
102 {
103 //m_log.Debug("[TAR ARCHIVE WRITER]: Writing final consecutive 0 blocks");
104  
105 // Write two consecutive 0 blocks to end the archive
106 byte[] finalZeroPadding = new byte[1024];
107 m_bw.Write(finalZeroPadding);
108  
109 m_bw.Flush();
110 m_bw.Close();
111 }
112  
113 public static byte[] ConvertDecimalToPaddedOctalBytes(int d, int padding)
114 {
115 string oString = "";
116  
117 while (d > 0)
118 {
119 oString = Convert.ToString((byte)'0' + d & 7) + oString;
120 d >>= 3;
121 }
122  
123 while (oString.Length < padding)
124 {
125 oString = "0" + oString;
126 }
127  
128 byte[] oBytes = m_asciiEncoding.GetBytes(oString);
129  
130 return oBytes;
131 }
132  
133 /// <summary>
134 /// Write a particular entry
135 /// </summary>
136 /// <param name="filePath"></param>
137 /// <param name="data"></param>
138 /// <param name="fileType"></param>
139 protected void WriteEntry(string filePath, byte[] data, char fileType)
140 {
141 byte[] header = new byte[512];
142  
143 // file path field (100)
144 byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
145 int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
146 Array.Copy(nameBytes, header, nameSize);
147  
148 // file mode (8)
149 byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
150 Array.Copy(modeBytes, 0, header, 100, 7);
151  
152 // owner user id (8)
153 byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
154 Array.Copy(ownerIdBytes, 0, header, 108, 7);
155  
156 // group user id (8)
157 byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
158 Array.Copy(groupIdBytes, 0, header, 116, 7);
159  
160 // file size in bytes (12)
161 int fileSize = data.Length;
162 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: File size of {0} is {1}", filePath, fileSize);
163  
164 byte[] fileSizeBytes = ConvertDecimalToPaddedOctalBytes(fileSize, 11);
165  
166 Array.Copy(fileSizeBytes, 0, header, 124, 11);
167  
168 // last modification time (12)
169 byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
170 Array.Copy(lastModTimeBytes, 0, header, 136, 11);
171  
172 // entry type indicator (1)
173 header[156] = m_asciiEncoding.GetBytes(new char[] { fileType })[0];
174  
175 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
176 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
177  
178 // check sum for header block (8) [calculated last]
179 Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
180  
181 int checksum = 0;
182 foreach (byte b in header)
183 {
184 checksum += b;
185 }
186  
187 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Decimal header checksum is {0}", checksum);
188  
189 byte[] checkSumBytes = ConvertDecimalToPaddedOctalBytes(checksum, 6);
190  
191 Array.Copy(checkSumBytes, 0, header, 148, 6);
192  
193 header[154] = 0;
194  
195 // Write out header
196 m_bw.Write(header);
197  
198 // Write out data
199 m_bw.Write(data);
200  
201 if (data.Length % 512 != 0)
202 {
203 int paddingRequired = 512 - (data.Length % 512);
204  
205 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Padding data with {0} bytes", paddingRequired);
206  
207 byte[] padding = new byte[paddingRequired];
208 m_bw.Write(padding);
209 }
210 }
211 }
212 }