xref: /haiku/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinksDirectory.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "PackageLinksDirectory.h"
8 
9 #include <AutoDeleter.h>
10 
11 #include "DebugSupport.h"
12 #include "PackageLinkDirectory.h"
13 #include "PackageLinksListener.h"
14 #include "Utils.h"
15 
16 
17 PackageLinksDirectory::PackageLinksDirectory()
18 	:
19 	Directory(0),
20 	fListener(NULL)
21 		// the ID needs to be assigned later, when added to a volume
22 {
23 	get_real_time(fModifiedTime);
24 }
25 
26 
27 PackageLinksDirectory::~PackageLinksDirectory()
28 {
29 }
30 
31 
32 timespec
33 PackageLinksDirectory::ModifiedTime() const
34 {
35 	return fModifiedTime;
36 }
37 
38 
39 status_t
40 PackageLinksDirectory::AddPackage(Package* package)
41 {
42 	// Create a package link directory -- there might already be one, but since
43 	// that's unlikely, we don't bother to check and recheck later.
44 	PackageLinkDirectory* linkDirectory
45 		= new(std::nothrow) PackageLinkDirectory;
46 	if (linkDirectory == NULL)
47 		return B_NO_MEMORY;
48 	BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory,
49 		true);
50 
51 	status_t error = linkDirectory->Init(this, package);
52 	if (error != B_OK)
53 		RETURN_ERROR(error);
54 
55 	// add the link directory
56 	NodeWriteLocker writeLocker(this);
57 	if (Node* child = FindChild(linkDirectory->Name())) {
58 		// There already is an entry with the name.
59 		PackageLinkDirectory* otherLinkDirectory
60 			= dynamic_cast<PackageLinkDirectory*>(child);
61 		if (otherLinkDirectory == NULL)
62 			RETURN_ERROR(B_BAD_VALUE);
63 
64 		// There's already a package link directory. Delete the one we created
65 		// and add the package to the pre-existing one.
66 		linkDirectory->RemovePackage(package, NULL);
67 		linkDirectory = otherLinkDirectory;
68 		linkDirectory->AddPackage(package, fListener);
69 	} else {
70 		// No entry is in the way, so just add the link directory.
71 		AddChild(linkDirectory);
72 
73 		if (fListener != NULL) {
74 			NodeWriteLocker writeLocker(linkDirectory);
75 			fListener->PackageLinkNodeAdded(linkDirectory);
76 		}
77 	}
78 
79 	return B_OK;
80 }
81 
82 
83 void
84 PackageLinksDirectory::RemovePackage(Package* package)
85 {
86 	NodeWriteLocker writeLocker(this);
87 
88 	// get the package's link directory and remove the package from it
89 	PackageLinkDirectory* linkDirectory = package->LinkDirectory();
90 	if (linkDirectory == NULL)
91 		return;
92 
93 	BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory);
94 
95 	linkDirectory->RemovePackage(package, fListener);
96 
97 	// if empty, remove the link directory itself
98 	if (linkDirectory->IsEmpty()) {
99 		if (fListener != NULL) {
100 			NodeWriteLocker linkDirectoryWriteLocker(linkDirectory);
101 			fListener->PackageLinkNodeRemoved(linkDirectory);
102 		}
103 
104 		RemoveChild(linkDirectory);
105 	}
106 }
107 
108 
109 void
110 PackageLinksDirectory::UpdatePackageDependencies(Package* package)
111 {
112 	NodeWriteLocker writeLocker(this);
113 
114 	PackageLinkDirectory* linkDirectory = package->LinkDirectory();
115 	if (linkDirectory == NULL)
116 		return;
117 
118 	linkDirectory->UpdatePackageDependencies(package, fListener);
119 }
120 
121