"Fossies" - the Fresh Open Source Software Archive 
Member "unipkg-0.6.5/unipkglib/unipkg-arch.c" (16 Dec 2005, 13944 Bytes) of package /linux/privat/old/unipkg-0.6.5.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /******************************************************************************\
2 * *
3 * UNIPKG (c) iSteve <isteve@bofh.cz>, 2005 *
4 * *
5 * Universal PacKaGer. *
6 * Licensed under GNU/GPL - if you don't like the software, fix it! *
7 * *
8 \******************************************************************************/
9
10 ///////////////////////////////////////////////////////////////////////////////
11 // //
12 // B A S E I N C L U S I O N S A N D D E F I N I T I O N S //
13 // //
14 ///////////////////////////////////////////////////////////////////////////////
15 #define _GNU_SOURCE
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <sys/types.h>
22 #include <sys/mman.h>
23 #include <sys/stat.h>
24
25 #ifdef HAVE_SYSMACROS_H
26 #include <sys/sysmacros.h>
27 #endif
28
29 #include <errno.h>
30 #include <zlib.h>
31
32 #include "../archive.h"
33 #include "../common.h"
34 #include "../compression.h"
35
36 ///////////////////////////////////////////////////////////////////////////////
37 // //
38 // B A S E F U N C T I O N S //
39 // //
40 ///////////////////////////////////////////////////////////////////////////////
41
42 // SWITCH_CONTROL_NAMES()
43 //
44 // Identifies the filename as a significant file.
45 //
46 // Parameters:
47 // the filename
48 //
49 // Return value:
50 // 0 if .PKGINFO
51 // 1 if .FILELIST
52 // 2 if .INSTALL or ._install
53 // -1 if none of above (eg. md5sum)
54 // -2 if none of above, but matches "\.[A-Z]*"
55 static int switch_control_names(char *fn) {
56 char *bn;
57
58 bn = basename(fn);
59 if (!strcmp(basename(fn), ".PKGINFO")) { return 0; }
60 if (!strcmp(basename(fn), ".FILELIST")) { return 1; }
61 if ((!strcmp(basename(fn), ".INSTALL")) || (!strcmp(basename(fn), "._install"))) { return 2; }
62 return -1;
63 }
64
65 // GETPKGINFOHDR()
66 //
67 // Gets a value from arch's pkginfo file
68 //
69 // Parameters:
70 // the whole control file
71 // the header we look for
72 // the size of the control file
73 //
74 // Return value:
75 // malloced string
76 static char *getpkginfohdr(char *fullfile, char *hdr, off_t size) {
77 char *start, *end, *tar;
78
79 if ((start = pstrnstr(fullfile, hdr, size, 0)) == NULL) {
80 return NULL;
81 }
82 if (start != fullfile) { // Is it at the start of the file?
83 if (*(start-1) != '\n') { // No? And is it on a new line?
84 return NULL; // No? Baibai.
85 }
86 }
87 start = start + strlen(hdr);
88
89 while ((*start == ' ') && (start < fullfile+size)) { start++; } // Skip all spaces after the start, since there may be issues.
90 if (start == fullfile + size) return NULL;
91 if (*start == '=') start++;
92 if (start == fullfile + size) return NULL;
93 while ((*start == ' ') && (start < fullfile+size)) { start++; } // Skip all spaces after the equation
94
95 if ((end = pstrnstr(start, "\n", size, 0)) == NULL) {
96 return NULL;
97 }
98 tar = malloc((int)end - (int)start + 1);
99 strncpy(tar, start, (int)end - (int)start);
100 tar[(int)end - (int)start] = 0x0;
101 return tar;
102 }
103
104 ///////////////////////////////////////////////////////////////////////////////
105 // //
106 // A P I F U N C T I O N S //
107 // //
108 ///////////////////////////////////////////////////////////////////////////////
109
110 int identify(packdef pdef) {
111 c_compdata cstream;
112 comarchive *tar_archive;
113 struct stat statbuf;
114 void *filemap;
115
116 char *obuf;
117 unsigned long obuflen;
118
119 int err;
120
121 fstat(fileno(pdef.filepointer), &statbuf);
122 filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
123 if (filemap == MAP_FAILED) { return 2; }
124
125 obuflen = 512;
126 obuf = malloc(obuflen);
127
128 err = decompression_setup(&cstream, filemap, 0, statbuf.st_size, obuf, obuflen, C_GZIP);
129 if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
130 decompression_cleanup(&cstream);
131 munmap(filemap, statbuf.st_size);
132 free(obuf);
133 return 2;
134 }
135
136 tar_archive = init_archive(AT_TAR);
137 do {
138 if (tar_archive->stage == AS_NEWFILE) {
139 if (switch_control_names(tar_archive->name) == 0) {
140 deinit_archive(tar_archive);
141 decompression_cleanup(&cstream);
142 free(obuf);
143 munmap(filemap, statbuf.st_size);
144
145 return 0;
146 }
147 }
148
149 update_nextblock(tar_archive);
150 if (tar_archive->nextblock > obuflen) {
151 obuflen = tar_archive->nextblock;
152 obuf = realloc(obuf, obuflen);
153 }
154
155 if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
156 break;
157
158 if (decompression_ammount_not_processed(&cstream) > 0)
159 break;
160
161 update_stage(tar_archive);
162
163 switch (tar_archive->stage) {
164 case AS_DATA:
165 update_upfilesize(tar_archive);
166 break;
167 case AS_HEADER:
168 clear_archive_member(tar_archive);
169 break;
170 }
171
172 err = parse_block(tar_archive, obuf);
173
174 if (err)
175 break;
176 } while (decompression_ammount_left(&cstream, 0) > 0);
177 deinit_archive(tar_archive);
178 decompression_cleanup(&cstream);
179
180 free(obuf);
181 munmap(filemap, statbuf.st_size);
182
183 return 1;
184 }
185 int pkgdetails(packdef pdef, pkginfo *pinfo) {
186 c_compdata cstream;
187 comarchive *tar_archive;
188 struct stat statbuf;
189 void *filemap;
190
191 char *obuf;
192 unsigned long obuflen;
193
194 int err;
195
196 char *fullfile;
197
198 fstat(fileno(pdef.filepointer), &statbuf);
199 filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
200 if (filemap == MAP_FAILED) { return 1; }
201
202 obuflen = 512;
203 obuf = malloc(obuflen);
204
205 err = decompression_setup(&cstream, filemap, 0, statbuf.st_size, obuf, obuflen, C_GZIP);
206 if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
207 decompression_cleanup(&cstream);
208 munmap(filemap, statbuf.st_size);
209 free(obuf);
210 return 1;
211 }
212
213 fullfile = NULL;
214
215 tar_archive = init_archive(AT_TAR);
216 do {
217 if (tar_archive->stage == AS_NEWFILE) {
218 switch (switch_control_names(tar_archive->name)) {
219 case 0:
220 case 2:
221 fullfile = malloc(tar_archive->filesize);
222 break;
223
224 case -1:
225 addfile(pinfo, absolutizestr(tar_archive->name, "/"), (tar_archive->ftype == AF_DIRECTORY) ? F_DIRECTORY : F_REGULAR);
226 pinfo->pkgsize += tar_archive->filesize;
227 break;
228 }
229 }
230
231 update_nextblock(tar_archive);
232 if (tar_archive->nextblock > obuflen) {
233 obuflen = tar_archive->nextblock;
234 obuf = realloc(obuf, obuflen);
235 }
236
237 if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
238 break;
239
240 if (decompression_ammount_not_processed(&cstream) > 0)
241 break;
242
243 update_stage(tar_archive);
244
245 switch (tar_archive->stage) {
246 case AS_DATA:
247 if (fullfile != NULL) {
248 memcpy(fullfile + tar_archive->upfilesize, obuf, ((tar_archive->filesize - tar_archive->upfilesize) > tar_archive->nextblock) ? tar_archive->nextblock : tar_archive->filesize - tar_archive->upfilesize);
249 }
250
251 update_upfilesize(tar_archive);
252 break;
253 case AS_HEADER:
254 if (fullfile != NULL) {
255 switch (switch_control_names(tar_archive->name)) {
256 case 0:
257 pinfo->name = getpkginfohdr(fullfile, "pkgname", tar_archive->filesize);
258 pinfo->version = getpkginfohdr(fullfile, "pkgver", tar_archive->filesize);
259 pinfo->description = getpkginfohdr(fullfile, "pkgdesc", tar_archive->filesize);
260 break;
261 case 2:
262 // A hack; we copy the script to all possible places and alter arguments. Cool, innit?
263 pinfo->preinst.len = tar_archive->filesize;
264 pinfo->postinst.len = tar_archive->filesize;
265 pinfo->prerm.len = tar_archive->filesize;
266 pinfo->postrm.len = tar_archive->filesize;
267
268 pinfo->preinst.data = malloc(pinfo->preinst.len);
269 pinfo->postinst.data = malloc(pinfo->postinst.len);
270 pinfo->prerm.data = malloc(pinfo->prerm.len);
271 pinfo->postrm.data = malloc(pinfo->postrm.len);
272
273 memcpy(pinfo->preinst.data, fullfile, tar_archive->filesize);
274 memcpy(pinfo->postinst.data, fullfile, tar_archive->filesize);
275 memcpy(pinfo->prerm.data, fullfile, tar_archive->filesize);
276 memcpy(pinfo->postrm.data, fullfile, tar_archive->filesize);
277
278 pinfo->preinst.parameters[A_IRRELEVANT] = strdup("pre_install");
279 pinfo->preinst.parameters[A_UPGRADE] = strdup("pre_upgrade");
280 pinfo->preinst.parameters[A_DOWNGRADE] = strdup("pre_upgrade");
281 pinfo->preinst.parameters[A_REINSTALL] = strdup("pre_upgrade");
282
283 pinfo->postinst.parameters[A_IRRELEVANT] = strdup("post_install");
284 pinfo->postinst.parameters[A_UPGRADE] = strdup("post_upgrade");
285 pinfo->postinst.parameters[A_DOWNGRADE] = strdup("post_upgrade");
286 pinfo->postinst.parameters[A_REINSTALL] = strdup("post_upgrade");
287
288 pinfo->prerm.parameters[A_IRRELEVANT] = strdup("pre_remove");
289
290 pinfo->postrm.parameters[A_IRRELEVANT] = strdup("post_remove");
291 break;
292 }
293 free(fullfile);
294 fullfile = NULL;
295 }
296 clear_archive_member(tar_archive);
297 break;
298 }
299
300 err = parse_block(tar_archive, obuf);
301
302 if (err)
303 break;
304 } while (decompression_ammount_left(&cstream, 0) > 0);
305 deinit_archive(tar_archive);
306 decompression_cleanup(&cstream);
307
308 free(obuf);
309 munmap(filemap, statbuf.st_size);
310
311 if (pinfo->description == NULL) { pinfo->description = strdup("ArchLinux package, no description."); }
312 if (pinfo->version == NULL) { pinfo->version = strdup("unknown"); }
313 if (pinfo->name == NULL) { return 1; }
314
315 return 0;
316 }
317 int pkginstall(packdef pdef) {
318 c_compdata cstream;
319 comarchive *tar_archive;
320 struct stat statbuf;
321 void *filemap;
322
323 char *obuf;
324 unsigned long obuflen;
325
326 int err;
327 FILE *fpout;
328 char *curpath;
329
330 fpout = NULL;
331 curpath = NULL;
332
333 fstat(fileno(pdef.filepointer), &statbuf);
334 filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
335 if (filemap == MAP_FAILED) { return 1; }
336
337 obuflen = 512;
338 obuf = malloc(obuflen);
339
340 err = decompression_setup(&cstream, filemap, 0, statbuf.st_size, obuf, obuflen, C_GZIP);
341 if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
342 decompression_cleanup(&cstream);
343 munmap(filemap, statbuf.st_size);
344 free(obuf);
345 return 1;
346 }
347
348 tar_archive = init_archive(AT_TAR);
349 do {
350 if (tar_archive->stage == AS_NEWFILE) {
351 free(curpath);
352 curpath = absolutizestr(tar_archive->name, pdef.destdir);
353 if (switch_control_names(tar_archive->name) == -1) {
354 switch (tar_archive->ftype) {
355 case AF_REGULAR:
356 if (fpout != NULL) {
357 fclose(fpout);
358 }
359 if ((fpout = fopen(curpath, "w")) == NULL) {
360 free(curpath);
361 free(obuf);
362 decompression_cleanup(&cstream);
363 munmap(filemap, statbuf.st_size);
364 deinit_archive(tar_archive);
365 return 1;
366 }
367
368 FCHOWNMOD(fileno(fpout), tar_archive->mode, tar_archive->uid, tar_archive->gid);
369
370 if (tar_archive->filesize == 0) {
371 // Nothing to write. We just created it.
372 fclose(fpout);
373 fpout = NULL;
374
375 // For SUID and SGID; fchown + file open for writing + suid/sgid = suid/sgid may be ignored
376 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
377 }
378 break;
379 case AF_SYMLINK:
380 symlink(tar_archive->linktarget, curpath);
381 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
382 break;
383 case AF_DEVNODE:
384 mknod(curpath, tar_archive->mode, makedev(tar_archive->dmajor, tar_archive->dminor));
385 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
386 break;
387 case AF_FIFOBUF:
388 mkfifo(curpath, tar_archive->mode);
389 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
390 break;
391 case AF_DIRECTORY:
392 if (stat(curpath, &statbuf)) {
393 mkdir(curpath, tar_archive->mode);
394 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
395 }
396 break;
397 }
398 }
399 }
400
401 update_nextblock(tar_archive);
402 if (tar_archive->nextblock > obuflen) {
403 obuflen = tar_archive->nextblock;
404 obuf = realloc(obuf, obuflen);
405 }
406
407 if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
408 break;
409
410 if (decompression_ammount_not_processed(&cstream) > 0)
411 break;
412
413 update_stage(tar_archive);
414
415 switch (tar_archive->stage) {
416 case AS_DATA:
417 if (tar_archive->ftype == AF_REGULAR) {
418 if (fpout != NULL) {
419 fwrite(obuf, ((tar_archive->filesize - tar_archive->upfilesize) > tar_archive->nextblock) ? tar_archive->nextblock : tar_archive->filesize - tar_archive->upfilesize, 1, fpout);
420 }
421 }
422
423 update_upfilesize(tar_archive);
424 break;
425 case AS_HEADER:
426 if (tar_archive->ftype == AF_REGULAR) {
427 if (fpout != NULL) {
428 fsync(fileno(fpout));
429 fclose(fpout);
430 fpout = NULL;
431
432 // For SUID and SGID; fchown + file open for writing + suid/sgid = suid/sgid may be ignored
433 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
434 }
435 }
436 clear_archive_member(tar_archive);
437 break;
438 }
439
440 err = parse_block(tar_archive, obuf);
441
442 if (err)
443 break;
444 } while (decompression_ammount_left(&cstream, 0) > 0);
445 deinit_archive(tar_archive);
446 decompression_cleanup(&cstream);
447 free(curpath);
448 free(obuf);
449 munmap(filemap, statbuf.st_size);
450 return 0;
451 }