void DirectFilenameDB::CacheFile( const RString &sPath )
{
	CHECKPOINT_M( root+sPath );
	RString sDir = Dirname( sPath );
	FileSet *pFileSet = GetFileSet( sDir, false );
	if( pFileSet == NULL )
	{
		// This directory isn't cached so do nothing.
		m_Mutex.Unlock(); // Locked by GetFileSet()
		return;
	}
	while( !pFileSet->m_bFilled )
		m_Mutex.Wait();
		
#if defined(WIN32)
	// There is almost surely a better way to do this
	WIN32_FIND_DATA fd;
	HANDLE hFind = DoFindFirstFile( root+sPath, &fd );
	if( hFind == INVALID_HANDLE_VALUE )
	{
		m_Mutex.Unlock(); // Locked by GetFileSet()
		return;
	}
	File f( fd.cFileName );
	f.dir = !!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
	f.size = fd.nFileSizeLow;
	f.hash = fd.ftLastWriteTime.dwLowDateTime;
	
	pFileSet->files.insert( f );
	FindClose( hFind );
#else
	File f( Basename(sPath) );
	
	struct stat st;
	if( DoStat(root+sPath, &st) == -1 )
	{
		int iError = errno;
		/* If it's a broken symlink, ignore it.  Otherwise, warn. */
		/* Huh? */
		WARN( ssprintf("File '%s' is gone! (%s)",
			       sPath.c_str(), strerror(iError)) );
	}
	else
	{
		f.dir = (st.st_mode & S_IFDIR);
		f.size = (int)st.st_size;
		f.hash = st.st_mtime;
	}
	
	pFileSet->files.insert(f);
#endif
	m_Mutex.Unlock(); // Locked by GetFileSet()	
}
Exemple #2
0
int DrawStatBar( HDC hDC, RECT rect, int width, int status, int hp, int mn, int st )
{
	HGDIOBJ hOld = NULL;
	POINT pt[2];
	rect.right = rect.left + width + 2;

	int o = ( rect.bottom - rect.top - 20 ) / 2;
	if ( o > 0 )
		rect.top += o;
	rect.bottom = rect.top + 6 + 6 + 6 + 1;

	hOld = SelectObject( hDC, GetStockObject( BLACK_PEN ) );
	FrameRect( hDC, &rect, (HBRUSH)GetStockObject( BLACK_BRUSH ) );

	pt[0].x = rect.left;
	pt[1].x = rect.right;

	pt[0].y = rect.top + 6;
	pt[1].y = rect.top + 6;
	Polyline( hDC, pt, 2 );
	
	pt[0].y = rect.top + 6 + 6;
	pt[1].y = rect.top + 6 + 6;
	Polyline( hDC, pt, 2 );

	if ( status == 1 ) // poisoned
		DoStat( hDC, 0xFF, rect.top+1, rect.left+1, 5, (int)((double(hp+1)/100.0)*width) );
	else
		DoStat( hDC, hp, rect.top+1, rect.left+1, 5, (int)((double(hp+1)/100.0)*width) );

	DoStat( hDC, mn, rect.top+1+6, rect.left+1, 5, (int)((double(mn+1)/100)*width) );
	DoStat( hDC, st, rect.top+2+6+5, rect.left+1, 5, (int)((double(st+1)/100)*width) );
    
	SelectObject( hDC, hOld );
	return width+2;
}
void DirectFilenameDB::PopulateFileSet( FileSet &fs, const RString &path )
{
	RString sPath = path;

#if defined(XBOX)
	/* Xbox doesn't handle path names which end with ".", which are used when using an
	 * alternative song directory */
	if( sPath.size() > 0 && sPath.Right(1) == "." )
		sPath.erase( sPath.size() - 1 );
#endif

	/* Resolve path cases (path/Path -> PATH/path). */
	ResolvePath( sPath );

	fs.age.GetDeltaTime(); /* reset */
	fs.files.clear();

#if defined(WIN32)
	WIN32_FIND_DATA fd;

	if ( sPath.size() > 0  && sPath.Right(1) == "/" )
		sPath.erase( sPath.size() - 1 );

	HANDLE hFind = DoFindFirstFile( root+sPath+"/*", &fd );
	CHECKPOINT_M( root+sPath+"/*" );

	if( hFind == INVALID_HANDLE_VALUE )
		return;

	do {
		if( !strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..") )
			continue;

		File f;
		f.SetName( fd.cFileName );
		f.dir = !!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
		f.size = fd.nFileSizeLow;
		f.hash = fd.ftLastWriteTime.dwLowDateTime;

		fs.files.insert( f );
	} while( FindNextFile( hFind, &fd ) );
	FindClose( hFind );
#else
	/* Ugly: POSIX threads are not guaranteed to have per-thread cwds, and only
	 * a few systems have openat() or equivalent; one or the other is needed
	 * to do efficient, thread-safe directory traversal.  Instead, we have to
	 * use absolute paths, which forces the system to re-parse the directory
	 * for each file.  This isn't a major issue, since most large directory
	 * scans are I/O-bound. */
	 
	DIR *pDir = opendir(root+sPath);
	if( pDir == NULL )
		return;

	while( struct dirent *pEnt = readdir(pDir) )
	{
		if( !strcmp(pEnt->d_name, ".") )
			continue;
		if( !strcmp(pEnt->d_name, "..") )
			continue;
		
		File f( pEnt->d_name );
		
		struct stat st;
		if( DoStat(root+sPath + "/" + pEnt->d_name, &st) == -1 )
		{
			int iError = errno;
			/* If it's a broken symlink, ignore it.  Otherwise, warn. */
			if( lstat(root+sPath + "/" + pEnt->d_name, &st) == 0 )
				continue;
			
			/* Huh? */
			WARN( ssprintf("Got file '%s' in '%s' from list, but can't stat? (%s)",
					pEnt->d_name, sPath.c_str(), strerror(iError)) );
			continue;
		}
		else
		{
			f.dir = (st.st_mode & S_IFDIR);
			f.size = (int)st.st_size;
			f.hash = st.st_mtime;
		}

		fs.files.insert(f);
	}
	       
	closedir( pDir );
#endif

	/*
	 * Check for any ".ignore" markers.  If a marker exists, hide the marker and its 
	 * corresponding file.
	 * For example, if "file.xml.ignore" exists, hide both it and "file.xml" by 
	 * removing them from the file set.
	 * Ignore markers are used for convenience during build staging and are not used in 
	 * performance-critical situations.  To avoid incurring some of the overheard 
	 * due to ignore markers, delete the file instead instead of using an ignore marker.
	 */
	static const RString IGNORE_MARKER_BEGINNING = "ignore-";

	vector<RString> vsFilesToRemove;
	for( set<File>::iterator iter = fs.files.lower_bound(IGNORE_MARKER_BEGINNING); 
		 iter != fs.files.end(); 
		 ++iter )
	{
		if( !BeginsWith( iter->lname, IGNORE_MARKER_BEGINNING ) )
			break;
		RString sFileLNameToIgnore = iter->lname.Right( iter->lname.length() - IGNORE_MARKER_BEGINNING.length() );
		vsFilesToRemove.push_back( iter->name );
		vsFilesToRemove.push_back( sFileLNameToIgnore );
	}
	
	FOREACH_CONST( RString, vsFilesToRemove, iter )
	{
		// Erase the file corresponding to the ignore marker
		File fileToDelete;
		fileToDelete.SetName( *iter );
		set<File>::iterator iter2 = fs.files.find( fileToDelete );
		if( iter2 != fs.files.end() )
			fs.files.erase( iter2 );
	}
/* mkdir -p.  Doesn't fail if Path already exists and is a directory. */
bool CreateDirectories( RString Path )
{
	/* XXX: handle "//foo/bar" paths in Windows */
	vector<RString> parts;
	RString curpath;

	/* If Path is absolute, add the initial slash ("ignore empty" will remove it). */
	if( Path.Left(1) == "/" )
		curpath = "/";

	/* Ignore empty, so eg. "/foo/bar//baz" doesn't try to create "/foo/bar" twice. */
	split( Path, "/", parts, true );

	for(unsigned i = 0; i < parts.size(); ++i)
	{
		if( i )
			curpath += "/";
		curpath += parts[i];

#if defined(WIN32)
		if( curpath.size() == 2 && curpath[1] == ':' )  /* C: */
		{
			/* Don't try to create the drive letter alone. */
			continue;
		}
#endif

		if( DoMkdir(curpath, 0777) == 0 )
			continue;

#if defined(WIN32)
		/* When creating a directory that already exists over Samba, Windows is
		 * returning ENOENT instead of EEXIST. */
		/* I can't reproduce this anymore.  If we get ENOENT, log it but keep
		 * going. */
		if( errno == ENOENT )
		{
			WARN( ssprintf("Couldn't create %s: %s", curpath.c_str(), strerror(errno)) );
			errno = EEXIST;
		}
#endif

		if( errno == EEXIST )
		{
			/* Make sure it's a directory. */
			struct stat st;
			if( DoStat(curpath, &st) != -1 && !(st.st_mode & S_IFDIR) )
			{
				WARN( ssprintf("Couldn't create %s: path exists and is not a directory", curpath.c_str()) );
				return false;
			}

			continue;		// we expect to see this error
		}

		WARN( ssprintf("Couldn't create %s: %s", curpath.c_str(), strerror(errno)) );
		return false;
	}
	
	return true;
}
Exemple #5
0
static void copyConfigFiles(const FXString& srcfile,const FXString& dstfile, FXString &errors,FXint level)
{
  if (srcfile!=dstfile) {
    FXString name,linkname;
    FXStat srcstat;
    FXStat dststat;
    if (DoStat(srcfile,srcstat)) {
      if (DoStat(dstfile,dststat)) {
        errno=0;
        Error(_("File exists"), dstfile);
        return;
      }
      if (srcstat.isDirectory()) {
# ifdef WIN32
        if ((level==2) && (FXPath::name(srcfile)=="servers")) {
          FXDir::remove(srcfile);
          return;
        }
# endif
        if (!dststat.isDirectory()) {
          if (!FXDir::create(dstfile,srcstat.mode()|FXIO::OwnerWrite)) {
             Error(_("Create failed"), dstfile);
             return;
          }
        }
        FXDir dir(srcfile);
        if (dir.isOpen()) {
          while(dir.next(name)) {
            if (name[0]=='.' && (name[1]=='\0' || (name[1]=='.' && name[2]=='\0'))) continue;
            copyConfigFiles(srcfile+PATHSEP+name,dstfile+PATHSEP+name,errors,level+1);
          }
        } else {
          Error(_("Access failed"), srcfile);
        }
        return;
      }
      FXString newname=dstfile.text();
# ifndef WIN32
      if ((level==2) && ((FXPath::name(srcfile)=="settings")||(FXPath::name(srcfile)=="styles"))) {
        newname+=".rc";
      }
# endif
      if (srcstat.isFile()) {
        if (!FXFile::copy(srcfile,newname,false)) {
          Error(_("Copy failed"), srcfile);
        }
        return;
      }
      if (srcstat.isLink()) {
        linkname=FXFile::symlink(srcfile);
        if (!FXFile::symlink(linkname,newname)) {
          Error(_("Link failed"), newname);
        }
        return;
      }
      if (srcstat.isFifo()) {
        if (!FXPipe::create(dstfile,srcstat.mode())) {
          Error(_("Create fifo failed"), dstfile);
        }
        return;
      }
      if (srcstat.isSocket()) {
        errno=0;
        Error(_("Ignored socket"), srcfile);
        return;
      }
      if (srcstat.isCharacter()||srcstat.isBlock()) {
        errno=0;
        Error(_("Ignored device node"), srcfile);
        return;
      }
    }
  }
}