xref: /haiku/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkSymlink.cpp (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
1 /*
2  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "PackageLinkSymlink.h"
8 
9 #include <algorithm>
10 
11 #include <NodeMonitor.h>
12 
13 #include "AutoPackageAttributeDirectoryCookie.h"
14 #include "DebugSupport.h"
15 #include "NodeListener.h"
16 #include "PackageLinksListener.h"
17 #include "Utils.h"
18 #include "Volume.h"
19 
20 
21 static const char* const kUnknownLinkTarget = "?";
22 
23 static const char* const kLinkPaths[PackageLinkSymlink::TYPE_ENUM_COUNT]
24 		[PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT] = {
25 	{
26 		"../..",
27 		"../../../home/config",
28 		kUnknownLinkTarget
29 	},
30 	{
31 		"../../../system/settings",
32 		"../../../home/config/settings",
33 		kUnknownLinkTarget
34 	}
35 };
36 
37 
38 static const char*
39 link_path_for_mount_type(MountType mountType, PackageLinkSymlink::Type linkType)
40 {
41 	if (mountType < 0 || mountType >= PACKAGE_FS_MOUNT_TYPE_ENUM_COUNT
42 		|| linkType < 0 || linkType >= PackageLinkSymlink::TYPE_ENUM_COUNT) {
43 		return kUnknownLinkTarget;
44 	}
45 
46 	return kLinkPaths[linkType][mountType];
47 }
48 
49 
50 // #pragma mark - OldAttributes
51 
52 
53 struct PackageLinkSymlink::OldAttributes : OldNodeAttributes {
54 	OldAttributes(const timespec& modifiedTime, off_t fileSize)
55 		:
56 		fModifiedTime(modifiedTime),
57 		fFileSize(fileSize)
58 	{
59 	}
60 
61 	virtual timespec ModifiedTime() const
62 	{
63 		return fModifiedTime;
64 	}
65 
66 	virtual off_t FileSize() const
67 	{
68 		return fFileSize;
69 	}
70 
71 private:
72 	timespec	fModifiedTime;
73 	off_t		fFileSize;
74 };
75 
76 
77 // #pragma mark - PackageLinkSymlink
78 
79 
80 PackageLinkSymlink::PackageLinkSymlink(Package* package, Type type)
81 	:
82 	Node(0),
83 	fPackage(),
84 	fLinkPath(kUnknownLinkTarget),
85 	fType(type)
86 {
87 	Update(package, NULL);
88 }
89 
90 
91 PackageLinkSymlink::~PackageLinkSymlink()
92 {
93 }
94 
95 
96 void
97 PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener)
98 {
99 	OldAttributes oldAttributes(fModifiedTime, FileSize());
100 
101 	fPackage = package;
102 
103 	if (package != NULL) {
104 		fLinkPath = package->InstallPath();
105 		if (fLinkPath[0] != '\0') {
106 			if (fType == TYPE_SETTINGS)
107 				fLinkPath = ".self/settings";
108 		} else {
109 			fLinkPath = link_path_for_mount_type(
110 				package->Volume()->MountType(), fType);
111 		}
112 	} else
113 		fLinkPath = kUnknownLinkTarget;
114 
115 	get_real_time(fModifiedTime);
116 
117 	if (listener != NULL) {
118 		listener->PackageLinkNodeChanged(this,
119 			B_STAT_SIZE | B_STAT_MODIFICATION_TIME, oldAttributes);
120 	}
121 }
122 
123 
124 mode_t
125 PackageLinkSymlink::Mode() const
126 {
127 	return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
128 }
129 
130 
131 timespec
132 PackageLinkSymlink::ModifiedTime() const
133 {
134 	return fModifiedTime;
135 }
136 
137 
138 off_t
139 PackageLinkSymlink::FileSize() const
140 {
141 	return strlen(fLinkPath);
142 }
143 
144 
145 status_t
146 PackageLinkSymlink::Read(off_t offset, void* buffer, size_t* bufferSize)
147 {
148 	return B_BAD_VALUE;
149 }
150 
151 
152 status_t
153 PackageLinkSymlink::Read(io_request* request)
154 {
155 	return B_BAD_VALUE;
156 }
157 
158 
159 status_t
160 PackageLinkSymlink::ReadSymlink(void* buffer, size_t* bufferSize)
161 {
162 	size_t linkLength = strnlen(fLinkPath, B_PATH_NAME_LENGTH);
163 
164 	size_t bytesToCopy = std::min(linkLength, *bufferSize);
165 
166 	*bufferSize = linkLength;
167 
168 	memcpy(buffer, fLinkPath, bytesToCopy);
169 	return B_OK;
170 }
171 
172 
173 status_t
174 PackageLinkSymlink::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
175 {
176 	AutoPackageAttributeDirectoryCookie* cookie = new(std::nothrow)
177 		AutoPackageAttributeDirectoryCookie();
178 	if (cookie == NULL)
179 		return B_NO_MEMORY;
180 
181 	_cookie = cookie;
182 	return B_OK;
183 }
184 
185 
186 status_t
187 PackageLinkSymlink::OpenAttribute(const StringKey& name, int openMode,
188 	AttributeCookie*& _cookie)
189 {
190 	if (!fPackage.IsSet())
191 		return B_ENTRY_NOT_FOUND;
192 
193 	return AutoPackageAttributes::OpenCookie(fPackage, name, openMode, _cookie);
194 }
195