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