Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
NSDataOOExtensions.m
Go to the documentation of this file.
1/*
2
3NSDataOOExtensions.m
4
5Extensions to NSData.
6
7
8Copyright (C) 2008-2013 Jens Ayton and contributors
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files (the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions:
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27
28*/
29
30#import "OOCocoa.h"
31#import "unzip.h"
32
33#define ZIP_BUFFER_SIZE 8192
34
35@implementation NSData (OOExtensions)
36
37+ (instancetype) oo_dataWithOXZFile:(NSString *)path
38{
39 NSUInteger i, cl;
40 NSArray *components = [path pathComponents];
41 cl = [components count];
42 for (i = 0 ; i < cl ; i++)
43 {
44 NSString *component = [components objectAtIndex:i];
45 if ([[[component pathExtension] lowercaseString] isEqualToString:@"oxz"])
46 {
47 break;
48 }
49 }
50 // if i == cl then the path is entirely uncompressed
51 if (i == cl)
52 {
53/* -initWithContentsOfMappedFile fails quietly under OS X if there's no file,
54 but GNUstep complains. */
55#if OOLITE_MAC_OS_X
56 return [[[NSData alloc] initWithContentsOfMappedFile:path] autorelease];
57#else
58 NSFileManager *fmgr = [NSFileManager defaultManager];
59 BOOL dir;
60
61 if ([fmgr fileExistsAtPath:path isDirectory:&dir])
62 {
63 if (!dir)
64 {
65 if ([[fmgr fileAttributesAtPath:path traverseLink:NO] fileSize] == 0)
66 {
67 OOLog(kOOLogFileNotFound, @"Expected file but found empty file at %@", path);
68 }
69 else
70 {
71 return [[[NSData alloc] initWithContentsOfMappedFile:path] autorelease];
72 }
73 }
74 else
75 {
76 OOLog(kOOLogFileNotFound, @"Expected file but found directory at %@", path);
77 }
78 }
79 return nil;
80#endif
81 }
82 // otherwise components 0..i are the OXZ path, and i+1..n are the
83 // path inside the OXZ
84 NSRange range;
85 range.location = 0; range.length = i+1;
86 NSString *zipFile = [NSString pathWithComponents:[components subarrayWithRange:range]];
87 range.location = i+1; range.length = cl-(i+1);
88 NSString *containedFile = [NSString pathWithComponents:[components subarrayWithRange:range]];
89
90 unzFile uf = NULL;
91 const char* zipname = [zipFile UTF8String];
92 if (zipname != NULL)
93 {
94 uf = unzOpen64(zipname);
95 }
96 if (uf == NULL)
97 {
98 // This is not necessarily an error - the OXZ manager tries to
99 // do this as a test for the presence of managed OXZs
100// OOLog(kOOLogFileNotFound, @"Could not unzip OXZ at %@", zipFile);
101 return nil;
102 }
103 const char* filename = [containedFile UTF8String];
104 // unzLocateFile(*, *, 1) = case-sensitive extract
105 if (unzLocateFile(uf, filename, 1) != UNZ_OK)
106 {
107 unzClose(uf);
108 /* Much of the time this function is called with the
109 * expectation that the file may not necessarily exist -
110 * e.g. on plist merges, config scans, etc. So don't add log
111 * entries for this failure mode */
112// OOLog(kOOLogFileNotFound, @"Could not find %@ within OXZ at %@", containedFile, zipFile);
113 return nil;
114 }
115
116 int err = UNZ_OK;
117 unz_file_info64 file_info = {0};
118 err = unzGetCurrentFileInfo64(uf, &file_info, NULL, 0, NULL, 0, NULL, 0);
119 if (err != UNZ_OK)
120 {
121 unzClose(uf);
122 OOLog(kOOLogFileNotFound, @"Could not get properties of %@ within OXZ at %@", containedFile, zipFile);
123 return nil;
124 }
125
126 err = unzOpenCurrentFile(uf);
127 if (err != UNZ_OK)
128 {
129 unzClose(uf);
130 OOLog(kOOLogFileNotFound, @"Could not read %@ within OXZ at %@", containedFile, zipFile);
131 return nil;
132 }
133
134
135
136 NSMutableData *tmp = [NSMutableData dataWithCapacity:file_info.uncompressed_size];
137 void *buf = (void*)malloc(ZIP_BUFFER_SIZE);
138 do
139 {
141 if (err < 0)
142 {
143 OOLog(kOOLogFileNotFound, @"Could not read %@ within OXZ at %@ (err %d)", containedFile, zipFile, err);
144 break;
145 }
146 if (err == 0)
147 {
148 break;
149 }
150 [tmp appendBytes:buf length:err];
151 }
152 while (err > 0);
153 free(buf);
154
155 err = unzCloseCurrentFile(uf);
156 if (err != UNZ_OK)
157 {
158 unzClose(uf);
159 OOLog(kOOLogFileNotFound, @"Could not close %@ within OXZ at %@", containedFile, zipFile);
160 return nil;
161 }
162
163 unzClose(uf);
164 return [[tmp retain] autorelease];
165
166}
167
168@end
#define ZIP_BUFFER_SIZE
#define OOLog(class, format,...)
Definition OOLogging.h:88
NSString *const kOOLogFileNotFound
Definition OOLogging.m:652
return nil
const char * filename
Definition ioapi.h:133
voidpf void * buf
Definition ioapi.h:134
int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity)
Definition unzip.c:1238
int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)
Definition unzip.c:1130
int ZEXPORT unzOpenCurrentFile(unzFile file)
Definition unzip.c:1653
int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
Definition unzip.c:1696
unzFile ZEXPORT unzOpen64(const void *path)
Definition unzip.c:801
int ZEXPORT unzCloseCurrentFile(unzFile file)
Definition unzip.c:2016
int ZEXPORT unzClose(unzFile file)
Definition unzip.c:811
voidp unzFile
Definition unzip.h:70
#define UNZ_OK
Definition unzip.h:74