52c7832a6cae47e61e920f7e3c5bda543dee0667
[sfrench/samba-autobuild/.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   put a ea_list into a pre-allocated buffer - buffer must be at least
41   of size ea_list_size()
42 */
43 void ea_put_list(char *data, uint_t num_eas, struct ea_struct *eas)
44 {
45         int i;
46         uint32_t ea_size;
47
48         ea_size = ea_list_size(num_eas, eas);
49
50         SIVAL(data, 0, ea_size);
51         data += 4;
52
53         for (i=0;i<num_eas;i++) {
54                 uint_t nlen = strlen(eas[i].name.s);
55                 SCVAL(data, 0, eas[i].flags);
56                 SCVAL(data, 1, nlen);
57                 SSVAL(data, 2, eas[i].value.length);
58                 memcpy(data+4, eas[i].name.s, nlen+1);
59                 memcpy(data+4+nlen+1, eas[i].value.data, eas[i].value.length);
60                 data += 4+nlen+1+eas[i].value.length;
61         }
62 }
63
64
65 /*
66   pull a ea_struct from a buffer. Return the number of bytes consumed
67 */
68 uint_t ea_pull_struct(const DATA_BLOB *blob, 
69                       TALLOC_CTX *mem_ctx,
70                       struct ea_struct *ea)
71 {
72         uint8_t nlen;
73         uint16_t vlen;
74
75         if (blob->length < 6) {
76                 return 0;
77         }
78
79         ea->flags = CVAL(blob->data, 0);
80         nlen = CVAL(blob->data, 1);
81         vlen = SVAL(blob->data, 2);
82
83         if (nlen+1+vlen > blob->length-4) {
84                 return 0;
85         }
86
87         ea->name.s = talloc_strndup(mem_ctx, blob->data+4, nlen);
88         ea->name.private_length = nlen;
89         ea->value = data_blob_talloc(mem_ctx, NULL, vlen+1);
90         if (!ea->value.data) return 0;
91         if (vlen) {
92                 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
93         }
94         ea->value.data[vlen] = 0;
95         ea->value.length--;
96
97         return 4 + nlen+1 + vlen;
98 }
99
100
101 /*
102   pull a ea_list from a buffer
103 */
104 NTSTATUS ea_pull_list(const DATA_BLOB *blob, 
105                       TALLOC_CTX *mem_ctx,
106                       uint_t *num_eas, struct ea_struct **eas)
107 {
108         int n;
109         uint32_t ea_size, ofs;
110
111         if (blob->length < 4) {
112                 return NT_STATUS_INFO_LENGTH_MISMATCH;
113         }
114
115         ea_size = IVAL(blob->data, 0);
116         if (ea_size > blob->length) {
117                 return NT_STATUS_INVALID_PARAMETER;
118         }
119         
120         ofs = 4;        
121         n = 0;
122         *num_eas = 0;
123         *eas = NULL;
124
125         while (ofs+6 < ea_size) {
126                 uint_t len;
127                 DATA_BLOB blob2;
128
129                 blob2.data = blob->data + ofs;
130                 blob2.length = ea_size - ofs;
131
132                 *eas = talloc_realloc(mem_ctx, *eas, sizeof(**eas) * (n+1));
133                 if (! *eas) return NT_STATUS_NO_MEMORY;
134
135                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
136                 if (len == 0) {
137                         return NT_STATUS_INVALID_PARAMETER;
138                 }
139
140                 ofs += len;
141                 n++;
142         }
143
144         *num_eas = n;
145
146         return NT_STATUS_OK;
147 }
148