예제 #1
0
int regmulti_rest_getfile(cregmulti *m, int index, cdico **filehead, char *data, u64 *datsize, u32 bufsize)
{
    u32 offset;
    u64 filesize;
    
    if (!m || !filehead)
    {   errprintf("invalid param\n");
        return -1;
    }
    
    if (index >= m->count)
    {   errprintf("index=%d out of scope: the structure only contains %ld items\n", index, (long)m->count);
        return -1;
    }
    
    // ---- return the header to the calling function
    *filehead=m->objhead[index];
    
    // ---- return the data to the calling function
    if (dico_get_u64(m->objhead[index], DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_SIZE, &filesize)!=0)
    {   errprintf("Cannot read filesize DISKITEMKEY_SIZE from archive\n");
        return -1;
    }
    if (dico_get_u32(m->objhead[index], DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MULTIFILESOFFSET, &offset)!=0)
    {   errprintf("Cannot read filesize DISKITEMKEY_SIZE from archive\n");
        return -1;
    }
    *datsize=filesize;
    memcpy(data, m->data+offset, filesize);
    
    return 0;
}
예제 #2
0
void *thread_reader_fct(void *args)
{
    char magic[FSA_SIZEOF_MAGIC];
    struct s_blockinfo blkinfo;
    u32 endofarchive=false;
    carchreader *ai=NULL;
    cdico *dico=NULL;
    int skipblock;
    u16 fsid;
    int sumok;
    int status;
    u64 errors;
    s64 lres;
    int res;
    
    // init
    errors=0;
    inc_secthreads();

    if ((ai=(carchreader *)args)==NULL)
    {   errprintf("ai is NULL\n");
        goto thread_reader_fct_error;
    }
    
    // open archive file
    if (archreader_volpath(ai)!=0)
    {   errprintf("archreader_volpath() failed\n");
        goto thread_reader_fct_error;
    }
    
    if (archreader_open(ai)!=0)
    {   errprintf("archreader_open(%s) failed\n", ai->basepath);
        goto thread_reader_fct_error;
    }
    
    // read volume header
    if (archreader_read_volheader(ai)!=0)
    {   errprintf("archio_read_volheader() failed\n");
        goto thread_reader_fct_error;
    }
    
    // ---- read main archive header
    if ((res=archreader_read_header(ai, magic, &dico, false, &fsid))!=FSAERR_SUCCESS)
    {   errprintf("archreader_read_header() failed to read the archive header\n");
        goto thread_reader_fct_error; // this header is required to continue
    }
    
    if (dico_get_u32(dico, 0, MAINHEADKEY_ARCHIVEID, &ai->archid)!=0)
    {   msgprintf(3, "cannot get archive-id from main header\n");
        goto thread_reader_fct_error;
    }
    
    if ((lres=queue_add_header(&g_queue, dico, magic, fsid))!=FSAERR_SUCCESS)
    {   errprintf("queue_add_header()=%ld=%s failed to add the archive header\n", (long)lres, error_int_to_string(lres));
        goto thread_reader_fct_error;
    }
    
    // read all other data from file (filesys-header, normal objects headers, ...)
    while (endofarchive==false && get_stopfillqueue()==false)
    {
        if ((res=archreader_read_header(ai, magic, &dico, true, &fsid))!=FSAERR_SUCCESS)
        {   dico_destroy(dico);
            msgprintf(MSG_STACK, "archreader_read_header() failed to read next header\n");
            if (res==OLDERR_MINOR) // header is corrupt or not what we expected
            {   errors++;
                msgprintf(MSG_DEBUG1, "OLDERR_MINOR\n");
                continue;
            }
            else // fatal error (eg: cannot read archive from disk)
            {
                msgprintf(MSG_DEBUG1, "!OLDERR_MINOR\n");
                goto thread_reader_fct_error;
            }
        }
        
        // read header and see if it's for archive management or higher level data
        if (strncmp(magic, FSA_MAGIC_VOLF, FSA_SIZEOF_MAGIC)==0) // header is "end of volume"
        {
            archreader_close(ai);
            
            // check the "end of archive" flag in header
            if (dico_get_u32(dico, 0, VOLUMEFOOTKEY_LASTVOL, &endofarchive)!=0)
            {   errprintf("cannot get compr from block-header\n");
                goto thread_reader_fct_error;
            }
            msgprintf(MSG_VERB2, "End of volume [%s]\n", ai->volpath);
            if (endofarchive!=true)
            {
                archreader_incvolume(ai, false);
                while (regfile_exists(ai->volpath)!=true)
                {
                    // wait until the queue is empty so that the main thread does not pollute the screen
                    while (queue_count(&g_queue)>0)
                        usleep(5000);
                    fflush(stdout);
                    fflush(stderr);
                    msgprintf(MSG_FORCE, "File [%s] is not found, please type the path to volume %ld:\n", ai->volpath, (long)ai->curvol);
                    fprintf(stdout, "New path:> ");
                    res=scanf("%256s", ai->volpath);
                }
                
                msgprintf(MSG_VERB2, "New volume is [%s]\n", ai->volpath);
                if (archreader_open(ai)!=0)
                {   msgprintf(MSG_STACK, "archreader_open() failed\n");
                    goto thread_reader_fct_error;
                }
                if (archreader_read_volheader(ai)!=0)
                {      msgprintf(MSG_STACK, "archio_read_volheader() failed\n");
                    goto thread_reader_fct_error;
                }
            }
            dico_destroy(dico);
        }
        else // high-level archive (not involved in volume management)
        {
            if (strncmp(magic, FSA_MAGIC_BLKH, FSA_SIZEOF_MAGIC)==0) // header starts a data block
            {
                skipblock=(g_fsbitmap[fsid]==0);
                //errprintf("DEBUG: skipblock=%d g_fsbitmap[fsid=%d]=%d\n", skipblock, (int)fsid, (int)g_fsbitmap[fsid]);
                if (archreader_read_block(ai, dico, skipblock, &sumok, &blkinfo)!=0)
                {   msgprintf(MSG_STACK, "archreader_read_block() failed\n");
                    goto thread_reader_fct_error;
                }
                
                if (skipblock==false)
                {
                    status=((sumok==true)?QITEM_STATUS_TODO:QITEM_STATUS_DONE);
                    if ((lres=queue_add_block(&g_queue, &blkinfo, status))!=FSAERR_SUCCESS)
                    {   if (lres!=FSAERR_NOTOPEN)
                            errprintf("queue_add_block()=%ld=%s failed\n", (long)lres, error_int_to_string(lres));
                        goto thread_reader_fct_error;
                    }
                    if (sumok==false) errors++;
                    dico_destroy(dico);
                }
            }
            else // another higher level header
            {
                // if it's a global header or a if this local header belongs to a filesystem that the main thread needs
                if (fsid==FSA_FILESYSID_NULL || g_fsbitmap[fsid]==1)
                {
                    if ((lres=queue_add_header(&g_queue, dico, magic, fsid))!=FSAERR_SUCCESS)
                    {   msgprintf(MSG_STACK, "queue_add_header()=%ld=%s failed\n", (long)lres, error_int_to_string(lres));
                        goto thread_reader_fct_error;
                    }
                }
                else // header not used: remove data strucutre in dynamic memory
                {
                    dico_destroy(dico);
                }
            }
        }
    }
    
thread_reader_fct_error:
    msgprintf(MSG_DEBUG1, "THREAD-READER: queue_set_end_of_queue(&g_queue, true)\n");
    queue_set_end_of_queue(&g_queue, true); // don't wait for more data from this thread
    dec_secthreads();
    msgprintf(MSG_DEBUG1, "THREAD-READER: exit\n");
    return NULL;
}
예제 #3
0
int archreader_read_block(carchreader *ai, cdico *in_blkdico, int in_skipblock, int *out_sumok, struct s_blockinfo *out_blkinfo)
{
    u32 arblockcsumorig;
    u32 arblockcsumcalc;
    u32 curblocksize; // data size
    u64 blockoffset; // offset of the block in the file
    u16 compalgo; // compression algo used
    u16 cryptalgo; // encryption algo used
    u32 finalsize; // compressed  block size
    u32 compsize;
    u8 *buffer;
    bool corrupt;
    
    assert(ai);
    assert(out_sumok);
    assert(in_blkdico);
    assert(out_blkinfo);
    
    // init
    memset(out_blkinfo, 0, sizeof(struct s_blockinfo));
    *out_sumok=-1;
    
    if (dico_get_u64(in_blkdico, 0, BLOCKHEADITEMKEY_BLOCKOFFSET, &blockoffset)!=0)
    {   msgprintf(3, "cannot get blockoffset from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_REALSIZE, &curblocksize)!=0 || curblocksize>FSA_MAX_BLKSIZE)
    {   msgprintf(3, "cannot get blocksize from block-header\n");
        return -1;
    }
    
    if (dico_get_u16(in_blkdico, 0, BLOCKHEADITEMKEY_COMPRESSALGO, &compalgo)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_COMPRESSALGO from block-header\n");
        return -1;
    }
    
    if (dico_get_u16(in_blkdico, 0, BLOCKHEADITEMKEY_ENCRYPTALGO, &cryptalgo)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_ENCRYPTALGO from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_ARSIZE, &finalsize)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_ARSIZE from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_COMPSIZE, &compsize)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_COMPSIZE from block-header\n");
        return -1;
    }
    
    if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_ARCSUM, &arblockcsumorig)!=0)
    {   msgprintf(3, "cannot get BLOCKHEADITEMKEY_ARCSUM from block-header\n");
        return -1;
    }
    
    if (in_skipblock==true) // the main thread does not need that block (block belongs to a filesys we want to skip)
    {
        if (lseek64(ai->archfd, (long)finalsize, SEEK_CUR)<0)
        {   sysprintf("cannot skip block (finalsize=%ld) failed\n", (long)finalsize);
            return -1;
        }
        return 0;
    }
    
    // ---- allocate memory
    if ((buffer=malloc(finalsize))==NULL)
    {   errprintf("cannot allocate block: malloc(%d) failed\n", finalsize);
        return FSAERR_ENOMEM;
    }
    
    if (read(ai->archfd, buffer, (long)finalsize)!=(long)finalsize)
    {   sysprintf("cannot read block (finalsize=%ld) failed\n", (long)finalsize);
        free(buffer);
        return -1;
    }
    
    // prepare blkinfo
    out_blkinfo->blkdata=(char*)buffer;
    out_blkinfo->blkrealsize=curblocksize;
    out_blkinfo->blkoffset=blockoffset;
    out_blkinfo->blkarcsum=arblockcsumorig;
    out_blkinfo->blkcompalgo=compalgo;
    out_blkinfo->blkcryptalgo=cryptalgo;
    out_blkinfo->blkarsize=finalsize;
    out_blkinfo->blkcompsize=compsize;
    
    // ---- checksum
    arblockcsumcalc=fletcher32(buffer, finalsize);
    corrupt=false;
    if (arblockcsumcalc!=arblockcsumorig) // bad checksum
    {
        errprintf("block is corrupt at offset=%ld, blksize=%ld\n", (long)blockoffset, (long)curblocksize);
        corrupt=!g_options.keepcorrupt;
    }
    if (corrupt) {
        free(out_blkinfo->blkdata);
        if ((out_blkinfo->blkdata=malloc(curblocksize))==NULL)
        {   errprintf("cannot allocate block: malloc(%d) failed\n", curblocksize);
            return FSAERR_ENOMEM;
        }
        memset(out_blkinfo->blkdata, 0, curblocksize);
        *out_sumok=false;
        // go to the beginning of the corrupted contents so that the next header is searched here
        if (lseek64(ai->archfd, -(long long)finalsize, SEEK_CUR)<0)
        {   errprintf("lseek64() failed\n");
        }
    }
    else // no corruption detected
    {
        *out_sumok=true;
    }
    
    return 0;
}
예제 #4
0
int archreader_read_volheader(carchreader *ai)
{
    char creatver[FSA_MAX_PROGVERLEN];
    char filefmt[FSA_MAX_FILEFMTLEN];
    char magic[FSA_SIZEOF_MAGIC];
    cdico *d;
    u32 volnum;
    u32 readid;
    u16 fsid;
    int res;
    int ret=0;
    
    // init
    assert(ai);
    memset(magic, 0, sizeof(magic));

    // ---- a. read header from archive file
    if ((res=archreader_read_header(ai, magic, &d, false, &fsid))!=FSAERR_SUCCESS)
    {   errprintf("archreader_read_header() failed to read the archive header\n");
        return -1;
    }
    
    // ---- b. check the magic is what we expected
    if (strncmp(magic, FSA_MAGIC_VOLH, FSA_SIZEOF_MAGIC)!=0)
    {   errprintf("magic is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_VOLH);
        ret=-1; goto archio_read_volheader_error;
    }
    
    if (dico_get_u32(d, 0, VOLUMEHEADKEY_ARCHID, &readid)!=0)
    {   errprintf("cannot get VOLUMEHEADKEY_ARCHID from the volume header\n");
        ret=-1; goto archio_read_volheader_error;
    }
    
    // ---- c. check the archive id
    if (ai->archid==0) // archid not know: this is the first volume
    {
        ai->archid=readid;
    }
    else if (readid!=ai->archid) // archid known: not the first volume
    {   errprintf("wrong header id: found=%.8x and expected=%.8x\n", readid, ai->archid);
        ret=-1; goto archio_read_volheader_error;
    }
    
    // ---- d. check the volnum
    if (dico_get_u32(d, 0, VOLUMEHEADKEY_VOLNUM, &volnum)!=0)
    {   errprintf("cannot get VOLUMEHEADKEY_VOLNUM from the volume header\n");
        ret=-1; goto archio_read_volheader_error;
    }
    if (volnum!=ai->curvol) // not the right volume number
    {   errprintf("wrong volume number in [%s]: volnum is %d and we need volnum %d\n", ai->volpath, (int)volnum, (int)ai->curvol);
        ret=-1; goto archio_read_volheader_error;
    }
    
    // ---- d. check the the file format
    if (dico_get_data(d, 0, VOLUMEHEADKEY_FILEFORMATVER, filefmt, FSA_MAX_FILEFMTLEN, NULL)!=0)
    {   errprintf("cannot find VOLUMEHEADKEY_FILEFORMATVER in main-header\n");
        ret=-1; goto archio_read_volheader_error;
    }
    
    if (ai->filefmt[0]==0) // filefmt not know: this is the first volume
    {
        memcpy(ai->filefmt, filefmt, FSA_MAX_FILEFMTLEN);
    }
    else if (strncmp(filefmt, ai->filefmt, FSA_MAX_FILEFMTLEN)!=0)
    {
        errprintf("This archive is based on a different file format: [%s]. Cannot continue.\n", ai->filefmt);
        errprintf("It has been created with fsarchiver [%s], you should extrat the archive using that version.\n", ai->creatver);
        errprintf("The current version of the program is [%s], and it's based on format [%s]\n", FSA_VERSION, FSA_FILEFORMAT);
        ret=-1; goto archio_read_volheader_error;
    }
    
    if (dico_get_data(d, 0, VOLUMEHEADKEY_PROGVERCREAT, creatver, FSA_MAX_PROGVERLEN, NULL)!=0)
    {   errprintf("cannot find VOLUMEHEADKEY_PROGVERCREAT in main-header\n");
        ret=-1; goto archio_read_volheader_error;
    }
    
    if (ai->creatver[0]==0)
        memcpy(ai->creatver, creatver, FSA_MAX_PROGVERLEN);
    
archio_read_volheader_error:
    dico_destroy(d);
    
    return ret;
}