/** * @file header.c CPIO header * * $Id: header.c,v 1.6 2003/01/01 06:22:32 chipx86 Exp $ * * @Copyright (C) 1999-2003 The GNUpdate Project. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include "cpio.h" /* Return a 16-bit integer with the bytes swapped. */ #define __swabShort(i) ((((i) << 8) & 0xFF00) | (((i) >> 8) & 0x00FF)) #define __skipPadding(fp, modulo) \ cxSeek(fp, ((modulo) - cxTell(fp) % (modulo)) % (modulo), SEEK_CUR); static CxStatus __readNewAsciiHeader(CxFP *fp, CxArchive *archive, char checkCrc) { char buffer[112]; CpioNewHeader header; CxDirectory *dir, *root; CxFile *file; char *dirName, *baseName; if (cxRead(buffer, 1, 104, fp) != 104) return CX_CORRUPT; buffer[104] = '\0'; sscanf(buffer, "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx", &header.inode, &header.mode, &header.uid, &header.gid, &header.nlink, &header.mtime, &header.fileSize, &header.devMajor, &header.devMinor, &header.rDevMajor, &header.rDevMinor, &header.nameSize, &header.checksum); /* Read the filename. */ header.filename = (char *)malloc(header.nameSize); if (cxRead(header.filename, 1, header.nameSize, fp) != header.nameSize) { free(header.filename); return CX_CORRUPT; } if (!strcmp(header.filename, CPIO_TRAILER)) { free(header.filename); return CX_EOF; } /* Get the parts of the filename. */ if (*header.filename == '.') cxSplitPath(header.filename + 1, &dirName, &baseName); else cxSplitPath(header.filename, &dirName, &baseName); /* Create the file. */ file = cxNewFile(); #if 0 if (*header.filename == '.' && header.filename[1] == '/') cxSetFilePath(file, header.filename + 1); else cxSetFilePath(file, header.filename); #endif cxSetFileName(file, baseName); cxSetFileMode(file, (mode_t)header.mode); cxSetFileUid(file, (uid_t)header.uid); cxSetFileGid(file, (gid_t)header.gid); cxSetFileSize(file, (size_t)header.fileSize); cxSetFileDate(file, (time_t)header.mtime); cxSetFileCompressedSize(file, cxGetFileSize(file)); archive->archiveSize += cxGetFileCompressedSize(file); root = cxGetArchiveRoot(archive); /* Get the directory. */ if (dirName != NULL) { dir = cxGetDirectory(root, dirName); if (dir == NULL) { /* Create it. */ dir = cxMkDir(root, dirName); } free(dirName); } else dir = root; /* Add the file. */ cxDirAddFile(dir, file); /* Clean up. */ free(header.filename); free(baseName); /* Skip the padding and data. */ __skipPadding(fp, 4); /* Save this location: The start of the data. */ file->moduleData = (void *)cxTell(fp); /* Go past the rest. */ cxSeek(fp, cxGetFileSize(file), SEEK_CUR); __skipPadding(fp, 4); return CX_SUCCESS; } static CxStatus __readOldAsciiHeader(CxFP *fp, CxArchive *archive) { printf("Old ASCII header\n"); return CX_NOT_SUPPORTED; } static CxStatus __readBinaryHeader(CxFP *fp, CxArchive *archive) { printf("Binary header\n"); return CX_NOT_SUPPORTED; } CxStatus cxCpioReadHeader(CxFP *fp, CxArchive *archive) { char buffer[CPIO_MAGICS_LEN]; size_t s; /* Read in 6 bytes, the size of the largest magic string. */ s = cxRead(buffer, 1, CPIO_MAGICS_LEN, fp); if (s == 0) return CX_EOF; else if (s < 0) return CX_ERROR; else if (s < CPIO_MAGICS_LEN) return CX_CORRUPT; /* Find out what we've got here. */ if (!strncmp(buffer, CPIO_MAGICS_ASCII, CPIO_MAGICS_LEN)) return __readNewAsciiHeader(fp, archive, 0); else if (!strncmp(buffer, CPIO_MAGICS_CRC, CPIO_MAGICS_LEN)) return __readNewAsciiHeader(fp, archive, 1); else if (!strncmp(buffer, CPIO_MAGICS_CHR, CPIO_MAGICS_LEN)) return __readOldAsciiHeader(fp, archive); else if ((*((unsigned short *)buffer) == CPIO_MAGICN_BIN) || (*((unsigned short *)buffer) == __swabShort(CPIO_MAGICN_BIN))) return __readBinaryHeader(fp, archive); return CX_INVALID_FORMAT; }