00001
00010 #include "system.h"
00011
00012 #include <rpmio_internal.h>
00013 #include <rpmlib.h>
00014
00015 #include "cpio.h"
00016 #include "fsm.h"
00017
00018 #include "rpmerr.h"
00019 #include "debug.h"
00020
00021
00022
00031 static int strntoul(const char *str, char **endptr, int base, int num)
00032
00033
00034 {
00035 char * buf, * end;
00036 unsigned long ret;
00037
00038 buf = alloca(num + 1);
00039 strncpy(buf, str, num);
00040 buf[num] = '\0';
00041
00042 ret = strtoul(buf, &end, base);
00043
00044 if (*end != '\0')
00045 *endptr = ((char *)str) + (end - buf);
00046 else
00047 *endptr = ((char *)str) + strlen(buf);
00048
00049
00050 return ret;
00051 }
00052
00053 #define GET_NUM_FIELD(phys, log) \
00054 \
00055 log = strntoul(phys, &end, 16, sizeof(phys)); \
00056 \
00057 if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER;
00058 #define SET_NUM_FIELD(phys, val, space) \
00059 sprintf(space, "%8.8lx", (unsigned long) (val)); \
00060 \
00061 memcpy(phys, space, 8) \
00062
00063
00064 int cpioTrailerWrite(FSM_t fsm)
00065 {
00066 struct cpioCrcPhysicalHeader * hdr =
00067 (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
00068 int rc;
00069
00070
00071 memset(hdr, '0', PHYS_HDR_SIZE);
00072 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
00073 memcpy(hdr->nlink, "00000001", 8);
00074 memcpy(hdr->namesize, "0000000b", 8);
00075 memcpy(fsm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, sizeof(CPIO_TRAILER));
00076
00077
00078
00079 fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER);
00080 rc = fsmNext(fsm, FSM_DWRITE);
00081
00082
00083
00084
00085
00086 if (!rc)
00087 rc = fsmNext(fsm, FSM_PAD);
00088
00089 return rc;
00090 }
00091
00092 int cpioHeaderWrite(FSM_t fsm, struct stat * st)
00093 {
00094 struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
00095 char field[64];
00096 size_t len;
00097 dev_t dev;
00098 int rc = 0;
00099
00100 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
00101 SET_NUM_FIELD(hdr->inode, st->st_ino, field);
00102 SET_NUM_FIELD(hdr->mode, st->st_mode, field);
00103 SET_NUM_FIELD(hdr->uid, st->st_uid, field);
00104 SET_NUM_FIELD(hdr->gid, st->st_gid, field);
00105 SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
00106 SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
00107 SET_NUM_FIELD(hdr->filesize, st->st_size, field);
00108
00109 dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
00110 dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
00111 dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
00112 dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
00113
00114 len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, len, field);
00115 memcpy(hdr->checksum, "00000000", 8);
00116
00117 memcpy(fsm->rdbuf + PHYS_HDR_SIZE, fsm->path, len);
00118
00119
00120
00121 fsm->rdnb = PHYS_HDR_SIZE + len;
00122 rc = fsmNext(fsm, FSM_DWRITE);
00123 if (!rc && fsm->rdnb != fsm->wrnb)
00124 rc = CPIOERR_WRITE_FAILED;
00125 if (!rc)
00126 rc = fsmNext(fsm, FSM_PAD);
00127 return rc;
00128 }
00129
00130 int cpioHeaderRead(FSM_t fsm, struct stat * st)
00131
00132 {
00133 struct cpioCrcPhysicalHeader hdr;
00134 int nameSize;
00135 char * end;
00136 int major, minor;
00137 int rc = 0;
00138
00139 fsm->wrlen = PHYS_HDR_SIZE;
00140 rc = fsmNext(fsm, FSM_DREAD);
00141 if (!rc && fsm->rdnb != fsm->wrlen)
00142 rc = CPIOERR_READ_FAILED;
00143 if (rc) return rc;
00144
00145 memcpy(&hdr, fsm->wrbuf, fsm->rdnb);
00146
00147
00148 if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
00149 strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1))
00150 return CPIOERR_BAD_MAGIC;
00151
00152 GET_NUM_FIELD(hdr.inode, st->st_ino);
00153 GET_NUM_FIELD(hdr.mode, st->st_mode);
00154 GET_NUM_FIELD(hdr.uid, st->st_uid);
00155 GET_NUM_FIELD(hdr.gid, st->st_gid);
00156 GET_NUM_FIELD(hdr.nlink, st->st_nlink);
00157 GET_NUM_FIELD(hdr.mtime, st->st_mtime);
00158 GET_NUM_FIELD(hdr.filesize, st->st_size);
00159
00160 GET_NUM_FIELD(hdr.devMajor, major);
00161 GET_NUM_FIELD(hdr.devMinor, minor);
00162
00163 st->st_dev = makedev(major, minor);
00164
00165
00166 GET_NUM_FIELD(hdr.rdevMajor, major);
00167 GET_NUM_FIELD(hdr.rdevMinor, minor);
00168
00169 st->st_rdev = makedev(major, minor);
00170
00171
00172 GET_NUM_FIELD(hdr.namesize, nameSize);
00173 if (nameSize >= fsm->wrsize)
00174 return CPIOERR_BAD_HEADER;
00175
00176 { char * t = xmalloc(nameSize + 1);
00177 fsm->wrlen = nameSize;
00178 rc = fsmNext(fsm, FSM_DREAD);
00179 if (!rc && fsm->rdnb != fsm->wrlen)
00180 rc = CPIOERR_BAD_HEADER;
00181 if (rc) {
00182 t = _free(t);
00183 fsm->path = NULL;
00184 return rc;
00185 }
00186
00187 memcpy(t, fsm->wrbuf, fsm->rdnb);
00188 t[nameSize] = '\0';
00189
00190 fsm->path = t;
00191 }
00192
00193 return 0;
00194 }
00195
00196 const char *const cpioStrerror(int rc)
00197 {
00198 static char msg[256];
00199 char *s;
00200 int l, myerrno = errno;
00201
00202 strcpy(msg, "cpio: ");
00203
00204 switch (rc) {
00205 default:
00206 s = msg + strlen(msg);
00207 sprintf(s, _("(error 0x%x)"), (unsigned)rc);
00208 s = NULL;
00209 break;
00210 case CPIOERR_BAD_MAGIC: s = _("Bad magic"); break;
00211 case CPIOERR_BAD_HEADER: s = _("Bad/unreadable header");break;
00212
00213 case CPIOERR_OPEN_FAILED: s = "open"; break;
00214 case CPIOERR_CHMOD_FAILED: s = "chmod"; break;
00215 case CPIOERR_CHOWN_FAILED: s = "chown"; break;
00216 case CPIOERR_WRITE_FAILED: s = "write"; break;
00217 case CPIOERR_UTIME_FAILED: s = "utime"; break;
00218 case CPIOERR_UNLINK_FAILED: s = "unlink"; break;
00219 case CPIOERR_RENAME_FAILED: s = "rename"; break;
00220 case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
00221 case CPIOERR_STAT_FAILED: s = "stat"; break;
00222 case CPIOERR_LSTAT_FAILED: s = "lstat"; break;
00223 case CPIOERR_MKDIR_FAILED: s = "mkdir"; break;
00224 case CPIOERR_RMDIR_FAILED: s = "rmdir"; break;
00225 case CPIOERR_MKNOD_FAILED: s = "mknod"; break;
00226 case CPIOERR_MKFIFO_FAILED: s = "mkfifo"; break;
00227 case CPIOERR_LINK_FAILED: s = "link"; break;
00228 case CPIOERR_READLINK_FAILED: s = "readlink"; break;
00229 case CPIOERR_READ_FAILED: s = "read"; break;
00230 case CPIOERR_COPY_FAILED: s = "copy"; break;
00231 case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon"; break;
00232
00233 case CPIOERR_HDR_SIZE: s = _("Header size too big"); break;
00234 case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
00235 case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
00236 case CPIOERR_MD5SUM_MISMATCH: s = _("MD5 sum mismatch"); break;
00237 case CPIOERR_INTERNAL: s = _("Internal error"); break;
00238 case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
00239 case CPIOERR_ENOENT: s = strerror(ENOENT); break;
00240 case CPIOERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
00241 }
00242
00243
00244 l = sizeof(msg) - strlen(msg) - 1;
00245 if (s != NULL) {
00246 if (l > 0) strncat(msg, s, l);
00247 l -= strlen(s);
00248 }
00249
00250 if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
00251 s = _(" failed - ");
00252 if (l > 0) strncat(msg, s, l);
00253 l -= strlen(s);
00254 if (l > 0) strncat(msg, strerror(myerrno), l);
00255 }
00256
00257 return msg;
00258 }