r1965: add cli_setattrE (inspired by samba4-code). needed for further
[nivanova/samba-autobuild/.git] / source3 / libsmb / clifile.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client file operations
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Jeremy Allison 2001-2002
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 #define NO_SYSLOG
23
24 #include "includes.h"
25
26 /****************************************************************************
27  Hard/Symlink a file (UNIX extensions).
28  Creates new name (sym)linked to oldname.
29 ****************************************************************************/
30
31 static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, BOOL hard_link)
32 {
33         unsigned int data_len = 0;
34         unsigned int param_len = 0;
35         uint16 setup = TRANSACT2_SETPATHINFO;
36         char param[sizeof(pstring)+6];
37         pstring data;
38         char *rparam=NULL, *rdata=NULL;
39         char *p;
40         size_t oldlen = 2*(strlen(oldname)+1);
41         size_t newlen = 2*(strlen(newname)+1);
42
43         memset(param, 0, sizeof(param));
44         SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
45         p = &param[6];
46
47         p += clistr_push(cli, p, newname, MIN(newlen, sizeof(param)-6), STR_TERMINATE);
48         param_len = PTR_DIFF(p, param);
49
50         p = data;
51         p += clistr_push(cli, p, oldname, MIN(oldlen,sizeof(data)), STR_TERMINATE);
52         data_len = PTR_DIFF(p, data);
53
54         if (!cli_send_trans(cli, SMBtrans2,
55                 NULL,                        /* name */
56                 -1, 0,                          /* fid, flags */
57                 &setup, 1, 0,                   /* setup, length, max */
58                 param, param_len, 2,            /* param, length, max */
59                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
60                 )) {
61                         return False;
62         }
63
64         if (!cli_receive_trans(cli, SMBtrans2,
65                 &rparam, &param_len,
66                 &rdata, &data_len)) {
67                         return False;
68         }
69
70         SAFE_FREE(rdata);
71         SAFE_FREE(rparam);
72
73         return True;
74 }
75
76 /****************************************************************************
77  Map standard UNIX permissions onto wire representations.
78 ****************************************************************************/
79
80 uint32  unix_perms_to_wire(mode_t perms)
81 {
82         unsigned int ret = 0;
83
84         ret |= ((perms & S_IXOTH) ?  UNIX_X_OTH : 0);
85         ret |= ((perms & S_IWOTH) ?  UNIX_W_OTH : 0);
86         ret |= ((perms & S_IROTH) ?  UNIX_R_OTH : 0);
87         ret |= ((perms & S_IXGRP) ?  UNIX_X_GRP : 0);
88         ret |= ((perms & S_IWGRP) ?  UNIX_W_GRP : 0);
89         ret |= ((perms & S_IRGRP) ?  UNIX_R_GRP : 0);
90         ret |= ((perms & S_IXUSR) ?  UNIX_X_USR : 0);
91         ret |= ((perms & S_IWUSR) ?  UNIX_W_USR : 0);
92         ret |= ((perms & S_IRUSR) ?  UNIX_R_USR : 0);
93 #ifdef S_ISVTX
94         ret |= ((perms & S_ISVTX) ?  UNIX_STICKY : 0);
95 #endif
96 #ifdef S_ISGID
97         ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
98 #endif
99 #ifdef S_ISUID
100         ret |= ((perms & S_ISUID) ?  UNIX_SET_UID : 0);
101 #endif
102         return ret;
103 }
104
105 /****************************************************************************
106  Symlink a file (UNIX extensions).
107 ****************************************************************************/
108
109 BOOL cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
110 {
111         return cli_link_internal(cli, oldname, newname, False);
112 }
113
114 /****************************************************************************
115  Hard a file (UNIX extensions).
116 ****************************************************************************/
117
118 BOOL cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
119 {
120         return cli_link_internal(cli, oldname, newname, True);
121 }
122
123 /****************************************************************************
124  Chmod or chown a file internal (UNIX extensions).
125 ****************************************************************************/
126
127 static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid)
128 {
129         unsigned int data_len = 0;
130         unsigned int param_len = 0;
131         uint16 setup = TRANSACT2_SETPATHINFO;
132         char param[sizeof(pstring)+6];
133         char data[100];
134         char *rparam=NULL, *rdata=NULL;
135         char *p;
136
137         memset(param, 0, sizeof(param));
138         memset(data, 0, sizeof(data));
139         SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC);
140         p = &param[6];
141
142         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
143         param_len = PTR_DIFF(p, param);
144
145         SIVAL(data,40,uid);
146         SIVAL(data,48,gid);
147         SIVAL(data,84,mode);
148
149         data_len = 100;
150
151         if (!cli_send_trans(cli, SMBtrans2,
152                 NULL,                        /* name */
153                 -1, 0,                          /* fid, flags */
154                 &setup, 1, 0,                   /* setup, length, max */
155                 param, param_len, 2,            /* param, length, max */
156                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
157                 )) {
158                         return False;
159         }
160
161         if (!cli_receive_trans(cli, SMBtrans2,
162                 &rparam, &param_len,
163                 &rdata, &data_len)) {
164                         return False;
165         }
166
167         SAFE_FREE(rdata);
168         SAFE_FREE(rparam);
169
170         return True;
171 }
172
173 /****************************************************************************
174  chmod a file (UNIX extensions).
175 ****************************************************************************/
176
177 BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
178 {
179         return cli_unix_chmod_chown_internal(cli, fname, 
180                 unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE);
181 }
182
183 /****************************************************************************
184  chown a file (UNIX extensions).
185 ****************************************************************************/
186
187 BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
188 {
189         return cli_unix_chmod_chown_internal(cli, fname, SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid);
190 }
191
192 /****************************************************************************
193  Rename a file.
194 ****************************************************************************/
195
196 BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
197 {
198         char *p;
199
200         memset(cli->outbuf,'\0',smb_size);
201         memset(cli->inbuf,'\0',smb_size);
202
203         set_message(cli->outbuf,1, 0, True);
204
205         SCVAL(cli->outbuf,smb_com,SMBmv);
206         SSVAL(cli->outbuf,smb_tid,cli->cnum);
207         cli_setup_packet(cli);
208
209         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
210
211         p = smb_buf(cli->outbuf);
212         *p++ = 4;
213         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
214         *p++ = 4;
215         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
216
217         cli_setup_bcc(cli, p);
218
219         cli_send_smb(cli);
220         if (!cli_receive_smb(cli))
221                 return False;
222
223         if (cli_is_error(cli))
224                 return False;
225
226         return True;
227 }
228
229 /****************************************************************************
230  NT Rename a file.
231 ****************************************************************************/
232
233 BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
234 {
235         char *p;
236
237         memset(cli->outbuf,'\0',smb_size);
238         memset(cli->inbuf,'\0',smb_size);
239
240         set_message(cli->outbuf, 4, 0, True);
241
242         SCVAL(cli->outbuf,smb_com,SMBntrename);
243         SSVAL(cli->outbuf,smb_tid,cli->cnum);
244         cli_setup_packet(cli);
245
246         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
247         SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_RENAME);
248
249         p = smb_buf(cli->outbuf);
250         *p++ = 4;
251         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
252         *p++ = 4;
253         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
254
255         cli_setup_bcc(cli, p);
256
257         cli_send_smb(cli);
258         if (!cli_receive_smb(cli))
259                 return False;
260
261         if (cli_is_error(cli))
262                 return False;
263
264         return True;
265 }
266
267 /****************************************************************************
268  NT hardlink a file.
269 ****************************************************************************/
270
271 BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
272 {
273         char *p;
274
275         memset(cli->outbuf,'\0',smb_size);
276         memset(cli->inbuf,'\0',smb_size);
277
278         set_message(cli->outbuf, 4, 0, True);
279
280         SCVAL(cli->outbuf,smb_com,SMBntrename);
281         SSVAL(cli->outbuf,smb_tid,cli->cnum);
282         cli_setup_packet(cli);
283
284         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
285         SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_HARD_LINK);
286
287         p = smb_buf(cli->outbuf);
288         *p++ = 4;
289         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
290         *p++ = 4;
291         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
292
293         cli_setup_bcc(cli, p);
294
295         cli_send_smb(cli);
296         if (!cli_receive_smb(cli))
297                 return False;
298
299         if (cli_is_error(cli))
300                 return False;
301
302         return True;
303 }
304
305 /****************************************************************************
306  Delete a file.
307 ****************************************************************************/
308
309 BOOL cli_unlink(struct cli_state *cli, const char *fname)
310 {
311         char *p;
312
313         memset(cli->outbuf,'\0',smb_size);
314         memset(cli->inbuf,'\0',smb_size);
315
316         set_message(cli->outbuf,1, 0,True);
317
318         SCVAL(cli->outbuf,smb_com,SMBunlink);
319         SSVAL(cli->outbuf,smb_tid,cli->cnum);
320         cli_setup_packet(cli);
321
322         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
323   
324         p = smb_buf(cli->outbuf);
325         *p++ = 4;      
326         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
327
328         cli_setup_bcc(cli, p);
329         cli_send_smb(cli);
330         if (!cli_receive_smb(cli)) {
331                 return False;
332         }
333
334         if (cli_is_error(cli)) {
335                 return False;
336         }
337
338         return True;
339 }
340
341 /****************************************************************************
342  Create a directory.
343 ****************************************************************************/
344
345 BOOL cli_mkdir(struct cli_state *cli, const char *dname)
346 {
347         char *p;
348
349         memset(cli->outbuf,'\0',smb_size);
350         memset(cli->inbuf,'\0',smb_size);
351
352         set_message(cli->outbuf,0, 0,True);
353
354         SCVAL(cli->outbuf,smb_com,SMBmkdir);
355         SSVAL(cli->outbuf,smb_tid,cli->cnum);
356         cli_setup_packet(cli);
357
358         p = smb_buf(cli->outbuf);
359         *p++ = 4;      
360         p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
361
362         cli_setup_bcc(cli, p);
363
364         cli_send_smb(cli);
365         if (!cli_receive_smb(cli)) {
366                 return False;
367         }
368
369         if (cli_is_error(cli)) {
370                 return False;
371         }
372
373         return True;
374 }
375
376 /****************************************************************************
377  Remove a directory.
378 ****************************************************************************/
379
380 BOOL cli_rmdir(struct cli_state *cli, const char *dname)
381 {
382         char *p;
383
384         memset(cli->outbuf,'\0',smb_size);
385         memset(cli->inbuf,'\0',smb_size);
386
387         set_message(cli->outbuf,0, 0, True);
388
389         SCVAL(cli->outbuf,smb_com,SMBrmdir);
390         SSVAL(cli->outbuf,smb_tid,cli->cnum);
391         cli_setup_packet(cli);
392
393         p = smb_buf(cli->outbuf);
394         *p++ = 4;      
395         p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
396
397         cli_setup_bcc(cli, p);
398
399         cli_send_smb(cli);
400         if (!cli_receive_smb(cli)) {
401                 return False;
402         }
403
404         if (cli_is_error(cli)) {
405                 return False;
406         }
407
408         return True;
409 }
410
411 /****************************************************************************
412  Set or clear the delete on close flag.
413 ****************************************************************************/
414
415 int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
416 {
417         unsigned int data_len = 1;
418         unsigned int param_len = 6;
419         uint16 setup = TRANSACT2_SETFILEINFO;
420         pstring param;
421         unsigned char data;
422         char *rparam=NULL, *rdata=NULL;
423
424         memset(param, 0, param_len);
425         SSVAL(param,0,fnum);
426         SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
427
428         data = flag ? 1 : 0;
429
430         if (!cli_send_trans(cli, SMBtrans2,
431                                                 NULL,                        /* name */
432                                                 -1, 0,                          /* fid, flags */
433                                                 &setup, 1, 0,                   /* setup, length, max */
434                                                 param, param_len, 2,            /* param, length, max */
435                                                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
436                                                 )) {
437                 return False;
438         }
439
440         if (!cli_receive_trans(cli, SMBtrans2,
441                                                 &rparam, &param_len,
442                                                 &rdata, &data_len)) {
443                 return False;
444         }
445
446         SAFE_FREE(rdata);
447         SAFE_FREE(rparam);
448
449         return True;
450 }
451
452 /****************************************************************************
453  Open a file - exposing the full horror of the NT API :-).
454  Used in smbtorture.
455 ****************************************************************************/
456
457 int cli_nt_create_full(struct cli_state *cli, const char *fname, 
458                  uint32 CreatFlags, uint32 DesiredAccess,
459                  uint32 FileAttributes, uint32 ShareAccess,
460                  uint32 CreateDisposition, uint32 CreateOptions,
461                  uint8 SecuityFlags)
462 {
463         char *p;
464         int len;
465
466         memset(cli->outbuf,'\0',smb_size);
467         memset(cli->inbuf,'\0',smb_size);
468
469         set_message(cli->outbuf,24,0,True);
470
471         SCVAL(cli->outbuf,smb_com,SMBntcreateX);
472         SSVAL(cli->outbuf,smb_tid,cli->cnum);
473         cli_setup_packet(cli);
474
475         SSVAL(cli->outbuf,smb_vwv0,0xFF);
476         if (cli->use_oplocks)
477                 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
478         
479         SIVAL(cli->outbuf,smb_ntcreate_Flags, CreatFlags);
480         SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
481         SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
482         SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
483         SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
484         SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
485         SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
486         SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
487         SCVAL(cli->outbuf,smb_ntcreate_SecurityFlags, SecuityFlags);
488
489         p = smb_buf(cli->outbuf);
490         /* this alignment and termination is critical for netapp filers. Don't change */
491         p += clistr_align_out(cli, p, 0);
492         len = clistr_push(cli, p, fname, -1, 0);
493         p += len;
494         SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
495         /* sigh. this copes with broken netapp filer behaviour */
496         p += clistr_push(cli, p, "", -1, STR_TERMINATE);
497
498         cli_setup_bcc(cli, p);
499
500         cli_send_smb(cli);
501         if (!cli_receive_smb(cli)) {
502                 return -1;
503         }
504
505         if (cli_is_error(cli)) {
506                 return -1;
507         }
508
509         return SVAL(cli->inbuf,smb_vwv2 + 1);
510 }
511
512 /****************************************************************************
513  Open a file.
514 ****************************************************************************/
515
516 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
517 {
518         return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0,
519                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0, 0x0);
520 }
521
522 /****************************************************************************
523  Open a file
524  WARNING: if you open with O_WRONLY then getattrE won't work!
525 ****************************************************************************/
526
527 int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
528 {
529         char *p;
530         unsigned openfn=0;
531         unsigned accessmode=0;
532
533         if (flags & O_CREAT)
534                 openfn |= (1<<4);
535         if (!(flags & O_EXCL)) {
536                 if (flags & O_TRUNC)
537                         openfn |= (1<<1);
538                 else
539                         openfn |= (1<<0);
540         }
541
542         accessmode = (share_mode<<4);
543
544         if ((flags & O_ACCMODE) == O_RDWR) {
545                 accessmode |= 2;
546         } else if ((flags & O_ACCMODE) == O_WRONLY) {
547                 accessmode |= 1;
548         } 
549
550 #if defined(O_SYNC)
551         if ((flags & O_SYNC) == O_SYNC) {
552                 accessmode |= (1<<14);
553         }
554 #endif /* O_SYNC */
555
556         if (share_mode == DENY_FCB) {
557                 accessmode = 0xFF;
558         }
559
560         memset(cli->outbuf,'\0',smb_size);
561         memset(cli->inbuf,'\0',smb_size);
562
563         set_message(cli->outbuf,15,0,True);
564
565         SCVAL(cli->outbuf,smb_com,SMBopenX);
566         SSVAL(cli->outbuf,smb_tid,cli->cnum);
567         cli_setup_packet(cli);
568
569         SSVAL(cli->outbuf,smb_vwv0,0xFF);
570         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
571         SSVAL(cli->outbuf,smb_vwv3,accessmode);
572         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
573         SSVAL(cli->outbuf,smb_vwv5,0);
574         SSVAL(cli->outbuf,smb_vwv8,openfn);
575
576         if (cli->use_oplocks) {
577                 /* if using oplocks then ask for a batch oplock via
578                    core and extended methods */
579                 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
580                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
581                 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
582         }
583   
584         p = smb_buf(cli->outbuf);
585         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
586
587         cli_setup_bcc(cli, p);
588
589         cli_send_smb(cli);
590         if (!cli_receive_smb(cli)) {
591                 return -1;
592         }
593
594         if (cli_is_error(cli)) {
595                 return -1;
596         }
597
598         return SVAL(cli->inbuf,smb_vwv2);
599 }
600
601 /****************************************************************************
602  Close a file.
603 ****************************************************************************/
604
605 BOOL cli_close(struct cli_state *cli, int fnum)
606 {
607         memset(cli->outbuf,'\0',smb_size);
608         memset(cli->inbuf,'\0',smb_size);
609
610         set_message(cli->outbuf,3,0,True);
611
612         SCVAL(cli->outbuf,smb_com,SMBclose);
613         SSVAL(cli->outbuf,smb_tid,cli->cnum);
614         cli_setup_packet(cli);
615
616         SSVAL(cli->outbuf,smb_vwv0,fnum);
617         SIVALS(cli->outbuf,smb_vwv1,-1);
618
619         cli_send_smb(cli);
620         if (!cli_receive_smb(cli)) {
621                 return False;
622         }
623
624         return !cli_is_error(cli);
625 }
626
627
628 /****************************************************************************
629  send a lock with a specified locktype 
630  this is used for testing LOCKING_ANDX_CANCEL_LOCK
631 ****************************************************************************/
632 NTSTATUS cli_locktype(struct cli_state *cli, int fnum, 
633                       uint32 offset, uint32 len, int timeout, unsigned char locktype)
634 {
635         char *p;
636         int saved_timeout = cli->timeout;
637
638         memset(cli->outbuf,'\0',smb_size);
639         memset(cli->inbuf,'\0', smb_size);
640
641         set_message(cli->outbuf,8,0,True);
642
643         SCVAL(cli->outbuf,smb_com,SMBlockingX);
644         SSVAL(cli->outbuf,smb_tid,cli->cnum);
645         cli_setup_packet(cli);
646
647         SCVAL(cli->outbuf,smb_vwv0,0xFF);
648         SSVAL(cli->outbuf,smb_vwv2,fnum);
649         SCVAL(cli->outbuf,smb_vwv3,locktype);
650         SIVALS(cli->outbuf, smb_vwv4, timeout);
651         SSVAL(cli->outbuf,smb_vwv6,0);
652         SSVAL(cli->outbuf,smb_vwv7,1);
653
654         p = smb_buf(cli->outbuf);
655         SSVAL(p, 0, cli->pid);
656         SIVAL(p, 2, offset);
657         SIVAL(p, 6, len);
658
659         p += 10;
660
661         cli_setup_bcc(cli, p);
662
663         cli_send_smb(cli);
664
665         if (timeout != 0) {
666                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
667         }
668
669         if (!cli_receive_smb(cli)) {
670                 cli->timeout = saved_timeout;
671                 return NT_STATUS_UNSUCCESSFUL;
672         }
673
674         cli->timeout = saved_timeout;
675
676         return cli_nt_error(cli);
677 }
678
679
680 /****************************************************************************
681  Lock a file.
682  note that timeout is in units of 2 milliseconds
683 ****************************************************************************/
684 BOOL cli_lock(struct cli_state *cli, int fnum, 
685               uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
686 {
687         char *p;
688         int saved_timeout = cli->timeout;
689
690         memset(cli->outbuf,'\0',smb_size);
691         memset(cli->inbuf,'\0', smb_size);
692
693         set_message(cli->outbuf,8,0,True);
694
695         SCVAL(cli->outbuf,smb_com,SMBlockingX);
696         SSVAL(cli->outbuf,smb_tid,cli->cnum);
697         cli_setup_packet(cli);
698
699         SCVAL(cli->outbuf,smb_vwv0,0xFF);
700         SSVAL(cli->outbuf,smb_vwv2,fnum);
701         SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
702         SIVALS(cli->outbuf, smb_vwv4, timeout);
703         SSVAL(cli->outbuf,smb_vwv6,0);
704         SSVAL(cli->outbuf,smb_vwv7,1);
705
706         p = smb_buf(cli->outbuf);
707         SSVAL(p, 0, cli->pid);
708         SIVAL(p, 2, offset);
709         SIVAL(p, 6, len);
710
711         p += 10;
712
713         cli_setup_bcc(cli, p);
714
715         cli_send_smb(cli);
716
717         if (timeout != 0) {
718                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
719         }
720
721         if (!cli_receive_smb(cli)) {
722                 cli->timeout = saved_timeout;
723                 return False;
724         }
725
726         cli->timeout = saved_timeout;
727
728         if (cli_is_error(cli)) {
729                 return False;
730         }
731
732         return True;
733 }
734
735 /****************************************************************************
736  Unlock a file.
737 ****************************************************************************/
738
739 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
740 {
741         char *p;
742
743         memset(cli->outbuf,'\0',smb_size);
744         memset(cli->inbuf,'\0',smb_size);
745
746         set_message(cli->outbuf,8,0,True);
747
748         SCVAL(cli->outbuf,smb_com,SMBlockingX);
749         SSVAL(cli->outbuf,smb_tid,cli->cnum);
750         cli_setup_packet(cli);
751
752         SCVAL(cli->outbuf,smb_vwv0,0xFF);
753         SSVAL(cli->outbuf,smb_vwv2,fnum);
754         SCVAL(cli->outbuf,smb_vwv3,0);
755         SIVALS(cli->outbuf, smb_vwv4, 0);
756         SSVAL(cli->outbuf,smb_vwv6,1);
757         SSVAL(cli->outbuf,smb_vwv7,0);
758
759         p = smb_buf(cli->outbuf);
760         SSVAL(p, 0, cli->pid);
761         SIVAL(p, 2, offset);
762         SIVAL(p, 6, len);
763         p += 10;
764         cli_setup_bcc(cli, p);
765         cli_send_smb(cli);
766         if (!cli_receive_smb(cli)) {
767                 return False;
768         }
769
770         if (cli_is_error(cli)) {
771                 return False;
772         }
773
774         return True;
775 }
776
777 /****************************************************************************
778  Lock a file with 64 bit offsets.
779 ****************************************************************************/
780
781 BOOL cli_lock64(struct cli_state *cli, int fnum, 
782                 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
783 {
784         char *p;
785         int saved_timeout = cli->timeout;
786         int ltype;
787
788         if (! (cli->capabilities & CAP_LARGE_FILES)) {
789                 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
790         }
791
792         ltype = (lock_type == READ_LOCK? 1 : 0);
793         ltype |= LOCKING_ANDX_LARGE_FILES;
794
795         memset(cli->outbuf,'\0',smb_size);
796         memset(cli->inbuf,'\0', smb_size);
797
798         set_message(cli->outbuf,8,0,True);
799
800         SCVAL(cli->outbuf,smb_com,SMBlockingX);
801         SSVAL(cli->outbuf,smb_tid,cli->cnum);
802         cli_setup_packet(cli);
803
804         SCVAL(cli->outbuf,smb_vwv0,0xFF);
805         SSVAL(cli->outbuf,smb_vwv2,fnum);
806         SCVAL(cli->outbuf,smb_vwv3,ltype);
807         SIVALS(cli->outbuf, smb_vwv4, timeout);
808         SSVAL(cli->outbuf,smb_vwv6,0);
809         SSVAL(cli->outbuf,smb_vwv7,1);
810
811         p = smb_buf(cli->outbuf);
812         SIVAL(p, 0, cli->pid);
813         SOFF_T_R(p, 4, offset);
814         SOFF_T_R(p, 12, len);
815         p += 20;
816
817         cli_setup_bcc(cli, p);
818         cli_send_smb(cli);
819
820         if (timeout != 0) {
821                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
822         }
823
824         if (!cli_receive_smb(cli)) {
825                 cli->timeout = saved_timeout;
826                 return False;
827         }
828
829         cli->timeout = saved_timeout;
830
831         if (cli_is_error(cli)) {
832                 return False;
833         }
834
835         return True;
836 }
837
838 /****************************************************************************
839  Unlock a file with 64 bit offsets.
840 ****************************************************************************/
841
842 BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
843 {
844         char *p;
845
846         if (! (cli->capabilities & CAP_LARGE_FILES)) {
847                 return cli_unlock(cli, fnum, offset, len);
848         }
849
850         memset(cli->outbuf,'\0',smb_size);
851         memset(cli->inbuf,'\0',smb_size);
852
853         set_message(cli->outbuf,8,0,True);
854
855         SCVAL(cli->outbuf,smb_com,SMBlockingX);
856         SSVAL(cli->outbuf,smb_tid,cli->cnum);
857         cli_setup_packet(cli);
858
859         SCVAL(cli->outbuf,smb_vwv0,0xFF);
860         SSVAL(cli->outbuf,smb_vwv2,fnum);
861         SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES);
862         SIVALS(cli->outbuf, smb_vwv4, 0);
863         SSVAL(cli->outbuf,smb_vwv6,1);
864         SSVAL(cli->outbuf,smb_vwv7,0);
865
866         p = smb_buf(cli->outbuf);
867         SIVAL(p, 0, cli->pid);
868         SOFF_T_R(p, 4, offset);
869         SOFF_T_R(p, 12, len);
870         p += 20;
871         cli_setup_bcc(cli, p);
872         cli_send_smb(cli);
873         if (!cli_receive_smb(cli)) {
874                 return False;
875         }
876
877         if (cli_is_error(cli)) {
878                 return False;
879         }
880
881         return True;
882 }
883
884
885 /****************************************************************************
886  Do a SMBgetattrE call.
887 ****************************************************************************/
888
889 BOOL cli_getattrE(struct cli_state *cli, int fd, 
890                   uint16 *attr, SMB_BIG_UINT *size, 
891                   time_t *c_time, time_t *a_time, time_t *m_time)
892 {
893         memset(cli->outbuf,'\0',smb_size);
894         memset(cli->inbuf,'\0',smb_size);
895
896         set_message(cli->outbuf,1,0,True);
897
898         SCVAL(cli->outbuf,smb_com,SMBgetattrE);
899         SSVAL(cli->outbuf,smb_tid,cli->cnum);
900         cli_setup_packet(cli);
901
902         SSVAL(cli->outbuf,smb_vwv0,fd);
903
904         cli_send_smb(cli);
905         if (!cli_receive_smb(cli)) {
906                 return False;
907         }
908         
909         if (cli_is_error(cli)) {
910                 return False;
911         }
912
913         if (size) {
914                 *size = IVAL(cli->inbuf, smb_vwv6);
915         }
916
917         if (attr) {
918                 *attr = SVAL(cli->inbuf,smb_vwv10);
919         }
920
921         if (c_time) {
922                 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
923         }
924
925         if (a_time) {
926                 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
927         }
928
929         if (m_time) {
930                 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
931         }
932
933         return True;
934 }
935
936 /****************************************************************************
937  Do a SMBgetatr call
938 ****************************************************************************/
939
940 BOOL cli_getatr(struct cli_state *cli, const char *fname, 
941                 uint16 *attr, size_t *size, time_t *t)
942 {
943         char *p;
944
945         memset(cli->outbuf,'\0',smb_size);
946         memset(cli->inbuf,'\0',smb_size);
947
948         set_message(cli->outbuf,0,0,True);
949
950         SCVAL(cli->outbuf,smb_com,SMBgetatr);
951         SSVAL(cli->outbuf,smb_tid,cli->cnum);
952         cli_setup_packet(cli);
953
954         p = smb_buf(cli->outbuf);
955         *p++ = 4;
956         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
957
958         cli_setup_bcc(cli, p);
959
960         cli_send_smb(cli);
961         if (!cli_receive_smb(cli)) {
962                 return False;
963         }
964         
965         if (cli_is_error(cli)) {
966                 return False;
967         }
968
969         if (size) {
970                 *size = IVAL(cli->inbuf, smb_vwv3);
971         }
972
973         if (t) {
974                 *t = make_unix_date3(cli->inbuf+smb_vwv1);
975         }
976
977         if (attr) {
978                 *attr = SVAL(cli->inbuf,smb_vwv0);
979         }
980
981
982         return True;
983 }
984
985 /****************************************************************************
986  Do a SMBsetattrE call.
987 ****************************************************************************/
988
989 BOOL cli_setattrE(struct cli_state *cli, int fd,
990                   time_t c_time, time_t a_time, time_t m_time)
991
992 {
993         char *p;
994
995         memset(cli->outbuf,'\0',smb_size);
996         memset(cli->inbuf,'\0',smb_size);
997
998         set_message(cli->outbuf,7,0,True);
999
1000         SCVAL(cli->outbuf,smb_com,SMBsetattrE);
1001         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1002         cli_setup_packet(cli);
1003
1004         SSVAL(cli->outbuf,smb_vwv0, fd);
1005         put_dos_date3(cli->outbuf,smb_vwv1, c_time);
1006         put_dos_date3(cli->outbuf,smb_vwv3, a_time);
1007         put_dos_date3(cli->outbuf,smb_vwv5, m_time);
1008
1009         p = smb_buf(cli->outbuf);
1010         *p++ = 4;
1011
1012         cli_setup_bcc(cli, p);
1013
1014         cli_send_smb(cli);
1015         if (!cli_receive_smb(cli)) {
1016                 return False;
1017         }
1018         
1019         if (cli_is_error(cli)) {
1020                 return False;
1021         }
1022
1023         return True;
1024 }
1025
1026 /****************************************************************************
1027  Do a SMBsetatr call.
1028 ****************************************************************************/
1029
1030 BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
1031 {
1032         char *p;
1033
1034         memset(cli->outbuf,'\0',smb_size);
1035         memset(cli->inbuf,'\0',smb_size);
1036
1037         set_message(cli->outbuf,8,0,True);
1038
1039         SCVAL(cli->outbuf,smb_com,SMBsetatr);
1040         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1041         cli_setup_packet(cli);
1042
1043         SSVAL(cli->outbuf,smb_vwv0, attr);
1044         put_dos_date3(cli->outbuf,smb_vwv1, t);
1045
1046         p = smb_buf(cli->outbuf);
1047         *p++ = 4;
1048         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
1049         *p++ = 4;
1050
1051         cli_setup_bcc(cli, p);
1052
1053         cli_send_smb(cli);
1054         if (!cli_receive_smb(cli)) {
1055                 return False;
1056         }
1057         
1058         if (cli_is_error(cli)) {
1059                 return False;
1060         }
1061
1062         return True;
1063 }
1064
1065 /****************************************************************************
1066  Check for existance of a dir.
1067 ****************************************************************************/
1068 BOOL cli_chkpath(struct cli_state *cli, const char *path)
1069 {
1070         pstring path2;
1071         char *p;
1072         
1073         pstrcpy(path2,path);
1074         trim_char(path2,'\0','\\');
1075         if (!*path2)
1076                 *path2 = '\\';
1077         
1078         memset(cli->outbuf,'\0',smb_size);
1079         set_message(cli->outbuf,0,0,True);
1080         SCVAL(cli->outbuf,smb_com,SMBchkpth);
1081         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1082         cli_setup_packet(cli);
1083         p = smb_buf(cli->outbuf);
1084         *p++ = 4;
1085         p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
1086
1087         cli_setup_bcc(cli, p);
1088
1089         cli_send_smb(cli);
1090         if (!cli_receive_smb(cli)) {
1091                 return False;
1092         }
1093
1094         if (cli_is_error(cli)) return False;
1095
1096         return True;
1097 }
1098
1099 /****************************************************************************
1100  Query disk space.
1101 ****************************************************************************/
1102
1103 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
1104 {
1105         memset(cli->outbuf,'\0',smb_size);
1106         set_message(cli->outbuf,0,0,True);
1107         SCVAL(cli->outbuf,smb_com,SMBdskattr);
1108         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1109         cli_setup_packet(cli);
1110
1111         cli_send_smb(cli);
1112         if (!cli_receive_smb(cli)) {
1113                 return False;
1114         }
1115
1116         *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
1117         *total = SVAL(cli->inbuf,smb_vwv0);
1118         *avail = SVAL(cli->inbuf,smb_vwv3);
1119         
1120         return True;
1121 }
1122
1123 /****************************************************************************
1124  Create and open a temporary file.
1125 ****************************************************************************/
1126
1127 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
1128 {
1129         int len;
1130         char *p;
1131
1132         memset(cli->outbuf,'\0',smb_size);
1133         memset(cli->inbuf,'\0',smb_size);
1134
1135         set_message(cli->outbuf,3,0,True);
1136
1137         SCVAL(cli->outbuf,smb_com,SMBctemp);
1138         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1139         cli_setup_packet(cli);
1140
1141         SSVAL(cli->outbuf,smb_vwv0,0);
1142         SIVALS(cli->outbuf,smb_vwv1,-1);
1143
1144         p = smb_buf(cli->outbuf);
1145         *p++ = 4;
1146         p += clistr_push(cli, p, path, -1, STR_TERMINATE);
1147
1148         cli_setup_bcc(cli, p);
1149
1150         cli_send_smb(cli);
1151         if (!cli_receive_smb(cli)) {
1152                 return -1;
1153         }
1154
1155         if (cli_is_error(cli)) {
1156                 return -1;
1157         }
1158
1159         /* despite the spec, the result has a -1, followed by
1160            length, followed by name */
1161         p = smb_buf(cli->inbuf);
1162         p += 4;
1163         len = smb_buflen(cli->inbuf) - 4;
1164         if (len <= 0) return -1;
1165
1166         if (tmp_path) {
1167                 pstring path2;
1168                 clistr_pull(cli, path2, p, 
1169                             sizeof(path2), len, STR_ASCII);
1170                 *tmp_path = strdup(path2);
1171         }
1172
1173         return SVAL(cli->inbuf,smb_vwv0);
1174 }
1175
1176
1177 /* 
1178    send a raw ioctl - used by the torture code
1179 */
1180 NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob)
1181 {
1182         memset(cli->outbuf,'\0',smb_size);
1183         memset(cli->inbuf,'\0',smb_size);
1184
1185         set_message(cli->outbuf, 3, 0, True);
1186         SCVAL(cli->outbuf,smb_com,SMBioctl);
1187         cli_setup_packet(cli);
1188
1189         SSVAL(cli->outbuf, smb_vwv0, fnum);
1190         SSVAL(cli->outbuf, smb_vwv1, code>>16);
1191         SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
1192
1193         cli_send_smb(cli);
1194         if (!cli_receive_smb(cli)) {
1195                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1196         }
1197
1198         if (cli_is_error(cli)) {
1199                 return cli_nt_error(cli);
1200         }
1201
1202         *blob = data_blob(NULL, 0);
1203
1204         return NT_STATUS_OK;
1205 }
1206
1207 /*********************************************************
1208  Set an extended attribute utility fn.
1209 *********************************************************/
1210
1211 static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
1212                         const char *ea_name, const char *ea_val, size_t ea_len)
1213 {       
1214         unsigned int data_len = 0;
1215         char *data = NULL;
1216         char *rparam=NULL, *rdata=NULL;
1217         char *p;
1218         size_t ea_namelen = strlen(ea_name);
1219
1220         data_len = 4 + 4 + ea_namelen + 1 + ea_len;
1221         data = malloc(data_len);
1222         if (!data) {
1223                 return False;
1224         }
1225         p = data;
1226         SIVAL(p,0,data_len);
1227         p += 4;
1228         SCVAL(p, 0, 0); /* EA flags. */
1229         SCVAL(p, 1, ea_namelen);
1230         SSVAL(p, 2, ea_len);
1231         memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
1232         memcpy(p+4+ea_namelen+1, ea_val, ea_len);
1233
1234         if (!cli_send_trans(cli, SMBtrans2,
1235                 NULL,                        /* name */
1236                 -1, 0,                          /* fid, flags */
1237                 &setup, 1, 0,                   /* setup, length, max */
1238                 param, param_len, 2,            /* param, length, max */
1239                 data,  data_len, cli->max_xmit /* data, length, max */
1240                 )) {
1241                         return False;
1242         }
1243
1244         if (!cli_receive_trans(cli, SMBtrans2,
1245                 &rparam, &param_len,
1246                 &rdata, &data_len)) {
1247                         return False;
1248         }
1249
1250         SAFE_FREE(data);
1251         SAFE_FREE(rdata);
1252         SAFE_FREE(rparam);
1253
1254         return True;
1255 }
1256
1257 /*********************************************************
1258  Set an extended attribute on a pathname.
1259 *********************************************************/
1260
1261 BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
1262 {
1263         uint16 setup = TRANSACT2_SETPATHINFO;
1264         unsigned int param_len = 0;
1265         char param[sizeof(pstring)+6];
1266         size_t srclen = 2*(strlen(path)+1);
1267         char *p;
1268
1269         memset(param, 0, sizeof(param));
1270         SSVAL(param,0,SMB_INFO_SET_EA);
1271         p = &param[6];
1272
1273         p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE);
1274         param_len = PTR_DIFF(p, param);
1275
1276         return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
1277 }
1278
1279 /*********************************************************
1280  Set an extended attribute on an fnum.
1281 *********************************************************/
1282
1283 BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
1284 {
1285         char param[6];
1286         uint16 setup = TRANSACT2_SETFILEINFO;
1287
1288         memset(param, 0, 6);
1289         SSVAL(param,0,fnum);
1290         SSVAL(param,2,SMB_INFO_SET_EA);
1291
1292         return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
1293 }
1294
1295 /*********************************************************
1296  Get an extended attribute list tility fn.
1297 *********************************************************/
1298
1299 static BOOL cli_get_ea_list(struct cli_state *cli,
1300                 uint16 setup, char *param, unsigned int param_len,
1301                 TALLOC_CTX *ctx,
1302                 size_t *pnum_eas,
1303                 struct ea_struct **pea_list)
1304 {
1305         unsigned int data_len = 0;
1306         unsigned int rparam_len, rdata_len;
1307         char *rparam=NULL, *rdata=NULL;
1308         char *p;
1309         size_t ea_size;
1310         size_t num_eas;
1311         BOOL ret = False;
1312         struct ea_struct *ea_list;
1313
1314         *pnum_eas = 0;
1315         *pea_list = NULL;
1316
1317         if (!cli_send_trans(cli, SMBtrans2,
1318                         NULL,           /* Name */
1319                         -1, 0,          /* fid, flags */
1320                         &setup, 1, 0,   /* setup, length, max */
1321                         param, param_len, 10, /* param, length, max */
1322                         NULL, data_len, cli->max_xmit /* data, length, max */
1323                                 )) {
1324                 return False;
1325         }
1326
1327         if (!cli_receive_trans(cli, SMBtrans2,
1328                         &rparam, &rparam_len,
1329                         &rdata, &rdata_len)) {
1330                 return False;
1331         }
1332
1333         if (!rdata || rdata_len < 4) {
1334                 goto out;
1335         }
1336
1337         ea_size = (size_t)IVAL(rdata,0);
1338         if (ea_size > rdata_len) {
1339                 goto out;
1340         }
1341
1342         if (ea_size == 0) {
1343                 /* No EA's present. */
1344                 ret = True;
1345                 goto out;
1346         }
1347
1348         p = rdata + 4;
1349         ea_size -= 4;
1350
1351         /* Validate the EA list and count it. */
1352         for (num_eas = 0; ea_size >= 4; num_eas++) {
1353                 unsigned int ea_namelen = CVAL(p,1);
1354                 unsigned int ea_valuelen = SVAL(p,2);
1355                 if (ea_namelen == 0) {
1356                         goto out;
1357                 }
1358                 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
1359                         goto out;
1360                 }
1361                 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
1362                 p += 4 + ea_namelen + 1 + ea_valuelen;
1363         }
1364
1365         if (num_eas == 0) {
1366                 ret = True;
1367                 goto out;
1368         }
1369
1370         *pnum_eas = num_eas;
1371         if (!pea_list) {
1372                 /* Caller only wants number of EA's. */
1373                 ret = True;
1374                 goto out;
1375         }
1376
1377         ea_list = (struct ea_struct *)talloc(ctx, num_eas*sizeof(struct ea_struct));
1378         if (!ea_list) {
1379                 goto out;
1380         }
1381
1382         ea_size = (size_t)IVAL(rdata,0);
1383         p = rdata + 4;
1384
1385         for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
1386                 struct ea_struct *ea = &ea_list[num_eas];
1387                 fstring unix_ea_name;
1388                 unsigned int ea_namelen = CVAL(p,1);
1389                 unsigned int ea_valuelen = SVAL(p,2);
1390
1391                 ea->flags = CVAL(p,0);
1392                 unix_ea_name[0] = '\0';
1393                 pull_ascii_fstring(unix_ea_name, p + 4);
1394                 ea->name = talloc_strdup(ctx, unix_ea_name);
1395                 /* Ensure the value is null terminated (in case it's a string). */
1396                 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
1397                 if (!ea->value.data) {
1398                         goto out;
1399                 }
1400                 if (ea_valuelen) {
1401                         memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
1402                 }
1403                 ea->value.data[ea_valuelen] = 0;
1404                 ea->value.length--;
1405                 p += 4 + ea_namelen + 1 + ea_valuelen;
1406         }
1407
1408         *pea_list = ea_list;
1409         ret = True;
1410
1411  out :
1412
1413         SAFE_FREE(rdata);
1414         SAFE_FREE(rparam);
1415         return ret;
1416 }
1417
1418 /*********************************************************
1419  Get an extended attribute list from a pathname.
1420 *********************************************************/
1421
1422 BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
1423                 TALLOC_CTX *ctx,
1424                 size_t *pnum_eas,
1425                 struct ea_struct **pea_list)
1426 {
1427         uint16 setup = TRANSACT2_QPATHINFO;
1428         unsigned int param_len = 0;
1429         char param[sizeof(pstring)+6];
1430         char *p;
1431
1432         p = param;
1433         memset(p, 0, 6);
1434         SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
1435         p += 6;
1436         p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
1437         param_len = PTR_DIFF(p, param);
1438
1439         return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
1440 }
1441
1442 /*********************************************************
1443  Get an extended attribute list from an fnum.
1444 *********************************************************/
1445
1446 BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
1447                 TALLOC_CTX *ctx,
1448                 size_t *pnum_eas,
1449                 struct ea_struct **pea_list)
1450 {
1451         uint16 setup = TRANSACT2_QFILEINFO;
1452         char param[6];
1453
1454         memset(param, 0, 6);
1455         SSVAL(param,0,fnum);
1456         SSVAL(param,2,SMB_INFO_SET_EA);
1457
1458         return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
1459 }