示例#1
0
std::string CChainWalkSet::CheckOrRotatePreCalcFile()
{
	char sPreCalcFileName[255];

	// 255 files limit to be sure
	for (; preCalcPart < 255; preCalcPart++)
	{
		sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), preCalcPart);
		std::string sReturnPreCalcPath(sPreCalcFileName);

		long fileLen = 0;

		FILE* file = fopen(sReturnPreCalcPath.c_str(), "ab");
		if(file!=NULL)
		{
			fileLen = GetFileLen(sReturnPreCalcPath);

			long unsigned int nextFileLen = fileLen + (sizeof(uint64_t) * (m_nRainbowChainLen-1));
			// Rotate to next file if we are going to pass 2GB filesize
			if (nextFileLen < ((unsigned)2 * 1024 * 1024 * 1024))
			{
				// We might want to vPrecalcFiles.push_back(sReturnPreCalcPath) if we just created this file
				// We don't as only newly generated chainwalksets will be stored to this new file, so we don't have to look there
				if (debug) printf("Debug: Using for precalc: %s\n", sReturnPreCalcPath.c_str());
				fclose(file);
				return sReturnPreCalcPath;
			}
			fclose(file);
		}
	}

	return std::string("");
}
示例#2
0
//打开脚本文件
bool CScript::OpenFile(char* strFilePath)
{
	m_strFileName.assign(strFilePath);

	SAFE_DELETE(m_pFileData);

	m_nFileLen = GetFileLen(strFilePath);
	if(m_nFileLen < 0)
	{
		ShowMessage("Open file %s failed.", strFilePath);
		return false;
	}

	m_pFileData = new char[m_nFileLen+1];

	//读数据
	FILE* fp = fopen(strFilePath, "rb");
	fread(m_pFileData, m_nFileLen, 1, fp);
	fclose(fp);

	m_bScanningStr = false;
	m_nFileOffset = 0;

	return true;
}
示例#3
0
bool BaseLog::OpenLog(const char* lpszFileName) {
	if (m_f != NULL)
		return false;
	if (lpszFileName == NULL) {
		m_strFileName  = PathHelp::os_get_application_path();
		m_strFileName += "log\\";
		m_strFileName += GetCurrentModuleName();
		m_strFileName += ".log";
	} else {
		m_strFileName  = PathHelp::os_get_application_path();
		m_strFileName += lpszFileName;
	}

	int nSize = GetFileLen( m_strFileName.c_str() );
	if (nSize > 1024*1024*5)
		remove(m_strFileName.c_str());

	m_f = fopen (m_strFileName.c_str(), "a+");
	if (!m_f) {
		m_isOpen = false;
		return false;
	}
	m_isOpen = true;
	m_filter.Init(m_strFileName.c_str());
	return true;
}
///////////////////////////////////////////////////////////////////////////////
// Name:	CheckDelPidFiles
// Author:	Mihai Buha ([email protected])
// Description:	removes all the pidfiles specified, but not too frequently
// Parameters:	p_pszNames - input - null-terminated array of filenames
//		p_szMissNames - output - if not null, fill with names of
//			missing files. Take care to allocate enough memory for
//			"Watchdog: <all filenames in p_pszNames> " or else bad
//			things will happen.
// Returns:	true if all pidfiles existed or timeout not expired
//		false if some pidfile was missing (controlling app was dead -
//			did not create a file during latest 2 intervals)
///////////////////////////////////////////////////////////////////////////////
bool CheckDelPidFiles (const char** p_pszNames, char* p_szMissNames)
{
	static clock_t last_checked;
	static long n_SC_CLK_TCK;
	static bool last_existed = true;
	clock_t timestamp;
	bool status = true;
	bool exists = true;
	if(!n_SC_CLK_TCK) n_SC_CLK_TCK = sysconf( _SC_CLK_TCK);

	timestamp = GetClockTicks();
	if( timestamp < last_checked){ // large uptime overflowed the clock_t
		last_checked = timestamp;
	}
	if( timestamp - last_checked < PIDFILES_FACTOR * PIDFILES_TIMEOUT * n_SC_CLK_TCK){
		return status;
	}
	last_checked = timestamp;
	int i;
	for( i=0; p_pszNames[i]; ++i)
	{
		int nFileLen = GetFileLen(p_pszNames[i]);
		if ( nFileLen > 0)
		{	unlink( p_pszNames[i]);
			continue;
		}
		if (nFileLen == 0)
		{	LOG("CheckDelPidFiles: file %s len==0",  p_pszNames[i]);
			unlink( p_pszNames[i]);
		}

		LOG_ERR( "CheckDelPidFiles: pidfile %s missing!", p_pszNames[i]);
		if( exists && p_szMissNames){
			sprintf( p_szMissNames, "Watchdog: ");
		}
		exists = false;
		if( p_szMissNames){
			strcat( p_szMissNames, p_pszNames[i]);
			strcat( p_szMissNames, " ");
		}
		system_to( 60, NIVIS_TMP"take_system_snapshot.sh "ACTIVITY_DATA_PATH"snapshot_warning.txt &");

	}
	status = exists || last_existed;
	last_existed = exists;
	return status;
}
示例#5
0
int main(int argc, char **argv) {    
    int retval;
    double fd;
    char output_path[512]; //, chkpt_path[512];
    //FILE* state;	
    retval = boinc_init();
    if (retval) {
        fprintf(stderr, "boinc_init returned %d\n", retval);
        exit(retval);
    }

	// extract a --device option
	std::vector<char*> argVec;
	int cudaDevice = -1;
	for(int ii = 0; ii < argc; ii++) {
		if(cudaDevice < 0 && strcmp(argv[ii], "--device") == 0 && ii + 1 < argc)
			cudaDevice = atoi(argv[++ii]);
		else
			argVec.push_back(argv[ii]);
	}
	argc = (int)argVec.size();
	argv = &argVec[0];
	if(cudaDevice < 0)
		cudaDevice = 0;

	boinc_begin_critical_section();

	// set the cuda device
	if ( rcuda::SetCudaDevice(cudaDevice) != 0 ) {
		fprintf(stderr, "Error setting device %u. Temporary exiting for 60 secs\n", cudaDevice);
		boinc_temporary_exitHack();
	}
	cudaDeviceProp deviceProp;
	if(cudaGetDeviceProperties(&deviceProp, cudaDevice) == cudaErrorInvalidDevice) {
		fprintf(stderr, "Error querying device %u. Temporary exiting for 60 secs\n", cudaDevice);
		boinc_temporary_exitHack();
	}
#ifdef WIN32
	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
#endif
	int buffCount = 0x2000;
	int chainSize = 100;
	if(deviceProp.major == 1) {	
/*		
		buffCount = deviceProp.multiProcessorCount * 8;// 8 blocks per multiprocessor
		buffCount *= deviceProp.maxThreadsPerBlock / 64; // (BLOCK_X_SIZE)
//		buffCount *= 24;
		if(deviceProp.minor <= 1) buffCount *= 24; // 24 warps per multiprocessor for compute 1.0 and 1.1
		else buffCount *= 32; // 32 warps per multiprocessor for compute 1.2 and 1.3		
		*/
		buffCount = 0x2000;
	}
	else if(deviceProp.major == 2) {		
		chainSize = 200;
/*		buffCount = deviceProp.multiProcessorCount * 8;// 8 blocks per multiprocessor
		buffCount *= deviceProp.maxThreadsPerBlock / 64; //(BLOCK_X_SIZE)		
		buffCount *= 32; // 48 warps per multiprocessor for compute 2.x
/*		if(deviceProp.minor == 1) {
			buffCount *= 2;
		}
*/		
		buffCount = 0x4000;
	}
	if(cudaDevice > 0) {
		chainSize = 1000;
	}
	if(argc < 10)
	{
		fprintf(stderr, "Not enough parameters");
		return -1;
	}
	std::string sHashRoutineName, sCharsetName, sSalt, sCheckPoints;
	uint32 nRainbowChainCount, nPlainLenMin, nPlainLenMax, nRainbowTableIndex, nRainbowChainLen;
	uint64 nChainStart;
	sHashRoutineName = argv[1];
	sCharsetName = argv[2];
	nPlainLenMin = atoi(argv[3]);
	nPlainLenMax = atoi(argv[4]);
	nRainbowTableIndex = atoi(argv[5]);
	nRainbowChainLen = atoi(argv[6]);
	nRainbowChainCount = atoi(argv[7]);
#ifdef _WIN32
	nChainStart = _atoi64(argv[8]);
#else
	nChainStart = atoll(argv[8]);
#endif
	sCheckPoints = argv[9];
	std::vector<int> vCPPositions;
	char *cp = strtok((char *)sCheckPoints.c_str(), ",");
	while(cp != NULL)
	{
		vCPPositions.push_back(atoi(cp));
		cp = strtok(NULL, ",");
	}
	if(argc == 11)
	{
		sSalt = argv[10];
	}
	//std::cout << "Starting ChainGenerator" << std::endl;
	// Setup CChainWalkContext
	//std::cout << "ChainGenerator started." << std::endl;

	if (!CChainWalkContext::SetHashRoutine(sHashRoutineName))
	{
		fprintf(stderr, "hash routine %s not supported\n", sHashRoutineName.c_str());
		return 1;
	}
	//std::cout << "Hash routine validated" << std::endl;

	if (!CChainWalkContext::SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax))
	{	
		std::cerr << "charset " << sCharsetName << " not supported" << std::endl;
		return 2;
	}
	//std::cout << "Plain charset validated" << std::endl;

	if (!CChainWalkContext::SetRainbowTableIndex(nRainbowTableIndex))
	{
		std::cerr << "invalid rainbow table index " << nRainbowTableIndex << std::endl;
		return 3;
	}
	//std::cout << "Rainbowtable index validated" << std::endl;

	if(sHashRoutineName == "mscache")// || sHashRoutineName == "lmchall" || sHashRoutineName == "halflmchall")
	{
		// Convert username to unicode
		const char *szSalt = sSalt.c_str();
		int salt_length = strlen(szSalt);
		unsigned char cur_salt[256];
		for (int i=0; i<salt_length; i++)
		{
			cur_salt[i*2] = szSalt[i];
			cur_salt[i*2+1] = 0x00;
		}
		CChainWalkContext::SetSalt(cur_salt, salt_length*2);
	}
	else if(sHashRoutineName == "halflmchall")
	{ // The salt is hardcoded into the hash routine
	//	CChainWalkContext::SetSalt((unsigned char*)&salt, 8);
	}
	else if(sHashRoutineName == "oracle")
	{
		CChainWalkContext::SetSalt((unsigned char *)sSalt.c_str(), sSalt.length());
	}
	//std::cout << "Opening chain file" << std::endl;
	
	// Open file
	boinc_resolve_filename("result", output_path, sizeof(output_path));
	fclose(boinc_fopen(output_path, "a"));
	FILE *outfile = boinc_fopen(output_path, "r+b");
	
	if (outfile == NULL)
	{
		std::cerr << "failed to create " << output_path << std::endl;
		return 4;
	}
	
	// Check existing chains
	unsigned int nDataLen = (unsigned int)GetFileLen(outfile);
	
	// Round to boundary
	nDataLen = nDataLen / 10 * 10;
	if (nDataLen == nRainbowChainCount * 10)
	{		
		std::cerr << "precomputation of this rainbow table already finished" << std::endl;
		fclose(outfile);
		return 0;
	}

	fseek(outfile, nDataLen, SEEK_SET);
	//XXX size_t isn't 32/64 clean
	size_t nReturn;
	CChainWalkContext cwc;
	uint64 nIndex[2];
	//time_t tStart = time(NULL);

//	std::cout << "Starting to generate chains" << std::endl;
	int maxCalcBuffSize = rcuda::GetChainsBufferSize( buffCount );
	std::cerr << "maxCalcBuffSize - estimated: " << buffCount << ". Chosen: " << maxCalcBuffSize << std::endl;
	uint64 *calcBuff = new uint64[2*maxCalcBuffSize];
	int ii;

	CudaCWCExtender ex(&cwc);
	rcuda::RCudaTask cuTask;
	ex.Init();

	for(int nCurrentCalculatedChains = nDataLen / 10, calcSize; nCurrentCalculatedChains < nRainbowChainCount; )
	{		
		fd = (double)nCurrentCalculatedChains / (double)nRainbowChainCount;
		boinc_fraction_done(fd);
		
		cuTask.hash = ex.GetHash();
		cuTask.startIdx = nChainStart + nCurrentCalculatedChains;
		cuTask.idxCount = std::min<int>(nRainbowChainCount - nCurrentCalculatedChains, maxCalcBuffSize);
		cuTask.dimVec = ex.GetPlainDimVec();
		cuTask.dimVecSize = ex.GetPlainDimVecSize()/2;
		cuTask.charSet = ex.GetCharSet();
		cuTask.charSetSize = ex.GetCharSetSize();
		cuTask.cpPositions = &vCPPositions[0];
		cuTask.cpPosSize = vCPPositions.size();
		cuTask.reduceOffset = ex.GetReduceOffset();
		cuTask.plainSpaceTotal = ex.GetPlainSpaceTotal();
		cuTask.rainbowChainLen = nRainbowChainLen;
		cuTask.kernChainSize = chainSize;
		for(ii = 0; ii < cuTask.idxCount; ii++) {
			calcBuff[2*ii] = cuTask.startIdx + ii;
			calcBuff[2*ii+1] = 0;
		}
		calcSize = rcuda::CalcChainsOnCUDA(&cuTask, calcBuff);

		BOINC_STATUS boinc_status;
		boinc_get_status(&boinc_status);

		if (boinc_status.quit_request || boinc_status.abort_request)
		{
			boinc_end_critical_section();
			while (1) boinc_sleep(1);
		}

		if(calcSize > 0) {
			nCurrentCalculatedChains += calcSize;
			for(ii = 0; ii < cuTask.idxCount; ii++) {
				nIndex[0] = cuTask.startIdx + ii;
//				nReturn = fwrite(nIndex, 1, 8, outfile);
				nReturn = fwrite(calcBuff+(2*ii), 1, 8, outfile);
				nReturn += fwrite(calcBuff+(2*ii+1), 1, 2, outfile);
				if(nReturn != 10) {
					std::cerr << "disk write fail" << std::endl;
					fclose(outfile);
					return 9;
				}
			}
		} else {
			std::cerr << "Calculations on CUDA failed!" << std::endl;
			fclose(outfile);
			return -1;	
		}
	}
	delete [] calcBuff;
#ifdef _DEBUG
	std::cout << "Generation completed" << std::endl;
#endif
	fclose(outfile);
    
	boinc_fraction_done(1);
	boinc_finish(0);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief removes all the pidfiles specified, but not too frequently
/// @author	Mihai Buha ([email protected])
/// @param[in]	p_pszNames null-terminated array of filenames
/// @param[out]	p_szMissNames if not null, fill with names of
///			missing files. Take care to allocate enough memory for
///			"Watchdog: <all filenames in p_pszNames> " or else bad
///			things will happen.
/// @retval true  All pidfiles existed or timeout not expired
/// @retval false Some pidfile was missing (controlling app was dead -
///			did not create a file during latest 2 intervals)
//////////////////////////////////////////////////////////////////////////////
bool CWatchdogMngr::checkDelPidFiles (const char** p_pszNames, char* p_szMissNames)
{
	clock_t timestamp ;
	static clock_t sStartTime = GetClockTicks();
	static clock_t last_checked;
	static bool last_existed = true;
	bool status = true;
	bool exists = true;

	timestamp = GetClockTicks();
	if( timestamp < last_checked)
	{ // large uptime overflowed the clock_t
		last_checked = timestamp;
		sStartTime = timestamp;
	}
	if( (timestamp - last_checked < WTD_PID_VRFY_INTERVAL * sysconf(_SC_CLK_TCK)) 
		|| (timestamp - sStartTime < WTD_PID_VRFY_INTERVAL * sysconf(_SC_CLK_TCK))
		)
	{
		return true;
	}

	last_checked = timestamp;
	for( unsigned i=0; p_pszNames[i]; ++i)
	{
		int nFileLen = GetFileLen(p_pszNames[i]);

		if (nFileLen == 0)
		{	
			usleep(30*1000);//wait a little maybe in process of writing the pid file
			nFileLen = GetFileLen(p_pszNames[i]);
		}

		if ( nFileLen > 0)
		{	unlink( p_pszNames[i]);
			continue;
		}
		if (nFileLen == 0)
		{	
			ERR("checkDelPidFiles: pidfile[%s] len==0",  p_pszNames[i]);
			systemf_to( 20 ,"log2flash 'WTD: ERR:checkDelPidFiles: pidfile[%s] len==0' &",  p_pszNames[i]);
			unlink( p_pszNames[i]);			
		}

		LOG( "ERR:Missing [%s]", p_pszNames[i]);

		if ( exists )
		{
			exists = false;
		}

		if( p_szMissNames )
		{
			strcat( p_szMissNames, p_pszNames[i]);
			strcat( p_szMissNames, ",");
		}
	}
	// Take snapshot if any of the pidfiles is missing.
	if (! exists)
	{
		system_to( 60, NIVIS_TMP"take_system_snapshot.sh "ACTIVITY_DATA_PATH"snapshot_warning.txt &");
	}

	status = exists || last_existed;
	last_existed = exists;
	return status;
}
示例#7
0
bool player_impl::open(const char *movie, int media_type, int render_type)
{
	// 如果未关闭原来的媒体, 则先关闭.
	if (m_avplay || m_source)
		close();

	// 未创建窗口, 无法播放, 返回失败.
	if (!m_window)
		return false;

	char filename[MAX_PATH];
	int len = strlen(movie) + 1;

	strcpy(filename, movie);

	int64_t file_lentgh = 0;
	if (media_type == MEDIA_TYPE_FILE || media_type == MEDIA_TYPE_BT)
	{
		file_lentgh = GetFileLen(movie);
		__android_log_print(ANDROID_LOG_INFO,"open","%s   %d\n",movie,file_lentgh);
		if (file_lentgh < 0)
		{
			::logger("get file size failed!\n");
			return false;
		}
	}

	do {
		// 创建avplay.
		m_avplay = alloc_avplay_context();
		if (!m_avplay)
		{
			::logger("allocate avplay context failed!\n");
			break;
		}

		// 为avplay创建demux.
		demux_context *demux = alloc_demux_context();
		configure(m_avplay, demux, MEDIA_DEMUX);

		// 目前只有除youku之外, 都使用generic_demux.
		if (media_type != MEDIA_TYPE_YK)
		{
			demux->init_demux = generic_init_demux;
			demux->read_packet = generic_read_packet;
			demux->seek_packet = generic_packet_seek;
			demux->read_pause = generic_read_pause;
			demux->read_play = generic_read_play;
			demux->stream_index = generic_stream_index;
			demux->query_avcodec_id = generic_query_avcodec_id;
			demux->destory = generic_destory;
		}
		else
		{
			// TODO: 实现youku相关的demux.
			break;
		}

		// 初始化avplay.
		if (initialize(m_avplay, filename, media_type, demux) != 0)
		{
			::logger("initialize avplay failed!\n");
			break;
		}

		// TODO: 如果是bt类型, 则在此得到视频文件列表, 并添加到m_media_list.
		// if (media_type == MEDIA_TYPE_BT)
		// {
		// 	bt_source_info *bt_info = &m_avplay->m_source_ctx->info.bt;
		// 	for (int i = 0; i < bt_info->info_size; i++)
		// 	{
		// 		std::string name = std::string(bt_info->info[i].file_name);
		// 		m_media_list.insert(std::make_pair(filename, name));
		// 	}
		// }

		// 分配音频和视频的渲染器.
		m_audio = alloc_audio_render();
		if (!m_audio)
		{
			::logger("allocate audio render failed!\n");
			break;
		}

		m_video = alloc_video_render(&m_window);
		if (!m_video)
		{
			::logger("allocate video render failed!\n");
			break;
		}

		// 初始化音频和视频渲染器.
		init_audio(m_audio);
		init_video(m_video, render_type);

		// 配置音频视频渲染器.
		configure(m_avplay, m_video, VIDEO_RENDER);
		configure(m_avplay, m_audio, AUDIO_RENDER);

		// 得到视频宽高.
		if (m_avplay->m_video_ctx)
		{
			m_video_width = m_avplay->m_video_ctx->width;
			m_video_height = m_avplay->m_video_ctx->height;
		}

		// 打开视频实时码率和帧率计算.
		enable_calc_frame_rate(m_avplay);
		enable_calc_bit_rate(m_avplay);
		//__android_log_print(ANDROID_LOG_INFO,"m_window--","%d\n",m_window);

		return true;

	} while (0);

	if (m_avplay)
		free_avplay_context(m_avplay);
	m_avplay = NULL;
	if (m_source)
		free_media_source(m_source);
	if (m_audio)
		free_audio_render(m_audio);
	if (m_video)
		free_video_render(m_video);

	::logger("open avplay failed!\n");

	return true;
}
示例#8
0
int main(int argc, char* argv[])
{
	if (argc != 3)
	{
		Logo();

		printf("usage: rtdump rainbow_table_pathname rainbow_chain_index\n");
		return 0;
	}
	string sPathName = argv[1];
	int nRainbowChainIndex = atoi(argv[2]);

	int nRainbowChainLen, nRainbowChainCount;
	if (!CChainWalkContext::SetupWithPathName(sPathName, nRainbowChainLen, nRainbowChainCount))
		return 0;
	if (nRainbowChainIndex < 0 || nRainbowChainIndex > nRainbowChainCount - 1)
	{
		printf("valid rainbow chain index range: 0 - %d\n", nRainbowChainCount - 1);
		return 0;
	}

	// Open file
	FILE* file = fopen(sPathName.c_str(), "rb");
	if (file == NULL)
	{
		printf("failed to open %s\n", sPathName.c_str());
		return 0;
	}

	// Dump
	if (GetFileLen(file) != nRainbowChainCount * 16)
		printf("rainbow table size check fail\n");
	else
	{
		// Read required chain
		RainbowChain chain;
		fseek(file, nRainbowChainIndex * 16, SEEK_SET);
		fread(&chain, 1, 16, file);

		// Dump required chain
		CChainWalkContext cwc;
		cwc.SetIndex(chain.nIndexS);
		int nPos;
		for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
		{
			cwc.IndexToPlain();
			cwc.PlainToHash();
			printf("#%-4d  %s  %s  %s\n", nPos,
										  uint64tohexstr(cwc.GetIndex()).c_str(),
										  cwc.GetPlainBinary().c_str(),
										  cwc.GetHash().c_str());
			cwc.HashToIndex(nPos);
		}
		printf("#%-4d  %s\n", nPos, uint64tohexstr(cwc.GetIndex()).c_str());
		if (cwc.GetIndex() != chain.nIndexE)
			printf("\nwarning: rainbow chain integrity check fail!\n");
	}

	// Close file
	fclose(file);

	return 0;
}
示例#9
0
int main(int argc, char **argv) {    
    int retval;
    double fd;
    char output_path[512]; //, chkpt_path[512];
    //FILE* state;	
    retval = boinc_init();
    if (retval) {
        fprintf(stderr, "boinc_init returned %d\n", retval);
        exit(retval);
    }
	

    // get size of input file (used to compute fraction done)
    //
    //file_size(input_path, fsize);

    // See if there's a valid checkpoint file.
    // If so seek input file and truncate output file
    //


	if(argc < 10)
	{
		fprintf(stderr, "Not enough parameters");
		return -1;
	}
	std::string sHashRoutineName, sCharsetName, sSalt, sCheckPoints;
	uint32 nRainbowChainCount, nPlainLenMin, nPlainLenMax, nRainbowTableIndex, nRainbowChainLen;
	uint64 nChainStart;
	sHashRoutineName = argv[1];
	sCharsetName = argv[2];
	nPlainLenMin = atoi(argv[3]);
	nPlainLenMax = atoi(argv[4]);
	nRainbowTableIndex = atoi(argv[5]);
	nRainbowChainLen = atoi(argv[6]);
	nRainbowChainCount = atoi(argv[7]);
#ifdef _WIN32

	nChainStart = _atoi64(argv[8]);

#else
	nChainStart = atoll(argv[8]);
#endif
	sCheckPoints = argv[9];
	std::vector<uint32> vCPPositions;
	char *cp = strtok((char *)sCheckPoints.c_str(), ",");
	while(cp != NULL)
	{
		vCPPositions.push_back(atoi(cp));
		cp = strtok(NULL, ",");
	}
	if(argc == 11)
	{
		sSalt = argv[10];
	}
	//std::cout << "Starting ChainGenerator" << std::endl;
	// Setup CChainWalkContext
	//std::cout << "ChainGenerator started." << std::endl;

	if (!CChainWalkContext::SetHashRoutine(sHashRoutineName))
	{
		fprintf(stderr, "hash routine %s not supported\n", sHashRoutineName.c_str());
		return 1;
	}
	//std::cout << "Hash routine validated" << std::endl;

	if (!CChainWalkContext::SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax))
	{	
		std::cerr << "charset " << sCharsetName << " not supported" << std::endl;
		return 2;
	}
	//std::cout << "Plain charset validated" << std::endl;

	if (!CChainWalkContext::SetRainbowTableIndex(nRainbowTableIndex))
	{
		std::cerr << "invalid rainbow table index " << nRainbowTableIndex << std::endl;
		return 3;
	}
	//std::cout << "Rainbowtable index validated" << std::endl;

	if(sHashRoutineName == "mscache")// || sHashRoutineName == "lmchall" || sHashRoutineName == "halflmchall")
	{
		// Convert username to unicode
		const char *szSalt = sSalt.c_str();
		int salt_length = strlen(szSalt);
		unsigned char cur_salt[256];
		for (int i=0; i<salt_length; i++)
		{
			cur_salt[i*2] = szSalt[i];
			cur_salt[i*2+1] = 0x00;
		}
		CChainWalkContext::SetSalt(cur_salt, salt_length*2);
	}
	else if(sHashRoutineName == "halflmchall")
	{ // The salt is hardcoded into the hash routine
	//	CChainWalkContext::SetSalt((unsigned char*)&salt, 8);
	}
	else if(sHashRoutineName == "oracle")
	{
		CChainWalkContext::SetSalt((unsigned char *)sSalt.c_str(), sSalt.length());
	}
	//std::cout << "Opening chain file" << std::endl;

	
	// Open file
    boinc_resolve_filename("result", output_path, sizeof(output_path));
	fclose(boinc_fopen(output_path, "a"));
	FILE *outfile = boinc_fopen(output_path, "r+b");
	
	if (outfile == NULL)
	{
		std::cerr << "failed to create " << output_path << std::endl;
		return 4;
	}
	
	// Check existing chains
	unsigned int nDataLen = (unsigned int)GetFileLen(outfile);
	
	// Round to boundary
	nDataLen = nDataLen / 10 * 10;
	if (nDataLen == nRainbowChainCount * 10)
	{		
		std::cerr << "precomputation of this rainbow table already finished" << std::endl;
		fclose(outfile);
		return 0;
	}
	nChainStart += (nDataLen / 10);
	fseek(outfile, nDataLen, SEEK_SET);
	//XXX size_t isn't 32/64 clean
	size_t nReturn;
	CChainWalkContext cwc;
	uint64 nIndex[2];
	//time_t tStart = time(NULL);

//	std::cout << "Starting to generate chains" << std::endl;
	for(uint32 nCurrentCalculatedChains = nDataLen / 10; nCurrentCalculatedChains < nRainbowChainCount; nCurrentCalculatedChains++)
	{		
		uint32 cpcheck = 0;
		unsigned short checkpoint = 0;
		fd = (double)nCurrentCalculatedChains / (double)nRainbowChainCount;
		boinc_fraction_done(fd);
		cwc.SetIndex(nChainStart++); // use a given index now!
		nIndex[0] = cwc.GetIndex();
		
		for (uint32 nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
		{
		//	std::cout << "IndexToPlain()" << std::endl;
			cwc.IndexToPlain();
		//	std::cout << "PlainToHash()" << std::endl;
			cwc.PlainToHash();
		//	std::cout << "HashToIndex()" << std::endl;
			cwc.HashToIndex(nPos);
			if(cpcheck < vCPPositions.size() && nPos == vCPPositions[cpcheck])
			{
				
				checkpoint |= (1 << cpcheck) & (unsigned short)cwc.GetIndex() << cpcheck;
				cpcheck++;
			}
		}
		//std::cout << "GetIndex()" << std::endl;

		nIndex[1] = cwc.GetIndex();
		// Write chain to disk
		if ((nReturn = fwrite(&nIndex[1], 1, 8, outfile)) != 8)
		{
			std::cerr << "disk write fail" << std::endl;
			fclose(outfile);
			return 9;
		}
		if((nReturn = fwrite(&checkpoint, 1, 2, outfile)) != 2)
		{
			std::cerr << "disk write fail" << std::endl;
			fclose(outfile);
			return 9;
		}
	}
	//std::cout << "Generation completed" << std::endl;
	fclose(outfile);
    
	boinc_fraction_done(1);
	boinc_finish(0);
}