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