Exemple #1
0
static int
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
{
    zip_int64_t offstart, offdata, offend;
    struct zip_stat st;
    zip_source_t *s2;
    int ret;
    int is_zip64;
    zip_flags_t flags;
    
    if (zip_source_stat(src, &st) < 0) {
	_zip_error_set_from_source(&za->error, src);
	return -1;
    }

    if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
	st.valid |= ZIP_STAT_COMP_METHOD;
	st.comp_method = ZIP_CM_STORE;
    }

    if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
	de->comp_method = st.comp_method;
    else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
	st.valid |= ZIP_STAT_COMP_SIZE;
	st.comp_size = st.size;
    }
    else {
	/* we'll recompress */
	st.valid &= ~ZIP_STAT_COMP_SIZE;
    }


    flags = ZIP_EF_LOCAL;

    if ((st.valid & ZIP_STAT_SIZE) == 0)
	flags |= ZIP_FL_FORCE_ZIP64;
    else {
	de->uncomp_size = st.size;
	
	if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
	    if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
		  || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
		flags |= ZIP_FL_FORCE_ZIP64;
	}
	else
	    de->comp_size = st.comp_size;
    }

    if ((offstart = zip_source_tell_write(za->src)) < 0) {
        return -1;
    }

    /* as long as we don't support non-seekable output, clear data descriptor bit */
    de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
    if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
	return -1;


    if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
	zip_source_t *s_store, *s_crc;
	zip_compression_implementation comp_impl;
	
	if (st.comp_method != ZIP_CM_STORE) {
	    if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
		zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
		return -1;
	    }
	    if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
		/* error set by comp_impl */
		return -1;
	    }
	}
	else {
	    /* to have the same reference count to src as in the case where it's not stored */
	    zip_source_keep(src);
	    s_store = src;
	}

	s_crc = zip_source_crc(za, s_store, 0);
	zip_source_free(s_store);
	if (s_crc == NULL) {
	    return -1;
	}

	if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
	    if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) {
		zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
		zip_source_free(s_crc);
		return -1;
	    }
	    s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE);
	    zip_source_free(s_crc);
	    if (s2 == NULL) {
		return -1;
	    }
	}
	else {
	    s2 = s_crc;
	}
    }
    else {
	zip_source_keep(src);
	s2 = src;
    }

    if ((offdata = zip_source_tell_write(za->src)) < 0) {
        return -1;
    }

    ret = copy_source(za, s2);
	
    if (zip_source_stat(s2, &st) < 0)
	ret = -1;

    zip_source_free(s2);

    if (ret < 0)
	return -1;

    if ((offend = zip_source_tell_write(za->src)) < 0) {
        return -1;
    }

    if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
	_zip_error_set_from_source(&za->error, za->src);
	return -1;
    }

    if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
	zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

    if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
        if (st.valid & ZIP_STAT_MTIME)
            de->last_mod = st.mtime;
        else
            time(&de->last_mod);
    }
    de->comp_method = st.comp_method;
    de->crc = st.crc;
    de->uncomp_size = st.size;
    de->comp_size = (zip_uint64_t)(offend - offdata);

    if ((ret=_zip_dirent_write(za, de, flags)) < 0)
	return -1;
 
    if (is_zip64 != ret) {
	/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
	zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

   
    if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
	_zip_error_set_from_source(&za->error, za->src);
	return -1;
    }

    return 0;
}
Exemple #2
0
static int
add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft)
{
    off_t offstart, offdata, offend;
    struct zip_stat st;
    struct zip_source *s2;
    int ret;
    int is_zip64;
    zip_flags_t flags;
    
    if (zip_source_stat(src, &st) < 0) {
	_zip_error_set_from_source(&za->error, src);
	return -1;
    }

    if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
	st.valid |= ZIP_STAT_COMP_METHOD;
	st.comp_method = ZIP_CM_STORE;
    }

    if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
	de->comp_method = st.comp_method;
    else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
	st.valid |= ZIP_STAT_COMP_SIZE;
	st.comp_size = st.size;
    }
    else {
	/* we'll recompress */
	st.valid &= ~ZIP_STAT_COMP_SIZE;
    }


    flags = ZIP_EF_LOCAL;

    if ((st.valid & ZIP_STAT_SIZE) == 0)
	flags |= ZIP_FL_FORCE_ZIP64;
    else {
	de->uncomp_size = st.size;
	
	if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
	    if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
		 || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
		flags |= ZIP_FL_FORCE_ZIP64;
	}
	else
	    de->comp_size = st.comp_size;
    }


    offstart = ftello(ft);

    /* as long as we don't support non-seekable output, clear data descriptor bit */
    de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
    if ((is_zip64=_zip_dirent_write(de, ft, flags, &za->error)) < 0)
	return -1;


    if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
	struct zip_source *s_store, *s_crc;
	zip_compression_implementation comp_impl;
	
	if (st.comp_method != ZIP_CM_STORE) {
	    if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
		_zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
		return -1;
	    }
	    if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
		/* error set by comp_impl */
		return -1;
	    }
	}
	else
	    s_store = src;

	if ((s_crc=zip_source_crc(za, s_store, 0)) == NULL) {
	    if (s_store != src)
		zip_source_pop(s_store);
	    return -1;
	}

	/* TODO: deflate 0-byte files for torrentzip? */
	if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
	    if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) {
		_zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
		zip_source_pop(s_crc);
		if (s_store != src)
		    zip_source_pop(s_store);
		return -1;
	    }
	    if ((s2=comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
		zip_source_pop(s_crc);
		if (s_store != src)
		    zip_source_pop(s_store);
		return -1;
	    }
	}
	else
	    s2 = s_crc;
    }
    else
	s2 = src;

    offdata = ftello(ft);
	
    ret = copy_source(za, s2, ft);
	
    if (zip_source_stat(s2, &st) < 0)
	ret = -1;
    
    while (s2 != src) {
	if ((s2=zip_source_pop(s2)) == NULL) {
	    /* TODO: set erorr */
	    ret = -1;
	    break;
	}
    }

    if (ret < 0)
	return -1;

    offend = ftello(ft);

    if (fseeko(ft, offstart, SEEK_SET) < 0) {
	_zip_error_set(&za->error, ZIP_ER_SEEK, errno);
	return -1;
    }

    if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
	_zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

    if (st.valid & ZIP_STAT_MTIME)
	de->last_mod = st.mtime;
    else
	time(&de->last_mod);
    de->comp_method = st.comp_method;
    de->crc = st.crc;
    de->uncomp_size = st.size;
    de->comp_size = (zip_uint64_t)(offend - offdata);

    if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
	_zip_dirent_torrent_normalize(de);

    if ((ret=_zip_dirent_write(de, ft, flags, &za->error)) < 0)
	return -1;
 
    if (is_zip64 != ret) {
	/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
	_zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

   
    if (fseeko(ft, offend, SEEK_SET) < 0) {
	_zip_error_set(&za->error, ZIP_ER_SEEK, errno);
	return -1;
    }

    return 0;
}
Exemple #3
0
/* parse programm line arguments, set-up parameter, initialise and run the simulation */
int main(int argc, const char* argv[])
{
    int ret = 0;

    double energy_keV, distance1_m, f_m, distance2_m;
    struct parameters parameters;
    //argument structures for funtions and field memory allocation 
    struct s2c s2c; 			s2c.field = malloc(sizeof(struct field));
    struct insidecrl insidecrl; 	insidecrl.field = malloc(sizeof(struct field));
    struct c2f c2f;			c2f.field = malloc(sizeof(struct field));

    int tag = tag_val;           //tag determines whether initially create field or read from file
    int current=0;	         //int used to keep track of the step the simulation goes through (identifying propagation)
    double distance;		 //distance to perform fourier propagation
    char fnameread[20];		 //name of the file to be read
    char fnamewrite[20];	 //name of the file to wite to

    if (argc != 5)
    {
	fprintf(stderr, "usage: %s <energy/keV> <distance1/m> <f/m> <distance2/m>\n", argv[0]);
	ret = -1;
	goto cleanup;
    }

    energy_keV  = atof(argv[1]); /* energy in keV */
    distance1_m = atof(argv[2]); /* distance from point-source to crl device in m */
    f_m         = atof(argv[3]); /* focal distance of individual lens in m */
    distance2_m = atof(argv[4]); /* distance from crl device to detector in m */

    parameters.xray.energy        = energy_keV;
    parameters.xray.wavelength    =   12.398/energy_keV*1e-10; /* conversion factor from keV to angstrom to metre */
    parameters.xray.wavenumber    =    2*M_PI / parameters.xray.wavelength;

    parameters.source.distance    = distance1_m;

    parameters.crl.f              = f_m;
    parameters.crl.aperture       =    1e-3; /* 1 mm */
    parameters.crl.separation     =   10e-6; /* 10 µm */
    parameters.crl.number         =   lenses;
    parameters.crl.deltafactor    =   3.53e-6;
    parameters.crl.R		  =  f_m*2.*M_PI*parameters.crl.deltafactor;

    parameters.detector.distance  = distance2_m;// (40/39 is q for s=40 and f=1);
    parameters.detector.number    = 1;		//to be defined by field propagation
    parameters.detector.width     = 1;		//to be defined by field propagation
//    print_parameters(&parameters, stdout);


    /* If noread then copy parameters to s2c and generate field*/
    if (tag==-1){
    copy_xray(&parameters.xray,   &s2c.xray);
    copy_source(&parameters.source, &s2c.source);
    source_to_crl(&s2c, parameters.crl.aperture);
////    printf("FIRST STEP:  Create field tag=%d \n", tag);
    if (padf) pad_field(s2c.field);
    write_field_to_file(s2c.field, "entrance_plane.txt", parameters.crl.aperture);
    }			

    /* copy parameters to insidecrl structure*/
    copy_xray(&parameters.xray, &insidecrl.xray);
    copy_crl(&parameters.crl, &insidecrl.crl);

    /* copy parameters to c2f structure for the propagation*/
    copy_xray(&insidecrl.xray, &c2f.xray);
    copy_crl(&parameters.crl, &c2f.crl);
    copy_detector(&parameters.detector,&c2f.detector); 

    //Pre-process: Create/read field and allocate memory. Starting point will be after the lens
    //if field is coming from entrance_plane (both generated or read) allocate and execute PREVIOUS phase-shifting 
    if (tag>0){
	sprintf(fnameread,"crl_plane");
	sprintf(fnameread,"%s%d.txt", fnameread, tag);
	read_field_from_file(insidecrl.field, fnameread);
	tag=-1;//CHANGE (fourier propagation)
        } 

	//Get entrance plane field	  
	else{
	   if (tag==-1){	
	    //Getting from field already generated
            insidecrl.field->size = malloc(s2c.field->dimensions*sizeof(int));
            insidecrl.field->values = malloc(s2c.field->components*sizeof(complex double));
            copy_field(s2c.field, insidecrl.field);  
	    }

	    //Reading from entrance_plane
            else if (tag==0){
	    sprintf(fnameread,"entrance_plane");
	    sprintf(fnameread,"%s.txt", fnameread);
	    read_field_from_file(insidecrl.field, fnameread);
	    tag=-1;
 	    }
////        printf("CRL STEP:  Apply phase-shift tag=%d \n", tag);
     	sprintf(fnamewrite,"crl_plane");
	sprintf(fnamewrite,"%s1.txt", fnamewrite);
        crl_inside(&insidecrl, fnamewrite);
	} 

    //Once N is set, get detector parameters
    parameters.detector.number=pix_num; //previously parameters.detector.number=insidecrl.field->components;
//    parameters.detector.width=parameters.detector.number*c2f.xray.wavelength*c2f.detector.distance/parameters.crl.aperture;
    parameters.detector.width=0.01;
    parameters.detector.intensity = malloc(parameters.detector.number * sizeof(double)); 

    copy_detector(&parameters.detector,&c2f.detector); 
    print_parameters(&parameters, stderr);

    // Start lens loop: while current state (lens) has not reached total lens amount. (phshift) + /PROP+(PHSHIFT)/
    //										      (previous) +/LOOP+(post)/
	while(current!=lenses){

////	   printf("NEW STEP:  current state=%d , tag=%d \n", current, tag);

	       // get field from previous steps, allocate if first time
	       if (current==0){
	           c2f.field->size = malloc(insidecrl.field->dimensions*sizeof(int));
	           c2f.field->values = malloc(insidecrl.field->components*sizeof(complex double));
	           }
	       copy_field(insidecrl.field, c2f.field);


//RUN 	   //perform fourier propagation: from CRL to CRL or Detector (different methods)
////	   printf("Call propagation... \n");
   	   if (current==(lenses-1)){
	   distance=parameters.detector.distance;
//           get_spherical(&c2f, tag, distance);
	   if (padf) pad_field(c2f.field);

	   if (ray_add) ray_addition(&c2f, tag, distance);
           else crl_to_focus(&c2f, tag, distance);
	   }
	   else{
           distance=parameters.crl.separation;  
           crl_to_fourier(&c2f, tag, distance);
	   }
	  

////    	   printf("distance for propagation %d was %f \n", current, distance);
////	   printf("propagation successfully done. \n");
	   copy_field(c2f.field, insidecrl.field);

	   //if not reached detector then phase-shift before propagation 
	   if (current!=(lenses-1)){
	   sprintf(fnamewrite,"crl_plane");
	   sprintf(fnamewrite,"%s%d.txt", fnamewrite, current+2);
           crl_inside(&insidecrl, fnamewrite);
	   }

	   current=current+1;
      }
      write_field_to_file(c2f.field, "det_plane.txt", parameters.detector.width);

    
    /* call gnuplot script to generate plots */
    system ("gnuplot gpscript.gp");

cleanup:
    if (parameters.detector.intensity)   free(parameters.detector.intensity);   parameters.detector.intensity=NULL;
    return ret;
}//main
Exemple #4
0
static int
add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de,
	 FILE *ft)
{
    off_t offstart, offdata, offend;
    struct zip_stat st;
    struct zip_source *s2;
    zip_compression_implementation comp_impl;
    int ret;
    
    if (zip_source_stat(src, &st) < 0) {
	_zip_error_set_from_source(&za->error, src);
	return -1;
    }

    offstart = ftello(ft);

    if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
	return -1;

    if ((s2=zip_source_crc(za, src, 0)) == NULL) {
	zip_source_pop(s2);
	return -1;
    }
    
    /* XXX: deflate 0-byte files for torrentzip? */
    if (((st.valid & ZIP_STAT_COMP_METHOD) == 0
	 || st.comp_method == ZIP_CM_STORE)
	&& ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
	comp_impl = NULL;
	if ((comp_impl=zip_get_compression_implementation(ZIP_CM_DEFLATE))
	    == NULL) {
	    _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
	    zip_source_pop(s2);
	    return -1;
	}
	if ((s2=comp_impl(za, s2, ZIP_CM_DEFLATE, ZIP_CODEC_ENCODE))
	    == NULL) {
	    /* XXX: set error? */
	    zip_source_pop(s2);
	    return -1;
	}
    }
    else
	s2 = src;

    offdata = ftello(ft);
	
    ret = copy_source(za, s2, ft);
	
    if (zip_source_stat(s2, &st) < 0)
	ret = -1;
    
    while (s2 != src) {
	if ((s2=zip_source_pop(s2)) == NULL) {
	    /* XXX: set erorr */
	    ret = -1;
	    break;
	}
    }

    if (ret < 0)
	return -1;

    offend = ftello(ft);

    if (fseeko(ft, offstart, SEEK_SET) < 0) {
	_zip_error_set(&za->error, ZIP_ER_SEEK, errno);
	return -1;
    }

    de->last_mod = st.mtime;
    de->comp_method = st.comp_method;
    de->crc = st.crc;
    de->uncomp_size = st.size;
    de->comp_size = offend - offdata;

    if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
	_zip_dirent_torrent_normalize(de);

    if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
	return -1;
    
    if (fseeko(ft, offend, SEEK_SET) < 0) {
	_zip_error_set(&za->error, ZIP_ER_SEEK, errno);
	return -1;
    }

    return 0;
}
Exemple #5
0
static int
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
{
    zip_int64_t offstart, offdata, offend;
    struct zip_stat st;
    zip_source_t *src_final, *src_tmp;
    int ret;
    int is_zip64;
    zip_flags_t flags;
    bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
    
    if (zip_source_stat(src, &st) < 0) {
	_zip_error_set_from_source(&za->error, src);
	return -1;
    }

    if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
	st.valid |= ZIP_STAT_COMP_METHOD;
	st.comp_method = ZIP_CM_STORE;
    }

    if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
	de->comp_method = st.comp_method;
    else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
	st.valid |= ZIP_STAT_COMP_SIZE;
	st.comp_size = st.size;
    }
    else {
	/* we'll recompress */
	st.valid &= ~ZIP_STAT_COMP_SIZE;
    }

    if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
	st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
	st.encryption_method = ZIP_EM_NONE;
    }

    flags = ZIP_EF_LOCAL;

    if ((st.valid & ZIP_STAT_SIZE) == 0)
	flags |= ZIP_FL_FORCE_ZIP64;
    else {
	de->uncomp_size = st.size;
	
	if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
	    if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
		  || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
		flags |= ZIP_FL_FORCE_ZIP64;
	}
	else
	    de->comp_size = st.comp_size;
    }

    if ((offstart = zip_source_tell_write(za->src)) < 0) {
        return -1;
    }

    /* as long as we don't support non-seekable output, clear data descriptor bit */
    de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
    if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
	return -1;

    needs_recompress = !((st.comp_method == de->comp_method) || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method == ZIP_CM_DEFLATE));
    needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
    needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
    needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);

    needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
    needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
    needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);

    src_final = src;
    zip_source_keep(src_final);

    if (needs_decrypt) {
	zip_encryption_implementation impl;
	
	if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
	    zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
	    zip_source_free(src_final);
	    return -1;
	}
	if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
	    /* error set by impl */
	    zip_source_free(src_final);
	    return -1;
	}

	zip_source_free(src_final);
	src_final = src_tmp;
    }
    
    if (needs_decompress) {
	zip_compression_implementation comp_impl;
	
	if ((comp_impl = _zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
	    zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
	    zip_source_free(src_final);
	    return -1;
	}
	if ((src_tmp = comp_impl(za, src_final, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
	    /* error set by comp_impl */
	    zip_source_free(src_final);
	    return -1;
	}

	zip_source_free(src_final);
	src_final = src_tmp;
    }

    if (needs_crc) {
	if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
	    zip_source_free(src_final);
	    return -1;
	}

	zip_source_free(src_final);
	src_final = src_tmp;
    }

    if (needs_compress) {
	zip_compression_implementation comp_impl;

	if ((comp_impl = _zip_get_compression_implementation(de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
	    zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
	    zip_source_free(src_final);
	    return -1;
	}
	if ((src_tmp = comp_impl(za, src_final, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
	    zip_source_free(src_final);
	    return -1;
	}
	
	zip_source_free(src_final);
	src_final = src_tmp;
    }

    
    if (needs_encrypt) {
	zip_encryption_implementation impl;
	const char *password = NULL;

	if (de->password) {
	    password = de->password;
	} else if (za->default_password) {
	    password = za->default_password;
	}
	
	if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
	    zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
	    zip_source_free(src_final);
	    return -1;
	}
	if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
	    /* error set by impl */
	    zip_source_free(src_final);
	    return -1;
	}

	zip_source_free(src_final);
	src_final = src_tmp;
    }


    if ((offdata = zip_source_tell_write(za->src)) < 0) {
        return -1;
    }

    ret = copy_source(za, src_final);
	
    if (zip_source_stat(src_final, &st) < 0) {
	ret = -1;
    }

    zip_source_free(src_final);

    if (ret < 0) {
	return -1;
    }

    if ((offend = zip_source_tell_write(za->src)) < 0) {
        return -1;
    }

    if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
	_zip_error_set_from_source(&za->error, za->src);
	return -1;
    }

    if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
	zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

    if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
        if (st.valid & ZIP_STAT_MTIME)
            de->last_mod = st.mtime;
        else
            time(&de->last_mod);
    }
    de->comp_method = st.comp_method;
    de->crc = st.crc;
    de->uncomp_size = st.size;
    de->comp_size = (zip_uint64_t)(offend - offdata);

    if ((ret=_zip_dirent_write(za, de, flags)) < 0)
	return -1;
 
    if (is_zip64 != ret) {
	/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
	zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

   
    if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
	_zip_error_set_from_source(&za->error, za->src);
	return -1;
    }

    return 0;
}