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/>.
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.h"
26 work out how many bytes on the wire a ea list will consume.
27 This assumes the names are strict ascii, which should be a
30 size_t ea_list_size(uint_t num_eas
, struct ea_struct
*eas
)
34 for (i
=0;i
<num_eas
;i
++) {
35 total
+= 4 + strlen(eas
[i
].name
.s
)+1 + eas
[i
].value
.length
;
41 work out how many bytes on the wire a ea name list will consume.
43 static uint_t
ea_name_list_size(uint_t num_names
, struct ea_name
*eas
)
47 for (i
=0;i
<num_names
;i
++) {
48 total
+= 1 + strlen(eas
[i
].name
.s
) + 1;
54 work out how many bytes on the wire a chained ea list will consume.
55 This assumes the names are strict ascii, which should be a
58 size_t ea_list_size_chained(uint_t num_eas
, struct ea_struct
*eas
, unsigned alignment
)
62 for (i
=0;i
<num_eas
;i
++) {
63 uint_t len
= 8 + strlen(eas
[i
].name
.s
)+1 + eas
[i
].value
.length
;
64 len
= (len
+ (alignment
-1)) & ~(alignment
-1);
71 put a ea_list into a pre-allocated buffer - buffer must be at least
72 of size ea_list_size()
74 void ea_put_list(uint8_t *data
, uint_t num_eas
, struct ea_struct
*eas
)
79 ea_size
= ea_list_size(num_eas
, eas
);
81 SIVAL(data
, 0, ea_size
);
84 for (i
=0;i
<num_eas
;i
++) {
85 uint_t nlen
= strlen(eas
[i
].name
.s
);
86 SCVAL(data
, 0, eas
[i
].flags
);
88 SSVAL(data
, 2, eas
[i
].value
.length
);
89 memcpy(data
+4, eas
[i
].name
.s
, nlen
+1);
90 memcpy(data
+4+nlen
+1, eas
[i
].value
.data
, eas
[i
].value
.length
);
91 data
+= 4+nlen
+1+eas
[i
].value
.length
;
97 put a chained ea_list into a pre-allocated buffer - buffer must be
98 at least of size ea_list_size()
100 void ea_put_list_chained(uint8_t *data
, uint_t num_eas
, struct ea_struct
*eas
,
105 for (i
=0;i
<num_eas
;i
++) {
106 uint_t nlen
= strlen(eas
[i
].name
.s
);
107 uint32_t len
= 8+nlen
+1+eas
[i
].value
.length
;
108 uint_t pad
= ((len
+ (alignment
-1)) & ~(alignment
-1)) - len
;
109 if (i
== num_eas
-1) {
112 SIVAL(data
, 0, len
+pad
);
114 SCVAL(data
, 4, eas
[i
].flags
);
115 SCVAL(data
, 5, nlen
);
116 SSVAL(data
, 6, eas
[i
].value
.length
);
117 memcpy(data
+8, eas
[i
].name
.s
, nlen
+1);
118 memcpy(data
+8+nlen
+1, eas
[i
].value
.data
, eas
[i
].value
.length
);
119 memset(data
+len
, 0, pad
);
126 pull a ea_struct from a buffer. Return the number of bytes consumed
128 uint_t
ea_pull_struct(const DATA_BLOB
*blob
,
130 struct ea_struct
*ea
)
137 if (blob
->length
< 6) {
141 ea
->flags
= CVAL(blob
->data
, 0);
142 nlen
= CVAL(blob
->data
, 1);
143 vlen
= SVAL(blob
->data
, 2);
145 if (nlen
+1+vlen
> blob
->length
-4) {
149 ea
->name
.s
= talloc_strndup(mem_ctx
, (const char *)(blob
->data
+4), nlen
);
150 ea
->name
.private_length
= nlen
;
151 ea
->value
= data_blob_talloc(mem_ctx
, NULL
, vlen
+1);
152 if (!ea
->value
.data
) return 0;
154 memcpy(ea
->value
.data
, blob
->data
+4+nlen
+1, vlen
);
156 ea
->value
.data
[vlen
] = 0;
159 return 4 + nlen
+1 + vlen
;
164 pull a ea_list from a buffer
166 NTSTATUS
ea_pull_list(const DATA_BLOB
*blob
,
168 uint_t
*num_eas
, struct ea_struct
**eas
)
171 uint32_t ea_size
, ofs
;
173 if (blob
->length
< 4) {
174 return NT_STATUS_INFO_LENGTH_MISMATCH
;
177 ea_size
= IVAL(blob
->data
, 0);
178 if (ea_size
> blob
->length
) {
179 return NT_STATUS_INVALID_PARAMETER
;
187 while (ofs
< ea_size
) {
191 blob2
.data
= blob
->data
+ ofs
;
192 blob2
.length
= ea_size
- ofs
;
194 *eas
= talloc_realloc(mem_ctx
, *eas
, struct ea_struct
, n
+1);
195 if (! *eas
) return NT_STATUS_NO_MEMORY
;
197 len
= ea_pull_struct(&blob2
, mem_ctx
, &(*eas
)[n
]);
199 return NT_STATUS_INVALID_PARAMETER
;
213 pull a chained ea_list from a buffer
215 NTSTATUS
ea_pull_list_chained(const DATA_BLOB
*blob
,
217 uint_t
*num_eas
, struct ea_struct
**eas
)
222 if (blob
->length
< 4) {
223 return NT_STATUS_INFO_LENGTH_MISMATCH
;
231 while (ofs
< blob
->length
) {
234 uint32_t next_ofs
= IVAL(blob
->data
, ofs
);
236 blob2
.data
= blob
->data
+ ofs
+ 4;
237 blob2
.length
= blob
->length
- (ofs
+ 4);
239 *eas
= talloc_realloc(mem_ctx
, *eas
, struct ea_struct
, n
+1);
240 if (! *eas
) return NT_STATUS_NO_MEMORY
;
242 len
= ea_pull_struct(&blob2
, mem_ctx
, &(*eas
)[n
]);
244 return NT_STATUS_INVALID_PARAMETER
;
249 if (ofs
+4 > blob
->length
) {
250 return NT_STATUS_INVALID_PARAMETER
;
253 if (next_ofs
== 0) break;
263 pull a ea_name from a buffer. Return the number of bytes consumed
265 static uint_t
ea_pull_name(const DATA_BLOB
*blob
,
271 if (blob
->length
< 2) {
275 nlen
= CVAL(blob
->data
, 0);
277 if (nlen
+2 > blob
->length
) {
281 ea
->name
.s
= talloc_strndup(mem_ctx
, (const char *)(blob
->data
+1), nlen
);
282 ea
->name
.private_length
= nlen
;
289 pull a ea_name list from a buffer
291 NTSTATUS
ea_pull_name_list(const DATA_BLOB
*blob
,
293 uint_t
*num_names
, struct ea_name
**ea_names
)
296 uint32_t ea_size
, ofs
;
298 if (blob
->length
< 4) {
299 return NT_STATUS_INFO_LENGTH_MISMATCH
;
302 ea_size
= IVAL(blob
->data
, 0);
303 if (ea_size
> blob
->length
) {
304 return NT_STATUS_INVALID_PARAMETER
;
312 while (ofs
< ea_size
) {
316 blob2
.data
= blob
->data
+ ofs
;
317 blob2
.length
= ea_size
- ofs
;
319 *ea_names
= talloc_realloc(mem_ctx
, *ea_names
, struct ea_name
, n
+1);
320 if (! *ea_names
) return NT_STATUS_NO_MEMORY
;
322 len
= ea_pull_name(&blob2
, mem_ctx
, &(*ea_names
)[n
]);
324 return NT_STATUS_INVALID_PARAMETER
;
338 put a ea_name list into a data blob
340 bool ea_push_name_list(TALLOC_CTX
*mem_ctx
,
341 DATA_BLOB
*data
, uint_t num_names
, struct ea_name
*eas
)
347 ea_size
= ea_name_list_size(num_names
, eas
);
349 *data
= data_blob_talloc(mem_ctx
, NULL
, ea_size
);
350 if (data
->data
== NULL
) {
354 SIVAL(data
->data
, 0, ea_size
);
357 for (i
=0;i
<num_names
;i
++) {
358 uint_t nlen
= strlen(eas
[i
].name
.s
);
359 SCVAL(data
->data
, off
, nlen
);
360 memcpy(data
->data
+off
+1, eas
[i
].name
.s
, nlen
+1);