~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to lib/cpio.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** \ingroup payload
 
2
 * \file lib/cpio.c
 
3
 *  Handle cpio payloads within rpm packages.
 
4
 *
 
5
 * \warning FIXME: We don't translate between cpio and system mode bits! These
 
6
 * should both be the same, but really odd things are going to happen if
 
7
 * that's not true!
 
8
 */
 
9
 
 
10
#include "system.h"
 
11
#include <rpmlib.h>
 
12
 
 
13
#include "fsm.h"
 
14
#include "rpmerr.h"
 
15
#include "debug.h"
 
16
 
 
17
/*@access FSM_t @*/
 
18
 
 
19
/*@-exportheadervar@*/
 
20
extern int _fsm_debug;
 
21
/*@=exportheadervar@*/
 
22
 
 
23
/**
 
24
 * Convert string to unsigned integer (with buffer size check).
 
25
 * @param               input string
 
26
 * @retval              address of 1st character not processed
 
27
 * @param base          numerical conversion base
 
28
 * @param num           max no. of bytes to read
 
29
 * @return              converted integer
 
30
 */
 
31
static int strntoul(const char *str, /*@out@*/char **endptr, int base, int num)
 
32
        /*@modifies *endptr @*/
 
33
{
 
34
    char * buf, * end;
 
35
    unsigned long ret;
 
36
 
 
37
    buf = alloca(num + 1);
 
38
    strncpy(buf, str, num);
 
39
    buf[num] = '\0';
 
40
 
 
41
    ret = strtoul(buf, &end, base);
 
42
    if (*end != '\0')
 
43
        *endptr = ((char *)str) + (end - buf);  /* XXX discards const */
 
44
    else
 
45
        *endptr = ((char *)str) + strlen(buf);
 
46
 
 
47
    return ret;
 
48
}
 
49
 
 
50
#define GET_NUM_FIELD(phys, log) \
 
51
        log = strntoul(phys, &end, 16, sizeof(phys)); \
 
52
        if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER;
 
53
#define SET_NUM_FIELD(phys, val, space) \
 
54
        sprintf(space, "%8.8lx", (unsigned long) (val)); \
 
55
        memcpy(phys, space, 8);
 
56
 
 
57
int cpioTrailerWrite(FSM_t fsm)
 
58
{
 
59
    struct cpioCrcPhysicalHeader * hdr =
 
60
        (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
 
61
    int rc;
 
62
 
 
63
    memset(hdr, '0', PHYS_HDR_SIZE);
 
64
    memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
 
65
    memcpy(hdr->nlink, "00000001", 8);
 
66
    memcpy(hdr->namesize, "0000000b", 8);
 
67
    memcpy(fsm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, sizeof(CPIO_TRAILER));
 
68
 
 
69
    /* XXX DWRITE uses rdnb for I/O length. */
 
70
    fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER);
 
71
    rc = fsmStage(fsm, FSM_DWRITE);
 
72
 
 
73
    /*
 
74
     * GNU cpio pads to 512 bytes here, but we don't. This may matter for
 
75
     * tape device(s) and/or concatenated cpio archives. <shrug>
 
76
     */
 
77
    if (!rc)
 
78
        rc = fsmStage(fsm, FSM_PAD);
 
79
 
 
80
    return rc;
 
81
}
 
82
 
 
83
int cpioHeaderWrite(FSM_t fsm, struct stat * st)
 
84
{
 
85
    struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
 
86
    char field[64];
 
87
    size_t len;
 
88
    dev_t dev;
 
89
    int rc = 0;
 
90
 
 
91
    memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
 
92
    SET_NUM_FIELD(hdr->inode, st->st_ino, field);
 
93
    SET_NUM_FIELD(hdr->mode, st->st_mode, field);
 
94
    SET_NUM_FIELD(hdr->uid, st->st_uid, field);
 
95
    SET_NUM_FIELD(hdr->gid, st->st_gid, field);
 
96
    SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
 
97
    SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
 
98
    SET_NUM_FIELD(hdr->filesize, st->st_size, field);
 
99
 
 
100
    dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
 
101
    dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
 
102
    dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
 
103
    dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
 
104
 
 
105
    len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, len, field);
 
106
    memcpy(hdr->checksum, "00000000", 8);
 
107
    memcpy(fsm->rdbuf + PHYS_HDR_SIZE, fsm->path, len);
 
108
 
 
109
    /* XXX DWRITE uses rdnb for I/O length. */
 
110
    fsm->rdnb = PHYS_HDR_SIZE + len;
 
111
    rc = fsmStage(fsm, FSM_DWRITE);
 
112
    if (!rc && fsm->rdnb != fsm->wrnb)
 
113
        rc = CPIOERR_WRITE_FAILED;
 
114
    if (!rc)
 
115
        rc = fsmStage(fsm, FSM_PAD);
 
116
    return rc;
 
117
}
 
118
 
 
119
int cpioHeaderRead(FSM_t fsm, struct stat * st)
 
120
        /*@modifies fsm, *st @*/
 
121
{
 
122
    struct cpioCrcPhysicalHeader hdr;
 
123
    int nameSize;
 
124
    char * end;
 
125
    int major, minor;
 
126
    int rc = 0;
 
127
 
 
128
    fsm->wrlen = PHYS_HDR_SIZE;
 
129
    rc = fsmStage(fsm, FSM_DREAD);
 
130
    if (!rc && fsm->rdnb != fsm->wrlen)
 
131
        rc = CPIOERR_READ_FAILED;
 
132
    if (rc) return rc;
 
133
    memcpy(&hdr, fsm->wrbuf, fsm->rdnb);
 
134
 
 
135
    if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
 
136
        strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1))
 
137
        return CPIOERR_BAD_MAGIC;
 
138
 
 
139
    GET_NUM_FIELD(hdr.inode, st->st_ino);
 
140
    GET_NUM_FIELD(hdr.mode, st->st_mode);
 
141
    GET_NUM_FIELD(hdr.uid, st->st_uid);
 
142
    GET_NUM_FIELD(hdr.gid, st->st_gid);
 
143
    GET_NUM_FIELD(hdr.nlink, st->st_nlink);
 
144
    GET_NUM_FIELD(hdr.mtime, st->st_mtime);
 
145
    GET_NUM_FIELD(hdr.filesize, st->st_size);
 
146
 
 
147
    GET_NUM_FIELD(hdr.devMajor, major);
 
148
    GET_NUM_FIELD(hdr.devMinor, minor);
 
149
    st->st_dev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ;
 
150
 
 
151
    GET_NUM_FIELD(hdr.rdevMajor, major);
 
152
    GET_NUM_FIELD(hdr.rdevMinor, minor);
 
153
    st->st_rdev = /*@-shiftsigned@*/ makedev(major, minor) /*@=shiftsigned@*/ ;
 
154
 
 
155
    GET_NUM_FIELD(hdr.namesize, nameSize);
 
156
    if (nameSize >= fsm->wrsize)
 
157
        return CPIOERR_BAD_HEADER;
 
158
 
 
159
    {   char * t = xmalloc(nameSize + 1);
 
160
        fsm->wrlen = nameSize;
 
161
        rc = fsmStage(fsm, FSM_DREAD);
 
162
        if (!rc && fsm->rdnb != fsm->wrlen)
 
163
            rc = CPIOERR_BAD_HEADER;
 
164
        if (rc) {
 
165
            t = _free(t);
 
166
            fsm->path = NULL;
 
167
            return rc;
 
168
        }
 
169
        memcpy(t, fsm->wrbuf, fsm->rdnb);
 
170
        t[nameSize] = '\0';
 
171
        fsm->path = t;
 
172
    }
 
173
 
 
174
    return 0;
 
175
}
 
176
 
 
177
const char *const cpioStrerror(int rc)
 
178
{
 
179
    static char msg[256];
 
180
    char *s;
 
181
    int l, myerrno = errno;
 
182
 
 
183
    strcpy(msg, "cpio: ");
 
184
    switch (rc) {
 
185
    default:
 
186
        s = msg + strlen(msg);
 
187
        sprintf(s, _("(error 0x%x)"), (unsigned)rc);
 
188
        s = NULL;
 
189
        break;
 
190
    case CPIOERR_BAD_MAGIC:     s = _("Bad magic");             break;
 
191
    case CPIOERR_BAD_HEADER:    s = _("Bad/unreadable  header");break;
 
192
 
 
193
    case CPIOERR_OPEN_FAILED:   s = "open";     break;
 
194
    case CPIOERR_CHMOD_FAILED:  s = "chmod";    break;
 
195
    case CPIOERR_CHOWN_FAILED:  s = "chown";    break;
 
196
    case CPIOERR_WRITE_FAILED:  s = "write";    break;
 
197
    case CPIOERR_UTIME_FAILED:  s = "utime";    break;
 
198
    case CPIOERR_UNLINK_FAILED: s = "unlink";   break;
 
199
    case CPIOERR_RENAME_FAILED: s = "rename";   break;
 
200
    case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
 
201
    case CPIOERR_STAT_FAILED:   s = "stat";     break;
 
202
    case CPIOERR_LSTAT_FAILED:  s = "lstat";    break;
 
203
    case CPIOERR_MKDIR_FAILED:  s = "mkdir";    break;
 
204
    case CPIOERR_RMDIR_FAILED:  s = "rmdir";    break;
 
205
    case CPIOERR_MKNOD_FAILED:  s = "mknod";    break;
 
206
    case CPIOERR_MKFIFO_FAILED: s = "mkfifo";   break;
 
207
    case CPIOERR_LINK_FAILED:   s = "link";     break;
 
208
    case CPIOERR_READLINK_FAILED: s = "readlink";       break;
 
209
    case CPIOERR_READ_FAILED:   s = "read";     break;
 
210
    case CPIOERR_COPY_FAILED:   s = "copy";     break;
 
211
 
 
212
    case CPIOERR_HDR_SIZE:      s = _("Header size too big");   break;
 
213
    case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type");  break;
 
214
    case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
 
215
    case CPIOERR_MD5SUM_MISMATCH: s = _("MD5 sum mismatch");    break;
 
216
    case CPIOERR_INTERNAL:      s = _("Internal error");        break;
 
217
    case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
 
218
    }
 
219
 
 
220
    l = sizeof(msg) - strlen(msg) - 1;
 
221
    if (s != NULL) {
 
222
        if (l > 0) strncat(msg, s, l);
 
223
        l -= strlen(s);
 
224
    }
 
225
    if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
 
226
        s = _(" failed - ");
 
227
        if (l > 0) strncat(msg, s, l);
 
228
        l -= strlen(s);
 
229
        if (l > 0) strncat(msg, strerror(myerrno), l);
 
230
    }
 
231
    return msg;
 
232
}