2 Unix SMB/CIFS implementation.
3 parsing of EA (extended attribute) lists
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libcli/raw/libcliraw.h"
25 work out how many bytes on the wire a ea list will consume.
26 This assumes the names are strict ascii, which should be a
29 uint_t ea_list_size(uint_t num_eas, struct ea_struct *eas)
33 for (i=0;i<num_eas;i++) {
34 total += 4 + strlen(eas[i].name.s)+1 + eas[i].value.length;
40 work out how many bytes on the wire a chained ea list will consume.
41 This assumes the names are strict ascii, which should be a
44 uint_t ea_list_size_chained(uint_t num_eas, struct ea_struct *eas)
48 for (i=0;i<num_eas;i++) {
49 uint_t len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
57 put a ea_list into a pre-allocated buffer - buffer must be at least
58 of size ea_list_size()
60 void ea_put_list(void *data, uint_t num_eas, struct ea_struct *eas)
65 ea_size = ea_list_size(num_eas, eas);
67 SIVAL(data, 0, ea_size);
70 for (i=0;i<num_eas;i++) {
71 uint_t nlen = strlen(eas[i].name.s);
72 SCVAL(data, 0, eas[i].flags);
74 SSVAL(data, 2, eas[i].value.length);
75 memcpy(data+4, eas[i].name.s, nlen+1);
76 memcpy(data+4+nlen+1, eas[i].value.data, eas[i].value.length);
77 data += 4+nlen+1+eas[i].value.length;
83 put a chained ea_list into a pre-allocated buffer - buffer must be
84 at least of size ea_list_size()
86 void ea_put_list_chained(void *data, uint_t num_eas, struct ea_struct *eas)
90 for (i=0;i<num_eas;i++) {
91 uint_t nlen = strlen(eas[i].name.s);
92 uint32_t len = 8+nlen+1+eas[i].value.length;
93 uint_t pad = ((len + 3) & ~3) - len;
97 SIVAL(data, 0, len+pad);
99 SCVAL(data, 4, eas[i].flags);
100 SCVAL(data, 5, nlen);
101 SSVAL(data, 6, eas[i].value.length);
102 memcpy(data+8, eas[i].name.s, nlen+1);
103 memcpy(data+8+nlen+1, eas[i].value.data, eas[i].value.length);
104 memset(data+len, 0, pad);
111 pull a ea_struct from a buffer. Return the number of bytes consumed
113 uint_t ea_pull_struct(const DATA_BLOB *blob,
115 struct ea_struct *ea)
120 if (blob->length < 6) {
124 ea->flags = CVAL(blob->data, 0);
125 nlen = CVAL(blob->data, 1);
126 vlen = SVAL(blob->data, 2);
128 if (nlen+1+vlen > blob->length-4) {
132 ea->name.s = talloc_strndup(mem_ctx, blob->data+4, nlen);
133 ea->name.private_length = nlen;
134 ea->value = data_blob_talloc(mem_ctx, NULL, vlen+1);
135 if (!ea->value.data) return 0;
137 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
139 ea->value.data[vlen] = 0;
142 return 4 + nlen+1 + vlen;
147 pull a ea_list from a buffer
149 NTSTATUS ea_pull_list(const DATA_BLOB *blob,
151 uint_t *num_eas, struct ea_struct **eas)
154 uint32_t ea_size, ofs;
156 if (blob->length < 4) {
157 return NT_STATUS_INFO_LENGTH_MISMATCH;
160 ea_size = IVAL(blob->data, 0);
161 if (ea_size > blob->length) {
162 return NT_STATUS_INVALID_PARAMETER;
170 while (ofs < ea_size) {
174 blob2.data = blob->data + ofs;
175 blob2.length = ea_size - ofs;
177 *eas = talloc_realloc(mem_ctx, *eas, sizeof(**eas) * (n+1));
178 if (! *eas) return NT_STATUS_NO_MEMORY;
180 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
182 return NT_STATUS_INVALID_PARAMETER;
196 pull a chained ea_list from a buffer
198 NTSTATUS ea_pull_list_chained(const DATA_BLOB *blob,
200 uint_t *num_eas, struct ea_struct **eas)
205 if (blob->length < 4) {
206 return NT_STATUS_INFO_LENGTH_MISMATCH;
214 while (ofs < blob->length) {
217 uint32_t next_ofs = IVAL(blob->data, ofs);
219 blob2.data = blob->data + ofs + 4;
220 blob2.length = blob->length - (ofs + 4);
222 *eas = talloc_realloc(mem_ctx, *eas, sizeof(**eas) * (n+1));
223 if (! *eas) return NT_STATUS_NO_MEMORY;
225 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
227 return NT_STATUS_INVALID_PARAMETER;
232 if (ofs+4 > blob->length) {
233 return NT_STATUS_INVALID_PARAMETER;
236 if (next_ofs == 0) break;