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 3 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, see <http://www.gnu.org/licenses/>.
24 work out how many bytes on the wire a ea list will consume.
25 This assumes the names are strict ascii, which should be a
28 size_t ea_list_size(uint_t num_eas, struct ea_struct *eas)
32 for (i=0;i<num_eas;i++) {
33 total += 4 + strlen(eas[i].name.s)+1 + eas[i].value.length;
39 work out how many bytes on the wire a ea name list will consume.
41 static uint_t ea_name_list_size(uint_t num_names, struct ea_name *eas)
45 for (i=0;i<num_names;i++) {
46 total += 1 + strlen(eas[i].name.s) + 1;
52 work out how many bytes on the wire a chained ea list will consume.
53 This assumes the names are strict ascii, which should be a
56 size_t ea_list_size_chained(uint_t num_eas, struct ea_struct *eas)
60 for (i=0;i<num_eas;i++) {
61 uint_t len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
69 put a ea_list into a pre-allocated buffer - buffer must be at least
70 of size ea_list_size()
72 void ea_put_list(uint8_t *data, uint_t num_eas, struct ea_struct *eas)
77 ea_size = ea_list_size(num_eas, eas);
79 SIVAL(data, 0, ea_size);
82 for (i=0;i<num_eas;i++) {
83 uint_t nlen = strlen(eas[i].name.s);
84 SCVAL(data, 0, eas[i].flags);
86 SSVAL(data, 2, eas[i].value.length);
87 memcpy(data+4, eas[i].name.s, nlen+1);
88 memcpy(data+4+nlen+1, eas[i].value.data, eas[i].value.length);
89 data += 4+nlen+1+eas[i].value.length;
95 put a chained ea_list into a pre-allocated buffer - buffer must be
96 at least of size ea_list_size()
98 void ea_put_list_chained(uint8_t *data, uint_t num_eas, struct ea_struct *eas)
102 for (i=0;i<num_eas;i++) {
103 uint_t nlen = strlen(eas[i].name.s);
104 uint32_t len = 8+nlen+1+eas[i].value.length;
105 uint_t pad = ((len + 3) & ~3) - len;
106 if (i == num_eas-1) {
109 SIVAL(data, 0, len+pad);
111 SCVAL(data, 4, eas[i].flags);
112 SCVAL(data, 5, nlen);
113 SSVAL(data, 6, eas[i].value.length);
114 memcpy(data+8, eas[i].name.s, nlen+1);
115 memcpy(data+8+nlen+1, eas[i].value.data, eas[i].value.length);
116 memset(data+len, 0, pad);
123 pull a ea_struct from a buffer. Return the number of bytes consumed
125 uint_t ea_pull_struct(const DATA_BLOB *blob,
127 struct ea_struct *ea)
132 if (blob->length < 6) {
136 ea->flags = CVAL(blob->data, 0);
137 nlen = CVAL(blob->data, 1);
138 vlen = SVAL(blob->data, 2);
140 if (nlen+1+vlen > blob->length-4) {
144 ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+4), nlen);
145 ea->name.private_length = nlen;
146 ea->value = data_blob_talloc(mem_ctx, NULL, vlen+1);
147 if (!ea->value.data) return 0;
149 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
151 ea->value.data[vlen] = 0;
154 return 4 + nlen+1 + vlen;
159 pull a ea_list from a buffer
161 NTSTATUS ea_pull_list(const DATA_BLOB *blob,
163 uint_t *num_eas, struct ea_struct **eas)
166 uint32_t ea_size, ofs;
168 if (blob->length < 4) {
169 return NT_STATUS_INFO_LENGTH_MISMATCH;
172 ea_size = IVAL(blob->data, 0);
173 if (ea_size > blob->length) {
174 return NT_STATUS_INVALID_PARAMETER;
182 while (ofs < ea_size) {
186 blob2.data = blob->data + ofs;
187 blob2.length = ea_size - ofs;
189 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
190 if (! *eas) return NT_STATUS_NO_MEMORY;
192 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
194 return NT_STATUS_INVALID_PARAMETER;
208 pull a chained ea_list from a buffer
210 NTSTATUS ea_pull_list_chained(const DATA_BLOB *blob,
212 uint_t *num_eas, struct ea_struct **eas)
217 if (blob->length < 4) {
218 return NT_STATUS_INFO_LENGTH_MISMATCH;
226 while (ofs < blob->length) {
229 uint32_t next_ofs = IVAL(blob->data, ofs);
231 blob2.data = blob->data + ofs + 4;
232 blob2.length = blob->length - (ofs + 4);
234 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
235 if (! *eas) return NT_STATUS_NO_MEMORY;
237 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
239 return NT_STATUS_INVALID_PARAMETER;
244 if (ofs+4 > blob->length) {
245 return NT_STATUS_INVALID_PARAMETER;
248 if (next_ofs == 0) break;
258 pull a ea_name from a buffer. Return the number of bytes consumed
260 static uint_t ea_pull_name(const DATA_BLOB *blob,
266 if (blob->length < 2) {
270 nlen = CVAL(blob->data, 0);
272 if (nlen+2 > blob->length) {
276 ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+1), nlen);
277 ea->name.private_length = nlen;
284 pull a ea_name list from a buffer
286 NTSTATUS ea_pull_name_list(const DATA_BLOB *blob,
288 uint_t *num_names, struct ea_name **ea_names)
291 uint32_t ea_size, ofs;
293 if (blob->length < 4) {
294 return NT_STATUS_INFO_LENGTH_MISMATCH;
297 ea_size = IVAL(blob->data, 0);
298 if (ea_size > blob->length) {
299 return NT_STATUS_INVALID_PARAMETER;
307 while (ofs < ea_size) {
311 blob2.data = blob->data + ofs;
312 blob2.length = ea_size - ofs;
314 *ea_names = talloc_realloc(mem_ctx, *ea_names, struct ea_name, n+1);
315 if (! *ea_names) return NT_STATUS_NO_MEMORY;
317 len = ea_pull_name(&blob2, mem_ctx, &(*ea_names)[n]);
319 return NT_STATUS_INVALID_PARAMETER;
333 put a ea_name list into a data blob
335 BOOL ea_push_name_list(TALLOC_CTX *mem_ctx,
336 DATA_BLOB *data, uint_t num_names, struct ea_name *eas)
342 ea_size = ea_name_list_size(num_names, eas);
344 *data = data_blob_talloc(mem_ctx, NULL, ea_size);
345 if (data->data == NULL) {
349 SIVAL(data->data, 0, ea_size);
352 for (i=0;i<num_names;i++) {
353 uint_t nlen = strlen(eas[i].name.s);
354 SCVAL(data->data, off, nlen);
355 memcpy(data->data+off+1, eas[i].name.s, nlen+1);