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 "DebugSupport.h"
14#include "NodeListener.h"
15#include "PackageLinksListener.h"
16#include "Utils.h"
17#include "Volume.h"
18
19
20static const char* const kSystemLinkPath = "../..";
21static const char* const kCommonLinkPath = "../../../common";
22static const char* const kHomeLinkPath = "../../../home/config";
23
24static const char* const kUnknownLinkTarget = "?";
25
26
27static const char*
28link_path_for_mount_type(MountType type)
29{
30	switch (type) {
31		case MOUNT_TYPE_SYSTEM:
32			return kSystemLinkPath;
33		case MOUNT_TYPE_COMMON:
34			return kCommonLinkPath;
35		case MOUNT_TYPE_HOME:
36			return kHomeLinkPath;
37		case MOUNT_TYPE_CUSTOM:
38		default:
39			return "?";
40	}
41}
42
43
44// #pragma mark - OldAttributes
45
46
47struct PackageLinkSymlink::OldAttributes : OldNodeAttributes {
48	OldAttributes(const timespec& modifiedTime, off_t fileSize)
49		:
50		fModifiedTime(modifiedTime),
51		fFileSize(fileSize)
52	{
53	}
54
55	virtual timespec ModifiedTime() const
56	{
57		return fModifiedTime;
58	}
59
60	virtual off_t FileSize() const
61	{
62		return fFileSize;
63	}
64
65private:
66	timespec	fModifiedTime;
67	off_t		fFileSize;
68};
69
70
71// #pragma mark - PackageLinkSymlink
72
73
74PackageLinkSymlink::PackageLinkSymlink(Package* package)
75	:
76	Node(0),
77	fLinkPath(kUnknownLinkTarget)
78{
79	Update(package, NULL);
80}
81
82
83PackageLinkSymlink::~PackageLinkSymlink()
84{
85}
86
87
88void
89PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener)
90{
91	OldAttributes oldAttributes(fModifiedTime, FileSize());
92
93	if (package != NULL) {
94		fLinkPath = package->InstallPath();
95		if (fLinkPath == NULL) {
96			fLinkPath = link_path_for_mount_type(
97				package->Domain()->Volume()->MountType());
98		}
99	} else
100		fLinkPath = kUnknownLinkTarget;
101
102	get_real_time(fModifiedTime);
103
104	if (listener != NULL) {
105		listener->PackageLinkNodeChanged(this,
106			B_STAT_SIZE | B_STAT_MODIFICATION_TIME, oldAttributes);
107	}
108}
109
110
111mode_t
112PackageLinkSymlink::Mode() const
113{
114	return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
115}
116
117
118timespec
119PackageLinkSymlink::ModifiedTime() const
120{
121	return fModifiedTime;
122}
123
124
125off_t
126PackageLinkSymlink::FileSize() const
127{
128	return strlen(fLinkPath);
129}
130
131
132status_t
133PackageLinkSymlink::Read(off_t offset, void* buffer, size_t* bufferSize)
134{
135	return B_BAD_VALUE;
136}
137
138
139status_t
140PackageLinkSymlink::Read(io_request* request)
141{
142	return B_BAD_VALUE;
143}
144
145
146status_t
147PackageLinkSymlink::ReadSymlink(void* buffer, size_t* bufferSize)
148{
149	size_t toCopy = std::min(strlen(fLinkPath), *bufferSize);
150	memcpy(buffer, fLinkPath, toCopy);
151	*bufferSize = toCopy;
152
153	return B_OK;
154}
155