1 /**
2 * @file libcomprex/archive_io.c Archive I/O Functions
3 *
4 * $Id: archive_io.c,v 1.12 2003/01/02 02:49:38 chipx86 Exp $
5 *
6 * @Copyright (C) 2001-2003 The GNUpdate Project.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23 #include <stdio.h>
24 #include <libcomprex/internal.h>
25
26 CxArchive *
cxOpenArchive(const char * path)27 cxOpenArchive(const char *path)
28 {
29 CxArchive *archive;
30
31 if (path == NULL)
32 return NULL;
33
34 cxOpenArchiveOrFile(path, CX_MODE_READ_ONLY, NULL, &archive);
35
36 return archive;
37 }
38
39 CxArchive *
cxOpenArchiveStream(FILE * fp)40 cxOpenArchiveStream(FILE *fp)
41 {
42 CxArchive *archive;
43
44 if (fp == NULL)
45 return NULL;
46
47 cxInternalOpenStream(fp, CX_MODE_READ_ONLY, NULL, &archive);
48
49 return archive;
50 }
51
52 CxArchive *
cxOpenArchiveFromHandle(CxFile * file,CxAccessMode mode)53 cxOpenArchiveFromHandle(CxFile *file, CxAccessMode mode)
54 {
55 CxFP *fp;
56 CxArchive *archive;
57
58 if (file == NULL)
59 return NULL;
60
61 if ((fp = cxOpenFileHandle(file, mode)) == NULL)
62 return NULL;
63
64 cxOpenArchiveOrFile2(fp, CX_MODE_READ_ONLY, NULL, &archive);
65
66 return archive;
67 }
68
69 CxArchive *
cxOpenArchiveBuffer(char * buffer,size_t size)70 cxOpenArchiveBuffer(char *buffer, size_t size)
71 {
72 CxArchive *archive;
73
74 if (buffer == NULL || size == 0)
75 return NULL;
76
77 cxInternalOpenBuffer(buffer, size, CX_MODE_READ_ONLY, NULL, &archive);
78
79 return archive;
80 }
81
82 void
cxCloseArchive(CxArchive * archive)83 cxCloseArchive(CxArchive *archive)
84 {
85 if (archive == NULL)
86 return;
87
88 cxDestroyArchive(archive);
89 }
90
91 CxStatus
cxSaveArchive(CxArchive * archive,const char * path)92 cxSaveArchive(CxArchive *archive, const char *path)
93 {
94 const char *ext;
95 char *basename;
96 CxFP *fp;
97 CxModule *module;
98 CxStatus status;
99
100 if (archive == NULL)
101 return CX_ERROR;
102
103 if (path == NULL)
104 {
105 if (cxGetArchiveFileName(archive) == NULL)
106 return CX_ERROR;
107
108 path = cxGetArchiveFileName(archive);
109 }
110
111 ext = strrchr(path, '.');
112
113 if (ext == NULL)
114 return CX_NOT_SUPPORTED;
115
116 ext++;
117
118 /* Let's find a module that can save this. */
119 for (module = cxGetFirstModule(CX_MODULE_ARCHIVE);
120 module != NULL;
121 module = module->next)
122 {
123 if (module->ops.archive->supportsExtension(ext))
124 {
125 cxSetArchiveModule(archive, module);
126 break;
127 }
128 }
129
130 if (archive->module == NULL)
131 return CX_NOT_SUPPORTED;
132
133 /* Try to open the file for writing. */
134 fp = cxOpenFile(path, CX_MODE_READ_WRITE);
135
136 if (fp == NULL)
137 return CX_ERROR;
138
139 /* Set info about the archive. */
140 basename = cxGetBaseName(path);
141 cxSetArchiveFileName(archive, basename);
142 free(basename);
143
144 cxSetArchivePhysicalPath(archive, path);
145 cxSetArchivePath(archive, path);
146
147 cxSetArchiveLocal(archive, 1);
148
149 /* Write the archive. */
150 status = archive->module->ops.archive->saveArchive(archive, fp);
151
152 /* TODO: Set info about the file size and archive size. */
153
154 /* Close up. */
155 cxClose(fp);
156
157 return status;
158 }
159
160 CxStatus
cxExtractArchive(CxArchive * archive)161 cxExtractArchive(CxArchive *archive)
162 {
163 CxFsIterator *iter;
164 CxFsNode *node;
165 size_t fileCount, onFile = 0;
166
167 if (archive == NULL)
168 return CX_ERROR;
169
170 iter = cxNewFsIterator(archive, CX_FSITER_FILES_DIRS);
171 fileCount = cxGetArchiveFileCount(archive);
172
173 if (iter == NULL)
174 return CX_ERROR;
175
176 for (node = cxGetFsIterFirst(iter);
177 node != NULL;
178 node = cxGetFsIterNext(iter))
179 {
180 if (cxGetFsNodeType(node) == CX_FSNODETYPE_DIRECTORY)
181 {
182 cxMakePhysDirs(cxGetDirPath(node), archive);
183 }
184 else if (cxGetFsNodeType(node) == CX_FSNODETYPE_FILE)
185 {
186 /* Do you invoke my wrath?! */
187 if (archive->ex_callback != NULL)
188 archive->ex_callback(archive, node, ++onFile, fileCount);
189
190 cxInternalExtractFile(node, cxGetFsNodePath(node));
191 }
192 }
193
194 return CX_SUCCESS;
195 }
196
197