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/>.
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.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 size_t ea_list_size(unsigned int num_eas
, struct ea_struct
*eas
)
31 unsigned int total
= 4;
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 ea name list will consume.
42 static unsigned int ea_name_list_size(unsigned int num_names
, struct ea_name
*eas
)
44 unsigned int total
= 4;
46 for (i
=0;i
<num_names
;i
++) {
47 total
+= 1 + strlen(eas
[i
].name
.s
) + 1;
53 work out how many bytes on the wire a chained ea list will consume.
54 This assumes the names are strict ascii, which should be a
57 size_t ea_list_size_chained(unsigned int num_eas
, struct ea_struct
*eas
, unsigned alignment
)
59 unsigned int total
= 0;
61 for (i
=0;i
<num_eas
;i
++) {
62 unsigned int len
= 8 + strlen(eas
[i
].name
.s
)+1 + eas
[i
].value
.length
;
63 len
= (len
+ (alignment
-1)) & ~(alignment
-1);
70 put a ea_list into a pre-allocated buffer - buffer must be at least
71 of size ea_list_size()
73 void ea_put_list(uint8_t *data
, unsigned int num_eas
, struct ea_struct
*eas
)
78 ea_size
= ea_list_size(num_eas
, eas
);
80 SIVAL(data
, 0, ea_size
);
83 for (i
=0;i
<num_eas
;i
++) {
84 unsigned int nlen
= strlen(eas
[i
].name
.s
);
85 SCVAL(data
, 0, eas
[i
].flags
);
87 SSVAL(data
, 2, eas
[i
].value
.length
);
88 memcpy(data
+4, eas
[i
].name
.s
, nlen
+1);
89 if (eas
[i
].value
.length
> 0) {
90 memcpy(data
+ 4 + nlen
+ 1,
94 data
+= 4+nlen
+1+eas
[i
].value
.length
;
100 put a chained ea_list into a pre-allocated buffer - buffer must be
101 at least of size ea_list_size()
103 void ea_put_list_chained(uint8_t *data
, unsigned int num_eas
, struct ea_struct
*eas
,
108 for (i
=0;i
<num_eas
;i
++) {
109 unsigned int nlen
= strlen(eas
[i
].name
.s
);
110 uint32_t len
= 8+nlen
+1+eas
[i
].value
.length
;
111 unsigned int pad
= ((len
+ (alignment
-1)) & ~(alignment
-1)) - len
;
112 if (i
== num_eas
-1) {
115 SIVAL(data
, 0, len
+pad
);
117 SCVAL(data
, 4, eas
[i
].flags
);
118 SCVAL(data
, 5, nlen
);
119 SSVAL(data
, 6, eas
[i
].value
.length
);
120 memcpy(data
+8, eas
[i
].name
.s
, nlen
+1);
121 memcpy(data
+8+nlen
+1, eas
[i
].value
.data
, eas
[i
].value
.length
);
122 memset(data
+len
, 0, pad
);
129 pull a ea_struct from a buffer. Return the number of bytes consumed
131 unsigned int ea_pull_struct(const DATA_BLOB
*blob
,
133 struct ea_struct
*ea
)
140 if (blob
->length
< 6) {
144 ea
->flags
= CVAL(blob
->data
, 0);
145 nlen
= CVAL(blob
->data
, 1);
146 vlen
= SVAL(blob
->data
, 2);
148 if (nlen
+1+vlen
> blob
->length
-4) {
152 ea
->name
.s
= talloc_strndup(mem_ctx
, (const char *)(blob
->data
+4), nlen
);
153 ea
->name
.private_length
= nlen
;
154 ea
->value
= data_blob_talloc(mem_ctx
, NULL
, vlen
+1);
155 if (!ea
->value
.data
) return 0;
157 memcpy(ea
->value
.data
, blob
->data
+4+nlen
+1, vlen
);
159 ea
->value
.data
[vlen
] = 0;
162 return 4 + nlen
+1 + vlen
;
167 pull a ea_list from a buffer
169 NTSTATUS
ea_pull_list(const DATA_BLOB
*blob
,
171 unsigned int *num_eas
, struct ea_struct
**eas
)
174 uint32_t ea_size
, ofs
;
176 if (blob
->length
< 4) {
177 return NT_STATUS_INFO_LENGTH_MISMATCH
;
180 ea_size
= IVAL(blob
->data
, 0);
181 if (ea_size
> blob
->length
) {
182 return NT_STATUS_INVALID_PARAMETER
;
190 while (ofs
< ea_size
) {
194 blob2
.data
= blob
->data
+ ofs
;
195 blob2
.length
= ea_size
- ofs
;
197 *eas
= talloc_realloc(mem_ctx
, *eas
, struct ea_struct
, n
+1);
198 if (! *eas
) return NT_STATUS_NO_MEMORY
;
200 len
= ea_pull_struct(&blob2
, mem_ctx
, &(*eas
)[n
]);
202 return NT_STATUS_INVALID_PARAMETER
;
216 pull a chained ea_list from a buffer
218 NTSTATUS
ea_pull_list_chained(const DATA_BLOB
*blob
,
220 unsigned int *num_eas
, struct ea_struct
**eas
)
225 if (blob
->length
< 4) {
226 return NT_STATUS_INFO_LENGTH_MISMATCH
;
234 while (ofs
< blob
->length
) {
237 uint32_t next_ofs
= IVAL(blob
->data
, ofs
);
239 blob2
.data
= blob
->data
+ ofs
+ 4;
240 blob2
.length
= blob
->length
- (ofs
+ 4);
242 *eas
= talloc_realloc(mem_ctx
, *eas
, struct ea_struct
, n
+1);
243 if (! *eas
) return NT_STATUS_NO_MEMORY
;
245 len
= ea_pull_struct(&blob2
, mem_ctx
, &(*eas
)[n
]);
247 return NT_STATUS_INVALID_PARAMETER
;
250 if (ofs
+ next_ofs
< ofs
) {
251 return NT_STATUS_INVALID_PARAMETER
;
255 if (ofs
+4 > blob
->length
|| ofs
+4 < ofs
) {
256 return NT_STATUS_INVALID_PARAMETER
;
259 if (next_ofs
== 0) break;
269 pull a ea_name from a buffer. Return the number of bytes consumed
271 static unsigned int ea_pull_name(const DATA_BLOB
*blob
,
277 if (blob
->length
< 2) {
281 nlen
= CVAL(blob
->data
, 0);
283 if (nlen
+2 > blob
->length
) {
287 ea
->name
.s
= talloc_strndup(mem_ctx
, (const char *)(blob
->data
+1), nlen
);
288 ea
->name
.private_length
= nlen
;
295 pull a ea_name list from a buffer
297 NTSTATUS
ea_pull_name_list(const DATA_BLOB
*blob
,
299 unsigned int *num_names
, struct ea_name
**ea_names
)
302 uint32_t ea_size
, ofs
;
304 if (blob
->length
< 4) {
305 return NT_STATUS_INFO_LENGTH_MISMATCH
;
308 ea_size
= IVAL(blob
->data
, 0);
309 if (ea_size
> blob
->length
) {
310 return NT_STATUS_INVALID_PARAMETER
;
318 while (ofs
< ea_size
) {
322 blob2
.data
= blob
->data
+ ofs
;
323 blob2
.length
= ea_size
- ofs
;
325 *ea_names
= talloc_realloc(mem_ctx
, *ea_names
, struct ea_name
, n
+1);
326 if (! *ea_names
) return NT_STATUS_NO_MEMORY
;
328 len
= ea_pull_name(&blob2
, mem_ctx
, &(*ea_names
)[n
]);
330 return NT_STATUS_INVALID_PARAMETER
;
344 put a ea_name list into a data blob
346 bool ea_push_name_list(TALLOC_CTX
*mem_ctx
,
347 DATA_BLOB
*data
, unsigned int num_names
, struct ea_name
*eas
)
353 ea_size
= ea_name_list_size(num_names
, eas
);
355 *data
= data_blob_talloc(mem_ctx
, NULL
, ea_size
);
356 if (data
->data
== NULL
) {
360 SIVAL(data
->data
, 0, ea_size
);
363 for (i
=0;i
<num_names
;i
++) {
364 unsigned int nlen
= strlen(eas
[i
].name
.s
);
365 SCVAL(data
->data
, off
, nlen
);
366 memcpy(data
->data
+off
+1, eas
[i
].name
.s
, nlen
+1);