diff options
author | Justin Clarke Casey | 2009-03-04 18:33:05 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2009-03-04 18:33:05 +0000 |
commit | b57497fd41ad4cc56af40139ba940b5a4bbd47a6 (patch) | |
tree | 58bebd6dc61420dd01139cbddde61c955f63c9d9 /OpenSim/Region | |
parent | IObjectFace needs to be public to compile. (diff) | |
download | opensim-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')
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 | ||
28 | using System; | 28 | using System; |
29 | using System.IO; | 29 | using System.IO; |
30 | using System.Reflection; | ||
30 | using System.Text; | 31 | using System.Text; |
32 | using log4net; | ||
31 | 33 | ||
32 | namespace OpenSim.Region.CoreModules.World.Archiver | 34 | namespace 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 | } |