r96: Stupid f&%'n UNIX extensions.... SETPATHINFO
[kai/samba.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 SMBsetatr call.
987 ****************************************************************************/
988
989 BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
990 {
991         char *p;
992
993         memset(cli->outbuf,'\0',smb_size);
994         memset(cli->inbuf,'\0',smb_size);
995
996         set_message(cli->outbuf,8,0,True);
997
998         SCVAL(cli->outbuf,smb_com,SMBsetatr);
999         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1000         cli_setup_packet(cli);
1001
1002         SSVAL(cli->outbuf,smb_vwv0, attr);
1003         put_dos_date3(cli->outbuf,smb_vwv1, t);
1004
1005         p = smb_buf(cli->outbuf);
1006         *p++ = 4;
1007         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
1008         *p++ = 4;
1009
1010         cli_setup_bcc(cli, p);
1011
1012         cli_send_smb(cli);
1013         if (!cli_receive_smb(cli)) {
1014                 return False;
1015         }
1016         
1017         if (cli_is_error(cli)) {
1018                 return False;
1019         }
1020
1021         return True;
1022 }
1023
1024 /****************************************************************************
1025  Check for existance of a dir.
1026 ****************************************************************************/
1027 BOOL cli_chkpath(struct cli_state *cli, const char *path)
1028 {
1029         pstring path2;
1030         char *p;
1031         
1032         pstrcpy(path2,path);
1033         trim_char(path2,'\0','\\');
1034         if (!*path2)
1035                 *path2 = '\\';
1036         
1037         memset(cli->outbuf,'\0',smb_size);
1038         set_message(cli->outbuf,0,0,True);
1039         SCVAL(cli->outbuf,smb_com,SMBchkpth);
1040         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1041         cli_setup_packet(cli);
1042         p = smb_buf(cli->outbuf);
1043         *p++ = 4;
1044         p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
1045
1046         cli_setup_bcc(cli, p);
1047
1048         cli_send_smb(cli);
1049         if (!cli_receive_smb(cli)) {
1050                 return False;
1051         }
1052
1053         if (cli_is_error(cli)) return False;
1054
1055         return True;
1056 }
1057
1058 /****************************************************************************
1059  Query disk space.
1060 ****************************************************************************/
1061
1062 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
1063 {
1064         memset(cli->outbuf,'\0',smb_size);
1065         set_message(cli->outbuf,0,0,True);
1066         SCVAL(cli->outbuf,smb_com,SMBdskattr);
1067         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1068         cli_setup_packet(cli);
1069
1070         cli_send_smb(cli);
1071         if (!cli_receive_smb(cli)) {
1072                 return False;
1073         }
1074
1075         *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
1076         *total = SVAL(cli->inbuf,smb_vwv0);
1077         *avail = SVAL(cli->inbuf,smb_vwv3);
1078         
1079         return True;
1080 }
1081
1082 /****************************************************************************
1083  Create and open a temporary file.
1084 ****************************************************************************/
1085
1086 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
1087 {
1088         int len;
1089         char *p;
1090
1091         memset(cli->outbuf,'\0',smb_size);
1092         memset(cli->inbuf,'\0',smb_size);
1093
1094         set_message(cli->outbuf,3,0,True);
1095
1096         SCVAL(cli->outbuf,smb_com,SMBctemp);
1097         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1098         cli_setup_packet(cli);
1099
1100         SSVAL(cli->outbuf,smb_vwv0,0);
1101         SIVALS(cli->outbuf,smb_vwv1,-1);
1102
1103         p = smb_buf(cli->outbuf);
1104         *p++ = 4;
1105         p += clistr_push(cli, p, path, -1, STR_TERMINATE);
1106
1107         cli_setup_bcc(cli, p);
1108
1109         cli_send_smb(cli);
1110         if (!cli_receive_smb(cli)) {
1111                 return -1;
1112         }
1113
1114         if (cli_is_error(cli)) {
1115                 return -1;
1116         }
1117
1118         /* despite the spec, the result has a -1, followed by
1119            length, followed by name */
1120         p = smb_buf(cli->inbuf);
1121         p += 4;
1122         len = smb_buflen(cli->inbuf) - 4;
1123         if (len <= 0) return -1;
1124
1125         if (tmp_path) {
1126                 pstring path2;
1127                 clistr_pull(cli, path2, p, 
1128                             sizeof(path2), len, STR_ASCII);
1129                 *tmp_path = strdup(path2);
1130         }
1131
1132         return SVAL(cli->inbuf,smb_vwv0);
1133 }
1134
1135
1136 /* 
1137    send a raw ioctl - used by the torture code
1138 */
1139 NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob)
1140 {
1141         memset(cli->outbuf,'\0',smb_size);
1142         memset(cli->inbuf,'\0',smb_size);
1143
1144         set_message(cli->outbuf, 3, 0, True);
1145         SCVAL(cli->outbuf,smb_com,SMBioctl);
1146         cli_setup_packet(cli);
1147
1148         SSVAL(cli->outbuf, smb_vwv0, fnum);
1149         SSVAL(cli->outbuf, smb_vwv1, code>>16);
1150         SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
1151
1152         cli_send_smb(cli);
1153         if (!cli_receive_smb(cli)) {
1154                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1155         }
1156
1157         if (cli_is_error(cli)) {
1158                 return cli_nt_error(cli);
1159         }
1160
1161         *blob = data_blob(NULL, 0);
1162
1163         return NT_STATUS_OK;
1164 }
1165
1166 /*********************************************************
1167  Set an extended attribute utility fn.
1168 *********************************************************/
1169
1170 static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
1171                         const char *ea_name, const char *ea_val, size_t ea_len)
1172 {       
1173         unsigned int data_len = 0;
1174         char *data = NULL;
1175         char *rparam=NULL, *rdata=NULL;
1176         char *p;
1177         size_t ea_namelen = strlen(ea_name);
1178
1179         data_len = 4 + 4 + ea_namelen + 1 + ea_len;
1180         data = malloc(data_len);
1181         if (!data) {
1182                 return False;
1183         }
1184         p = data;
1185         SIVAL(p,0,data_len);
1186         p += 4;
1187         SCVAL(p, 0, 0); /* EA flags. */
1188         SCVAL(p, 1, ea_namelen);
1189         SSVAL(p, 2, ea_len);
1190         memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
1191         memcpy(p+4+ea_namelen+1, ea_val, ea_len);
1192
1193         if (!cli_send_trans(cli, SMBtrans2,
1194                 NULL,                        /* name */
1195                 -1, 0,                          /* fid, flags */
1196                 &setup, 1, 0,                   /* setup, length, max */
1197                 param, param_len, 2,            /* param, length, max */
1198                 data,  data_len, cli->max_xmit /* data, length, max */
1199                 )) {
1200                         return False;
1201         }
1202
1203         if (!cli_receive_trans(cli, SMBtrans2,
1204                 &rparam, &param_len,
1205                 &rdata, &data_len)) {
1206                         return False;
1207         }
1208
1209         SAFE_FREE(data);
1210         SAFE_FREE(rdata);
1211         SAFE_FREE(rparam);
1212
1213         return True;
1214 }
1215
1216 /*********************************************************
1217  Set an extended attribute on a pathname.
1218 *********************************************************/
1219
1220 BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
1221 {
1222         uint16 setup = TRANSACT2_SETPATHINFO;
1223         unsigned int param_len = 0;
1224         char param[sizeof(pstring)+6];
1225         size_t srclen = 2*(strlen(path)+1);
1226         char *p;
1227
1228         memset(param, 0, sizeof(param));
1229         SSVAL(param,0,SMB_INFO_SET_EA);
1230         p = &param[6];
1231
1232         p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE);
1233         param_len = PTR_DIFF(p, param);
1234
1235         return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
1236 }
1237
1238 /*********************************************************
1239  Set an extended attribute on an fnum.
1240 *********************************************************/
1241
1242 BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
1243 {
1244         char param[6];
1245         uint16 setup = TRANSACT2_SETFILEINFO;
1246
1247         memset(param, 0, 6);
1248         SSVAL(param,0,fnum);
1249         SSVAL(param,2,SMB_INFO_SET_EA);
1250
1251         return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
1252 }
1253
1254 /*********************************************************
1255  Get an extended attribute list tility fn.
1256 *********************************************************/
1257
1258 static BOOL cli_get_ea_list(struct cli_state *cli,
1259                 uint16 setup, char *param, unsigned int param_len,
1260                 TALLOC_CTX *ctx,
1261                 size_t *pnum_eas,
1262                 struct ea_struct **pea_list)
1263 {
1264         unsigned int data_len = 0;
1265         unsigned int rparam_len, rdata_len;
1266         char *rparam=NULL, *rdata=NULL;
1267         char *p;
1268         size_t ea_size;
1269         size_t num_eas;
1270         BOOL ret = False;
1271         struct ea_struct *ea_list;
1272
1273         *pnum_eas = 0;
1274         *pea_list = NULL;
1275
1276         if (!cli_send_trans(cli, SMBtrans2,
1277                         NULL,           /* Name */
1278                         -1, 0,          /* fid, flags */
1279                         &setup, 1, 0,   /* setup, length, max */
1280                         param, param_len, 10, /* param, length, max */
1281                         NULL, data_len, cli->max_xmit /* data, length, max */
1282                                 )) {
1283                 return False;
1284         }
1285
1286         if (!cli_receive_trans(cli, SMBtrans2,
1287                         &rparam, &rparam_len,
1288                         &rdata, &rdata_len)) {
1289                 return False;
1290         }
1291
1292         if (!rdata || rdata_len < 4) {
1293                 goto out;
1294         }
1295
1296         ea_size = (size_t)IVAL(rdata,0);
1297         if (ea_size > rdata_len) {
1298                 goto out;
1299         }
1300
1301         if (ea_size == 0) {
1302                 /* No EA's present. */
1303                 ret = True;
1304                 goto out;
1305         }
1306
1307         p = rdata + 4;
1308         ea_size -= 4;
1309
1310         /* Validate the EA list and count it. */
1311         for (num_eas = 0; ea_size >= 4; num_eas++) {
1312                 unsigned int ea_namelen = CVAL(p,1);
1313                 unsigned int ea_valuelen = SVAL(p,2);
1314                 if (ea_namelen == 0) {
1315                         goto out;
1316                 }
1317                 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
1318                         goto out;
1319                 }
1320                 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
1321                 p += 4 + ea_namelen + 1 + ea_valuelen;
1322         }
1323
1324         if (num_eas == 0) {
1325                 ret = True;
1326                 goto out;
1327         }
1328
1329         *pnum_eas = num_eas;
1330         if (!pea_list) {
1331                 /* Caller only wants number of EA's. */
1332                 ret = True;
1333                 goto out;
1334         }
1335
1336         ea_list = (struct ea_struct *)talloc(ctx, num_eas*sizeof(struct ea_struct));
1337         if (!ea_list) {
1338                 goto out;
1339         }
1340
1341         ea_size = (size_t)IVAL(rdata,0);
1342         p = rdata + 4;
1343
1344         for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
1345                 struct ea_struct *ea = &ea_list[num_eas];
1346                 fstring unix_ea_name;
1347                 unsigned int ea_namelen = CVAL(p,1);
1348                 unsigned int ea_valuelen = SVAL(p,2);
1349
1350                 ea->flags = CVAL(p,0);
1351                 unix_ea_name[0] = '\0';
1352                 pull_ascii_fstring(unix_ea_name, p + 4);
1353                 ea->name = talloc_strdup(ctx, unix_ea_name);
1354                 /* Ensure the value is null terminated (in case it's a string). */
1355                 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
1356                 if (!ea->value.data) {
1357                         goto out;
1358                 }
1359                 if (ea_valuelen) {
1360                         memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
1361                 }
1362                 ea->value.data[ea_valuelen] = 0;
1363                 ea->value.length--;
1364                 p += 4 + ea_namelen + 1 + ea_valuelen;
1365         }
1366
1367         *pea_list = ea_list;
1368         ret = True;
1369
1370  out :
1371
1372         SAFE_FREE(rdata);
1373         SAFE_FREE(rparam);
1374         return ret;
1375 }
1376
1377 /*********************************************************
1378  Get an extended attribute list from a pathname.
1379 *********************************************************/
1380
1381 BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
1382                 TALLOC_CTX *ctx,
1383                 size_t *pnum_eas,
1384                 struct ea_struct **pea_list)
1385 {
1386         uint16 setup = TRANSACT2_QPATHINFO;
1387         unsigned int param_len = 0;
1388         char param[sizeof(pstring)+6];
1389         char *p;
1390
1391         p = param;
1392         memset(p, 0, 6);
1393         SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
1394         p += 6;
1395         p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
1396         param_len = PTR_DIFF(p, param);
1397
1398         return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
1399 }
1400
1401 /*********************************************************
1402  Get an extended attribute list from an fnum.
1403 *********************************************************/
1404
1405 BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
1406                 TALLOC_CTX *ctx,
1407                 size_t *pnum_eas,
1408                 struct ea_struct **pea_list)
1409 {
1410         uint16 setup = TRANSACT2_QFILEINFO;
1411         char param[6];
1412
1413         memset(param, 0, 6);
1414         SSVAL(param,0,fnum);
1415         SSVAL(param,2,SMB_INFO_SET_EA);
1416
1417         return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
1418 }