1/*
2 * Copyright 2001-2005, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Erik Jaesler (erik@cgsoftware.com)
7 */
8
9/**	Extra messaging utility functions */
10
11#include <string.h>
12#include <ByteOrder.h>
13
14#include <MessageUtils.h>
15
16namespace BPrivate {
17
18uint32
19CalculateChecksum(const uint8 *buffer, int32 size)
20{
21	uint32 sum = 0;
22	uint32 temp = 0;
23
24	while (size > 3) {
25		sum += B_BENDIAN_TO_HOST_INT32(*(int32 *)buffer);
26		buffer += 4;
27		size -= 4;
28	}
29
30	while (size > 0) {
31		temp = (temp << 8) + *buffer++;
32		size -= 1;
33	}
34
35	return sum + temp;
36}
37
38
39/* entry_ref support functions */
40status_t
41entry_ref_flatten(char *buffer, size_t *size, const entry_ref *ref)
42{
43	if (*size < sizeof(ref->device) + sizeof(ref->directory))
44		return B_BUFFER_OVERFLOW;
45
46	memcpy((void *)buffer, (const void *)&ref->device, sizeof(ref->device));
47	buffer += sizeof(ref->device);
48	memcpy((void *)buffer, (const void *)&ref->directory, sizeof(ref->directory));
49	buffer += sizeof(ref->directory);
50	*size -= sizeof(ref->device) + sizeof(ref->directory);
51
52	size_t nameLength = 0;
53	if (ref->name) {
54		nameLength = strlen(ref->name) + 1;
55		if (*size < nameLength)
56			return B_BUFFER_OVERFLOW;
57
58		memcpy((void *)buffer, (const void *)ref->name, nameLength);
59	}
60
61	*size = sizeof(ref->device) + sizeof(ref->directory) + nameLength;
62
63	return B_OK;
64}
65
66
67status_t
68entry_ref_unflatten(entry_ref *ref, const char *buffer, size_t size)
69{
70	if (size < sizeof(ref->device) + sizeof(ref->directory)) {
71		*ref = entry_ref();
72		return B_BAD_VALUE;
73	}
74
75	memcpy((void *)&ref->device, (const void *)buffer, sizeof(ref->device));
76	buffer += sizeof(ref->device);
77	memcpy((void *)&ref->directory, (const void *)buffer,
78		sizeof(ref->directory));
79	buffer += sizeof(ref->directory);
80
81	if (ref->device != ~(dev_t)0 && size > sizeof(ref->device)
82			+ sizeof(ref->directory)) {
83		ref->set_name(buffer);
84		if (ref->name == NULL) {
85			*ref = entry_ref();
86			return B_NO_MEMORY;
87		}
88	} else
89		ref->set_name(NULL);
90
91	return B_OK;
92}
93
94
95status_t
96entry_ref_swap(char *buffer, size_t size)
97{
98	if (size < sizeof(dev_t) + sizeof(ino_t))
99		return B_BAD_VALUE;
100
101	dev_t *dev = (dev_t *)buffer;
102	*dev = B_SWAP_INT32(*dev);
103	buffer += sizeof(dev_t);
104
105	ino_t *ino = (ino_t *)buffer;
106	*ino = B_SWAP_INT64(*ino);
107
108	return B_OK;
109}
110
111
112/* node_ref support functions */
113status_t
114node_ref_flatten(char *buffer, size_t *size, const node_ref *ref)
115{
116	if (*size < sizeof(dev_t) + sizeof(ino_t))
117		return B_BUFFER_OVERFLOW;
118
119	memcpy((void *)buffer, (const void *)&ref->device, sizeof(ref->device));
120	buffer += sizeof(ref->device);
121	memcpy((void *)buffer, (const void *)&ref->node, sizeof(ref->node));
122	buffer += sizeof(ref->node);
123
124	return B_OK;
125}
126
127
128status_t
129node_ref_unflatten(node_ref *ref, const char *buffer, size_t size)
130{
131	if (size < sizeof(dev_t) + sizeof(ino_t)) {
132		*ref = node_ref();
133		return B_BAD_VALUE;
134	}
135
136	memcpy((void *)&ref->device, (const void *)buffer, sizeof(dev_t));
137	buffer += sizeof(dev_t);
138	memcpy((void *)&ref->node, (const void *)buffer, sizeof(ino_t));
139	buffer += sizeof(ino_t);
140
141	return B_OK;
142}
143
144
145status_t
146node_ref_swap(char *buffer, size_t size)
147{
148	if (size < sizeof(dev_t) + sizeof(ino_t))
149		return B_BAD_VALUE;
150
151	dev_t *dev = (dev_t *)buffer;
152	*dev = B_SWAP_INT32(*dev);
153	buffer += sizeof(dev_t);
154
155	ino_t *ino = (ino_t *)buffer;
156	*ino = B_SWAP_INT64(*ino);
157
158	return B_OK;
159}
160
161} // namespace BPrivate
162