opensim-development – Blame information for rev 1

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