1/*
2 * Copyright 2004-2015, Haiku Inc. All rights reserved.
3 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8
9//!	The mail daemon's settings
10
11
12#include <MailSettings.h>
13
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17
18#include <Directory.h>
19#include <Entry.h>
20#include <File.h>
21#include <FindDirectory.h>
22#include <MailDaemon.h>
23#include <Message.h>
24#include <Messenger.h>
25#include <Path.h>
26#include <PathFinder.h>
27#include <String.h>
28#include <Window.h>
29
30#include <MailPrivate.h>
31
32
33//	#pragma mark - BMailSettings
34
35
36BMailSettings::BMailSettings()
37{
38	Reload();
39}
40
41
42BMailSettings::~BMailSettings()
43{
44}
45
46
47status_t
48BMailSettings::InitCheck() const
49{
50	return B_OK;
51}
52
53
54status_t
55BMailSettings::Save()
56{
57	BPath path;
58	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
59	if (status != B_OK) {
60		fprintf(stderr, "Couldn't find user settings directory: %s\n",
61			strerror(status));
62		return status;
63	}
64
65	path.Append("Mail");
66
67	status = BPrivate::WriteMessageFile(fData, path, "new_mail_daemon");
68	if (status != B_OK)
69		return status;
70
71	BMessenger(B_MAIL_DAEMON_SIGNATURE).SendMessage(
72		BPrivate::kMsgSettingsUpdated);
73	return B_OK;
74}
75
76
77status_t
78BMailSettings::Reload()
79{
80	// Try directories from most specific to least
81	directory_which which[] = {
82		B_USER_SETTINGS_DIRECTORY,
83		B_SYSTEM_SETTINGS_DIRECTORY};
84	status_t status = B_ENTRY_NOT_FOUND;
85
86	for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) {
87		BPath path;
88		status = find_directory(which[i], &path);
89		if (status != B_OK)
90			continue;
91
92		path.Append("Mail/new_mail_daemon");
93		BFile file;
94		status = file.SetTo(path.Path(), B_READ_ONLY);
95		if (status != B_OK)
96			continue;
97
98		// read settings
99		BMessage settings;
100		status = settings.Unflatten(&file);
101		if (status != B_OK) {
102			fprintf(stderr, "Couldn't read settings from '%s': %s\n",
103				path.Path(), strerror(status));
104			continue;
105		}
106
107		// clobber old settings
108		fData = settings;
109		return B_OK;
110	}
111
112	return status;
113}
114
115
116//	# pragma mark - Global settings
117
118
119int32
120BMailSettings::WindowFollowsCorner()
121{
122	return fData.FindInt32("WindowFollowsCorner");
123}
124
125
126void
127BMailSettings::SetWindowFollowsCorner(int32 whichCorner)
128{
129	if (fData.ReplaceInt32("WindowFollowsCorner", whichCorner) != B_OK)
130		fData.AddInt32("WindowFollowsCorner", whichCorner);
131}
132
133
134uint32
135BMailSettings::ShowStatusWindow()
136{
137	int32 showStatusWindow;
138	if (fData.FindInt32("ShowStatusWindow", &showStatusWindow) != B_OK) {
139		// show during send and receive
140		return 2;
141	}
142
143	return showStatusWindow;
144}
145
146
147void
148BMailSettings::SetShowStatusWindow(uint32 mode)
149{
150	if (fData.ReplaceInt32("ShowStatusWindow", mode) != B_OK)
151		fData.AddInt32("ShowStatusWindow", mode);
152}
153
154
155bool
156BMailSettings::DaemonAutoStarts()
157{
158	return fData.FindBool("DaemonAutoStarts");
159}
160
161
162void
163BMailSettings::SetDaemonAutoStarts(bool startIt)
164{
165	if (fData.ReplaceBool("DaemonAutoStarts", startIt) != B_OK)
166		fData.AddBool("DaemonAutoStarts", startIt);
167}
168
169
170BRect
171BMailSettings::ConfigWindowFrame()
172{
173	return fData.FindRect("ConfigWindowFrame");
174}
175
176
177void
178BMailSettings::SetConfigWindowFrame(BRect frame)
179{
180	if (fData.ReplaceRect("ConfigWindowFrame", frame) != B_OK)
181		fData.AddRect("ConfigWindowFrame", frame);
182}
183
184
185BRect
186BMailSettings::StatusWindowFrame()
187{
188	BRect frame;
189	if (fData.FindRect("StatusWindowFrame", &frame) != B_OK)
190		return BRect(100, 100, 200, 120);
191
192	return frame;
193}
194
195
196void
197BMailSettings::SetStatusWindowFrame(BRect frame)
198{
199	if (fData.ReplaceRect("StatusWindowFrame", frame) != B_OK)
200		fData.AddRect("StatusWindowFrame", frame);
201}
202
203
204int32
205BMailSettings::StatusWindowWorkspaces()
206{
207	uint32 workspaces;
208	if (fData.FindInt32("StatusWindowWorkSpace", (int32*)&workspaces) != B_OK)
209		return B_ALL_WORKSPACES;
210
211	return workspaces;
212}
213
214
215void
216BMailSettings::SetStatusWindowWorkspaces(int32 workspace)
217{
218	if (fData.ReplaceInt32("StatusWindowWorkSpace", workspace) != B_OK)
219		fData.AddInt32("StatusWindowWorkSpace", workspace);
220
221	BMessage msg('wsch');
222	msg.AddInt32("StatusWindowWorkSpace",workspace);
223	BMessenger(B_MAIL_DAEMON_SIGNATURE).SendMessage(&msg);
224}
225
226
227int32
228BMailSettings::StatusWindowLook()
229{
230	return fData.FindInt32("StatusWindowLook");
231}
232
233
234void
235BMailSettings::SetStatusWindowLook(int32 look)
236{
237	if (fData.ReplaceInt32("StatusWindowLook", look) != B_OK)
238		fData.AddInt32("StatusWindowLook", look);
239
240	BMessage msg('lkch');
241	msg.AddInt32("StatusWindowLook", look);
242	BMessenger(B_MAIL_DAEMON_SIGNATURE).SendMessage(&msg);
243}
244
245
246bigtime_t
247BMailSettings::AutoCheckInterval()
248{
249	bigtime_t value;
250	if (fData.FindInt64("AutoCheckInterval", &value) != B_OK) {
251		// every 5 min
252		return 5 * 60 * 1000 * 1000;
253	}
254	return value;
255}
256
257
258void
259BMailSettings::SetAutoCheckInterval(bigtime_t interval)
260{
261	if (fData.ReplaceInt64("AutoCheckInterval", interval) != B_OK)
262		fData.AddInt64("AutoCheckInterval", interval);
263}
264
265
266bool
267BMailSettings::CheckOnlyIfPPPUp()
268{
269	return fData.FindBool("CheckOnlyIfPPPUp");
270}
271
272
273void
274BMailSettings::SetCheckOnlyIfPPPUp(bool yes)
275{
276	if (fData.ReplaceBool("CheckOnlyIfPPPUp", yes))
277		fData.AddBool("CheckOnlyIfPPPUp", yes);
278}
279
280
281bool
282BMailSettings::SendOnlyIfPPPUp()
283{
284	return fData.FindBool("SendOnlyIfPPPUp");
285}
286
287
288void
289BMailSettings::SetSendOnlyIfPPPUp(bool yes)
290{
291	if (fData.ReplaceBool("SendOnlyIfPPPUp", yes))
292		fData.AddBool("SendOnlyIfPPPUp", yes);
293}
294
295
296int32
297BMailSettings::DefaultOutboundAccount()
298{
299	return fData.FindInt32("DefaultOutboundAccount");
300}
301
302
303void
304BMailSettings::SetDefaultOutboundAccount(int32 to)
305{
306	if (fData.ReplaceInt32("DefaultOutboundAccount", to) != B_OK)
307		fData.AddInt32("DefaultOutboundAccount", to);
308}
309
310
311// #pragma mark -
312
313
314BMailAccounts::BMailAccounts()
315{
316	BPath path;
317	status_t status = AccountsPath(path);
318	if (status != B_OK)
319		return;
320
321	BDirectory dir(path.Path());
322	if (dir.InitCheck() != B_OK)
323		return;
324
325	std::vector<time_t> creationTimeList;
326	BEntry entry;
327	while (dir.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) {
328		BNode node(&entry);
329		time_t creationTime;
330		if (node.GetCreationTime(&creationTime) != B_OK)
331			continue;
332
333		BMailAccountSettings* account = new BMailAccountSettings(entry);
334		if (account->InitCheck() != B_OK) {
335			delete account;
336			continue;
337		}
338
339		// sort by creation time
340		int insertIndex = -1;
341		for (unsigned int i = 0; i < creationTimeList.size(); i++) {
342			if (creationTimeList[i] > creationTime) {
343				insertIndex = i;
344				break;
345			}
346		}
347		if (insertIndex < 0) {
348			fAccounts.AddItem(account);
349			creationTimeList.push_back(creationTime);
350		} else {
351			fAccounts.AddItem(account, insertIndex);
352			creationTimeList.insert(creationTimeList.begin() + insertIndex,
353				creationTime);
354		}
355	}
356}
357
358
359status_t
360BMailAccounts::AccountsPath(BPath& path)
361{
362	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
363	if (status != B_OK)
364		return status;
365	return path.Append("Mail/accounts");
366}
367
368
369BMailAccounts::~BMailAccounts()
370{
371	for (int i = 0; i < fAccounts.CountItems(); i++)
372		delete fAccounts.ItemAt(i);
373}
374
375
376int32
377BMailAccounts::CountAccounts()
378{
379	return fAccounts.CountItems();
380}
381
382
383BMailAccountSettings*
384BMailAccounts::AccountAt(int32 index)
385{
386	return fAccounts.ItemAt(index);
387}
388
389
390BMailAccountSettings*
391BMailAccounts::AccountByID(int32 id)
392{
393	for (int i = 0; i < fAccounts.CountItems(); i++) {
394		BMailAccountSettings* account = fAccounts.ItemAt(i);
395		if (account->AccountID() == id)
396			return account;
397	}
398	return NULL;
399}
400
401
402BMailAccountSettings*
403BMailAccounts::AccountByName(const char* name)
404{
405	for (int i = 0; i < fAccounts.CountItems(); i++) {
406		BMailAccountSettings* account = fAccounts.ItemAt(i);
407		if (strcmp(account->Name(), name) == 0)
408			return account;
409	}
410	return NULL;
411}
412
413
414// #pragma mark -
415
416
417BMailAddOnSettings::BMailAddOnSettings()
418{
419}
420
421
422BMailAddOnSettings::~BMailAddOnSettings()
423{
424}
425
426
427status_t
428BMailAddOnSettings::Load(const BMessage& message)
429{
430	const char* pathString = NULL;
431	if (message.FindString("add-on path", &pathString) != B_OK)
432		return B_BAD_VALUE;
433
434	BPath path(pathString);
435
436	if (!path.IsAbsolute()) {
437		BStringList paths;
438		BPathFinder().FindPaths(B_FIND_PATH_ADD_ONS_DIRECTORY, "mail_daemon",
439			paths);
440
441		status_t status = B_ENTRY_NOT_FOUND;
442
443		for (int32 i = 0; i < paths.CountStrings(); i++) {
444			path.SetTo(paths.StringAt(i), pathString);
445			BEntry entry(path.Path());
446			if (entry.Exists()) {
447				status = B_OK;
448				break;
449			}
450		}
451		if (status != B_OK)
452			return status;
453	}
454
455	status_t status = get_ref_for_path(path.Path(), &fRef);
456	if (status != B_OK)
457		return status;
458
459	BMessage settings;
460	message.FindMessage("settings", &settings);
461
462	MakeEmpty();
463	Append(settings);
464
465	fOriginalSettings = *this;
466	fOriginalRef = fRef;
467	return B_OK;
468}
469
470
471status_t
472BMailAddOnSettings::Save(BMessage& message)
473{
474	BPath path(&fRef);
475	status_t status = message.AddString("add-on path", _RelativizePath(path));
476	if (status == B_OK)
477		status = message.AddMessage("settings", this);
478	if (status != B_OK)
479		return status;
480
481	fOriginalSettings = *this;
482	fOriginalRef = fRef;
483	return B_OK;
484}
485
486
487void
488BMailAddOnSettings::SetAddOnRef(const entry_ref& ref)
489{
490	fRef = ref;
491}
492
493
494const entry_ref&
495BMailAddOnSettings::AddOnRef() const
496{
497	return fRef;
498}
499
500
501bool
502BMailAddOnSettings::HasBeenModified() const
503{
504	return fRef != fOriginalRef
505		|| !fOriginalSettings.HasSameData(*this, true, true);
506}
507
508
509/*!	Cuts off the ".../add-ons/mail_daemon" part of the provided \a path
510	in case it exists. Otherwise, the complete path will be returned.
511*/
512const char*
513BMailAddOnSettings::_RelativizePath(const BPath& path) const
514{
515	const char* string = path.Path();
516	const char* parentDirectory = "/mail_daemon/";
517	const char* at = strstr(string, parentDirectory);
518	if (at == NULL)
519		return string;
520
521	return at + strlen(parentDirectory);
522}
523
524
525// #pragma mark -
526
527
528BMailProtocolSettings::BMailProtocolSettings()
529	:
530	fFiltersSettings(5, true)
531{
532}
533
534
535BMailProtocolSettings::~BMailProtocolSettings()
536{
537}
538
539
540status_t
541BMailProtocolSettings::Load(const BMessage& message)
542{
543	status_t status = BMailAddOnSettings::Load(message);
544	if (status != B_OK)
545		return status;
546
547	type_code typeFound;
548	int32 countFound;
549	message.GetInfo("filters", &typeFound, &countFound);
550	if (typeFound != B_MESSAGE_TYPE)
551		return B_BAD_VALUE;
552
553	for (int i = 0; i < countFound; i++) {
554		int32 index = AddFilterSettings();
555		if (index < 0)
556			return B_NO_MEMORY;
557
558		BMailAddOnSettings* filterSettings = fFiltersSettings.ItemAt(index);
559
560		BMessage filterMessage;
561		message.FindMessage("filters", i, &filterMessage);
562		if (filterSettings->Load(filterMessage) != B_OK)
563			RemoveFilterSettings(index);
564	}
565	return B_OK;
566}
567
568
569status_t
570BMailProtocolSettings::Save(BMessage& message)
571{
572	status_t status = BMailAddOnSettings::Save(message);
573	if (status != B_OK)
574		return status;
575
576	for (int i = 0; i < CountFilterSettings(); i++) {
577		BMessage filter;
578		BMailAddOnSettings* filterSettings = fFiltersSettings.ItemAt(i);
579		filterSettings->Save(filter);
580		message.AddMessage("filters", &filter);
581	}
582	return B_OK;
583}
584
585
586int32
587BMailProtocolSettings::CountFilterSettings() const
588{
589	return fFiltersSettings.CountItems();
590}
591
592
593int32
594BMailProtocolSettings::AddFilterSettings(const entry_ref* ref)
595{
596	BMailAddOnSettings* filterSettings = new BMailAddOnSettings();
597	if (ref != NULL)
598		filterSettings->SetAddOnRef(*ref);
599
600	if (fFiltersSettings.AddItem(filterSettings))
601		return fFiltersSettings.CountItems() - 1;
602
603	delete filterSettings;
604	return -1;
605}
606
607
608void
609BMailProtocolSettings::RemoveFilterSettings(int32 index)
610{
611	fFiltersSettings.RemoveItemAt(index);
612}
613
614
615bool
616BMailProtocolSettings::MoveFilterSettings(int32 from, int32 to)
617{
618	if (from < 0 || from >= (int32)CountFilterSettings() || to < 0
619		|| to >= (int32)CountFilterSettings())
620		return false;
621	if (from == to)
622		return true;
623
624	BMailAddOnSettings* settings = fFiltersSettings.RemoveItemAt(from);
625	fFiltersSettings.AddItem(settings, to);
626	return true;
627}
628
629
630BMailAddOnSettings*
631BMailProtocolSettings::FilterSettingsAt(int32 index) const
632{
633	return fFiltersSettings.ItemAt(index);
634}
635
636
637bool
638BMailProtocolSettings::HasBeenModified() const
639{
640	if (BMailAddOnSettings::HasBeenModified())
641		return true;
642	for (int32 i = 0; i < CountFilterSettings(); i++) {
643		if (FilterSettingsAt(i)->HasBeenModified())
644			return true;
645	}
646	return false;
647}
648
649
650//	#pragma mark -
651
652
653BMailAccountSettings::BMailAccountSettings()
654	:
655	fStatus(B_OK),
656	fInboundEnabled(true),
657	fOutboundEnabled(true),
658	fModified(true)
659{
660	fAccountID = real_time_clock();
661}
662
663
664BMailAccountSettings::BMailAccountSettings(BEntry account)
665	:
666	fAccountFile(account),
667	fModified(false)
668{
669	fStatus = Reload();
670}
671
672
673BMailAccountSettings::~BMailAccountSettings()
674{
675
676}
677
678
679void
680BMailAccountSettings::SetAccountID(int32 id)
681{
682	fModified = true;
683	fAccountID = id;
684}
685
686
687int32
688BMailAccountSettings::AccountID() const
689{
690	return fAccountID;
691}
692
693
694void
695BMailAccountSettings::SetName(const char* name)
696{
697	fModified = true;
698	fAccountName = name;
699}
700
701
702const char*
703BMailAccountSettings::Name() const
704{
705	return fAccountName;
706}
707
708
709void
710BMailAccountSettings::SetRealName(const char* realName)
711{
712	fModified = true;
713	fRealName = realName;
714}
715
716
717const char*
718BMailAccountSettings::RealName() const
719{
720	return fRealName;
721}
722
723
724void
725BMailAccountSettings::SetReturnAddress(const char* returnAddress)
726{
727	fModified = true;
728	fReturnAdress = returnAddress;
729}
730
731
732const char*
733BMailAccountSettings::ReturnAddress() const
734{
735	return fReturnAdress;
736}
737
738
739bool
740BMailAccountSettings::SetInboundAddOn(const char* name)
741{
742	entry_ref ref;
743	if (_GetAddOnRef("mail_daemon/inbound_protocols", name, ref) != B_OK)
744		return false;
745
746	fInboundSettings.SetAddOnRef(ref);
747	return true;
748}
749
750
751bool
752BMailAccountSettings::SetOutboundAddOn(const char* name)
753{
754	entry_ref ref;
755	if (_GetAddOnRef("mail_daemon/outbound_protocols", name, ref) != B_OK)
756		return false;
757
758	fOutboundSettings.SetAddOnRef(ref);
759	return true;
760}
761
762
763const entry_ref&
764BMailAccountSettings::InboundAddOnRef() const
765{
766	return fInboundSettings.AddOnRef();
767}
768
769
770const entry_ref&
771BMailAccountSettings::OutboundAddOnRef() const
772{
773	return fOutboundSettings.AddOnRef();
774}
775
776
777BMailProtocolSettings&
778BMailAccountSettings::InboundSettings()
779{
780	return fInboundSettings;
781}
782
783
784const BMailProtocolSettings&
785BMailAccountSettings::InboundSettings() const
786{
787	return fInboundSettings;
788}
789
790
791BMailProtocolSettings&
792BMailAccountSettings::OutboundSettings()
793{
794	return fOutboundSettings;
795}
796
797
798const BMailProtocolSettings&
799BMailAccountSettings::OutboundSettings() const
800{
801	return fOutboundSettings;
802}
803
804
805bool
806BMailAccountSettings::HasInbound()
807{
808	return BEntry(&fInboundSettings.AddOnRef()).Exists();
809}
810
811
812bool
813BMailAccountSettings::HasOutbound()
814{
815	return BEntry(&fOutboundSettings.AddOnRef()).Exists();
816}
817
818
819void
820BMailAccountSettings::SetInboundEnabled(bool enabled)
821{
822	fInboundEnabled = enabled;
823	fModified = true;
824}
825
826
827bool
828BMailAccountSettings::IsInboundEnabled() const
829{
830	return fInboundEnabled;
831}
832
833
834void
835BMailAccountSettings::SetOutboundEnabled(bool enabled)
836{
837	fOutboundEnabled = enabled;
838	fModified = true;
839}
840
841
842bool
843BMailAccountSettings::IsOutboundEnabled() const
844{
845	return fOutboundEnabled;
846}
847
848
849status_t
850BMailAccountSettings::Reload()
851{
852	BFile file(&fAccountFile, B_READ_ONLY);
853	status_t status = file.InitCheck();
854	if (status != B_OK)
855		return status;
856	BMessage settings;
857	settings.Unflatten(&file);
858
859	int32 id;
860	if (settings.FindInt32("id", &id) == B_OK)
861		fAccountID = id;
862	settings.FindString("name", &fAccountName);
863	settings.FindString("real_name", &fRealName);
864	settings.FindString("return_address", &fReturnAdress);
865
866	BMessage inboundSettings;
867	settings.FindMessage("inbound", &inboundSettings);
868	fInboundSettings.Load(inboundSettings);
869	BMessage outboundSettings;
870	settings.FindMessage("outbound", &outboundSettings);
871	fOutboundSettings.Load(outboundSettings);
872
873	if (settings.FindBool("inbound_enabled", &fInboundEnabled) != B_OK)
874		fInboundEnabled = true;
875	if (settings.FindBool("outbound_enabled", &fOutboundEnabled) != B_OK)
876		fOutboundEnabled = true;
877
878	fModified = false;
879	return B_OK;
880}
881
882
883status_t
884BMailAccountSettings::Save()
885{
886	fModified = false;
887
888	BMessage settings;
889	settings.AddInt32("id", fAccountID);
890	settings.AddString("name", fAccountName);
891	settings.AddString("real_name", fRealName);
892	settings.AddString("return_address", fReturnAdress);
893
894	BMessage inboundSettings;
895	fInboundSettings.Save(inboundSettings);
896	settings.AddMessage("inbound", &inboundSettings);
897	BMessage outboundSettings;
898	fOutboundSettings.Save(outboundSettings);
899	settings.AddMessage("outbound", &outboundSettings);
900
901	settings.AddBool("inbound_enabled", fInboundEnabled);
902	settings.AddBool("outbound_enabled", fOutboundEnabled);
903
904	status_t status = _CreateAccountFilePath();
905	if (status != B_OK)
906		return status;
907
908	BFile file(&fAccountFile, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
909	status = file.InitCheck();
910	if (status != B_OK)
911		return status;
912	return settings.Flatten(&file);
913}
914
915
916status_t
917BMailAccountSettings::Delete()
918{
919	return fAccountFile.Remove();
920}
921
922
923bool
924BMailAccountSettings::HasBeenModified() const
925{
926	return fModified
927		|| fInboundSettings.HasBeenModified()
928		|| fOutboundSettings.HasBeenModified();
929}
930
931
932const BEntry&
933BMailAccountSettings::AccountFile() const
934{
935	return fAccountFile;
936}
937
938
939status_t
940BMailAccountSettings::_CreateAccountFilePath()
941{
942	BPath path;
943	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
944	if (status != B_OK)
945		return status;
946	path.Append("Mail/accounts");
947	create_directory(path.Path(), 777);
948
949	if (fAccountFile.InitCheck() == B_OK)
950		return B_OK;
951
952	BString fileName = fAccountName;
953	if (fileName == "")
954		fileName << fAccountID;
955	for (int i = 0; ; i++) {
956		BString testFileName = fileName;
957		if (i != 0) {
958			testFileName += "_";
959			testFileName << i;
960		}
961		BPath testPath(path);
962		testPath.Append(testFileName);
963		BEntry testEntry(testPath.Path());
964		if (!testEntry.Exists()) {
965			fileName = testFileName;
966			break;
967		}
968	}
969
970	path.Append(fileName);
971	return fAccountFile.SetTo(path.Path());
972}
973
974
975status_t
976BMailAccountSettings::_GetAddOnRef(const char* subPath, const char* name,
977	entry_ref& ref)
978{
979	BStringList paths;
980	BPathFinder().FindPaths(B_FIND_PATH_ADD_ONS_DIRECTORY, subPath, paths);
981
982	for (int32 i = 0; i < paths.CountStrings(); i++) {
983		BPath path(paths.StringAt(i), name);
984		BEntry entry(path.Path());
985		if (entry.Exists()) {
986			if (entry.GetRef(&ref) == B_OK)
987				return B_OK;
988		}
989	}
990	return B_ENTRY_NOT_FOUND;
991}
992