xref: /haiku/src/kits/debugger/files/FileManager.cpp (revision 6a2d53e7237764eab0c7b6d121772f26d636fb60)
1 /*
2  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2011-2017, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "FileManager.h"
8 
9 #include <new>
10 
11 #include <AutoDeleter.h>
12 #include <AutoLocker.h>
13 
14 #include "LocatableDirectory.h"
15 #include "LocatableFile.h"
16 #include "SourceFile.h"
17 #include "TeamFileManagerSettings.h"
18 
19 
20 // #pragma mark - EntryPath
21 
22 
23 struct FileManager::EntryPath {
24 	const char*	directory;
25 	const char*	name;
26 
EntryPathFileManager::EntryPath27 	EntryPath(const char* directory, const char* name)
28 		:
29 		directory(directory),
30 		name(name)
31 	{
32 	}
33 
EntryPathFileManager::EntryPath34 	EntryPath(const BString& directory, const BString& name)
35 		:
36 		directory(directory.Length() > 0 ? directory.String() : NULL),
37 		name(name.String())
38 	{
39 	}
40 
EntryPathFileManager::EntryPath41 	EntryPath(const LocatableEntry* entry)
42 		:
43 		directory(NULL),
44 		name(entry->Name())
45 	{
46 		LocatableDirectory* parent = entry->Parent();
47 		if (parent != NULL && strlen(parent->Path()) > 0)
48 			directory = parent->Path();
49 	}
50 
EntryPathFileManager::EntryPath51 	EntryPath(const EntryPath& other)
52 		:
53 		directory(other.directory),
54 		name(other.name)
55 	{
56 	}
57 
HashValueFileManager::EntryPath58 	size_t HashValue() const
59 	{
60 		return BString::HashValue(directory)
61 			^ BString::HashValue(name);
62 	}
63 
operator ==FileManager::EntryPath64 	bool operator==(const EntryPath& other) const
65 	{
66 		if (directory != other.directory
67 			&& (directory == NULL || other.directory == NULL
68 				|| strcmp(directory, other.directory) != 0)) {
69 			return false;
70 		}
71 
72 		return strcmp(name, other.name) == 0;
73 	}
74 };
75 
76 
77 // #pragma mark - EntryHashDefinition
78 
79 
80 struct FileManager::EntryHashDefinition {
81 	typedef EntryPath		KeyType;
82 	typedef	LocatableEntry	ValueType;
83 
HashKeyFileManager::EntryHashDefinition84 	size_t HashKey(const EntryPath& key) const
85 	{
86 		return key.HashValue();
87 	}
88 
HashFileManager::EntryHashDefinition89 	size_t Hash(const LocatableEntry* value) const
90 	{
91 		return HashKey(EntryPath(value));
92 	}
93 
CompareFileManager::EntryHashDefinition94 	bool Compare(const EntryPath& key, const LocatableEntry* value) const
95 	{
96 		return EntryPath(value) == key;
97 	}
98 
GetLinkFileManager::EntryHashDefinition99 	LocatableEntry*& GetLink(LocatableEntry* value) const
100 	{
101 		return value->fNext;
102 	}
103 };
104 
105 
106 // #pragma mark - Domain
107 
108 
109 class FileManager::Domain : private LocatableEntryOwner {
110 public:
Domain(FileManager * manager,bool isLocal)111 	Domain(FileManager* manager, bool isLocal)
112 		:
113 		fManager(manager),
114 		fIsLocal(isLocal)
115 	{
116 	}
117 
~Domain()118 	~Domain()
119 	{
120 		LocatableEntry* entry = fEntries.Clear(true);
121 		while (entry != NULL) {
122 			LocatableEntry* next = entry->fNext;
123 			entry->ReleaseReference();
124 			entry = next;
125 		}
126 	}
127 
Init()128 	status_t Init()
129 	{
130 		status_t error = fEntries.Init();
131 		if (error != B_OK)
132 			return error;
133 
134 		return B_OK;
135 	}
136 
GetFile(const BString & directoryPath,const BString & relativePath)137 	LocatableFile* GetFile(const BString& directoryPath,
138 		const BString& relativePath)
139 	{
140 		if (directoryPath.Length() == 0 || relativePath[0] == '/')
141 			return GetFile(relativePath);
142 		return GetFile(BString(directoryPath) << '/' << relativePath);
143 	}
144 
GetFile(const BString & path)145 	LocatableFile* GetFile(const BString& path)
146 	{
147 		BString directoryPath;
148 		BString name;
149 		_SplitPath(path, directoryPath, name);
150 		LocatableFile* file = _GetFile(directoryPath, name);
151 		if (file == NULL)
152 			return NULL;
153 
154 		// try to auto-locate the file
155 		if (LocatableDirectory* directory = file->Parent()) {
156 			if (directory->State() == LOCATABLE_ENTRY_UNLOCATED) {
157 				// parent not yet located -- try locate with the entry's path
158 				BString path;
159 				file->GetPath(path);
160 				_LocateEntry(file, path, true, true);
161 			} else {
162 				// parent already located -- locate the entry in the parent
163 				BString locatedDirectoryPath;
164 				if (directory->GetLocatedPath(locatedDirectoryPath))
165 					_LocateEntryInParentDir(file, locatedDirectoryPath, true);
166 			}
167 		}
168 
169 		return file;
170 	}
171 
EntryLocated(const BString & path,const BString & locatedPath)172 	void EntryLocated(const BString& path, const BString& locatedPath)
173 	{
174 		BString directory;
175 		BString name;
176 		_SplitPath(path, directory, name);
177 
178 		LocatableEntry* entry = _LookupEntry(EntryPath(directory, name));
179 		if (entry == NULL)
180 			return;
181 
182 		_LocateEntry(entry, locatedPath, false, true);
183 	}
184 
185 private:
Lock()186 	virtual bool Lock()
187 	{
188 		return fManager->Lock();
189 	}
190 
Unlock()191 	virtual void Unlock()
192 	{
193 		fManager->Unlock();
194 	}
195 
LocatableEntryUnused(LocatableEntry * entry)196 	virtual void LocatableEntryUnused(LocatableEntry* entry)
197 	{
198 		AutoLocker<FileManager> lock(fManager);
199 		if (fEntries.Lookup(EntryPath(entry)) == entry)
200 			fEntries.Remove(entry);
201 
202 		LocatableDirectory* parent = entry->Parent();
203 		if (parent != NULL)
204 			parent->RemoveEntry(entry);
205 	}
206 
_LocateDirectory(LocatableDirectory * directory,const BString & locatedPath,bool implicit)207 	bool _LocateDirectory(LocatableDirectory* directory,
208 		const BString& locatedPath, bool implicit)
209 	{
210 		if (directory == NULL
211 			|| directory->State() != LOCATABLE_ENTRY_UNLOCATED) {
212 			return false;
213 		}
214 
215 		if (!_LocateEntry(directory, locatedPath, implicit, true))
216 			return false;
217 
218 		_LocateEntries(directory, locatedPath, implicit);
219 
220 		return true;
221 	}
222 
_LocateEntry(LocatableEntry * entry,const BString & locatedPath,bool implicit,bool locateAncestors)223 	bool _LocateEntry(LocatableEntry* entry, const BString& locatedPath,
224 		bool implicit, bool locateAncestors)
225 	{
226 		if (implicit && entry->State() == LOCATABLE_ENTRY_LOCATED_EXPLICITLY)
227 			return false;
228 
229 		struct stat st;
230 		if (stat(locatedPath, &st) != 0)
231 			return false;
232 
233 		if (S_ISDIR(st.st_mode)) {
234 			LocatableDirectory* directory
235 				= dynamic_cast<LocatableDirectory*>(entry);
236 			if (directory == NULL)
237 				return false;
238 			entry->SetLocatedPath(locatedPath, implicit);
239 		} else if (S_ISREG(st.st_mode)) {
240 			LocatableFile* file = dynamic_cast<LocatableFile*>(entry);
241 			if (file == NULL)
242 				return false;
243 			entry->SetLocatedPath(locatedPath, implicit);
244 		}
245 
246 		// locate the ancestor directories, if requested
247 		if (locateAncestors) {
248 			BString locatedDirectory;
249 			BString locatedName;
250 			_SplitPath(locatedPath, locatedDirectory, locatedName);
251 			if (locatedName == entry->Name())
252 				_LocateDirectory(entry->Parent(), locatedDirectory, implicit);
253 		}
254 
255 		return true;
256 	}
257 
_LocateEntryInParentDir(LocatableEntry * entry,const BString & locatedDirectoryPath,bool implicit)258 	bool _LocateEntryInParentDir(LocatableEntry* entry,
259 		const BString& locatedDirectoryPath, bool implicit)
260 	{
261 		// construct the located entry path
262 		BString locatedEntryPath(locatedDirectoryPath);
263 		int32 pathLength = locatedEntryPath.Length();
264 		if (pathLength >= 1 && locatedEntryPath[pathLength - 1] != '/')
265 			locatedEntryPath << '/';
266 		locatedEntryPath << entry->Name();
267 
268 		return _LocateEntry(entry, locatedEntryPath, implicit, false);
269 	}
270 
_LocateEntries(LocatableDirectory * directory,const BString & locatedPath,bool implicit)271 	void _LocateEntries(LocatableDirectory* directory,
272 		const BString& locatedPath, bool implicit)
273 	{
274 		for (LocatableEntryList::ConstIterator it
275 				= directory->Entries().GetIterator();
276 			LocatableEntry* entry = it.Next();) {
277 			if (entry->State() == LOCATABLE_ENTRY_LOCATED_EXPLICITLY)
278 				continue;
279 
280 			 if (_LocateEntryInParentDir(entry, locatedPath, implicit)) {
281 				// recurse for directories
282 				if (LocatableDirectory* subDir
283 						= dynamic_cast<LocatableDirectory*>(entry)) {
284 					BString locatedEntryPath;
285 					if (subDir->GetLocatedPath(locatedEntryPath))
286 						_LocateEntries(subDir, locatedEntryPath, implicit);
287 				}
288 			}
289 		}
290 	}
291 
_GetFile(const BString & directoryPath,const BString & name)292 	LocatableFile* _GetFile(const BString& directoryPath, const BString& name)
293 	{
294 		BString normalizedDirPath;
295 		_NormalizePath(directoryPath, normalizedDirPath);
296 
297 		// if already known return the file
298 		LocatableEntry* entry = _LookupEntry(EntryPath(normalizedDirPath, name));
299 		if (entry != NULL) {
300 			LocatableFile* file = dynamic_cast<LocatableFile*>(entry);
301 			if (file == NULL)
302 				return NULL;
303 
304 			if (file->AcquireReference() == 0)
305 				fEntries.Remove(file);
306 			else
307 				return file;
308 		}
309 
310 		// no such file yet -- create it
311 		LocatableDirectory* directory = _GetDirectory(normalizedDirPath);
312 		if (directory == NULL)
313 			return NULL;
314 
315 		LocatableFile* file = new(std::nothrow) LocatableFile(this, directory,
316 			name);
317 		if (file == NULL) {
318 			directory->ReleaseReference();
319 			return NULL;
320 		}
321 
322 		directory->AddEntry(file);
323 
324 		fEntries.Insert(file);
325 
326 		return file;
327 	}
328 
_GetDirectory(const BString & path)329 	LocatableDirectory* _GetDirectory(const BString& path)
330 	{
331 		BString directoryPath;
332 		BString fileName;
333 		_SplitNormalizedPath(path, directoryPath, fileName);
334 
335 		// if already know return the directory
336 		LocatableEntry* entry
337 			= _LookupEntry(EntryPath(directoryPath, fileName));
338 		if (entry != NULL) {
339 			LocatableDirectory* directory
340 				= dynamic_cast<LocatableDirectory*>(entry);
341 			if (directory == NULL)
342 				return NULL;
343 			directory->AcquireReference();
344 			return directory;
345 		}
346 
347 		// get the parent directory
348 		LocatableDirectory* parentDirectory = NULL;
349 		if (directoryPath.Length() > 0) {
350 			parentDirectory = _GetDirectory(directoryPath);
351 			if (parentDirectory == NULL)
352 				return NULL;
353 		}
354 
355 		// create a new directory
356 		LocatableDirectory* directory = new(std::nothrow) LocatableDirectory(
357 			this, parentDirectory, path);
358 		if (directory == NULL) {
359 			parentDirectory->ReleaseReference();
360 			return NULL;
361 		}
362 
363 		// auto-locate, if possible
364 		if (fIsLocal) {
365 			BString dirPath;
366 			directory->GetPath(dirPath);
367 			directory->SetLocatedPath(dirPath, false);
368 		} else if (parentDirectory != NULL
369 			&& parentDirectory->State() != LOCATABLE_ENTRY_UNLOCATED) {
370 			BString locatedDirectoryPath;
371 			if (parentDirectory->GetLocatedPath(locatedDirectoryPath))
372 				_LocateEntryInParentDir(directory, locatedDirectoryPath, true);
373 		}
374 
375 		if (parentDirectory != NULL)
376 			parentDirectory->AddEntry(directory);
377 
378 		fEntries.Insert(directory);
379 		return directory;
380 	}
381 
_LookupEntry(const EntryPath & entryPath)382 	LocatableEntry* _LookupEntry(const EntryPath& entryPath)
383 	{
384 		LocatableEntry* entry = fEntries.Lookup(entryPath);
385 		if (entry == NULL)
386 			return NULL;
387 
388 		// if already unreferenced, remove it
389 		if (entry->CountReferences() == 0) {
390 			fEntries.Remove(entry);
391 			return NULL;
392 		}
393 
394 		return entry;
395 	}
396 
_NormalizePath(const BString & path,BString & _normalizedPath)397 	void _NormalizePath(const BString& path, BString& _normalizedPath)
398 	{
399 		BString normalizedPath;
400 		char* buffer = normalizedPath.LockBuffer(path.Length());
401 		int32 outIndex = 0;
402 		const char* remaining = path.String();
403 
404 		while (*remaining != '\0') {
405 			// collapse repeated slashes
406 			if (*remaining == '/') {
407 				buffer[outIndex++] = '/';
408 				remaining++;
409 				while (*remaining == '/')
410 					remaining++;
411 			}
412 
413 			if (*remaining == '\0') {
414 				// remove trailing slash (unless it's "/" only)
415 				if (outIndex > 1)
416 					outIndex--;
417 				break;
418 			}
419 
420 			// skip "." components
421 			if (*remaining == '.') {
422 				if (remaining[1] == '\0')
423 					break;
424 
425 				if (remaining[1] == '/') {
426 					remaining += 2;
427 					while (*remaining == '/')
428 						remaining++;
429 					continue;
430 				}
431 			}
432 
433 			// copy path component
434 			while (*remaining != '\0' && *remaining != '/')
435 				buffer[outIndex++] = *(remaining++);
436 		}
437 
438 		// If the path didn't change, use the original path (BString's copy on
439 		// write mechanism) rather than the new string.
440 		if (outIndex == path.Length()) {
441 			_normalizedPath = path;
442 		} else {
443 			normalizedPath.UnlockBuffer(outIndex);
444 			_normalizedPath = normalizedPath;
445 		}
446 	}
447 
_SplitPath(const BString & path,BString & _directory,BString & _name)448 	void _SplitPath(const BString& path, BString& _directory, BString& _name)
449 	{
450 		BString normalized;
451 		_NormalizePath(path, normalized);
452 		_SplitNormalizedPath(normalized, _directory, _name);
453 	}
454 
_SplitNormalizedPath(const BString & path,BString & _directory,BString & _name)455 	void _SplitNormalizedPath(const BString& path, BString& _directory,
456 		BString& _name)
457 	{
458 		// handle single component (including root dir) cases
459 		int32 lastSlash = path.FindLast('/');
460 		if (lastSlash < 0 || path.Length() == 1) {
461 			_directory = (const char*)NULL;
462 			_name = path;
463 			return;
464 		}
465 
466 		// handle root dir + one component and multi component cases
467 		if (lastSlash == 0)
468 			_directory = "/";
469 		else
470 			_directory.SetTo(path, lastSlash);
471 		_name = path.String() + (lastSlash + 1);
472 	}
473 
474 private:
475 	FileManager*		fManager;
476 	LocatableEntryTable	fEntries;
477 	bool				fIsLocal;
478 };
479 
480 
481 // #pragma mark - SourceFileEntry
482 
483 
484 struct FileManager::SourceFileEntry : public SourceFileOwner {
485 
486 	FileManager*		manager;
487 	BString				path;
488 	SourceFile*			file;
489 	SourceFileEntry*	next;
490 
SourceFileEntryFileManager::SourceFileEntry491 	SourceFileEntry(FileManager* manager, const BString& path)
492 		:
493 		manager(manager),
494 		path(path),
495 		file(NULL)
496 	{
497 	}
498 
SourceFileUnusedFileManager::SourceFileEntry499 	virtual void SourceFileUnused(SourceFile* sourceFile)
500 	{
501 		manager->_SourceFileUnused(this);
502 	}
503 
SourceFileDeletedFileManager::SourceFileEntry504 	virtual void SourceFileDeleted(SourceFile* sourceFile)
505 	{
506 		// We have already been removed from the table, so commit suicide.
507 		delete this;
508 	}
509 };
510 
511 
512 // #pragma mark - SourceFileHashDefinition
513 
514 
515 struct FileManager::SourceFileHashDefinition {
516 	typedef BString			KeyType;
517 	typedef	SourceFileEntry	ValueType;
518 
HashKeyFileManager::SourceFileHashDefinition519 	size_t HashKey(const BString& key) const
520 	{
521 		return key.HashValue();
522 	}
523 
HashFileManager::SourceFileHashDefinition524 	size_t Hash(const SourceFileEntry* value) const
525 	{
526 		return HashKey(value->path);
527 	}
528 
CompareFileManager::SourceFileHashDefinition529 	bool Compare(const BString& key, const SourceFileEntry* value) const
530 	{
531 		return value->path == key;
532 	}
533 
GetLinkFileManager::SourceFileHashDefinition534 	SourceFileEntry*& GetLink(SourceFileEntry* value) const
535 	{
536 		return value->next;
537 	}
538 };
539 
540 
541 // #pragma mark - FileManager
542 
543 
FileManager()544 FileManager::FileManager()
545 	:
546 	fLock("file manager"),
547 	fTargetDomain(NULL),
548 	fSourceDomain(NULL),
549 	fSourceFiles(NULL)
550 {
551 }
552 
553 
~FileManager()554 FileManager::~FileManager()
555 {
556 	delete fTargetDomain;
557 	delete fSourceDomain;
558 
559 	SourceFileEntry* entry = fSourceFiles->Clear();
560 	while (entry != NULL) {
561 		SourceFileEntry* next = entry->next;
562 		delete entry;
563 		entry = next;
564 	}
565 	delete fSourceFiles;
566 }
567 
568 
569 status_t
Init(bool targetIsLocal)570 FileManager::Init(bool targetIsLocal)
571 {
572 	status_t error = fLock.InitCheck();
573 	if (error != B_OK)
574 		return error;
575 
576 	// create target domain
577 	fTargetDomain = new(std::nothrow) Domain(this, targetIsLocal);
578 	if (fTargetDomain == NULL)
579 		return B_NO_MEMORY;
580 
581 	error = fTargetDomain->Init();
582 	if (error != B_OK)
583 		return error;
584 
585 	// create source domain
586 	fSourceDomain = new(std::nothrow) Domain(this, false);
587 	if (fSourceDomain == NULL)
588 		return B_NO_MEMORY;
589 
590 	error = fSourceDomain->Init();
591 	if (error != B_OK)
592 		return error;
593 
594 	// create source file table
595 	fSourceFiles = new(std::nothrow) SourceFileTable;
596 	if (fSourceFiles == NULL)
597 		return B_NO_MEMORY;
598 
599 	error = fSourceFiles->Init();
600 	if (error != B_OK)
601 		return error;
602 
603 	return B_OK;
604 }
605 
606 
607 LocatableFile*
GetTargetFile(const BString & directory,const BString & relativePath)608 FileManager::GetTargetFile(const BString& directory,
609 	const BString& relativePath)
610 {
611 	AutoLocker<FileManager> locker(this);
612 	return fTargetDomain->GetFile(directory, relativePath);
613 }
614 
615 
616 LocatableFile*
GetTargetFile(const BString & path)617 FileManager::GetTargetFile(const BString& path)
618 {
619 	AutoLocker<FileManager> locker(this);
620 	return fTargetDomain->GetFile(path);
621 }
622 
623 
624 void
TargetEntryLocated(const BString & path,const BString & locatedPath)625 FileManager::TargetEntryLocated(const BString& path,
626 	const BString& locatedPath)
627 {
628 	AutoLocker<FileManager> locker(this);
629 	fTargetDomain->EntryLocated(path, locatedPath);
630 }
631 
632 
633 LocatableFile*
GetSourceFile(const BString & directory,const BString & relativePath)634 FileManager::GetSourceFile(const BString& directory,
635 	const BString& relativePath)
636 {
637 	AutoLocker<FileManager> locker(this);
638 	LocatableFile* file = fSourceDomain->GetFile(directory, relativePath);
639 
640 	return file;
641 }
642 
643 
644 LocatableFile*
GetSourceFile(const BString & path)645 FileManager::GetSourceFile(const BString& path)
646 {
647 	AutoLocker<FileManager> locker(this);
648 	LocatableFile* file = fSourceDomain->GetFile(path);
649 
650 	return file;
651 }
652 
653 
654 status_t
SourceEntryLocated(const BString & path,const BString & locatedPath)655 FileManager::SourceEntryLocated(const BString& path,
656 	const BString& locatedPath)
657 {
658 	AutoLocker<FileManager> locker(this);
659 
660 	// check if we already have this path mapped. If so,
661 	// first clear the mapping, as the user may be attempting
662 	// to correct an existing entry.
663 	SourceFileEntry* entry = _LookupSourceFile(path);
664 	if (entry != NULL)
665 		_SourceFileUnused(entry);
666 
667 	fSourceDomain->EntryLocated(path, locatedPath);
668 
669 	try {
670 		fSourceLocationMappings[path] = locatedPath;
671 	} catch (...) {
672 		return B_NO_MEMORY;
673 	}
674 
675 	return B_OK;
676 }
677 
678 
679 status_t
LoadSourceFile(LocatableFile * file,SourceFile * & _sourceFile)680 FileManager::LoadSourceFile(LocatableFile* file, SourceFile*& _sourceFile)
681 {
682 	AutoLocker<FileManager> locker(this);
683 
684 	// get the path
685 	BString path;
686 	BString originalPath;
687 	file->GetPath(originalPath);
688 	if (!file->GetLocatedPath(path)) {
689 		// see if this is a file we have a lazy mapping for.
690 		if (!_LocateFileIfMapped(originalPath, file)
691 			|| !file->GetLocatedPath(path)) {
692 			return B_ENTRY_NOT_FOUND;
693 		}
694 	}
695 
696 	// we might already know the source file
697 	SourceFileEntry* entry = _LookupSourceFile(originalPath);
698 	if (entry != NULL) {
699 		entry->file->AcquireReference();
700 		_sourceFile = entry->file;
701 		return B_OK;
702 	}
703 
704 	// create the hash table entry
705 	entry = new(std::nothrow) SourceFileEntry(this, originalPath);
706 	if (entry == NULL)
707 		return B_NO_MEMORY;
708 
709 	// load the file
710 	SourceFile* sourceFile = new(std::nothrow) SourceFile(entry);
711 	if (sourceFile == NULL) {
712 		delete entry;
713 		return B_NO_MEMORY;
714 	}
715 	ObjectDeleter<SourceFile> sourceFileDeleter(sourceFile);
716 
717 	entry->file = sourceFile;
718 
719 	status_t error = sourceFile->Init(path);
720 	if (error != B_OK)
721 		return error;
722 
723 	fSourceFiles->Insert(entry);
724 
725 	_sourceFile = sourceFileDeleter.Detach();
726 	return B_OK;
727 }
728 
729 
730 status_t
LoadLocationMappings(TeamFileManagerSettings * settings)731 FileManager::LoadLocationMappings(TeamFileManagerSettings* settings)
732 {
733 	AutoLocker<FileManager> locker(this);
734 	for (int32 i = 0; i < settings->CountSourceMappings(); i++) {
735 		BString sourcePath;
736 		BString locatedPath;
737 
738 		if (settings->GetSourceMappingAt(i, sourcePath, locatedPath) != B_OK)
739 			return B_NO_MEMORY;
740 
741 		try {
742 			fSourceLocationMappings[sourcePath] = locatedPath;
743 		} catch (...) {
744 			return B_NO_MEMORY;
745 		}
746 	}
747 
748 	return B_OK;
749 }
750 
751 
752 status_t
SaveLocationMappings(TeamFileManagerSettings * settings)753 FileManager::SaveLocationMappings(TeamFileManagerSettings* settings)
754 {
755 	AutoLocker<FileManager> locker(this);
756 
757 	for (LocatedFileMap::const_iterator it = fSourceLocationMappings.begin();
758 		it != fSourceLocationMappings.end(); ++it) {
759 		status_t error = settings->AddSourceMapping(it->first, it->second);
760 		if (error != B_OK)
761 			return error;
762 	}
763 
764 	return B_OK;
765 }
766 
767 
768 FileManager::SourceFileEntry*
_LookupSourceFile(const BString & path)769 FileManager::_LookupSourceFile(const BString& path)
770 {
771 	SourceFileEntry* entry = fSourceFiles->Lookup(path);
772 	if (entry == NULL)
773 		return NULL;
774 
775 	// the entry might be unused already -- in that case remove it
776 	if (entry->file->CountReferences() == 0) {
777 		fSourceFiles->Remove(entry);
778 		return NULL;
779 	}
780 
781 	return entry;
782 }
783 
784 
785 void
_SourceFileUnused(SourceFileEntry * entry)786 FileManager::_SourceFileUnused(SourceFileEntry* entry)
787 {
788 	AutoLocker<FileManager> locker(this);
789 
790 	SourceFileEntry* otherEntry = fSourceFiles->Lookup(entry->path);
791 	if (otherEntry == entry)
792 		fSourceFiles->Remove(entry);
793 }
794 
795 
796 bool
_LocateFileIfMapped(const BString & sourcePath,LocatableFile * file)797 FileManager::_LocateFileIfMapped(const BString& sourcePath,
798 	LocatableFile* file)
799 {
800 	// called with lock held
801 
802 	LocatedFileMap::const_iterator it = fSourceLocationMappings.find(
803 		sourcePath);
804 	if (it != fSourceLocationMappings.end()
805 		&& file->State() != LOCATABLE_ENTRY_LOCATED_EXPLICITLY
806 		&& file->State() != LOCATABLE_ENTRY_LOCATED_IMPLICITLY) {
807 		fSourceDomain->EntryLocated(it->first, it->second);
808 		return true;
809 	}
810 
811 	return false;
812 }
813