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