r16671: allow usage of smbsrv_pull_passthru_sfileinfo() without,
[nivanova/samba-autobuild/.git] / source4 / smb_server / blob.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Andrew Tridgell 2003
5    Copyright (C) Stefan Metzmacher 2006
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "dlinklist.h"
24 #include "smb_server/smb_server.h"
25 #include "librpc/gen_ndr/ndr_misc.h"
26 #include "ntvfs/ntvfs.h"
27 #include "libcli/raw/libcliraw.h"
28
29 #define BLOB_CHECK(cmd) do { \
30         NTSTATUS _status; \
31         _status = cmd; \
32         NT_STATUS_NOT_OK_RETURN(_status); \
33 } while (0)
34
35 #define BLOB_CHECK_MIN_SIZE(blob, size) do { \
36         if ((blob)->length < (size)) { \
37                 return NT_STATUS_INFO_LENGTH_MISMATCH; \
38         } \
39 } while (0)
40
41 /* grow the data size of a trans2 reply */
42 NTSTATUS smbsrv_blob_grow_data(TALLOC_CTX *mem_ctx,
43                                DATA_BLOB *blob,
44                                uint32_t new_size)
45 {
46         if (new_size > blob->length) {
47                 uint8_t *p;
48                 p = talloc_realloc(mem_ctx, blob->data, uint8_t, new_size);
49                 NT_STATUS_HAVE_NO_MEMORY(p);
50                 blob->data = p;
51         }
52         blob->length = new_size;
53         return NT_STATUS_OK;
54 }
55
56 /* grow the data, zero filling any new bytes */
57 NTSTATUS smbsrv_blob_fill_data(TALLOC_CTX *mem_ctx,
58                                DATA_BLOB *blob,
59                                uint32_t new_size)
60 {
61         uint32_t old_size = blob->length;
62         BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, new_size));
63         if (new_size > old_size) {
64                 memset(blob->data + old_size, 0, new_size - old_size);
65         }
66         return NT_STATUS_OK;
67 }
68
69 /*
70   pull a string from a blob in a trans2 request
71 */
72 size_t smbsrv_blob_pull_string(struct smbsrv_request *req, 
73                                const DATA_BLOB *blob,
74                                uint16_t offset,
75                                const char **str,
76                                int flags)
77 {
78         *str = NULL;
79         /* we use STR_NO_RANGE_CHECK because the params are allocated
80            separately in a DATA_BLOB, so we need to do our own range
81            checking */
82         if (offset >= blob->length) {
83                 return 0;
84         }
85         
86         return req_pull_string(req, str, 
87                                blob->data + offset, 
88                                blob->length - offset,
89                                STR_NO_RANGE_CHECK | flags);
90 }
91
92 /*
93   push a string into the data section of a trans2 request
94   return the number of bytes consumed in the output
95 */
96 size_t smbsrv_blob_push_string(TALLOC_CTX *mem_ctx,
97                                DATA_BLOB *blob,
98                                uint32_t len_offset,
99                                uint32_t offset,
100                                const char *str,
101                                int dest_len,
102                                int default_flags,
103                                int flags)
104 {
105         int alignment = 0, ret = 0, pkt_len;
106
107         /* we use STR_NO_RANGE_CHECK because the params are allocated
108            separately in a DATA_BLOB, so we need to do our own range
109            checking */
110         if (!str || offset >= blob->length) {
111                 if (flags & STR_LEN8BIT) {
112                         SCVAL(blob->data, len_offset, 0);
113                 } else {
114                         SIVAL(blob->data, len_offset, 0);
115                 }
116                 return 0;
117         }
118
119         flags |= STR_NO_RANGE_CHECK;
120
121         if (dest_len == -1 || (dest_len > blob->length - offset)) {
122                 dest_len = blob->length - offset;
123         }
124
125         if (!(flags & (STR_ASCII|STR_UNICODE))) {
126                 flags |= default_flags;
127         }
128
129         if ((offset&1) && (flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
130                 alignment = 1;
131                 if (dest_len > 0) {
132                         SCVAL(blob->data + offset, 0, 0);
133                         ret = push_string(blob->data + offset + 1, str, dest_len-1, flags);
134                 }
135         } else {
136                 ret = push_string(blob->data + offset, str, dest_len, flags);
137         }
138
139         /* sometimes the string needs to be terminated, but the length
140            on the wire must not include the termination! */
141         pkt_len = ret;
142
143         if ((flags & STR_LEN_NOTERM) && (flags & STR_TERMINATE)) {
144                 if ((flags & STR_UNICODE) && ret >= 2) {
145                         pkt_len = ret-2;
146                 }
147                 if ((flags & STR_ASCII) && ret >= 1) {
148                         pkt_len = ret-1;
149                 }
150         }
151
152         if (flags & STR_LEN8BIT) {
153                 SCVAL(blob->data, len_offset, pkt_len);
154         } else {
155                 SIVAL(blob->data, len_offset, pkt_len);
156         }
157
158         return ret + alignment;
159 }
160
161 /*
162   append a string to the data section of a trans2 reply
163   len_offset points to the place in the packet where the length field
164   should go
165 */
166 NTSTATUS smbsrv_blob_append_string(TALLOC_CTX *mem_ctx,
167                                    DATA_BLOB *blob,
168                                    const char *str,
169                                    uint_t len_offset,
170                                    int default_flags,
171                                    int flags)
172 {
173         size_t ret;
174         uint32_t offset;
175         const int max_bytes_per_char = 3;
176
177         offset = blob->length;
178         BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, offset + (2+strlen_m(str))*max_bytes_per_char));
179         ret = smbsrv_blob_push_string(mem_ctx, blob, len_offset, offset, str, -1, default_flags, flags);
180         if (ret < 0) {
181                 return NT_STATUS_FOOBAR;
182         }
183         BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, offset + ret));
184         return NT_STATUS_OK;
185 }
186
187 NTSTATUS smbsrv_push_passthru_fsinfo(TALLOC_CTX *mem_ctx,
188                                      DATA_BLOB *blob,
189                                      enum smb_fsinfo_level level,
190                                      union smb_fsinfo *fsinfo,
191                                      int default_str_flags)
192 {
193         uint_t i;
194         DATA_BLOB guid_blob;
195
196         switch (level) {
197         case RAW_QFS_VOLUME_INFORMATION:
198                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 18));
199
200                 push_nttime(blob->data, 0, fsinfo->volume_info.out.create_time);
201                 SIVAL(blob->data,       8, fsinfo->volume_info.out.serial_number);
202                 SSVAL(blob->data,      16, 0); /* padding */
203                 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
204                                                      fsinfo->volume_info.out.volume_name.s,
205                                                      12, default_str_flags,
206                                                      STR_UNICODE));
207
208                 return NT_STATUS_OK;
209
210         case RAW_QFS_SIZE_INFORMATION:
211                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));
212
213                 SBVAL(blob->data,  0, fsinfo->size_info.out.total_alloc_units);
214                 SBVAL(blob->data,  8, fsinfo->size_info.out.avail_alloc_units);
215                 SIVAL(blob->data, 16, fsinfo->size_info.out.sectors_per_unit);
216                 SIVAL(blob->data, 20, fsinfo->size_info.out.bytes_per_sector);
217
218                 return NT_STATUS_OK;
219
220         case RAW_QFS_DEVICE_INFORMATION:
221                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
222
223                 SIVAL(blob->data,      0, fsinfo->device_info.out.device_type);
224                 SIVAL(blob->data,      4, fsinfo->device_info.out.characteristics);
225
226                 return NT_STATUS_OK;
227
228         case RAW_QFS_ATTRIBUTE_INFORMATION:
229                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 12));
230
231                 SIVAL(blob->data, 0, fsinfo->attribute_info.out.fs_attr);
232                 SIVAL(blob->data, 4, fsinfo->attribute_info.out.max_file_component_length);
233                 /* this must not be null terminated or win98 gets
234                    confused!  also note that w2k3 returns this as
235                    unicode even when ascii is negotiated */
236                 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
237                                                      fsinfo->attribute_info.out.fs_type.s,
238                                                      8, default_str_flags,
239                                                      STR_UNICODE));
240                 return NT_STATUS_OK;
241
242
243         case RAW_QFS_QUOTA_INFORMATION:
244                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 48));
245
246                 SBVAL(blob->data,   0, fsinfo->quota_information.out.unknown[0]);
247                 SBVAL(blob->data,   8, fsinfo->quota_information.out.unknown[1]);
248                 SBVAL(blob->data,  16, fsinfo->quota_information.out.unknown[2]);
249                 SBVAL(blob->data,  24, fsinfo->quota_information.out.quota_soft);
250                 SBVAL(blob->data,  32, fsinfo->quota_information.out.quota_hard);
251                 SBVAL(blob->data,  40, fsinfo->quota_information.out.quota_flags);
252
253                 return NT_STATUS_OK;
254
255
256         case RAW_QFS_FULL_SIZE_INFORMATION:
257                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 32));
258
259                 SBVAL(blob->data,  0, fsinfo->full_size_information.out.total_alloc_units);
260                 SBVAL(blob->data,  8, fsinfo->full_size_information.out.call_avail_alloc_units);
261                 SBVAL(blob->data, 16, fsinfo->full_size_information.out.actual_avail_alloc_units);
262                 SIVAL(blob->data, 24, fsinfo->full_size_information.out.sectors_per_unit);
263                 SIVAL(blob->data, 28, fsinfo->full_size_information.out.bytes_per_sector);
264
265                 return NT_STATUS_OK;
266
267         case RAW_QFS_OBJECTID_INFORMATION:
268                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 64));
269
270                 BLOB_CHECK(ndr_push_struct_blob(&guid_blob, mem_ctx, 
271                                                 &fsinfo->objectid_information.out.guid,
272                                                 (ndr_push_flags_fn_t)ndr_push_GUID));
273                 memcpy(blob->data, guid_blob.data, guid_blob.length);
274
275                 for (i=0;i<6;i++) {
276                         SBVAL(blob->data, 16 + 8*i, fsinfo->objectid_information.out.unknown[i]);
277                 }
278
279                 return NT_STATUS_OK;
280
281         default:
282                 return NT_STATUS_INVALID_LEVEL;
283         }
284
285         return NT_STATUS_INVALID_LEVEL;
286 }
287
288 NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
289                                        DATA_BLOB *blob,
290                                        enum smb_fileinfo_level level,
291                                        union smb_fileinfo *st,
292                                        int default_str_flags)
293 {
294         uint_t i;
295         size_t list_size;
296
297         switch (level) {
298         case RAW_FILEINFO_BASIC_INFORMATION:
299                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 40));
300
301                 push_nttime(blob->data,  0, st->basic_info.out.create_time);
302                 push_nttime(blob->data,  8, st->basic_info.out.access_time);
303                 push_nttime(blob->data, 16, st->basic_info.out.write_time);
304                 push_nttime(blob->data, 24, st->basic_info.out.change_time);
305                 SIVAL(blob->data,       32, st->basic_info.out.attrib);
306                 SIVAL(blob->data,       36, 0); /* padding */
307                 return NT_STATUS_OK;
308
309         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
310                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 56));
311
312                 push_nttime(blob->data,  0, st->network_open_information.out.create_time);
313                 push_nttime(blob->data,  8, st->network_open_information.out.access_time);
314                 push_nttime(blob->data, 16, st->network_open_information.out.write_time);
315                 push_nttime(blob->data, 24, st->network_open_information.out.change_time);
316                 SBVAL(blob->data,       32, st->network_open_information.out.alloc_size);
317                 SBVAL(blob->data,       40, st->network_open_information.out.size);
318                 SIVAL(blob->data,       48, st->network_open_information.out.attrib);
319                 SIVAL(blob->data,       52, 0); /* padding */
320                 return NT_STATUS_OK;
321
322         case RAW_FILEINFO_STANDARD_INFORMATION:
323                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 24));
324
325                 SBVAL(blob->data,  0, st->standard_info.out.alloc_size);
326                 SBVAL(blob->data,  8, st->standard_info.out.size);
327                 SIVAL(blob->data, 16, st->standard_info.out.nlink);
328                 SCVAL(blob->data, 20, st->standard_info.out.delete_pending);
329                 SCVAL(blob->data, 21, st->standard_info.out.directory);
330                 SSVAL(blob->data, 22, 0); /* padding */
331                 return NT_STATUS_OK;
332
333         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
334                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
335
336                 SIVAL(blob->data,  0, st->attribute_tag_information.out.attrib);
337                 SIVAL(blob->data,  4, st->attribute_tag_information.out.reparse_tag);
338                 return NT_STATUS_OK;
339
340         case RAW_FILEINFO_EA_INFORMATION:
341                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
342
343                 SIVAL(blob->data,  0, st->ea_info.out.ea_size);
344                 return NT_STATUS_OK;
345
346         case RAW_FILEINFO_MODE_INFORMATION:
347                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
348
349                 SIVAL(blob->data,  0, st->mode_information.out.mode);
350                 return NT_STATUS_OK;
351
352         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
353                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
354
355                 SIVAL(blob->data,  0, 
356                       st->alignment_information.out.alignment_requirement);
357                 return NT_STATUS_OK;
358
359         case RAW_FILEINFO_ACCESS_INFORMATION:
360                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
361
362                 SIVAL(blob->data,  0, st->access_information.out.access_flags);
363                 return NT_STATUS_OK;
364
365         case RAW_FILEINFO_POSITION_INFORMATION:
366                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
367
368                 SBVAL(blob->data,  0, st->position_information.out.position);
369                 return NT_STATUS_OK;
370
371         case RAW_FILEINFO_COMPRESSION_INFORMATION:
372                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 16));
373
374                 SBVAL(blob->data,  0, st->compression_info.out.compressed_size);
375                 SSVAL(blob->data,  8, st->compression_info.out.format);
376                 SCVAL(blob->data, 10, st->compression_info.out.unit_shift);
377                 SCVAL(blob->data, 11, st->compression_info.out.chunk_shift);
378                 SCVAL(blob->data, 12, st->compression_info.out.cluster_shift);
379                 SSVAL(blob->data, 13, 0); /* 3 bytes padding */
380                 SCVAL(blob->data, 15, 0);
381                 return NT_STATUS_OK;
382
383         case RAW_FILEINFO_INTERNAL_INFORMATION:
384                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 8));
385
386                 SBVAL(blob->data,  0, st->internal_information.out.file_id);
387                 return NT_STATUS_OK;
388
389         case RAW_FILEINFO_ALL_INFORMATION:
390                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 72));
391
392                 push_nttime(blob->data,  0, st->all_info.out.create_time);
393                 push_nttime(blob->data,  8, st->all_info.out.access_time);
394                 push_nttime(blob->data, 16, st->all_info.out.write_time);
395                 push_nttime(blob->data, 24, st->all_info.out.change_time);
396                 SIVAL(blob->data,       32, st->all_info.out.attrib);
397                 SIVAL(blob->data,       36, 0); /* padding */
398                 SBVAL(blob->data,       40, st->all_info.out.alloc_size);
399                 SBVAL(blob->data,       48, st->all_info.out.size);
400                 SIVAL(blob->data,       56, st->all_info.out.nlink);
401                 SCVAL(blob->data,       60, st->all_info.out.delete_pending);
402                 SCVAL(blob->data,       61, st->all_info.out.directory);
403                 SSVAL(blob->data,       62, 0); /* padding */
404                 SIVAL(blob->data,       64, st->all_info.out.ea_size);
405                 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
406                                                      st->all_info.out.fname.s,
407                                                      68, default_str_flags,
408                                                      STR_UNICODE));
409                 return NT_STATUS_OK;
410
411         case RAW_FILEINFO_NAME_INFORMATION:
412                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
413
414                 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
415                                                      st->name_info.out.fname.s,
416                                                      0, default_str_flags,
417                                                      STR_UNICODE));
418                 return NT_STATUS_OK;
419
420         case RAW_FILEINFO_ALT_NAME_INFORMATION:
421                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 4));
422
423                 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, 
424                                                      st->alt_name_info.out.fname.s,
425                                                      0, default_str_flags,
426                                                      STR_UNICODE));
427                 return NT_STATUS_OK;
428
429         case RAW_FILEINFO_STREAM_INFORMATION:
430                 for (i=0;i<st->stream_info.out.num_streams;i++) {
431                         uint32_t data_size = blob->length;
432                         uint8_t *data;
433
434                         BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, data_size + 24));
435                         data = blob->data + data_size;
436                         SBVAL(data,  8, st->stream_info.out.streams[i].size);
437                         SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
438                         BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
439                                                              st->stream_info.out.streams[i].stream_name.s,
440                                                              data_size + 4, default_str_flags,
441                                                              STR_UNICODE));
442                         if (i == st->stream_info.out.num_streams - 1) {
443                                 SIVAL(blob->data, data_size, 0);
444                         } else {
445                                 BLOB_CHECK(smbsrv_blob_fill_data(mem_ctx, blob, (blob->length+7)&~7));
446                                 SIVAL(blob->data, data_size, 
447                                       blob->length - data_size);
448                         }
449                 }
450                 return NT_STATUS_OK;
451
452         case RAW_FILEINFO_SMB2_ALL_EAS:
453                 /* if no eas are returned the backend should
454                  * have returned NO_EAS_ON_FILE or NO_MORE_EAS
455                  *
456                  * so it's a programmer error if num_eas == 0
457                  */
458                 if (st->all_eas.out.num_eas == 0) {
459                         smb_panic("0 eas for SMB2_ALL_EAS - programmer error in ntvfs backend");
460                 }
461
462                 list_size = ea_list_size_chained(st->all_eas.out.num_eas,
463                                                  st->all_eas.out.eas);
464                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));
465
466                 ea_put_list_chained(blob->data,
467                                     st->all_eas.out.num_eas,
468                                     st->all_eas.out.eas);
469                 return NT_STATUS_OK;
470
471         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
472                 BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 0x64));
473
474                 push_nttime(blob->data, 0x00, st->all_info2.out.create_time);
475                 push_nttime(blob->data, 0x08, st->all_info2.out.access_time);
476                 push_nttime(blob->data, 0x10, st->all_info2.out.write_time);
477                 push_nttime(blob->data, 0x18, st->all_info2.out.change_time);
478                 SIVAL(blob->data,       0x20, st->all_info2.out.attrib);
479                 SIVAL(blob->data,       0x24, st->all_info2.out.unknown1);
480                 SBVAL(blob->data,       0x28, st->all_info2.out.alloc_size);
481                 SBVAL(blob->data,       0x30, st->all_info2.out.size);
482                 SIVAL(blob->data,       0x38, st->all_info2.out.nlink);
483                 SCVAL(blob->data,       0x3C, st->all_info2.out.delete_pending);
484                 SCVAL(blob->data,       0x3D, st->all_info2.out.directory);
485                 SBVAL(blob->data,       0x40, st->all_info2.out.file_id);
486                 SIVAL(blob->data,       0x48, st->all_info2.out.ea_size);
487                 SIVAL(blob->data,       0x4C, st->all_info2.out.access_mask);
488                 SBVAL(blob->data,       0x50, st->all_info2.out.position);
489                 SBVAL(blob->data,       0x58, st->all_info2.out.mode);
490                 BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
491                                                      st->all_info2.out.fname.s,
492                                                      0x60, default_str_flags,
493                                                      STR_UNICODE));
494                 return NT_STATUS_OK;
495
496         default:
497                 return NT_STATUS_INVALID_LEVEL;
498         }
499
500         return NT_STATUS_INVALID_LEVEL;
501 }
502
503 NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
504                                         enum smb_setfileinfo_level level,
505                                         union smb_setfileinfo *st,
506                                         const DATA_BLOB *blob,
507                                         int default_str_flags,
508                                         struct smbsrv_request *req)
509 {
510         uint32_t len;
511         DATA_BLOB str_blob;
512
513         switch (level) {
514         case SMB_SFILEINFO_BASIC_INFORMATION:
515                 BLOB_CHECK_MIN_SIZE(blob, 36);
516
517                 st->basic_info.in.create_time = pull_nttime(blob->data,  0);
518                 st->basic_info.in.access_time = pull_nttime(blob->data,  8);
519                 st->basic_info.in.write_time =  pull_nttime(blob->data, 16);
520                 st->basic_info.in.change_time = pull_nttime(blob->data, 24);
521                 st->basic_info.in.attrib =      IVAL(blob->data,        32);
522
523                 return NT_STATUS_OK;
524
525         case SMB_SFILEINFO_DISPOSITION_INFORMATION:
526                 BLOB_CHECK_MIN_SIZE(blob, 1);
527
528                 st->disposition_info.in.delete_on_close = CVAL(blob->data, 0);
529
530                 return NT_STATUS_OK;
531
532         case SMB_SFILEINFO_ALLOCATION_INFORMATION:
533                 BLOB_CHECK_MIN_SIZE(blob, 8);
534
535                 st->allocation_info.in.alloc_size = BVAL(blob->data, 0);
536
537                 return NT_STATUS_OK;                            
538
539         case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
540                 BLOB_CHECK_MIN_SIZE(blob, 8);
541
542                 st->end_of_file_info.in.size = BVAL(blob->data, 0);
543
544                 return NT_STATUS_OK;
545
546         case RAW_SFILEINFO_RENAME_INFORMATION:
547                 if (!req) {
548                         /* 
549                          * TODO: get rid of smbsrv_request argument of
550                          * smbsrv_blob_pull_string()
551                          */
552                         return NT_STATUS_NOT_IMPLEMENTED;
553                 }
554                 BLOB_CHECK_MIN_SIZE(blob, 12);
555
556                 st->rename_information.in.overwrite = CVAL(blob->data, 0);
557                 st->rename_information.in.root_fid  = IVAL(blob->data, 4);
558                 len                                 = IVAL(blob->data, 8);
559                 str_blob.data = blob->data+12;
560                 str_blob.length = MIN(blob->length, len);
561                 smbsrv_blob_pull_string(req, &str_blob, 0,
562                                         &st->rename_information.in.new_name,
563                                         STR_UNICODE);
564                 if (st->rename_information.in.new_name == NULL) {
565                         return NT_STATUS_FOOBAR;
566                 }
567
568                 return NT_STATUS_OK;
569
570         case RAW_SFILEINFO_POSITION_INFORMATION:
571                 BLOB_CHECK_MIN_SIZE(blob, 8);
572
573                 st->position_information.in.position = BVAL(blob->data, 0);
574
575                 return NT_STATUS_OK;
576
577         case RAW_SFILEINFO_MODE_INFORMATION:
578                 BLOB_CHECK_MIN_SIZE(blob, 4);
579
580                 st->mode_information.in.mode = IVAL(blob->data, 0);
581
582                 return NT_STATUS_OK;
583
584         default:
585                 return NT_STATUS_INVALID_LEVEL;
586         }
587
588         return NT_STATUS_INVALID_LEVEL;
589 }