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