Merge pull request #3749 from BrzVlad/fix-mips-fix
[mono.git] / mcs / class / WindowsBase / ZipSharp / NativeUnzip.cs
1 // NativeUnzip.cs created with MonoDevelop
2 // User: alan at 13:11 20/10/2008
3 //
4 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
5 //
6
7 using System;
8 using System.Collections.Generic;
9 using System.IO;
10 using System.IO.Packaging;
11 using System.Runtime.InteropServices;
12 using System.Text;
13
14 namespace zipsharp
15 {
16         static class NativeUnzip
17         {
18                 enum ZipStringComparison
19                 {
20                         OSDefault = 0,
21                         CaseSensitive = 1,
22                         CaseInsensitive = 2
23                 }
24                 
25                 public static void CloseArchive (UnzipHandle handle)
26                 {
27                         unzClose (handle);
28                         handle.SetHandleAsInvalid ();
29                 }
30
31                 public static void CloseCurrentFile (UnzipHandle handle)
32                 {
33                         if (unzCloseCurrentFile (handle) != 0)
34                                 throw new Exception ("Could not close the active file");
35                 }
36
37                 static CompressionOption ConvertCompression (int compressionLevel)
38                 {
39                         switch (compressionLevel)
40                         {
41                         case 1:
42                         case 2:
43                                 return CompressionOption.SuperFast;
44                                 
45                         case 3:
46                         case 4:
47                                 return CompressionOption.Fast;
48                                 
49                         case 5:
50                         case 6:
51                                 return CompressionOption.Normal;
52                                 
53                         case 7:
54                         case 8:
55                         case 9:
56                                 return CompressionOption.Maximum;
57
58                         default:
59                                 return CompressionOption.NotCompressed;
60                         }
61                 }
62
63                 public static long CurrentFilePosition (UnzipHandle handle)
64                 {
65                         return unztell(handle).ToInt64 ();
66                 }
67
68                 public static long CurrentFileLength32 (UnzipHandle handle)
69                 {
70                         UnzipFileInfo32 info;
71                         int result = unzGetCurrentFileInfo_32 (handle, out info, null, 0, IntPtr.Zero, 0, null,  0);
72                         return result != 0 ? -1 : (long) info.uncompressed_size;
73                 }
74
75                 public static long CurrentFileLength64 (UnzipHandle handle)
76                 {
77                         UnzipFileInfo64 info;
78                         int result = unzGetCurrentFileInfo_64 (handle, out info, null, 0, IntPtr.Zero, 0, null,  0);
79                         return result != 0 ? -1 : (long) info.uncompressed_size;
80                 }
81
82                 static string GetCurrentFileName32 (UnzipHandle handle)
83                 {
84                         UnzipFileInfo32 info;
85                         if (unzGetCurrentFileInfo_32 (handle, out info, null, 0, IntPtr.Zero, 0, null, 0) != 0)
86                                 return null;
87                         var sbName = new StringBuilder ((int) info.size_filename + 1); // +1 to account for extra \0 at the end
88                         if (unzGetCurrentFileInfo_32 (handle, out info, sbName, (uint) sbName.Capacity, IntPtr.Zero, 0, null, 0) != 0)
89                                 return null;
90                         return sbName.ToString ();
91                 }
92
93                 static string GetCurrentFileName64 (UnzipHandle handle)
94                 {
95                         UnzipFileInfo64 info;
96                         if (unzGetCurrentFileInfo_64 (handle, out info, null, 0, IntPtr.Zero, 0, null, 0) != 0)
97                                 return null;
98                         var sbName = new StringBuilder ((int) info.size_filename + 1); // +1 to account for extra \0 at the end
99                         if (unzGetCurrentFileInfo_64 (handle, out info, sbName, (uint) sbName.Capacity, IntPtr.Zero, 0, null, 0) != 0)
100                                 return null;
101                         return sbName.ToString ();
102                 }
103
104                 public static string[] GetFiles32 (UnzipHandle handle)
105                 {
106                         return GetFiles (handle, GetCurrentFileName32);
107                 }
108
109                 public static string[] GetFiles64 (UnzipHandle handle)
110                 {
111                         return GetFiles (handle, GetCurrentFileName64);
112                 }
113
114                 private static string[] GetFiles (UnzipHandle handle, Func<UnzipHandle, string> getCurrentFileName)
115                 {
116                         GoToFirstFile (handle);
117                         var files = new List<string> ();
118                         string name;
119                         while ((name = getCurrentFileName (handle)) != null) {
120                                 files.Add (name);
121                                 if (!NativeUnzip.GoToNextFile (handle))
122                                         break;
123                         }
124                         
125                         return files.ToArray ();
126                 }
127
128                 static void GoToFirstFile (UnzipHandle handle)
129                 {
130                         if (NativeUnzip.unzGoToFirstFile (handle) != 0)
131                                 throw new Exception ("Zip file is invalid");
132                 }
133
134                 static bool GoToNextFile (UnzipHandle handle)
135                 {
136                         return unzGoToNextFile(handle) == 0;
137                 }
138                 
139                 public static UnzipHandle OpenArchive32 (ZlibFileFuncDef32 fileFuncs)
140                 {
141                         UnzipHandle handle = unzOpen2_32 ("", ref fileFuncs);
142                         if (handle.IsInvalid)
143                                 throw new Exception ("Could not open unzip archive");
144                         return handle;
145                 }
146
147                 public static UnzipHandle OpenArchive64 (ZlibFileFuncDef64 fileFuncs)
148                 {
149                         UnzipHandle handle = unzOpen2_64 ("", ref fileFuncs);
150                         if (handle.IsInvalid)
151                                 throw new Exception ("Could not open unzip archive");
152                         return handle;
153                 }
154
155                 public static void OpenFile (UnzipHandle handle, string name, out CompressionOption level)
156                 {
157                         if (unzLocateFile (handle, name, (int) ZipStringComparison.CaseInsensitive) != 0)
158                                 throw new Exception ("The file doesn't exist");
159                         
160                         int method, compression;
161                         // '0' means do not open in raw mode (raw == do not decompress)
162                         if (unzOpenCurrentFile2 (handle, out method, out compression, 0) != 0)
163                                 throw new Exception ("The file could not be opened");
164
165                         level = ConvertCompression (method == 0 ? 0 : compression);
166                 }
167
168                 public static unsafe int Read (UnzipHandle handle, byte[] buffer, int offset, int count)
169                 {
170                         if ((buffer.Length - offset) > count)
171                                 throw new ArgumentOutOfRangeException ("count", "Buffer is too small to read that amount of data");
172                         
173                         fixed (byte * b = &buffer[offset])
174                                 return unzReadCurrentFile (handle, b, (uint)count);
175                 }
176
177                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
178                 static extern int unzCloseCurrentFile (UnzipHandle handle);
179
180                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
181                 static extern IntPtr unztell (UnzipHandle handle);
182                 
183                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
184                 static extern int unzGoToFirstFile (UnzipHandle handle);
185
186                 [DllImport ("MonoPosixHelper", EntryPoint="unzOpen2", CallingConvention=CallingConvention.Cdecl)]
187                 static extern UnzipHandle unzOpen2_32 (string path,
188                                                        ref ZlibFileFuncDef32 pzlib_filefunc_def);
189
190                 [DllImport ("MonoPosixHelper", EntryPoint="unzOpen2", CallingConvention=CallingConvention.Cdecl)]
191                 static extern UnzipHandle unzOpen2_64 (string path,
192                                                        ref ZlibFileFuncDef64 pzlib_filefunc_def);
193
194                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
195                 static extern int unzGoToNextFile (UnzipHandle handle);
196
197                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
198                 static extern int unzLocateFile (UnzipHandle handle,
199                                                          string szFileName,
200                                                          int iCaseSensitivity);
201
202                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
203                 static extern int unzOpenCurrentFile2 (UnzipHandle handle,
204                                                        out int method,
205                                                        out int level,
206                                                        int raw);
207
208                 [DllImport ("MonoPosixHelper", EntryPoint="unzGetCurrentFileInfo", CallingConvention=CallingConvention.Cdecl)]
209                 static extern int unzGetCurrentFileInfo_32 (UnzipHandle handle,
210                                                             out UnzipFileInfo32 pfile_info,
211                                                             StringBuilder szFileName,
212                                                             uint fileNameBufferSize,   // uLong
213                                                             IntPtr extraField,         // void *
214                                                             uint extraFieldBufferSize, // uLong
215                                                             StringBuilder szComment,
216                                                             uint commentBufferSize);   // uLong
217
218                 [DllImport ("MonoPosixHelper", EntryPoint="unzGetCurrentFileInfo", CallingConvention=CallingConvention.Cdecl)]
219                 static extern int unzGetCurrentFileInfo_64 (UnzipHandle handle,
220                                                             out UnzipFileInfo64 pfile_info,
221                                                             StringBuilder szFileName,
222                                                             ulong fileNameBufferSize,   // uLong
223                                                             IntPtr extraField,          // void *
224                                                             ulong extraFieldBufferSize, // uLong
225                                                             StringBuilder szComment,
226                                                             ulong commentBufferSize);   // uLong
227
228                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
229                 static unsafe extern int unzReadCurrentFile (UnzipHandle handle,
230                                                               byte* buf, // voidp
231                                                               uint len);
232
233                 //[DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
234                 //static extern int unzSetOffset (UnzipHandle handle, IntPtr pos); // uLong
235                 
236                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
237                 static extern int unzClose (UnzipHandle handle);
238         }
239 }