3befb8ee4de20bbce9fec885373c556b8f62d0b0
[bbaumbach/samba-autobuild/.git] / source4 / libcli / raw / rawfileinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client trans2 operations
4    Copyright (C) James Myers 2003
5    Copyright (C) Andrew Tridgell 2003
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 "libcli/raw/libcliraw.h"
24
25 /* local macros to make the code more readable */
26 #define FINFO_CHECK_MIN_SIZE(size) if (blob->length < (size)) { \
27       DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected min of %d\n", \
28                blob->length, parms->generic.level, (size))); \
29       return NT_STATUS_INFO_LENGTH_MISMATCH; \
30 }
31 #define FINFO_CHECK_SIZE(size) if (blob->length != (size)) { \
32       DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected %d\n", \
33                blob->length, parms->generic.level, (size))); \
34       return NT_STATUS_INFO_LENGTH_MISMATCH; \
35 }
36
37 /****************************************************************************
38  Handle qfileinfo/qpathinfo trans2 backend.
39 ****************************************************************************/
40 static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
41                                      TALLOC_CTX *mem_ctx,
42                                      union smb_fileinfo *parms, 
43                                      DATA_BLOB *blob)
44 {       
45         uint_t len, ofs;
46
47         switch (parms->generic.level) {
48         case RAW_FILEINFO_GENERIC:
49         case RAW_FILEINFO_GETATTR:
50         case RAW_FILEINFO_GETATTRE:
51         case RAW_FILEINFO_SEC_DESC:
52                 /* not handled here */
53                 return NT_STATUS_INVALID_LEVEL;
54
55         case RAW_FILEINFO_STANDARD:
56                 FINFO_CHECK_SIZE(22);
57                 parms->standard.out.create_time = raw_pull_dos_date2(session->transport,
58                                                                      blob->data +  0);
59                 parms->standard.out.access_time = raw_pull_dos_date2(session->transport,
60                                                                      blob->data +  4);
61                 parms->standard.out.write_time =  raw_pull_dos_date2(session->transport,
62                                                                      blob->data +  8);
63                 parms->standard.out.size =        IVAL(blob->data,             12);
64                 parms->standard.out.alloc_size =  IVAL(blob->data,             16);
65                 parms->standard.out.attrib =      SVAL(blob->data,             20);
66                 return NT_STATUS_OK;
67
68         case RAW_FILEINFO_EA_SIZE:
69                 FINFO_CHECK_SIZE(26);
70                 parms->ea_size.out.create_time = raw_pull_dos_date2(session->transport,
71                                                                     blob->data +  0);
72                 parms->ea_size.out.access_time = raw_pull_dos_date2(session->transport,
73                                                                     blob->data +  4);
74                 parms->ea_size.out.write_time =  raw_pull_dos_date2(session->transport,
75                                                                     blob->data +  8);
76                 parms->ea_size.out.size =        IVAL(blob->data,             12);
77                 parms->ea_size.out.alloc_size =  IVAL(blob->data,             16);
78                 parms->ea_size.out.attrib =      SVAL(blob->data,             20);
79                 parms->ea_size.out.ea_size =     IVAL(blob->data,             22);
80                 return NT_STATUS_OK;
81
82         case RAW_FILEINFO_EA_LIST:
83                 FINFO_CHECK_MIN_SIZE(4);
84                 return ea_pull_list(blob, mem_ctx, 
85                                     &parms->ea_list.out.num_eas,
86                                     &parms->ea_list.out.eas);
87
88         case RAW_FILEINFO_ALL_EAS:
89                 FINFO_CHECK_MIN_SIZE(4);
90                 return ea_pull_list(blob, mem_ctx, 
91                                     &parms->all_eas.out.num_eas,
92                                     &parms->all_eas.out.eas);
93
94         case RAW_FILEINFO_IS_NAME_VALID:
95                 /* no data! */
96                 FINFO_CHECK_SIZE(0);
97                 return NT_STATUS_OK;
98
99         case RAW_FILEINFO_BASIC_INFO:
100         case RAW_FILEINFO_BASIC_INFORMATION:
101                 /* some servers return 40 bytes and some 36. w2k3 return 40, so thats
102                    what we should do, but we need to accept 36 */
103                 if (blob->length != 36) {
104                         FINFO_CHECK_SIZE(40);
105                 }
106                 parms->basic_info.out.create_time = smbcli_pull_nttime(blob->data, 0);
107                 parms->basic_info.out.access_time = smbcli_pull_nttime(blob->data, 8);
108                 parms->basic_info.out.write_time =  smbcli_pull_nttime(blob->data, 16);
109                 parms->basic_info.out.change_time = smbcli_pull_nttime(blob->data, 24);
110                 parms->basic_info.out.attrib =                 IVAL(blob->data, 32);
111                 return NT_STATUS_OK;
112
113         case RAW_FILEINFO_STANDARD_INFO:
114         case RAW_FILEINFO_STANDARD_INFORMATION:
115                 FINFO_CHECK_SIZE(24);
116                 parms->standard_info.out.alloc_size =     BVAL(blob->data, 0);
117                 parms->standard_info.out.size =           BVAL(blob->data, 8);
118                 parms->standard_info.out.nlink =          IVAL(blob->data, 16);
119                 parms->standard_info.out.delete_pending = CVAL(blob->data, 20);
120                 parms->standard_info.out.directory =      CVAL(blob->data, 21);
121                 return NT_STATUS_OK;
122
123         case RAW_FILEINFO_EA_INFO:
124         case RAW_FILEINFO_EA_INFORMATION:
125                 FINFO_CHECK_SIZE(4);
126                 parms->ea_info.out.ea_size = IVAL(blob->data, 0);
127                 return NT_STATUS_OK;
128
129         case RAW_FILEINFO_NAME_INFO:
130         case RAW_FILEINFO_NAME_INFORMATION:
131                 FINFO_CHECK_MIN_SIZE(4);
132                 smbcli_blob_pull_string(session, mem_ctx, blob, 
133                                      &parms->name_info.out.fname, 0, 4, STR_UNICODE);
134                 return NT_STATUS_OK;
135
136         case RAW_FILEINFO_ALL_INFO:
137         case RAW_FILEINFO_ALL_INFORMATION:
138                 FINFO_CHECK_MIN_SIZE(72);
139                 parms->all_info.out.create_time =           smbcli_pull_nttime(blob->data, 0);
140                 parms->all_info.out.access_time =           smbcli_pull_nttime(blob->data, 8);
141                 parms->all_info.out.write_time =            smbcli_pull_nttime(blob->data, 16);
142                 parms->all_info.out.change_time =           smbcli_pull_nttime(blob->data, 24);
143                 parms->all_info.out.attrib =                IVAL(blob->data, 32);
144                 parms->all_info.out.alloc_size =            BVAL(blob->data, 40);
145                 parms->all_info.out.size =                  BVAL(blob->data, 48);
146                 parms->all_info.out.nlink =                 IVAL(blob->data, 56);
147                 parms->all_info.out.delete_pending =        CVAL(blob->data, 60);
148                 parms->all_info.out.directory =             CVAL(blob->data, 61);
149 #if 1
150                 parms->all_info.out.ea_size =               IVAL(blob->data, 64);
151                 smbcli_blob_pull_string(session, mem_ctx, blob,
152                                      &parms->all_info.out.fname, 68, 72, STR_UNICODE);
153 #else
154                 /* this is what the CIFS spec says - and its totally
155                    wrong, but its useful having it here so we can
156                    quickly adapt to broken servers when running
157                    tests */
158                 parms->all_info.out.ea_size =               IVAL(blob->data, 72);
159                 /* access flags 4 bytes at 76
160                    current_position 8 bytes at 80
161                    mode 4 bytes at 88
162                    alignment 4 bytes at 92
163                 */
164                 smbcli_blob_pull_string(session, mem_ctx, blob,
165                                         &parms->all_info.out.fname, 96, 100, STR_UNICODE);
166 #endif
167                 return NT_STATUS_OK;
168
169         case RAW_FILEINFO_ALT_NAME_INFO:
170         case RAW_FILEINFO_ALT_NAME_INFORMATION:
171                 FINFO_CHECK_MIN_SIZE(4);
172                 smbcli_blob_pull_string(session, mem_ctx, blob, 
173                                      &parms->alt_name_info.out.fname, 0, 4, STR_UNICODE);
174                 return NT_STATUS_OK;
175
176         case RAW_FILEINFO_STREAM_INFO:
177         case RAW_FILEINFO_STREAM_INFORMATION:
178                 ofs = 0;
179                 parms->stream_info.out.num_streams = 0;
180                 parms->stream_info.out.streams = NULL;
181
182                 while (blob->length - ofs >= 24) {
183                         uint_t n = parms->stream_info.out.num_streams;
184                         parms->stream_info.out.streams = 
185                                 talloc_realloc_p(mem_ctx,
186                                                  parms->stream_info.out.streams,
187                                                  struct stream_struct,
188                                                  n+1);
189                         if (!parms->stream_info.out.streams) {
190                                 return NT_STATUS_NO_MEMORY;
191                         }
192                         parms->stream_info.out.streams[n].size =       BVAL(blob->data, ofs +  8);
193                         parms->stream_info.out.streams[n].alloc_size = BVAL(blob->data, ofs + 16);
194                         smbcli_blob_pull_string(session, mem_ctx, blob, 
195                                              &parms->stream_info.out.streams[n].stream_name, 
196                                              ofs+4, ofs+24, STR_UNICODE);
197                         parms->stream_info.out.num_streams++;
198                         len = IVAL(blob->data, ofs);
199                         if (len > blob->length - ofs) return NT_STATUS_INFO_LENGTH_MISMATCH;
200                         if (len == 0) break;
201                         ofs += len;
202                 }
203                 return NT_STATUS_OK;
204
205         case RAW_FILEINFO_INTERNAL_INFORMATION:
206                 FINFO_CHECK_SIZE(8);
207                 parms->internal_information.out.file_id = BVAL(blob->data, 0);
208                 return NT_STATUS_OK;
209
210         case RAW_FILEINFO_ACCESS_INFORMATION:
211                 FINFO_CHECK_SIZE(4);
212                 parms->access_information.out.access_flags = IVAL(blob->data, 0);
213                 return NT_STATUS_OK;
214
215         case RAW_FILEINFO_POSITION_INFORMATION:
216                 FINFO_CHECK_SIZE(8);
217                 parms->position_information.out.position = BVAL(blob->data, 0);
218                 return NT_STATUS_OK;
219
220         case RAW_FILEINFO_MODE_INFORMATION:
221                 FINFO_CHECK_SIZE(4);
222                 parms->mode_information.out.mode = IVAL(blob->data, 0);
223                 return NT_STATUS_OK;
224
225         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
226                 FINFO_CHECK_SIZE(4);
227                 parms->alignment_information.out.alignment_requirement 
228                         = IVAL(blob->data, 0);
229                 return NT_STATUS_OK;
230
231         case RAW_FILEINFO_COMPRESSION_INFO:
232         case RAW_FILEINFO_COMPRESSION_INFORMATION:
233                 FINFO_CHECK_SIZE(16);
234                 parms->compression_info.out.compressed_size = BVAL(blob->data,  0);
235                 parms->compression_info.out.format          = SVAL(blob->data,  8);
236                 parms->compression_info.out.unit_shift      = CVAL(blob->data, 10);
237                 parms->compression_info.out.chunk_shift     = CVAL(blob->data, 11);
238                 parms->compression_info.out.cluster_shift   = CVAL(blob->data, 12);
239                 /* 3 bytes of padding */
240                 return NT_STATUS_OK;
241
242         case RAW_FILEINFO_UNIX_BASIC:
243                 FINFO_CHECK_SIZE(100);
244                 parms->unix_basic_info.out.end_of_file        =            BVAL(blob->data,  0);
245                 parms->unix_basic_info.out.num_bytes          =            BVAL(blob->data,  8);
246                 parms->unix_basic_info.out.status_change_time = smbcli_pull_nttime(blob->data, 16);
247                 parms->unix_basic_info.out.access_time        = smbcli_pull_nttime(blob->data, 24);
248                 parms->unix_basic_info.out.change_time        = smbcli_pull_nttime(blob->data, 32);
249                 parms->unix_basic_info.out.uid                =            BVAL(blob->data, 40);
250                 parms->unix_basic_info.out.gid                =            BVAL(blob->data, 48);
251                 parms->unix_basic_info.out.file_type          =            IVAL(blob->data, 52);
252                 parms->unix_basic_info.out.dev_major          =            BVAL(blob->data, 60);
253                 parms->unix_basic_info.out.dev_minor          =            BVAL(blob->data, 68);
254                 parms->unix_basic_info.out.unique_id          =            BVAL(blob->data, 76);
255                 parms->unix_basic_info.out.permissions        =            BVAL(blob->data, 84);
256                 parms->unix_basic_info.out.nlink              =            BVAL(blob->data, 92);
257                 return NT_STATUS_OK;
258
259         case RAW_FILEINFO_UNIX_LINK:
260                 smbcli_blob_pull_string(session, mem_ctx, blob, 
261                                      &parms->unix_link_info.out.link_dest, 0, 4, STR_UNICODE);
262                 return NT_STATUS_OK;
263                 
264         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:             
265                 FINFO_CHECK_SIZE(56);
266                 parms->network_open_information.out.create_time = smbcli_pull_nttime(blob->data,  0);
267                 parms->network_open_information.out.access_time = smbcli_pull_nttime(blob->data,  8);
268                 parms->network_open_information.out.write_time =  smbcli_pull_nttime(blob->data, 16);
269                 parms->network_open_information.out.change_time = smbcli_pull_nttime(blob->data, 24);
270                 parms->network_open_information.out.alloc_size =             BVAL(blob->data, 32);
271                 parms->network_open_information.out.size =                   BVAL(blob->data, 40);
272                 parms->network_open_information.out.attrib =                 IVAL(blob->data, 48);
273                 return NT_STATUS_OK;
274
275         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
276                 FINFO_CHECK_SIZE(8);
277                 parms->attribute_tag_information.out.attrib =      IVAL(blob->data, 0);
278                 parms->attribute_tag_information.out.reparse_tag = IVAL(blob->data, 4);
279                 return NT_STATUS_OK;
280         }
281
282         return NT_STATUS_INVALID_LEVEL;
283 }
284
285 /****************************************************************************
286  Very raw query file info - returns param/data blobs - (async send)
287 ****************************************************************************/
288 static struct smbcli_request *smb_raw_fileinfo_blob_send(struct smbcli_tree *tree,
289                                                          uint16_t fnum, 
290                                                          uint16_t info_level,
291                                                          DATA_BLOB data)
292 {
293         struct smb_trans2 tp;
294         uint16_t setup = TRANSACT2_QFILEINFO;
295         struct smbcli_request *req;
296         TALLOC_CTX *mem_ctx = talloc_init("raw_fileinfo");
297         
298         tp.in.max_setup = 0;
299         tp.in.flags = 0; 
300         tp.in.timeout = 0;
301         tp.in.setup_count = 1;
302         tp.in.data = data;
303         tp.in.max_param = 2;
304         tp.in.max_data = 0xFFFF;
305         tp.in.setup = &setup;
306         
307         tp.in.params = data_blob_talloc(mem_ctx, NULL, 4);
308         if (!tp.in.params.data) {
309                 talloc_destroy(mem_ctx);
310                 return NULL;
311         }
312
313         SIVAL(tp.in.params.data, 0, fnum);
314         SSVAL(tp.in.params.data, 2, info_level);
315
316         req = smb_raw_trans2_send(tree, &tp);
317
318         talloc_destroy(mem_ctx);
319
320         return req;
321 }
322
323
324 /****************************************************************************
325  Very raw query file info - returns param/data blobs - (async recv)
326 ****************************************************************************/
327 static NTSTATUS smb_raw_fileinfo_blob_recv(struct smbcli_request *req,
328                                            TALLOC_CTX *mem_ctx,
329                                            DATA_BLOB *blob)
330 {
331         struct smb_trans2 tp;
332         NTSTATUS status = smb_raw_trans2_recv(req, mem_ctx, &tp);
333         if (NT_STATUS_IS_OK(status)) {
334                 *blob = tp.out.data;
335         }
336         return status;
337 }
338
339 /****************************************************************************
340  Very raw query path info - returns param/data blobs (async send)
341 ****************************************************************************/
342 static struct smbcli_request *smb_raw_pathinfo_blob_send(struct smbcli_tree *tree,
343                                                          const char *fname,
344                                                          uint16_t info_level,
345                                                          DATA_BLOB data)
346 {
347         struct smb_trans2 tp;
348         uint16_t setup = TRANSACT2_QPATHINFO;
349         struct smbcli_request *req;
350         TALLOC_CTX *mem_ctx = talloc_init("raw_pathinfo");
351
352         tp.in.max_setup = 0;
353         tp.in.flags = 0; 
354         tp.in.timeout = 0;
355         tp.in.setup_count = 1;
356         tp.in.data = data;
357         tp.in.max_param = 2;
358         tp.in.max_data = 0xFFFF;
359         tp.in.setup = &setup;
360         
361         tp.in.params = data_blob_talloc(mem_ctx, NULL, 6);
362         if (!tp.in.params.data) {
363                 talloc_destroy(mem_ctx);
364                 return NULL;
365         }
366
367         SSVAL(tp.in.params.data, 0, info_level);
368         SIVAL(tp.in.params.data, 2, 0);
369         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
370                                fname, STR_TERMINATE);
371         
372         req = smb_raw_trans2_send(tree, &tp);
373
374         talloc_destroy(mem_ctx);
375
376         return req;
377 }
378
379 /****************************************************************************
380  send a SMBgetatr (async send)
381 ****************************************************************************/
382 static struct smbcli_request *smb_raw_getattr_send(struct smbcli_tree *tree,
383                                                 union smb_fileinfo *parms)
384 {
385         struct smbcli_request *req;
386         
387         req = smbcli_request_setup(tree, SMBgetatr, 0, 0);
388         if (!req) return NULL;
389
390         smbcli_req_append_ascii4(req, parms->getattr.in.fname, STR_TERMINATE);
391         
392         if (!smbcli_request_send(req)) {
393                 smbcli_request_destroy(req);
394                 return NULL;
395         }
396
397         return req;
398 }
399
400 /****************************************************************************
401  send a SMBgetatr (async recv)
402 ****************************************************************************/
403 static NTSTATUS smb_raw_getattr_recv(struct smbcli_request *req,
404                                      union smb_fileinfo *parms)
405 {
406         if (!smbcli_request_receive(req) ||
407             smbcli_request_is_error(req)) {
408                 return smbcli_request_destroy(req);
409         }
410
411         SMBCLI_CHECK_WCT(req, 10);
412         parms->getattr.out.attrib =     SVAL(req->in.vwv, VWV(0));
413         parms->getattr.out.write_time = raw_pull_dos_date3(req->transport,
414                                                            req->in.vwv + VWV(1));
415         parms->getattr.out.size =       IVAL(req->in.vwv, VWV(3));
416
417 failed:
418         return smbcli_request_destroy(req);
419 }
420
421
422 /****************************************************************************
423  Handle SMBgetattrE (async send)
424 ****************************************************************************/
425 static struct smbcli_request *smb_raw_getattrE_send(struct smbcli_tree *tree,
426                                                  union smb_fileinfo *parms)
427 {
428         struct smbcli_request *req;
429         
430         req = smbcli_request_setup(tree, SMBgetattrE, 1, 0);
431         if (!req) return NULL;
432         
433         SSVAL(req->out.vwv, VWV(0), parms->getattre.in.fnum);
434         if (!smbcli_request_send(req)) {
435                 smbcli_request_destroy(req);
436                 return NULL;
437         }
438
439         return req;
440 }
441
442 /****************************************************************************
443  Handle SMBgetattrE (async send)
444 ****************************************************************************/
445 static NTSTATUS smb_raw_getattrE_recv(struct smbcli_request *req,
446                                       union smb_fileinfo *parms)
447 {
448         if (!smbcli_request_receive(req) ||
449             smbcli_request_is_error(req)) {
450                 return smbcli_request_destroy(req);
451         }
452         
453         SMBCLI_CHECK_WCT(req, 11);
454         parms->getattre.out.create_time =   raw_pull_dos_date2(req->transport,
455                                                                req->in.vwv + VWV(0));
456         parms->getattre.out.access_time =   raw_pull_dos_date2(req->transport,
457                                                                req->in.vwv + VWV(2));
458         parms->getattre.out.write_time  =   raw_pull_dos_date2(req->transport,
459                                                                req->in.vwv + VWV(4));
460         parms->getattre.out.size =          IVAL(req->in.vwv,             VWV(6));
461         parms->getattre.out.alloc_size =    IVAL(req->in.vwv,             VWV(8));
462         parms->getattre.out.attrib =        SVAL(req->in.vwv,             VWV(10));
463
464 failed:
465         return smbcli_request_destroy(req);
466 }
467
468
469 /****************************************************************************
470  Query file info (async send)
471 ****************************************************************************/
472 struct smbcli_request *smb_raw_fileinfo_send(struct smbcli_tree *tree,
473                                              union smb_fileinfo *parms)
474 {
475         DATA_BLOB data;
476         struct smbcli_request *req;
477
478         /* pass off the non-trans2 level to specialised functions */
479         if (parms->generic.level == RAW_FILEINFO_GETATTRE) {
480                 return smb_raw_getattrE_send(tree, parms);
481         }
482         if (parms->generic.level == RAW_FILEINFO_SEC_DESC) {
483                 return smb_raw_query_secdesc_send(tree, parms);
484         }
485         if (parms->generic.level >= RAW_FILEINFO_GENERIC) {
486                 return NULL;
487         }
488
489         data = data_blob(NULL, 0);
490
491         if (parms->generic.level == RAW_FILEINFO_EA_LIST) {
492                 if (!ea_push_name_list(tree, 
493                                        &data,
494                                        parms->ea_list.in.num_names,
495                                        parms->ea_list.in.ea_names)) {
496                         return NULL;
497                 }
498         }
499
500         req = smb_raw_fileinfo_blob_send(tree, 
501                                          parms->generic.in.fnum,
502                                          parms->generic.level, data);
503
504         data_blob_free(&data);
505
506         return req;
507 }
508
509 /****************************************************************************
510  Query file info (async recv)
511 ****************************************************************************/
512 NTSTATUS smb_raw_fileinfo_recv(struct smbcli_request *req,
513                                TALLOC_CTX *mem_ctx,
514                                union smb_fileinfo *parms)
515 {
516         DATA_BLOB blob;
517         NTSTATUS status;
518         struct smbcli_session *session = req?req->session:NULL;
519
520         if (parms->generic.level == RAW_FILEINFO_GETATTRE) {
521                 return smb_raw_getattrE_recv(req, parms);
522         }
523         if (parms->generic.level == RAW_FILEINFO_SEC_DESC) {
524                 return smb_raw_query_secdesc_recv(req, mem_ctx, parms);
525         }
526         if (parms->generic.level == RAW_FILEINFO_GETATTR) {
527                 return smb_raw_getattr_recv(req, parms);
528         }
529
530         status = smb_raw_fileinfo_blob_recv(req, mem_ctx, &blob);
531         if (!NT_STATUS_IS_OK(status)) {
532                 return status;
533         }
534
535         return smb_raw_info_backend(session, mem_ctx, parms, &blob);
536 }
537
538 /****************************************************************************
539  Query file info (sync interface)
540 ****************************************************************************/
541 NTSTATUS smb_raw_fileinfo(struct smbcli_tree *tree,
542                           TALLOC_CTX *mem_ctx,
543                           union smb_fileinfo *parms)
544 {
545         struct smbcli_request *req = smb_raw_fileinfo_send(tree, parms);
546         return smb_raw_fileinfo_recv(req, mem_ctx, parms);
547 }
548
549 /****************************************************************************
550  Query path info (async send)
551 ****************************************************************************/
552 struct smbcli_request *smb_raw_pathinfo_send(struct smbcli_tree *tree,
553                                              union smb_fileinfo *parms)
554 {
555         DATA_BLOB data;
556         struct smbcli_request *req;
557
558         if (parms->generic.level == RAW_FILEINFO_GETATTR) {
559                 return smb_raw_getattr_send(tree, parms);
560         }
561         if (parms->generic.level >= RAW_FILEINFO_GENERIC) {
562                 return NULL;
563         }
564         
565         data = data_blob(NULL, 0);
566
567         if (parms->generic.level == RAW_FILEINFO_EA_LIST) {
568                 if (!ea_push_name_list(tree, 
569                                        &data,
570                                        parms->ea_list.in.num_names,
571                                        parms->ea_list.in.ea_names)) {
572                         return NULL;
573                 }
574         }
575
576         req = smb_raw_pathinfo_blob_send(tree, parms->generic.in.fname,
577                                          parms->generic.level, data);
578         data_blob_free(&data);
579
580         return req;
581 }
582
583 /****************************************************************************
584  Query path info (async recv)
585 ****************************************************************************/
586 NTSTATUS smb_raw_pathinfo_recv(struct smbcli_request *req,
587                                TALLOC_CTX *mem_ctx,
588                                union smb_fileinfo *parms)
589 {
590         /* recv is idential to fileinfo */
591         return smb_raw_fileinfo_recv(req, mem_ctx, parms);
592 }
593
594 /****************************************************************************
595  Query path info (sync interface)
596 ****************************************************************************/
597 NTSTATUS smb_raw_pathinfo(struct smbcli_tree *tree,
598                           TALLOC_CTX *mem_ctx,
599                           union smb_fileinfo *parms)
600 {
601         struct smbcli_request *req = smb_raw_pathinfo_send(tree, parms);
602         return smb_raw_pathinfo_recv(req, mem_ctx, parms);
603 }