aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJustin Clarke Casey2009-03-04 18:33:05 +0000
committerJustin Clarke Casey2009-03-04 18:33:05 +0000
commitb57497fd41ad4cc56af40139ba940b5a4bbd47a6 (patch)
tree58bebd6dc61420dd01139cbddde61c955f63c9d9 /OpenSim/Region
parentIObjectFace needs to be public to compile. (diff)
downloadopensim-SC-b57497fd41ad4cc56af40139ba940b5a4bbd47a6.zip
opensim-SC-b57497fd41ad4cc56af40139ba940b5a4bbd47a6.tar.gz
opensim-SC-b57497fd41ad4cc56af40139ba940b5a4bbd47a6.tar.bz2
opensim-SC-b57497fd41ad4cc56af40139ba940b5a4bbd47a6.tar.xz
* Add gnu tar format long file name support to tar reading and writing.
* Not actually tested yet though existing code which doesn't require long file names looks fine
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs22
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs185
3 files changed, 126 insertions, 85 deletions
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index fe1c42b..3525e04 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -111,8 +111,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
111 111
112 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 112 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
113 { 113 {
114 m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", 114 m_log.WarnFormat(
115 filePath); 115 "[ARCHIVER]: Ignoring directory entry {0}", filePath);
116 } 116 }
117 else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) 117 else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
118 { 118 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs
index a1884d5..afe5938 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs
@@ -27,7 +27,9 @@
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Reflection;
30using System.Text; 31using System.Text;
32using log4net;
31 33
32namespace OpenSim.Region.CoreModules.World.Archiver 34namespace OpenSim.Region.CoreModules.World.Archiver
33{ 35{
@@ -36,7 +38,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
36 /// </summary> 38 /// </summary>
37 public class TarArchiveReader 39 public class TarArchiveReader
38 { 40 {
39 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 42
41 public enum TarEntryType 43 public enum TarEntryType
42 { 44 {
@@ -116,12 +118,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver
116 // If we've reached the end of the archive we'll be in null block territory, which means 118 // If we've reached the end of the archive we'll be in null block territory, which means
117 // the next byte will be 0 119 // the next byte will be 0
118 if (header[0] == 0) 120 if (header[0] == 0)
119 return null; 121 return null;
120 122
121 TarHeader tarHeader = new TarHeader(); 123 TarHeader tarHeader = new TarHeader();
122 124
123 tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100); 125 // If we're looking at a GNU tar long link then extract the long name and pull up the next header
124 tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray); 126 if (header[156] == (byte)'L')
127 {
128 int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11);
129 tarHeader.FilePath = m_asciiEncoding.GetString(m_br.ReadBytes(longNameLength));
130 m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath);
131 header = m_br.ReadBytes(512);
132 }
133 else
134 {
135 tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100);
136 tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
137 }
138
125 tarHeader.FileSize = ConvertOctalBytesToDecimal(header, 124, 11); 139 tarHeader.FileSize = ConvertOctalBytesToDecimal(header, 124, 11);
126 140
127 switch (header[156]) 141 switch (header[156])
diff --git a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs
index f8e649e..09ea7ec 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
75 { 75 {
76 m_files[filePath] = data; 76 m_files[filePath] = data;
77 } 77 }
78 78
79 /// <summary> 79 /// <summary>
80 /// Write the raw tar archive data to a stream. The stream will be closed on completion. 80 /// Write the raw tar archive data to a stream. The stream will be closed on completion.
81 /// </summary> 81 /// </summary>
@@ -87,84 +87,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
87 87
88 foreach (string filePath in m_files.Keys) 88 foreach (string filePath in m_files.Keys)
89 { 89 {
90 byte[] header = new byte[512]; 90 WriteFile(bw, filePath, m_files[filePath]);
91 byte[] data = m_files[filePath];
92
93 // file path field (100)
94 byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
95 int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
96 Array.Copy(nameBytes, header, nameSize);
97
98 // file mode (8)
99 byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
100 Array.Copy(modeBytes, 0, header, 100, 7);
101
102 // owner user id (8)
103 byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
104 Array.Copy(ownerIdBytes, 0, header, 108, 7);
105
106 // group user id (8)
107 byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
108 Array.Copy(groupIdBytes, 0, header, 116, 7);
109
110 // file size in bytes (12)
111 int fileSize = data.Length;
112 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: File size of {0} is {1}", filePath, fileSize);
113
114 byte[] fileSizeBytes = ConvertDecimalToPaddedOctalBytes(fileSize, 11);
115
116 Array.Copy(fileSizeBytes, 0, header, 124, 11);
117
118 // last modification time (12)
119 byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
120 Array.Copy(lastModTimeBytes, 0, header, 136, 11);
121
122 // link indicator (1)
123 //header[156] = m_asciiEncoding.GetBytes("0")[0];
124 if (filePath.EndsWith("/"))
125 {
126 header[156] = m_asciiEncoding.GetBytes("5")[0];
127 }
128 else
129 {
130 header[156] = 0;
131 }
132
133 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
134 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
135
136 // check sum for header block (8) [calculated last]
137 Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
138
139 int checksum = 0;
140 foreach (byte b in header)
141 {
142 checksum += b;
143 }
144
145 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Decimal header checksum is {0}", checksum);
146
147 byte[] checkSumBytes = ConvertDecimalToPaddedOctalBytes(checksum, 6);
148
149 Array.Copy(checkSumBytes, 0, header, 148, 6);
150
151 header[154] = 0;
152
153 // Write out header
154 bw.Write(header);
155
156 // Write out data
157 bw.Write(data);
158
159 if (data.Length % 512 != 0)
160 {
161 int paddingRequired = 512 - (data.Length % 512);
162
163 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Padding data with {0} bytes", paddingRequired);
164
165 byte[] padding = new byte[paddingRequired];
166 bw.Write(padding);
167 }
168 } 91 }
169 92
170 //m_log.Debug("[TAR ARCHIVE WRITER]: Writing final consecutive 0 blocks"); 93 //m_log.Debug("[TAR ARCHIVE WRITER]: Writing final consecutive 0 blocks");
@@ -195,6 +118,110 @@ namespace OpenSim.Region.CoreModules.World.Archiver
195 byte[] oBytes = m_asciiEncoding.GetBytes(oString); 118 byte[] oBytes = m_asciiEncoding.GetBytes(oString);
196 119
197 return oBytes; 120 return oBytes;
121 }
122
123 /// <summary>
124 /// Write a particular file of data
125 /// </summary>
126 /// <param name="filePath"></param>
127 /// <param name="data"></param>
128 protected void WriteFile(BinaryWriter bw, string filePath, byte[] data)
129 {
130 if (filePath.Length > 100)
131 WriteEntry(bw, "././@LongLink", m_asciiEncoding.GetBytes(filePath), 'L');
132
133 char fileType;
134
135 if (filePath.EndsWith("/"))
136 {
137 fileType = '5';
138 }
139 else
140 {
141 fileType = '0';
142 }
143
144 WriteEntry(bw, filePath, data, fileType);
198 } 145 }
146
147 /// <summary>
148 /// Write a particular file of data
149 /// </summary>
150 /// <param name="bw"></param>
151 /// <param name="filePath"></param>
152 /// <param name="data"></param>
153 /// <param name="fileType"></param>
154 protected void WriteEntry(BinaryWriter bw, string filePath, byte[] data, char fileType)
155 {
156 byte[] header = new byte[512];
157
158 // file path field (100)
159 byte[] nameBytes = m_asciiEncoding.GetBytes(filePath);
160 int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length;
161 Array.Copy(nameBytes, header, nameSize);
162
163 // file mode (8)
164 byte[] modeBytes = m_asciiEncoding.GetBytes("0000777");
165 Array.Copy(modeBytes, 0, header, 100, 7);
166
167 // owner user id (8)
168 byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764");
169 Array.Copy(ownerIdBytes, 0, header, 108, 7);
170
171 // group user id (8)
172 byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764");
173 Array.Copy(groupIdBytes, 0, header, 116, 7);
174
175 // file size in bytes (12)
176 int fileSize = data.Length;
177 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: File size of {0} is {1}", filePath, fileSize);
178
179 byte[] fileSizeBytes = ConvertDecimalToPaddedOctalBytes(fileSize, 11);
180
181 Array.Copy(fileSizeBytes, 0, header, 124, 11);
182
183 // last modification time (12)
184 byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332");
185 Array.Copy(lastModTimeBytes, 0, header, 136, 11);
186
187 // entry type indicator (1)
188 header[156] = m_asciiEncoding.GetBytes(new char[] { fileType })[0];
189
190 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7);
191 Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7);
192
193 // check sum for header block (8) [calculated last]
194 Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8);
195
196 int checksum = 0;
197 foreach (byte b in header)
198 {
199 checksum += b;
200 }
201
202 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Decimal header checksum is {0}", checksum);
203
204 byte[] checkSumBytes = ConvertDecimalToPaddedOctalBytes(checksum, 6);
205
206 Array.Copy(checkSumBytes, 0, header, 148, 6);
207
208 header[154] = 0;
209
210 // Write out header
211 bw.Write(header);
212
213 // Write out data
214 bw.Write(data);
215
216 if (data.Length % 512 != 0)
217 {
218 int paddingRequired = 512 - (data.Length % 512);
219
220 //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Padding data with {0} bytes", paddingRequired);
221
222 byte[] padding = new byte[paddingRequired];
223 bw.Write(padding);
224 }
225 }
199 } 226 }
200} 227}