r3902: fix compiler warnings
[samba.git] / source4 / libcli / raw / raweas.c
1 /* 
2    Unix SMB/CIFS implementation.
3    parsing of EA (extended attribute) lists
4    Copyright (C) Andrew Tridgell 2003
5    
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.
10    
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.
15    
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.
19 */
20
21 #include "includes.h"
22 #include "libcli/raw/libcliraw.h"
23
24 /*
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
27   reasonable assumption
28 */
29 uint_t ea_list_size(uint_t num_eas, struct ea_struct *eas)
30 {
31         uint_t total = 4;
32         int i;
33         for (i=0;i<num_eas;i++) {
34                 total += 4 + strlen(eas[i].name.s)+1 + eas[i].value.length;
35         }
36         return total;
37 }
38
39 /*
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
42   reasonable assumption
43 */
44 uint_t ea_list_size_chained(uint_t num_eas, struct ea_struct *eas)
45 {
46         uint_t total = 0;
47         int i;
48         for (i=0;i<num_eas;i++) {
49                 uint_t len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
50                 len = (len + 3) & ~3;
51                 total += len;
52         }
53         return total;
54 }
55
56 /*
57   put a ea_list into a pre-allocated buffer - buffer must be at least
58   of size ea_list_size()
59 */
60 void ea_put_list(void *data, uint_t num_eas, struct ea_struct *eas)
61 {
62         int i;
63         uint32_t ea_size;
64
65         ea_size = ea_list_size(num_eas, eas);
66
67         SIVAL(data, 0, ea_size);
68         data += 4;
69
70         for (i=0;i<num_eas;i++) {
71                 uint_t nlen = strlen(eas[i].name.s);
72                 SCVAL(data, 0, eas[i].flags);
73                 SCVAL(data, 1, nlen);
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;
78         }
79 }
80
81
82 /*
83   put a chained ea_list into a pre-allocated buffer - buffer must be
84   at least of size ea_list_size()
85 */
86 void ea_put_list_chained(void *data, uint_t num_eas, struct ea_struct *eas)
87 {
88         int i;
89
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;
94                 if (i == num_eas-1) {
95                         SIVAL(data, 0, 0);
96                 } else {
97                         SIVAL(data, 0, len+pad);
98                 }
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);
105                 data += len + pad;
106         }
107 }
108
109
110 /*
111   pull a ea_struct from a buffer. Return the number of bytes consumed
112 */
113 uint_t ea_pull_struct(const DATA_BLOB *blob, 
114                       TALLOC_CTX *mem_ctx,
115                       struct ea_struct *ea)
116 {
117         uint8_t nlen;
118         uint16_t vlen;
119
120         if (blob->length < 6) {
121                 return 0;
122         }
123
124         ea->flags = CVAL(blob->data, 0);
125         nlen = CVAL(blob->data, 1);
126         vlen = SVAL(blob->data, 2);
127
128         if (nlen+1+vlen > blob->length-4) {
129                 return 0;
130         }
131
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;
136         if (vlen) {
137                 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
138         }
139         ea->value.data[vlen] = 0;
140         ea->value.length--;
141
142         return 4 + nlen+1 + vlen;
143 }
144
145
146 /*
147   pull a ea_list from a buffer
148 */
149 NTSTATUS ea_pull_list(const DATA_BLOB *blob, 
150                               TALLOC_CTX *mem_ctx,
151                               uint_t *num_eas, struct ea_struct **eas)
152 {
153         int n;
154         uint32_t ea_size, ofs;
155
156         if (blob->length < 4) {
157                 return NT_STATUS_INFO_LENGTH_MISMATCH;
158         }
159
160         ea_size = IVAL(blob->data, 0);
161         if (ea_size > blob->length) {
162                 return NT_STATUS_INVALID_PARAMETER;
163         }
164
165         ofs = 4;
166         n = 0;
167         *num_eas = 0;
168         *eas = NULL;
169
170         while (ofs < ea_size) {
171                 uint_t len;
172                 DATA_BLOB blob2;
173
174                 blob2.data = blob->data + ofs;
175                 blob2.length = ea_size - ofs;
176
177                 *eas = talloc_realloc(mem_ctx, *eas, sizeof(**eas) * (n+1));
178                 if (! *eas) return NT_STATUS_NO_MEMORY;
179
180                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
181                 if (len == 0) {
182                         return NT_STATUS_INVALID_PARAMETER;
183                 }
184
185                 ofs += len;
186                 n++;
187         }
188
189         *num_eas = n;
190
191         return NT_STATUS_OK;
192 }
193
194
195 /*
196   pull a chained ea_list from a buffer
197 */
198 NTSTATUS ea_pull_list_chained(const DATA_BLOB *blob, 
199                               TALLOC_CTX *mem_ctx,
200                               uint_t *num_eas, struct ea_struct **eas)
201 {
202         int n;
203         uint32_t ofs;
204
205         if (blob->length < 4) {
206                 return NT_STATUS_INFO_LENGTH_MISMATCH;
207         }
208
209         ofs = 0;
210         n = 0;
211         *num_eas = 0;
212         *eas = NULL;
213
214         while (ofs < blob->length) {
215                 uint_t len;
216                 DATA_BLOB blob2;
217                 uint32_t next_ofs = IVAL(blob->data, ofs);
218
219                 blob2.data = blob->data + ofs + 4;
220                 blob2.length = blob->length - (ofs + 4);
221
222                 *eas = talloc_realloc(mem_ctx, *eas, sizeof(**eas) * (n+1));
223                 if (! *eas) return NT_STATUS_NO_MEMORY;
224
225                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
226                 if (len == 0) {
227                         return NT_STATUS_INVALID_PARAMETER;
228                 }
229
230                 ofs += next_ofs;
231
232                 if (ofs+4 > blob->length) {
233                         return NT_STATUS_INVALID_PARAMETER;
234                 }
235                 n++;
236                 if (next_ofs == 0) break;
237         }
238
239         *num_eas = n;
240
241         return NT_STATUS_OK;
242 }
243
244
245