source: MondoRescue/branches/stable/mindi-busybox/archival/libunarchive/get_header_cpio.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.3 KB
Line 
1/* Copyright 2002 Laurence Anderson
2 *
3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10#include <sys/sysmacros.h>     /* major() and minor() */
11#include "unarchive.h"
12#include "libbb.h"
13
14typedef struct hardlinks_s {
15    file_header_t *entry;
16    int inode;
17    struct hardlinks_s *next;
18} hardlinks_t;
19
20char get_header_cpio(archive_handle_t *archive_handle)
21{
22    static hardlinks_t *saved_hardlinks = NULL;
23    static unsigned short pending_hardlinks = 0;
24    file_header_t *file_header = archive_handle->file_header;
25    char cpio_header[110];
26    int namesize;
27    char dummy[16];
28    int major, minor, nlink, inode;
29
30    if (pending_hardlinks) { /* Deal with any pending hardlinks */
31        hardlinks_t *tmp;
32        hardlinks_t *oldtmp;
33
34        tmp = saved_hardlinks;
35        oldtmp = NULL;
36
37        while (tmp) {
38            bb_error_msg_and_die("need to fix this\n");
39            if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */
40                file_header = tmp->entry;
41                if (oldtmp) {
42                    oldtmp->next = tmp->next; /* Remove item from linked list */
43                } else {
44                    saved_hardlinks = tmp->next;
45                }
46                free(tmp);
47                continue;
48            }
49            oldtmp = tmp;
50            tmp = tmp->next;
51        }
52        pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */
53    }
54
55    /* There can be padding before archive header */
56    data_align(archive_handle, 4);
57
58    if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) {
59        return(EXIT_FAILURE);
60    }
61    archive_handle->offset += 110;
62
63    if ((strncmp(&cpio_header[0], "07070", 5) != 0) || ((cpio_header[5] != '1') && (cpio_header[5] != '2'))) {
64        bb_error_msg_and_die("Unsupported cpio format, use newc or crc");
65    }
66
67    {
68        unsigned long tmpsize;
69        sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
70            dummy, &inode, (unsigned int*)&file_header->mode,
71            (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
72            &nlink, &file_header->mtime, &tmpsize,
73            dummy, &major, &minor, &namesize, dummy);
74        file_header->size = tmpsize;
75    }
76
77    file_header->name = (char *) xzalloc(namesize + 1);
78    archive_xread_all(archive_handle, file_header->name, namesize); /* Read in filename */
79    archive_handle->offset += namesize;
80
81    /* Update offset amount and skip padding before file contents */
82    data_align(archive_handle, 4);
83
84    if (strcmp(file_header->name, "TRAILER!!!") == 0) {
85        printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */
86        if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
87            hardlinks_t *tmp = saved_hardlinks;
88            hardlinks_t *oldtmp = NULL;
89            while (tmp) {
90                bb_error_msg("%s not created: cannot resolve hardlink", tmp->entry->name);
91                oldtmp = tmp;
92                tmp = tmp->next;
93                free (oldtmp->entry->name);
94                free (oldtmp->entry);
95                free (oldtmp);
96            }
97            saved_hardlinks = NULL;
98            pending_hardlinks = 0;
99        }
100        return(EXIT_FAILURE);
101    }
102
103    if (S_ISLNK(file_header->mode)) {
104        file_header->link_name = (char *) xzalloc(file_header->size + 1);
105        archive_xread_all(archive_handle, file_header->link_name, file_header->size);
106        archive_handle->offset += file_header->size;
107        file_header->size = 0; /* Stop possible seeks in future */
108    } else {
109        file_header->link_name = NULL;
110    }
111    if (nlink > 1 && !S_ISDIR(file_header->mode)) {
112        if (file_header->size == 0) { /* Put file on a linked list for later */
113            hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
114            new->next = saved_hardlinks;
115            new->inode = inode;
116            new->entry = file_header;
117            saved_hardlinks = new;
118            return(EXIT_SUCCESS); // Skip this one
119        } else { /* Found the file with data in */
120            hardlinks_t *tmp = saved_hardlinks;
121            pending_hardlinks = 1;
122            while (tmp) {
123                if (tmp->inode == inode) {
124                    tmp->entry->link_name = bb_xstrdup(file_header->name);
125                    nlink--;
126                }
127                tmp = tmp->next;
128            }
129            if (nlink > 1) {
130                bb_error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
131            }
132        }
133    }
134    file_header->device = makedev(major, minor);
135
136    if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
137        archive_handle->action_data(archive_handle);
138        archive_handle->action_header(archive_handle->file_header);
139    } else {
140        data_skip(archive_handle);
141    }
142
143    archive_handle->offset += file_header->size;
144
145    free(file_header->link_name);
146
147    return (EXIT_SUCCESS);
148}
Note: See TracBrowser for help on using the repository browser.