void extract(const std::string & archive_name, const std::string & dest_dir, const std::string & password)
{
	bool already_extracted;
#ifdef WINDOWS
	already_extracted = contains(extracted_files, archive_name, false);
#else
	already_extracted = contains(extracted_files, archive_name, true);
#endif

	if (already_extracted)
		return;

	fprintf(stdout, "Extracting %s to %s\n", archive_name.c_str(), dest_dir.c_str());

	HANDLE archive;
	struct RAROpenArchiveData data;
	struct RARHeaderData header;

	if (!fileExists(archive_name))
		return;

	if (!createDir(dest_dir))
		return;

	data.ArcName = (char *)archive_name.c_str();
	data.OpenMode = RAR_OM_EXTRACT;
	data.CmtBuf = NULL;
	data.CmtBufSize = 0;


	//fprintf(stdout, "Opening %s\n", argv[1]);
	archive = RAROpenArchive(&data);

	if (!archive || data.OpenResult != 0)
	{
		fprintf(stderr, "Couldn't open %s\n", archive_name.c_str());
		return;
	}

	header.CmtBuf = NULL;

	//fprintf(stdout, "Clearing password\n");
	RARSetPassword(archive, (char*)password.c_str());

	MultipartInfo info;
	//fprintf(stdout, "Setting callback\n");
	RARSetCallback(archive, &missing_file, (ssize_t)&info);

	//fprintf(stdout, "Starting to process file\n");

	// the complete path to the file to be extracted
	std::string dest_path;

	start_timer();
	while (!RARReadHeader(archive, &header))
	{
		dest_path = dest_dir + PATH_SEP + header.FileName;
		if (pathExists(dest_path))
		{
			fprintf(stderr, "Skpping %s\n",  header.FileName);
			continue;
		}
		if (RARProcessFile(archive, RAR_EXTRACT, (char *)dest_dir.c_str(), NULL))
		{
			/*if (!pathExists(dest_path))
			{
				fprintf(stderr, "Couldn't create %s\n",  dest_path.c_str());
				break;
			}*/

			if (elapsed(five_seconds))
			{
				info.bytes_processed = 0;
				start_timer();
			}
		}
		else
		{
			break;
		}

		// (bytes / (1024 * 1024) = MBytes
		// ms / 1000 = s
		// (bytes / (1024 * 1024) / (ms / 1000) = 0.00095367431640625 * bytes/ms
		//fprintf(stdout, "%d MB/s", (int)(0.00095367431640625 * (info.bytes_processed / calc_elapsed())));
	}
	//fprintf(stdout, "Closing file\n");
	RARCloseArchive(archive);

	extracted_files.push_back(archive_name);
}
Exemple #2
0
extern u32 fs_rar_to_menu(const char *rarfile, u32 icolor, u32 selicolor, u32 selrcolor, u32 selbcolor)
{
	int fid;
	struct RAROpenArchiveData arcdata;
	struct RARHeaderDataEx header;
	int ret;
	HANDLE hrar;
	t_fs_filetype ft;
	t_win_menuitem item;

	if (menu_renew(&g_menu) == NULL) {
		return 0;
	}

	fid = freq_enter_hotzone();

	arcdata.ArcName = (char *) rarfile;
	arcdata.OpenMode = RAR_OM_LIST;
	arcdata.CmtBuf = NULL;
	arcdata.CmtBufSize = 0;

	hrar = RAROpenArchive(&arcdata);

	if (hrar == 0) {
		freq_leave(fid);
		return 0;
	}

	add_parent_to_menu(g_menu, icolor, selicolor, selrcolor, selbcolor);

	do {
		char t[20];

		if ((ret = RARReadHeaderEx(hrar, &header)) != 0) {
			if (ret != ERAR_UNKNOWN)
				break;
			RARCloseArchive(hrar);
			if ((hrar = reopen_rar_with_passwords(&arcdata)) == 0)
				break;
			if (RARReadHeaderEx(hrar, &header) != 0)
				break;
		}
		if (header.UnpSize == 0)
			continue;

		ft = fs_file_get_type(header.FileName);

		if (ft == fs_filetype_chm || ft == fs_filetype_zip || ft == fs_filetype_rar)
			continue;

		win_menuitem_new(&item);
		item.data = (void *) ft;

		if (header.Flags & 0x200) {
			char str[1024];
			const u8 *uni;

			memset(str, 0, 1024);
			uni = (u8 *) header.FileNameW;
			charsets_utf32_conv(uni, sizeof(header.FileNameW), (u8 *) str, sizeof(str));
			buffer_copy_string_len(item.compname, header.FileName, 256);
			filename_to_itemname(&item, str);
		} else {
			buffer_copy_string_len(item.compname, header.FileName, 256);
			filename_to_itemname(&item, header.FileName);
		}

		SPRINTF_S(t, "%u", (unsigned int) header.UnpSize);
		buffer_copy_string(item.shortname, t);
		item.selected = false;
		item.icolor = icolor;
		item.selicolor = selicolor;
		item.selrcolor = selrcolor;
		item.selbcolor = selbcolor;
		item.data3 = header.UnpSize;
		win_menu_add(g_menu, &item);
	} while (RARProcessFile(hrar, RAR_SKIP, NULL, NULL) == 0);

	RARCloseArchive(hrar);
	freq_leave(fid);

	return g_menu->size;
}