int archwriter_write_volheader(carchwriter *ai) { struct s_writebuf *wb=NULL; cdico *voldico; assert(ai); if ((wb=writebuf_alloc())==NULL) { msgprintf(MSG_STACK, "writebuf_alloc() failed\n"); return -1; } if ((voldico=dico_alloc())==NULL) { msgprintf(MSG_STACK, "voldico=dico_alloc() failed\n"); return -1; } // prepare header dico_add_u32(voldico, 0, VOLUMEHEADKEY_VOLNUM, ai->curvol); dico_add_u32(voldico, 0, VOLUMEHEADKEY_ARCHID, ai->archid); dico_add_string(voldico, 0, VOLUMEHEADKEY_FILEFORMATVER, FSA_FILEFORMAT); dico_add_string(voldico, 0, VOLUMEHEADKEY_PROGVERCREAT, FSA_VERSION); // write header to buffer if (writebuf_add_header(wb, voldico, FSA_MAGIC_VOLH, ai->archid, FSA_FILESYSID_NULL)!=0) { errprintf("archio_write_header() failed\n"); return -1; } // write header to file if (archwriter_write_buffer(ai, wb)!=0) { errprintf("archwriter_write_buffer() failed\n"); return -1; } dico_destroy(voldico); writebuf_destroy(wb); return 0; }
int archwriter_write_volfooter(carchwriter *ai, bool lastvol) { struct s_writebuf *wb=NULL; cdico *voldico; assert(ai); if ((wb=writebuf_alloc())==NULL) { errprintf("writebuf_alloc() failed\n"); return -1; } if ((voldico=dico_alloc())==NULL) { errprintf("voldico=dico_alloc() failed\n"); return -1; } // prepare header dico_add_u32(voldico, 0, VOLUMEFOOTKEY_VOLNUM, ai->curvol); dico_add_u32(voldico, 0, VOLUMEFOOTKEY_ARCHID, ai->archid); dico_add_u32(voldico, 0, VOLUMEFOOTKEY_LASTVOL, lastvol); // write header to buffer if (writebuf_add_header(wb, voldico, FSA_MAGIC_VOLF, ai->archid, FSA_FILESYSID_NULL)!=0) { msgprintf(MSG_STACK, "archio_write_header() failed\n"); return -1; } // write header to file if (archwriter_write_buffer(ai, wb)!=0) { msgprintf(MSG_STACK, "archwriter_write_data(size=%ld) failed\n", (long)wb->size); return -1; } dico_destroy(voldico); writebuf_destroy(wb); return 0; }
int archreader_read_header(carchreader *ai, char *magic, cdico **d, bool allowseek, u16 *fsid) { s64 curpos; u16 temp16; u32 temp32; u32 archid; int res; assert(ai); assert(d); assert(fsid); // init memset(magic, 0, FSA_SIZEOF_MAGIC); *fsid=FSA_FILESYSID_NULL; *d=NULL; if ((*d=dico_alloc())==NULL) { errprintf("dico_alloc() failed\n"); return OLDERR_FATAL; } // search for next read header marker and magic (it may be further if corruption in archive) if ((curpos=lseek64(ai->archfd, 0, SEEK_CUR))<0) { sysprintf("lseek64() failed to get the current position in archive\n"); return OLDERR_FATAL; } if ((res=archreader_read_data(ai, magic, FSA_SIZEOF_MAGIC))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read header magic: res=%d\n", res); return OLDERR_FATAL; } // we don't want to search for the magic if it's a volume header if (is_magic_valid(magic)!=true && allowseek!=true) { errprintf("cannot read header magic: this is not a valid fsarchiver file, or it has been created with a different version.\n"); return OLDERR_FATAL; } while (is_magic_valid(magic)!=true) { if (lseek64(ai->archfd, curpos++, SEEK_SET)<0) { sysprintf("lseek64(pos=%lld, SEEK_SET) failed\n", (long long)curpos); return OLDERR_FATAL; } if ((res=archreader_read_data(ai, magic, FSA_SIZEOF_MAGIC))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read header magic: res=%d\n", res); return OLDERR_FATAL; } } // read the archive id if ((res=archreader_read_data(ai, &temp32, sizeof(temp32)))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read archive-id in header: res=%d\n", res); return OLDERR_FATAL; } archid=le32_to_cpu(temp32); if (ai->archid) // only check archive-id if it's known (when main header has been read) { if (archid!=ai->archid) { errprintf("archive-id in header does not match: archid=[%.8x], expected=[%.8x]\n", archid, ai->archid); return OLDERR_MINOR; } } // read the filesystem id if ((res=archreader_read_data(ai, &temp16, sizeof(temp16)))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read filesystem-id in header: res=%d\n", res); return OLDERR_FATAL; } *fsid=le16_to_cpu(temp16); // read the dico of the header if ((res=archreader_read_dico(ai, *d))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "imgdisk_read_dico() failed\n"); return res; } return FSAERR_SUCCESS; }