示例#1
0
static bool ReadBMSFile( const RString &sPath, NameToData_t &mapNameToData )
{
	RageFile file;
	if( !file.Open(sPath) )
	{
		LOG->UserLog( "Song file", sPath, "couldn't be opened: %s", file.GetError().c_str() );
		return false;
	}

	while( !file.AtEOF() )
	{
		RString line;
		if( file.GetLine(line) == -1 )
		{
			LOG->UserLog( "Song file", sPath, "had a read error: %s", file.GetError().c_str() );
			return false;
		}

		StripCrnl( line );

		// BMS value names can be separated by a space or a colon.
		size_t iIndexOfSeparator = line.find_first_of( ": " );
		RString value_name = line.substr( 0, iIndexOfSeparator );
		RString value_data;
		if( iIndexOfSeparator != line.npos )
			value_data = line.substr( iIndexOfSeparator+1 );

		value_name.MakeLower();
		mapNameToData.insert( make_pair(value_name, value_data) );
	}

	return true;
}
示例#2
0
CString CryptManager::GetMD5( CString fn )
{
       struct MD5Context md5c;
       unsigned char digest[16];
       int iBytesRead;
       unsigned char buffer[1024];

       RageFile file;
       if( !file.Open( fn, RageFile::READ ) )
       {
               LOG->Warn( "GetMD5: Failed to open file '%s'", fn.c_str() );
               return "";
       }

       MD5Init(&md5c);
       while( !file.AtEOF() && file.GetError().empty() )
       {
               iBytesRead = file.Read( buffer, sizeof(buffer) );
               MD5Update(&md5c, buffer, iBytesRead);
       }
       MD5Final(digest, &md5c);

       return BinaryToHex( digest, sizeof(digest) );
}
void BackgroundLoader::LoadThread()
{
	while( !m_bShutdownThread )
	{
		/* Wait for a request.  It's normal for this to wait for a long time; don't
		 * fail on timeout. */
		m_StartSem.Wait();

		CString sFile = GetRequest();
		if( sFile.empty() )
			continue;

		{
			/* If the file already exists, short circuit. */
			m_Mutex.Lock();
			map<CString,int>::iterator it;
			it = m_FinishedRequests.find( sFile );
			if( it != m_FinishedRequests.end() )
			{
				++it->second;
				LOG->Trace("XXX: request %s done loading (already done), cnt now %i", sFile.c_str(), m_FinishedRequests[sFile] );
				m_Mutex.Unlock();
				continue;
			}
			m_Mutex.Unlock();
		}

		m_sThreadIsActive = true;

		LOG->Trace("XXX: reading %s", sFile.c_str());

		CString sCachePath = GetCachePath( sFile );

		/* Open the file and read it. */
		RageFile src;
		if( src.Open(sFile) )
		{
			/* If we're writing to a file cache ... */
			RageFile dst;

			bool bWriteToCache = g_bWriteToCache;
			if( bWriteToCache )
				bWriteToCache = dst.Open( sCachePath, RageFile::WRITE );
			LOG->Trace("XXX: go on '%s' to '%s'", sFile.c_str(), sCachePath.c_str());
			
			char buf[1024*4];
			while( !m_sThreadShouldAbort && !src.AtEOF() )
			{
				int got = src.Read( buf, sizeof(buf) );
				if( got > 0 && bWriteToCache )
					dst.Write( buf, got );
			}
			if( bWriteToCache )
				dst.Close();

			LOG->Trace("XXX: done");
		}
		src.Close();

		m_Mutex.Lock();
		if( !m_sThreadShouldAbort )
		{
			++m_FinishedRequests[sFile];
			LOG->Trace("XXX: request %s done loading, cnt now %i", sFile.c_str(), m_FinishedRequests[sFile] );
		}
		else
		{
			FILEMAN->Remove( sCachePath );

			LOG->Trace("XXX: request %s aborted", sFile.c_str() );
		}

		m_sThreadShouldAbort = false;
		m_sThreadIsActive = false;
		m_Mutex.Unlock();
	}
}
void MemoryCardDriverThreaded_Linux::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
{
	LOG->Trace( "GetUSBStorageDevices" );
	
	vDevicesOut.clear();

	{
		vector<RString> asDevices;
		RString sBlockDevicePath = "/sys/block/";
		GetFileList( sBlockDevicePath, asDevices );

		for( unsigned i = 0; i < asDevices.size(); ++i )
		{
			const RString &sDevice = asDevices[i];
			if( sDevice == "." || sDevice == ".." )
				continue;

			UsbStorageDevice usbd;

			RString sPath = sBlockDevicePath + sDevice + "/";
			usbd.sSysPath = sPath;

			/* Ignore non-removable devices. */
			RString sBuf;
			if( !ReadFile( sPath + "removable", sBuf ) )
				continue; // already warned
			if( atoi(sBuf) != 1 )
				continue;

			/*
			 * The kernel isn't exposing all of /sys atomically, so we end up missing
			 * the partition due to it not being shown yet.  It won't show up until the
			 * kernel has scanned the partition table, which can take a variable amount
			 * of time, sometimes over a second.  Watch for the "queue" sysfs directory,
			 * which is created after this, to tell when partition directories are created.
			 */
			RageTimer WaitUntil;
			WaitUntil += 5;
			RString sQueueFilePath = usbd.sSysPath + "queue";
			while(1)
			{
				if( WaitUntil.Ago() >= 0 )
				{
					LOG->Warn( "Timed out waiting for %s", sQueueFilePath.c_str() );
					break;
				}

				if( access(usbd.sSysPath, F_OK) == -1 )
				{
					LOG->Warn( "Block directory %s went away while we were waiting for %s",
							usbd.sSysPath.c_str(), sQueueFilePath.c_str() );
					break;
				}

				if( access(sQueueFilePath, F_OK) != -1 )
					break;

				usleep(10000);
			}

			/* Wait for udev to finish handling device node creation */
			ExecuteCommand( "udevadm settle" );

			/* If the first partition device exists, eg. /sys/block/uba/uba1, use it. */
			if( access(usbd.sSysPath + sDevice + "1", F_OK) != -1 )
			{
				LOG->Trace("OK");
				usbd.sDevice = "/dev/" + sDevice + "1";
			}
			else
			{
				LOG->Trace("error %s", strerror(errno));
				usbd.sDevice = "/dev/" + sDevice;
			}

			/*
			 * sPath/device should be a symlink to the actual device.  For USB
			 * devices, it looks like this:
			 *
			 * device -> ../../devices/pci0000:00/0000:00:02.1/usb2/2-1/2-1:1.0
			 *
			 * "2-1" is "bus-port".
			 */
			char szLink[256];
			int iRet = readlink( sPath + "device", szLink, sizeof(szLink) );
			if( iRet == -1 )
			{
				LOG->Warn( "readlink(\"%s\"): %s", (sPath + "device").c_str(), strerror(errno) );
			}
			else
			{
				/*
				 * The full path looks like
				 *
				 *   ../../devices/pci0000:00/0000:00:02.1/usb2/2-2/2-2.1/2-2.1:1.0
				 *
				 * In newer kernels, it looks like:
				 *
				 * ../../../3-2.1:1.0
				 *
				 * Each path element refers to a new hop in the chain.
				 *  "usb2" = second USB host
				 *  2-            second USB host,
				 *   -2           port 1 on the host,
				 *     .1         port 1 on an attached hub
				 *       .2       ... port 2 on the next hub ...
				 * 
				 * We want the bus number and the port of the last hop.  The level is
				 * the number of hops.
				 */
				szLink[iRet] = 0;
				vector<RString> asBits;
				split( szLink, "/", asBits );

				RString sHostPort = asBits[asBits.size()-1];
				if( !sHostPort.empty() )
				{
					/* Strip off the endpoint information after the colon. */
					size_t pos = sHostPort.find(':');
					if( pos != string::npos )
						sHostPort.erase( pos );
					
					/* sHostPort is eg. 2-2.1. */
					sHostPort.Replace( "-", "." );
					asBits.clear();
					split( sHostPort, ".", asBits );
					if( asBits.size() > 1 )
					{
						usbd.iBus = atoi( asBits[0] );
						usbd.iPort = atoi( asBits[asBits.size()-1] );
						usbd.iLevel = asBits.size() - 1;
					}
				}
			}

			if( ReadFile( sPath + "device/../idVendor", sBuf ) )
				sscanf( sBuf, "%x", &usbd.idVendor );

			if( ReadFile( sPath + "device/../idProduct", sBuf ) )
				sscanf( sBuf, "%x", &usbd.idProduct );

			if( ReadFile( sPath + "device/../serial", sBuf ) )
			{
				usbd.sSerial = sBuf;
				TrimRight( usbd.sSerial );
			}
			if( ReadFile( sPath + "device/../product", sBuf ) )
			{
				usbd.sProduct = sBuf;
				TrimRight( usbd.sProduct );
			}
			if( ReadFile( sPath + "device/../manufacturer", sBuf ) )
			{
				usbd.sVendor = sBuf;
				TrimRight( usbd.sVendor );
			}

			vDevicesOut.push_back( usbd );
		}
	}

	{
		// Find where each device is mounted. Output looks like:
		
		// /dev/sda1               /mnt/flash1             auto    noauto,owner 0 0
		// /dev/sdb1               /mnt/flash2             auto    noauto,owner 0 0
		// /dev/sdc1               /mnt/flash3             auto    noauto,owner 0 0
		
		RString fn = "/rootfs/etc/fstab";
		RageFile f;
		if( !f.Open(fn) )
		{
			LOG->Warn( "can't open '%s': %s", fn.c_str(), f.GetError().c_str() );
			return;
		}
		
		RString sLine;
		while( !f.AtEOF() )
		{
			switch( f.GetLine(sLine) )
			{
			case 0: continue; /* eof */
			case -1:
				LOG->Warn( "error reading '%s': %s", fn.c_str(), f.GetError().c_str() );
				return;
			}

			char szScsiDevice[1024];
			char szMountPoint[1024];
			int iRet = sscanf( sLine, "%s %s", szScsiDevice, szMountPoint );
			if( iRet != 2 || szScsiDevice[0] == '#')
				continue;	// don't process this line

			/* Get the real kernel device name, which should match
			 * the name from /sys/block, by following symlinks in
			 * /dev.  This allows us to specify persistent names in
			 * /etc/fstab using things like /dev/device/by-path. */
			char szUnderlyingDevice[PATH_MAX];
			if( realpath(szScsiDevice, szUnderlyingDevice) == NULL )
			{
				// "No such file or directory" is understandable
				if (errno != ENOENT)
					LOG->Warn( "realpath(\"%s\"): %s", szScsiDevice, strerror(errno) );
				continue;
			}

			RString sMountPoint = szMountPoint;
			TrimLeft( sMountPoint );
			TrimRight( sMountPoint );

			// search for the mountpoint corresponding to the device
			for( unsigned i=0; i<vDevicesOut.size(); i++ )
			{
				UsbStorageDevice& usbd = vDevicesOut[i];
				if( usbd.sDevice == szUnderlyingDevice )	// found our match
				{
					// Use the device entry from fstab so the mount command works
					usbd.sDevice = szScsiDevice;
					usbd.sOsMountDir = sMountPoint;
					break;	// stop looking for a match
				}
			}
		}
	}

	for( unsigned i=0; i<vDevicesOut.size(); i++ )
	{
		UsbStorageDevice& usbd = vDevicesOut[i];
		LOG->Trace( "    sDevice: %s, iBus: %d, iLevel: %d, iPort: %d, id: %04X:%04X, Vendor: '%s', Product: '%s', sSerial: \"%s\", sOsMountDir: %s",
				usbd.sDevice.c_str(), usbd.iBus, usbd.iLevel, usbd.iPort, usbd.idVendor, usbd.idProduct, usbd.sVendor.c_str(),
				usbd.sProduct.c_str(), usbd.sSerial.c_str(), usbd.sOsMountDir.c_str() );
	}
	
	/* Remove any devices that we couldn't find a mountpoint for. */
	for( unsigned i=0; i<vDevicesOut.size(); i++ )
	{
		UsbStorageDevice& usbd = vDevicesOut[i];
		if( usbd.sOsMountDir.empty() )
		{
			LOG->Trace( "Ignoring %s (couldn't find in /etc/fstab)", usbd.sDevice.c_str() );
			
			vDevicesOut.erase( vDevicesOut.begin()+i );
			--i;
		}
	}
	
	LOG->Trace( "Done with GetUSBStorageDevices" );
}
示例#5
0
void TitleSubst::Load(const CString &filename, const CString &section)
{
	RageFile f;
	if( !f.Open(filename) )
	{
		LOG->Trace("Error opening %s: %s", filename.c_str(), f.GetError().c_str() );
		return;
	}
	
	CString CurrentSection;
	TitleTrans tr;
	
	while (!f.AtEOF())
	{
		CString line;
		int ret = f.GetLine( line );
		if( ret == 0 )
			break;
		if( ret < 0 )
		{
			LOG->Trace("Error reading %s: %s", filename.c_str(), f.GetError().c_str() );
			break;
		}

		if(line.size() > 0 && utf8_get_char(line.c_str()) == 0xFEFF)
		{
			/* Annoying header that Windows puts on UTF-8 plaintext
			 * files; remove it. */
			line.erase(0, utf8_get_char_len(line[0]));
		}

		TrimLeft(line);
		TrimRight(line);

		if(line.size() == 0) continue; /* blank */
		if(line[0] == '#') continue; /* comment */

		if(!line.CompareNoCase("DontTransliterate"))
		{
			tr.translit = false;
			continue;
		}

		size_t pos = line.find_first_of(':');
		if(pos != string::npos)
		{
			/* x: y */
			CString id = line.substr(0, pos);
			CString txt = line.substr(pos+1);
			TrimLeft(txt);

			/* Surround each regex with ^(...)$, to force all comparisons to default
			 * to being a full-line match.  (Add ".*" manually if this isn't wanted.) */
			if(!id.CompareNoCase("TitleFrom")) tr.TitleFrom = "^(" + txt + ")$";
			else if(!id.CompareNoCase("ArtistFrom")) tr.ArtistFrom = "^(" + txt + ")$";
			else if(!id.CompareNoCase("SubtitleFrom")) tr.SubFrom = "^(" + txt + ")$";
			else if(!id.CompareNoCase("TitleTo")) tr.Dest.Title = txt;
			else if(!id.CompareNoCase("ArtistTo")) tr.Dest.Artist = txt;
			else if(!id.CompareNoCase("SubtitleTo")) tr.Dest.Subtitle = txt;
			else if(!id.CompareNoCase("TitleTransTo")) tr.Dest.TitleTranslit = txt;
			else if(!id.CompareNoCase("ArtistTransTo")) tr.Dest.ArtistTranslit = txt;
			else if(!id.CompareNoCase("SubtitleTransTo")) tr.Dest.SubtitleTranslit = txt;
			else
				LOG->Warn( "Unknown TitleSubst tag: \"%s\"", id.c_str() );
		}

		/* Add the translation if this is a terminator (*) or section
		 * marker ([foo]). */
		if(line[0] == '*' || line[0] == '[')
		{
			if(!CurrentSection.CompareNoCase(section))
				AddTrans(tr);
			
			/* Reset. */
			tr = TitleTrans();
		}

		if(line[0] == '[' && line[line.size()-1] == ']')
		{
			CurrentSection = line.substr(1, line.size()-2);
		}
	}
}
示例#6
0
void ConditionalBGA::Load(const CString &szScreenName)
{
	RageFile file;

	CString szConditionalBGAFile = THEME->GetCurThemeDir() + szScreenName + " ConditionalBGA.ini";


//	char filepath[512];
//	strcpy(filepath,""); // empty the path first
//	strcpy(filepath,szConditionalBGAFile.c_str());
	
	LOG->Trace("ConditionalBGA Load:%s",szConditionalBGAFile.c_str());

	bool loaded = file.Open(szConditionalBGAFile,RageFile::READ);
//	FILE* fp = NULL;
//	fp = fopen(filepath,"r");
	if(!loaded)
	{
		LOG->Trace("ConditionalBGA File Not Found");
		return;
	}
	else
	{
		CString currentline;
		int bgano=0;

		while(!file.AtEOF())
		{
			file.GetLine(currentline); // get the current line
	
			// kill any possible comments
			CStringArray asKillComments;
			asKillComments.clear(); // get rid of anything in there
			split(currentline, "#",asKillComments); // A comment starting with #
			if(!asKillComments.empty())
			{
				currentline = asKillComments[0]; // there was some commentstuff here, take the first bit to be the actual data
			}
			asKillComments.clear(); // get rid of anything in there
			split(currentline, "/",asKillComments); // A comment starting with // or /*
			if(!asKillComments.empty())
			{
				currentline = asKillComments[0]; // there was some commentstuff here, take the first bit to be the actual data
			}
			TrimRight(currentline); // nuke trailing whitespace

			// start parsing the data
			if(currentline.c_str()[0] == '[') // we found a new bganimation
			{
				if(!m_bgainfo.empty()) // last one wasnt empty
				{
					CheckBgaRequirements(m_bgainfo[bgano]);
					bgano++;
				}
				BgaCondInfo temp;
				m_bgainfo.push_back(temp);
				ClearINFO(bgano); // wipe out the old info structure.

				CStringArray asSplitLine;
				split(currentline,"[",asSplitLine);
				split(asSplitLine[0],"]",asSplitLine);
				if(!asSplitLine.empty() && asSplitLine.size() >= 1)
					m_bgainfo[bgano].bganame = asSplitLine[asSplitLine.size() - 1];
			}
			else
			{
				CStringArray asSplitLine;
				split(currentline,":",asSplitLine);
				if(asSplitLine.empty()) continue;

				if(!asSplitLine[0].CompareNoCase("clear") && asSplitLine.size() > 1)
				{
					if(!asSplitLine[1].CompareNoCase("true") || !asSplitLine[1].CompareNoCase("cleared") || !asSplitLine[1].CompareNoCase("clear")) // true / clear (any clear condition)
						m_bgainfo[bgano].cleared = CBGA_CSCLEARED;
					else if(!asSplitLine[1].CompareNoCase("false") || !asSplitLine[1].CompareNoCase("failed")) // false / failed 
						m_bgainfo[bgano].cleared = CBGA_CSFAILED;
					else if(!asSplitLine[1].CompareNoCase("maxcombo") || !asSplitLine[1].CompareNoCase("fullcombo")) // passed with maxcombo 
						m_bgainfo[bgano].cleared = CBGA_CSMAXCOMBO;
					else if(!asSplitLine[1].CompareNoCase("brokencombo")) // passed with a broken combo 
						m_bgainfo[bgano].cleared = CBGA_CSBROKECOMBO;	

			//		LOG->Trace("Clear Conditon: %d",info.cleared);
				}
				if(!asSplitLine[0].CompareNoCase("songtitle") && asSplitLine.size() > 1)
				{
					m_bgainfo[bgano].songtitle = asSplitLine[1];
				//	LOG->Trace("SongTitle: %s",info.songtitle.c_str());
				}
				if(!asSplitLine[0].CompareNoCase("songartist") && asSplitLine.size() > 1)
				{
					m_bgainfo[bgano].songartist = asSplitLine[1];
				//	LOG->Trace("SongArtist: %s",info.songartist.c_str());
				}
				if(!asSplitLine[0].CompareNoCase("songday") && asSplitLine.size() > 1)
				{
					CStringArray asDays;
					split( asSplitLine[1], ",", asDays );
					for( unsigned d=0; d<asDays.size(); d++ )
					{
						int dn = atoi(asDays[d].c_str());
						if(!(dn < 1 || dn > 32)) // ignore if date is out of range
						{
							m_bgainfo[bgano].songdays.push_back(dn);
						}
					}
			//		for(d=0; d<info.songdays.size(); d++)
			//		{
			//			LOG->Trace("SongDay: %d",info.songdays[d]);
			//		}
				}
				if(!asSplitLine[0].CompareNoCase("songmonth") && asSplitLine.size() > 1)
				{
					CStringArray asMonths;
					split( asSplitLine[1], ",", asMonths );
					for( unsigned d=0; d<asMonths.size(); d++ )
					{
						int dn = atoi(asMonths[d].c_str());
						if(!(dn < 1 || dn > 12)) // ignore if date is out of range
						{
							m_bgainfo[bgano].songmonths.push_back(dn);
						}
					}
		//			for(d=0; d<info.songmonths.size(); d++)
		//			{
		//				LOG->Trace("SongMonth: %d",info.songmonths[d]);
		//			}
				}

				// foot meter ratings
				if(!asSplitLine[0].CompareNoCase("songdifficulty") && asSplitLine.size() > 1)
				{
					CStringArray asDifficulties;
					split( asSplitLine[1], ",", asDifficulties );
					
					for(unsigned d=0;d<asDifficulties.size();d++)
					{
						// check to see if the last character is a +
						bool bHandled = false;
						if(asDifficulties[d].c_str()[strlen(asDifficulties[d].c_str())-1] == '+')
						{
							bHandled = true;
							CStringArray asVal;
							split(asDifficulties[d],"+",asVal);
							int temp=0;
							temp = 0 - atoi(asVal[0].c_str()); // negative numbers will indicate 'greater than' for this system
							m_bgainfo[bgano].songmeters.push_back(temp);
						}

						if(!bHandled) // didnt find the + (gt) so find a - (range)
						{
							bool isarange=false;
							for(unsigned b=0; b<strlen(asDifficulties[d].c_str());b++)
							{
								if(asDifficulties[d].c_str()[b] == '-')
								{
									bHandled = isarange = true;
									break;
								}
							}
							if(isarange)
							{
								CStringArray asVal;
								split(asDifficulties[d],"-",asVal);
								int imin=0,imax=0,itmp=0;
								imin=atoi(asVal[0].c_str());
								imax=atoi(asVal[1].c_str());
								itmp=imin;
								while(itmp<=imax) // fill in the values between the min and max range inclusive
								{
									m_bgainfo[bgano].songmeters.push_back(itmp);
									itmp++;
								}
							}
						}

						if(!bHandled) // its not a range so must be a value on its own
						{
							int tmp = atoi(asDifficulties[d].c_str());
							m_bgainfo[bgano].songmeters.push_back(tmp);
						}

					}
				}

				// mods that mustn't be present
				if(!asSplitLine[0].CompareNoCase("moddisallow") && asSplitLine.size() > 1)
				{
					m_bgainfo[bgano].dpoused = true;
					m_bgainfo[bgano].disallowedpo.FromString(asSplitLine[1]);

				}
				
				// heavy, light e.t.c.
				if(!asSplitLine[0].CompareNoCase("songrating") && asSplitLine.size() > 1)
				{
					CStringArray asDifficulties;
					split( asSplitLine[1], ",", asDifficulties );
					for( unsigned d=0; d<asDifficulties.size(); d++ )
					{
						m_bgainfo[bgano].difficulties.push_back(StringToDifficulty(asDifficulties[d]));
					}
		//			for(d=0; d<info.difficulties.size(); d++)
		//			{
		//				LOG->Trace("Difficulty: %d",info.difficulties[d]);
		//			}
				}
				if(!asSplitLine[0].CompareNoCase("grade") && asSplitLine.size() > 1)
				{
					CStringArray asGrades;
					split( asSplitLine[1], ",", asGrades );
					for( unsigned d=0; d<asGrades.size(); d++ )
					{
						m_bgainfo[bgano].grades.push_back(StringToGrade(asGrades[d]));
					}

				}
				if(!asSplitLine[0].CompareNoCase("style") && asSplitLine.size() > 1)
				{
					LOG->Info("Comparing Styles");
					CStringArray asStyles;
					split( asSplitLine[1], ",", asStyles );
					for( unsigned d=0; d<asStyles.size(); d++ )
					{
						LOG->Info( "Style:%s", asStyles[d].c_str() );

						m_bgainfo[bgano].styles.push_back(GAMEMAN->GameAndStringToStyle(GAMESTATE->m_pCurGame,asStyles[d]));
					}

				}


			}

		}
		if(bganimtouse.CompareNoCase("")!=0)
		{
			LOG->Info("Best Match BGA Was: %s",bganimtouse.c_str());
			bganim.LoadFromAniDir( THEME->GetPathToB(bganimtouse) );
		}

	}
	file.Close(); 
}