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