void do_update(char *fn, int erase_first)
{
    void *zdata;
    unsigned zsize;
    void *data;
    unsigned sz;
    zipfile_t zip;

    queue_info_dump();

    fb_queue_query_save("product", cur_product, sizeof(cur_product));

    zdata = load_file(fn, &zsize);
    if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));

    zip = init_zipfile(zdata, zsize);
    if(zip == 0) die("failed to access zipdata in '%s'");

    data = unzip_file(zip, "android-info.txt", &sz);
    if (data == 0) {
        char *tmp;
            /* fallback for older zipfiles */
        data = unzip_file(zip, "android-product.txt", &sz);
        if ((data == 0) || (sz < 1)) {
            die("update package has no android-info.txt or android-product.txt");
        }
        tmp = malloc(sz + 128);
        if (tmp == 0) die("out of memory");
        sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
        data = tmp;
        sz = strlen(tmp);
    }

    setup_requirements(data, sz);

    data = unzip_file(zip, "boot.img", &sz);
    if (data == 0) die("update package missing boot.img");
    do_update_signature(zip, "boot.sig");
    if (erase_first && needs_erase("boot")) {
        fb_queue_erase("boot");
    }
    fb_queue_flash("boot", data, sz);

    data = unzip_file(zip, "recovery.img", &sz);
    if (data != 0) {
        do_update_signature(zip, "recovery.sig");
        if (erase_first && needs_erase("recovery")) {
            fb_queue_erase("recovery");
        }
        fb_queue_flash("recovery", data, sz);
    }

    data = unzip_file(zip, "system.img", &sz);
    if (data == 0) die("update package missing system.img");
    do_update_signature(zip, "system.sig");
    if (erase_first && needs_erase("system")) {
        fb_queue_erase("system");
    }
    fb_queue_flash("system", data, sz);
}
void do_update(usb_handle *usb, char *fn, int erase_first)
{
    void *zdata;
    unsigned zsize;
    void *data;
    unsigned sz;
    zipfile_t zip;
    int fd;
    int rc;
    struct fastboot_buffer buf;
    size_t i;

    queue_info_dump();

    fb_queue_query_save("product", cur_product, sizeof(cur_product));

    zdata = load_file(fn, &zsize);
    if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));

    zip = init_zipfile(zdata, zsize);
    if(zip == 0) die("failed to access zipdata in '%s'");

    data = unzip_file(zip, "android-info.txt", &sz);
    if (data == 0) {
        char *tmp;
        /* fallback for older zipfiles */
        data = unzip_file(zip, "android-product.txt", &sz);
        if ((data == 0) || (sz < 1)) {
            die("update package has no android-info.txt or android-product.txt");
        }
        tmp = malloc(sz + 128);
        if (tmp == 0) die("out of memory");
        sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
        data = tmp;
        sz = strlen(tmp);
    }

    setup_requirements(data, sz);

    for (i = 0; i < ARRAY_SIZE(images); i++) {
        fd = unzip_to_file(zip, images[i].img_name);
        if (fd < 0) {
            if (images[i].is_optional)
                continue;
            die("update package missing %s", images[i].img_name);
        }
        rc = load_buf_fd(usb, fd, &buf);
        if (rc) die("cannot load %s from flash", images[i].img_name);
        do_update_signature(zip, images[i].sig_name);
        if (erase_first && needs_erase(images[i].part_name)) {
            fb_queue_erase(images[i].part_name);
        }
        flash_buf(images[i].part_name, &buf);
        /* not closing the fd here since the sparse code keeps the fd around
         * but hasn't mmaped data yet. The tmpfile will get cleaned up when the
         * program exits.
         */
    }
}
static void do_update_signature(ZipArchiveHandle zip, char* fn) {
    int64_t sz;
    void* data = unzip_file(zip, fn, &sz);
    if (data == nullptr) return;
    fb_queue_download("signature", data, sz);
    fb_queue_command("signature", "installing signature");
}
Exemple #4
0
/**
 * Unzip a file - replacing the file with the unzipped contents of the self
 */
static void uncompress_zip ( gchar *name )
{
	GError *error = NULL;
	GMappedFile *mf;

	if ((mf = g_mapped_file_new ( name, FALSE, &error )) == NULL) {
		g_critical(_("Couldn't map file %s: %s"), name, error->message);
		g_error_free(error);
		return;
	}
	gchar *file_contents = g_mapped_file_get_contents ( mf );

	void *unzip_mem = NULL;
	gulong ucsize;

	if ((unzip_mem = unzip_file (file_contents, &ucsize)) == NULL) {
		g_mapped_file_unref ( mf );
		return;
	}

	// This overwrites any previous file contents
	if ( ! g_file_set_contents ( name, unzip_mem, ucsize, &error ) ) {
		g_critical ( "Couldn't write file '%s', because of %s", name, error->message );
		g_error_free ( error );
	}
}
void do_update_signature(zipfile_t zip, char *fn)
{
    void *data;
    unsigned sz;
    data = unzip_file(zip, fn, &sz);
    if (data == 0) return;
    fb_queue_download("signature", data, sz);
    fb_queue_command("signature", "installing signature");
}
void do_update(usb_handle *usb, const char *filename, int erase_first)
{
    queue_info_dump();

    fb_queue_query_save("product", cur_product, sizeof(cur_product));

    ZipArchiveHandle zip;
    int error = OpenArchive(filename, &zip);
    if (error != 0) {
        CloseArchive(zip);
        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
    }

    unsigned sz;
    void* data = unzip_file(zip, "android-info.txt", &sz);
    if (data == 0) {
        CloseArchive(zip);
        die("update package '%s' has no android-info.txt", filename);
    }

    setup_requirements(reinterpret_cast<char*>(data), sz);

    for (size_t i = 0; i < ARRAY_SIZE(images); ++i) {
        int fd = unzip_to_file(zip, images[i].img_name);
        if (fd == -1) {
            if (images[i].is_optional) {
                continue;
            }
            CloseArchive(zip);
            exit(1); // unzip_to_file already explained why.
        }
        fastboot_buffer buf;
        int rc = load_buf_fd(usb, fd, &buf);
        if (rc) die("cannot load %s from flash", images[i].img_name);
        do_update_signature(zip, images[i].sig_name);
        if (erase_first && needs_erase(usb, images[i].part_name)) {
            fb_queue_erase(images[i].part_name);
        }
        flash_buf(images[i].part_name, &buf);
        /* not closing the fd here since the sparse code keeps the fd around
         * but hasn't mmaped data yet. The tmpfile will get cleaned up when the
         * program exits.
         */
    }

    CloseArchive(zip);
}
static int unzip_to_file(zipfile_t zip, char *name)
{
    int fd;
    char *data;
    unsigned sz;

    fd = fileno(tmpfile());
    if (fd < 0) {
        return -1;
    }

    data = unzip_file(zip, name, &sz);
    if (data == 0) {
        return -1;
    }

    if (write(fd, data, sz) != (ssize_t)sz) {
        fd = -1;
    }

    free(data);
    lseek(fd, 0, SEEK_SET);
    return fd;
}
Exemple #8
0
void do_flashall(char *fn)
{
    void *zdata;
    unsigned zsize;
    void *data;
    unsigned sz;
    zipfile_t zip;
    struct config conf;
    char ver[FB_RESPONSE_SZ + 1];
    char *pc;
    int status;

    /* get target IFWI major version */
    fprintf(stderr, "query system info...\n");
    fb_queue_query_save("ifwi", ver, sizeof(ver));
    usb = open_device();
    fb_execute_queue(usb);

    if ((pc = strchr(ver, '.')))
        *pc = 0;

    queue_info_dump();

    zdata = load_file(fn, &zsize);
    if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));

    zip = init_zipfile(zdata, zsize);
    if(zip == 0) die("failed to access zipdata in '%s', is it a zip file?", fn);

    /* is converted-system tarball? */
    data = unzip_file(zip, CONFIG_FILE, &sz);
    if (data == 0) {
        /* is raw container tarball? */
        data = unzip_file(zip, FW_CONFIG, &sz);
        if (data != 0 && parse_config(data, (size_t)sz, &conf, ver))
            die("parse config: %s failed.", FW_CONFIG);
        data = unzip_file(zip, PREOS_CONFIG, &sz);
        if (data != 0 && parse_config(data, (size_t)sz, &conf, ver))
            die("parse config: %s failed.", PREOS_CONFIG);
    } else {
        if (parse_config(data, (size_t)sz, &conf, ver))
            die("parse config failed.");
    }

    /*
     * every component is optional, no need to check
     * the second of unzip_file argument if it's not null
     * memcmp can handle NULL pointer.
     */
    data = unzip_file(zip, conf.fwr_dnx, &sz);
    if (data != 0)
        fb_queue_stream_flash("dnx", data, sz);

    data = unzip_file(zip, conf.ifwi, &sz);
    if (data != 0)
        fb_queue_stream_flash("ifwi", data, sz);

    data = unzip_file(zip, conf.boot, &sz);
    if (data != 0)
        fb_queue_stream_flash("boot", data, sz);

    data = unzip_file(zip, conf.preos, &sz);
    if (data != 0)
        fb_queue_stream_flash("preos", data, sz);

    /* try to get platform image.
     * first, try gziped.
     * second, try bzip2.
     * at last, try raw image
     */
    data = unzip_file(zip, PLATFORM_IMG ".gz", &sz);
    if (data == 0) {
        data = unzip_file(zip, PLATFORM_IMG ".bz2", &sz);
        if (data == 0) {
            data = unzip_file(zip, PLATFORM_IMG, &sz);
        }
    }
    if (data != 0)
        fb_queue_stream_flash("platform", data, sz);

    /* data and csa partition image */
    data = unzip_file(zip, DATA_IMG ".gz", &sz);
    if (data == 0) {
        data = unzip_file(zip, DATA_IMG ".bz2", &sz);
        if (data == 0) {
            data = unzip_file(zip, DATA_IMG, &sz);
        }
    }
    if (data != 0)
        fb_queue_stream_flash("data", data, sz);

    data = unzip_file(zip, CSA_IMG ".gz", &sz);
    if (data == 0) {
        data = unzip_file(zip, CSA_IMG ".bz2", &sz);
        if (data == 0) {
            data = unzip_file(zip, CSA_IMG, &sz);
        }
    }
    if (data != 0)
        fb_queue_stream_flash("csa", data, sz);
}
Exemple #9
0
BOOL file_loader::Load::From_ZIP ( LPSTR zipname, LPSTR filename, byte** data, int* length )
{
	int current_zip;

	for ( int x = 0; x != zip_optimize.count; x++ )
	{
		if ( strcmp ( zip_optimize.zipname [ x ], zipname ) == 0 )
		{
			current_zip = x;
			goto jump;
		}
	}

	back:
		zip_optimize.zipname [ zip_optimize.count ] = new char [ strlen ( zipname ) + 1 ];
		
		strcpy ( zip_optimize.zipname [ zip_optimize.count ], zipname );

		current_zip = zip_optimize.count;
		
		if ( zip_optimize.count == MAX_ZIPS )
		{
			zip_optimize.count--;
			delete zip_optimize.files [ zip_optimize.count ];
			goto back;
		}

		zip_optimize.count++;		
		
		zip_optimize.file [ current_zip ] = fopen ( zipname, "rb" );

		if ( zip_optimize.file [ current_zip ] == NULL )
			return FALSE;

		// read header
		fseek ( zip_optimize.file [ current_zip ], 0 - sizeof ( zip_dir_t ), SEEK_END );

		if ( fread ( &zip_optimize.dir [ current_zip ], 1, sizeof ( zip_dir_t ), zip_optimize.file [ current_zip ] ) != sizeof ( zip_dir_t ) )
			return FALSE;

		zip_optimize.files [ current_zip ] = new zfile_entry_t [ zip_optimize.dir [ current_zip ].count ];
		
		// navigate to file entries
		fseek ( zip_optimize.file [ current_zip ], zip_optimize.dir [ current_zip ].offset,SEEK_SET );

		int i;
		
		for ( i = 0; i < zip_optimize.dir [ current_zip ].count; i++ )
		{
			// read header followed by file name
			zip_file_t h;

			if ( fread ( &h, 1, sizeof ( zip_file_t ), zip_optimize.file [ current_zip ] ) != sizeof ( zip_file_t ) )
				return false;
			
			char name [ 256 ];
			memset ( name, 0, sizeof ( name ) );

			if ( fread ( name, 1, h.name_len, zip_optimize.file [ current_zip ] ) != h.name_len )
				return false;
			
			fseek ( zip_optimize.file [ current_zip ], h.extra_len + h.comment_len, SEEK_CUR );
					
			strcpy(zip_optimize.files [ current_zip ] [ i ].name, _strlwr ( name ) );

			zip_optimize.files [ current_zip ] [ i ].offset = h.offset;
			zip_optimize.files [ current_zip ] [ i ].size   = h.size;
			zip_optimize.files [ current_zip ] [ i ].csize  = h.csize;
		}


	jump:
		for ( i = 0; i < zip_optimize.dir [ current_zip ].count; i++ )
		{
			if ( strlen ( zip_optimize.files [ current_zip ] [ i ].name ) < strlen ( filename ) )
				continue;

			if ( _strnicmp (
							filename,
							zip_optimize.files [ current_zip ] [ i ].name + ( strlen ( zip_optimize.files [ current_zip ] [ i ].name ) - strlen ( filename ) ),
							strlen ( filename ) ) == 0
						  )
			{
				goto found;
			}
		}

		return FALSE;

	found:

		int idx = i;

		const zfile_entry_t& f = zip_optimize.files [ current_zip ] [ idx ];

		extern char* unzip_file ( const char* p, int& size );

		if ( f.size == 0 || f.csize == 0 )
			return FALSE;
		
		LF lf;
		fseek ( zip_optimize.file [ current_zip ], f.offset, SEEK_SET );

		if ( fread ( &lf, 1, sizeof ( LF ), zip_optimize.file [ current_zip ] ) != sizeof ( LF ) )
		{
			return false;
		}

		// compute the complete file size
		int size = f.csize + sizeof ( LF ) + lf.lf_fn_len + lf.lf_ef_len;

		// get temp buffer
		char* tmp = new char [ size ];
		
		if ( !tmp )
		{
			return false;
		}

		// back up a little and read the whole file
		fseek ( zip_optimize.file [ current_zip ], 0 - sizeof ( LF ), SEEK_CUR );

		if ( fread ( tmp, 1, size, zip_optimize.file [ current_zip ] ) != ( unsigned ) size )
		{
			// return false;
		}

		// unzip
		size = 0;
		char* unzippeddata = unzip_file ( tmp, size );
		delete tmp;

		if ( !unzippeddata || ( unsigned ) size != f.size )
		{
			// mismatch
			if ( unzippeddata )
			{
				
			}

			return false;
		}


		if ( data != NULL )
			*data = ( byte* ) unzippeddata;

		if ( length != NULL) 
			*length = size;

		return TRUE;
}
Exemple #10
0
inst_t
disk_install(const char *datfile, char *fromdir, char *destdir)
{
  char lsmfile[MAXPATH];		/* Linux software map file */
  char *s;

  int dat_count;				/* size of the dat array */
  int ret;
  int ch;
  int i;

  int pkg_yesToAll = 0;			/* Assume default yes to all = not specified */

  dat_t *dat_ary;				/* the DAT array */
  inst_t this;				/* return: no. of errors,warnings */

  /* Initialize variables */

  this.errors = 0;
  this.warnings = 0;

  /* Read dat file */
  dat_ary = dat_read (datfile, &dat_count);
  if (dat_ary == NULL)
    {
      s = catgets (cat, SET_ERRORS, MSG_ERROR, MSG_ERROR_STR);
      fprintf (stderr, s);
      log("<error msg=\"%s\" />\n", s);
      s = catgets (cat, SET_ERRORS, MSG_ERRALLOCMEMFDF, MSG_ERRALLOCMEMFDF_STR);
      fprintf (stderr, s);
      log("<error msg=\"%s\" />\n", s);

	pause();
      return (this);
    }
  if (dat_count < 1)
    {
      s = catgets (cat, SET_ERRORS, MSG_ERROR, MSG_ERROR_STR);
      fprintf (stderr, s);
      log("<error msg=\"%s\" />\n", s);
      s = catgets (cat, SET_ERRORS, MSG_ERREMPTYFLOPPYDATAFILE, MSG_ERREMPTYFLOPPYDATAFILE_STR);
      fprintf (stderr, s);
      log("<error msg=\"%s\" />\n", s);


	pause();
      free (dat_ary);
      return (this);
    }

  /* Run the install */

  for (i = 0; i < dat_count; i++) {
    /* Print the screen and progress bargraph */

    repaint_empty();

    box (14, 16, 66, 18);
    gotoxy (15, 17);
    bargraph (i, dat_count, 50 /* width */);

    /* Print the package name */

    gotoxy (2, 5);
    s = catgets (cat, SET_PKG_GENERAL, MSG_PACKAGE, MSG_PACKAGE_STR);
    cputs (s);

    cputs (dat_ary[i].name);

    /* Show the package description */

    /* Generate the lsmfile name */

    fnmerge (lsmfile, "", fromdir, dat_ary[i].name, "LSM");

    if (isfile (lsmfile))
      {
	lsm_description (8, 2, 10, lsmfile);
      }
    else
      {
	/* no lsm file. try it again with a plain txt file (or localized version) */

	fnmerge (lsmfile, "", fromdir, dat_ary[i].name, "");

	    gotoxy (2, 8);
	    cat_file (lsmfile, 10 /* no. lines */);
	  }

    /* Find out which ones the user wants to install */

    gotoxy (2, 25);
    switch (dat_ary[i].rank) {
    case 'n':
    case 'N':
      /* Do not install */

      log("<package name=\"%s\" choice=\"n\" />\n", dat_ary[i].name);
      s = catgets (cat, SET_PKG_NEED, MSG_SKIPPED, MSG_SKIPPED_STR);
      cputs (s);
      break;

    case 'y':
    case 'Y':
      /* Always install */

      log("<package name=\"%s\" choice=\"y\" ", dat_ary[i].name);
      s = catgets (cat, SET_PKG_NEED, MSG_REQUIRED, MSG_REQUIRED_STR);
      cputs (s);

      ret = unzip_file (dat_ary[i].name, fromdir, destdir);

      reregisterSIGINTHandler(); /* unzip installs its own SIGINT handler */

      if (ret != 0) {
	/* Print an error message */

	s = catgets (cat, SET_PKG_GENERAL, MSG_ERRREQPKG, MSG_ERRREQPKG_STR);
	cputs (s);
      log(">\n");
      log("<error msg=\"%s\" />\n", s);
      log("</package>\n");

	/* Return an error */

	this.errors++;

	/* Does the user want to continue anyway? */

	s = catgets (cat, SET_PROMPT_YN, MSG_CONTINSTDISK, MSG_CONTINSTDISK_STR);
	ch = select_yn(s, yes, no, NULL, NULL);

        if (ch)
        {
          log("<abort msg=\"User choose not to continue after error.\" />\n");
          return (this);
	  }
      }
      else /* ret == 0, ie no errors */
        log("/>\n");
      break;

    default:
      /* Optional */

      s = catgets (cat, SET_PKG_NEED, MSG_OPTIONAL, MSG_OPTIONAL_STR);
      cputs (s);

      /* Ask the user if you want to install it */

      s = catgets (cat, SET_PROMPT_YN, MSG_INSTALLPKG, MSG_INSTALLPKG_STR);
      if (!pkg_yesToAll)
	{
	      ch = select_yn (s, yes, no, 
                            catgets (cat, SET_PROMPT_YN, MSG_YESTOALL, MSG_YESTOALL_STR),
                            NULL);
		if (ch == 2) pkg_yesToAll = 1;
	}

      if (pkg_yesToAll || ch==0) /* Yes or YesToAll */
	{
        log("<package name=\"%s\" choice=\"y\" ", dat_ary[i].name);
	  ret = unzip_file (dat_ary[i].name, fromdir, destdir);

        reregisterSIGINTHandler(); /* unzip installs its own SIGINT handler */

	  if (ret != 0)
	    {
	      /* Print a warning message */

	      gotoxy (2, 13);
	      s = catgets (cat, SET_PKG_GENERAL, MSG_WARNOPTPKG, MSG_WARNOPTPKG_STR);
	      cputs (s);
            log(">\n");
            log("<warning msg=\"%s\" />\n", s);
            log("</package>\n");

		pause();
	      this.warnings++;
	    }
          else
            log("/>\n");
	}
      else /* user selected no */
          log("<package name=\"%s\" choice=\"n\" />\n", dat_ary[i].name);
      break;

    } /* switch */
  } /* for */

  /* Print the screen and 100% complete progress bargraph */
  repaint_empty();
  box (14, 16, 66, 18);
  gotoxy (15, 17);
  bargraph (1, 1, 50 /* width */);

  /* Free memory for this disk */

  free (dat_ary);
  return (this);
}
Exemple #11
0
inst_t
disk_install(const char *datfile, const char *descfile,
	     char *fromdir, char *destdir)
{
  char *s;
  char lsmfile[_MAX_PATH];		/* Linux software map file */
  int ret;
  int ch;
  int i;
  int dat_size = 30;			/* malloc size of the dat array */
  int dat_count;			/* size of the dat array */
  dat_t *dat_ary;			/* the DAT array */
  inst_t this;				/* return: no. of errors,warnings */

  /* Initialize variables */

  this.errors = 0;
  this.warnings = 0;

  /* Read dat file */

  dat_ary = malloc (sizeof (dat_t) * dat_size);
  if (dat_ary == NULL)
    {
      fprintf (stderr, "Error!\n");
      fprintf (stderr, "Unable to allocate enough memory for install floppy data file!\n");

      gotoxy (1, 25);
      s = catgets (cat, 1, 0, "Press any key to continue");
      cputs (s);

      getch();
      return (this);
    }

  dat_count = dat_read (datfile, dat_ary, dat_size);
  if (dat_count < 1)
    {
      fprintf (stderr, "Error!\n");
      fprintf (stderr, "The install floppy data file is empty!\n");

      gotoxy (1, 25);
      s = catgets (cat, 1, 0, "Press any key to continue");
      cputs (s);

      getch();
      free (dat_ary);
      return (this);
    }

  /* Run the install */

  for (i = 0; i < dat_count; i++) {
    /* Print the screen and progress bargraph */

    repaint_empty();
    gotoxy (15, 20);
    bargraph (i, dat_count, 50 /* width */);

    /* Print the package name */

    gotoxy (1, 5);
    s = catgets (cat, 3, 3, "Package: ");
    cputs (s);

    cputs (dat_ary[i].name);

    /* Show the package description */

    /* Generate the lsmfile name */

    _makepath (lsmfile, "", fromdir, dat_ary[i].name, "LSM");

    if (isfile (lsmfile))
      {
	lsm_description (8, 1, 10, lsmfile);
      }
    else
      {
	/* no lsm file. try it again with a plain txt file */

	_makepath (lsmfile, "", fromdir, dat_ary[i].name, "TXT");

	if (isfile (lsmfile))
	  {
	    cat_file (lsmfile, 8 /* start line */, 10 /* no. lines */);
	  }
      }

    /* Find out which ones the user wants to install */

    gotoxy (1, 23);
    switch (dat_ary[i].rank) {
    case 'n':
    case 'N':
      /* Do not install */

      s = catgets (cat, 4, 2, "SKIPPED");
      cputs (s);
      break;

    case 'y':
    case 'Y':
      /* Always install */

      s = catgets (cat, 4, 1, "REQUIRED");
      cputs (s);

      ret = unzip_file (dat_ary[i].name, fromdir, destdir);

      if (ret != 0) {
	/* Print an error message */

	s = catgets (cat, 3, 6, "ERROR!  Failed to install REQUIRED package.");
	cputs (s);

	/* Return an error */

	this.errors++;

	/* Does the user want to continue anyway? */

	gotoxy (1, 25);
	s = catgets (cat, 2, 3, "Continue installing this disk? [yn]");
	cputs (s);

	ch = getch_yn();

	if ((ch != 'y') && (ch != 'Y'))
	  {
	    return (this);
	  }
      }
      break;

    default:
      /* Optional */

      s = catgets (cat, 4, 0, "OPTIONAL");
      cputs (s);

      /* Ask the user if you want to install it */

      gotoxy (1, 23);
      s = catgets (cat, 2, 4, "Install this package? [yn]");
      cputs (s);

      ch = getch_yn();

      if ((ch == 'y') || (ch == 'Y'))
	{
	  ret = unzip_file (dat_ary[i].name, fromdir, destdir);

	  if (ret != 0)
	    {
	      /* Print a warning message */

	      gotoxy (1, 23);
	      s = catgets (cat, 3, 7, "WARNING!  Failed to install OPTIONAL package.");
	      cputs (s);

	      gotoxy (1, 25);
	      s = catgets (cat, 1, 0, "Press any key to continue");
	      cputs (s);

	      getch();
	      this.warnings++;
	    }
	}
      break;

    } /* switch */
  } /* for */

  /* Free memory for this disk */

  free (dat_ary);
  return (this);
}