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 memcpy(data
+4+nlen
+1, eas
[i
].value
.data
, eas
[i
].value
.length
);
90 data
+= 4+nlen
+1+eas
[i
].value
.length
;
96 put a chained ea_list into a pre-allocated buffer - buffer must be
97 at least of size ea_list_size()
99 void ea_put_list_chained(uint8_t *data
, unsigned int num_eas
, struct ea_struct
*eas
,
104 for (i
=0;i
<num_eas
;i
++) {
105 unsigned int nlen
= strlen(eas
[i
].name
.s
);
106 uint32_t len
= 8+nlen
+1+eas
[i
].value
.length
;
107 unsigned int pad
= ((len
+ (alignment
-1)) & ~(alignment
-1)) - len
;
108 if (i
== num_eas
-1) {
111 SIVAL(data
, 0, len
+pad
);
113 SCVAL(data
, 4, eas
[i
].flags
);
114 SCVAL(data
, 5, nlen
);
115 SSVAL(data
, 6, eas
[i
].value
.length
);
116 memcpy(data
+8, eas
[i
].name
.s
, nlen
+1);
117 memcpy(data
+8+nlen
+1, eas
[i
].value
.data
, eas
[i
].value
.length
);
118 memset(data
+len
, 0, pad
);
125 pull a ea_struct from a buffer. Return the number of bytes consumed
127 unsigned int ea_pull_struct(const DATA_BLOB
*blob
,
129 struct ea_struct
*ea
)
136 if (blob
->length
< 6) {
140 ea
->flags
= CVAL(blob
->data
, 0);
141 nlen
= CVAL(blob
->data
, 1);
142 vlen
= SVAL(blob
->data
, 2);
144 if (nlen
+1+vlen
> blob
->length
-4) {
148 ea
->name
.s
= talloc_strndup(mem_ctx
, (const char *)(blob
->data
+4), nlen
);
149 ea
->name
.private_length
= nlen
;
150 ea
->value
= data_blob_talloc(mem_ctx
, NULL
, vlen
+1);
151 if (!ea
->value
.data
) return 0;
153 memcpy(ea
->value
.data
, blob
->data
+4+nlen
+1, vlen
);
155 ea
->value
.data
[vlen
] = 0;
158 return 4 + nlen
+1 + vlen
;
163 pull a ea_list from a buffer
165 NTSTATUS
ea_pull_list(const DATA_BLOB
*blob
,
167 unsigned int *num_eas
, struct ea_struct
**eas
)
170 uint32_t ea_size
, ofs
;
172 if (blob
->length
< 4) {
173 return NT_STATUS_INFO_LENGTH_MISMATCH
;
176 ea_size
= IVAL(blob
->data
, 0);
177 if (ea_size
> blob
->length
) {
178 return NT_STATUS_INVALID_PARAMETER
;
186 while (ofs
< ea_size
) {
190 blob2
.data
= blob
->data
+ ofs
;
191 blob2
.length
= ea_size
- ofs
;
193 *eas
= talloc_realloc(mem_ctx
, *eas
, struct ea_struct
, n
+1);
194 if (! *eas
) return NT_STATUS_NO_MEMORY
;
196 len
= ea_pull_struct(&blob2
, mem_ctx
, &(*eas
)[n
]);
198 return NT_STATUS_INVALID_PARAMETER
;
212 pull a chained ea_list from a buffer
214 NTSTATUS
ea_pull_list_chained(const DATA_BLOB
*blob
,
216 unsigned int *num_eas
, struct ea_struct
**eas
)
221 if (blob
->length
< 4) {
222 return NT_STATUS_INFO_LENGTH_MISMATCH
;
230 while (ofs
< blob
->length
) {
233 uint32_t next_ofs
= IVAL(blob
->data
, ofs
);
235 blob2
.data
= blob
->data
+ ofs
+ 4;
236 blob2
.length
= blob
->length
- (ofs
+ 4);
238 *eas
= talloc_realloc(mem_ctx
, *eas
, struct ea_struct
, n
+1);
239 if (! *eas
) return NT_STATUS_NO_MEMORY
;
241 len
= ea_pull_struct(&blob2
, mem_ctx
, &(*eas
)[n
]);
243 return NT_STATUS_INVALID_PARAMETER
;
246 if (ofs
+ next_ofs
< ofs
) {
247 return NT_STATUS_INVALID_PARAMETER
;
251 if (ofs
+4 > blob
->length
|| ofs
+4 < ofs
) {
252 return NT_STATUS_INVALID_PARAMETER
;
255 if (next_ofs
== 0) break;
265 pull a ea_name from a buffer. Return the number of bytes consumed
267 static unsigned int ea_pull_name(const DATA_BLOB
*blob
,
273 if (blob
->length
< 2) {
277 nlen
= CVAL(blob
->data
, 0);
279 if (nlen
+2 > blob
->length
) {
283 ea
->name
.s
= talloc_strndup(mem_ctx
, (const char *)(blob
->data
+1), nlen
);
284 ea
->name
.private_length
= nlen
;
291 pull a ea_name list from a buffer
293 NTSTATUS
ea_pull_name_list(const DATA_BLOB
*blob
,
295 unsigned int *num_names
, struct ea_name
**ea_names
)
298 uint32_t ea_size
, ofs
;
300 if (blob
->length
< 4) {
301 return NT_STATUS_INFO_LENGTH_MISMATCH
;
304 ea_size
= IVAL(blob
->data
, 0);
305 if (ea_size
> blob
->length
) {
306 return NT_STATUS_INVALID_PARAMETER
;
314 while (ofs
< ea_size
) {
318 blob2
.data
= blob
->data
+ ofs
;
319 blob2
.length
= ea_size
- ofs
;
321 *ea_names
= talloc_realloc(mem_ctx
, *ea_names
, struct ea_name
, n
+1);
322 if (! *ea_names
) return NT_STATUS_NO_MEMORY
;
324 len
= ea_pull_name(&blob2
, mem_ctx
, &(*ea_names
)[n
]);
326 return NT_STATUS_INVALID_PARAMETER
;
340 put a ea_name list into a data blob
342 bool ea_push_name_list(TALLOC_CTX
*mem_ctx
,
343 DATA_BLOB
*data
, unsigned int num_names
, struct ea_name
*eas
)
349 ea_size
= ea_name_list_size(num_names
, eas
);
351 *data
= data_blob_talloc(mem_ctx
, NULL
, ea_size
);
352 if (data
->data
== NULL
) {
356 SIVAL(data
->data
, 0, ea_size
);
359 for (i
=0;i
<num_names
;i
++) {
360 unsigned int nlen
= strlen(eas
[i
].name
.s
);
361 SCVAL(data
->data
, off
, nlen
);
362 memcpy(data
->data
+off
+1, eas
[i
].name
.s
, nlen
+1);