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() }
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; }
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; } } } }