2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
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.
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.
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.
26 /****************************************************************************
28 ****************************************************************************/
30 BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
34 memset(cli->outbuf,'\0',smb_size);
35 memset(cli->inbuf,'\0',smb_size);
37 set_message(cli->outbuf,1, 0, True);
39 CVAL(cli->outbuf,smb_com) = SMBmv;
40 SSVAL(cli->outbuf,smb_tid,cli->cnum);
41 cli_setup_packet(cli);
43 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
45 p = smb_buf(cli->outbuf);
47 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
49 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
51 cli_setup_bcc(cli, p);
54 if (!cli_receive_smb(cli))
57 if (cli_is_error(cli))
63 /****************************************************************************
65 ****************************************************************************/
67 BOOL cli_unlink(struct cli_state *cli, const char *fname)
71 memset(cli->outbuf,'\0',smb_size);
72 memset(cli->inbuf,'\0',smb_size);
74 set_message(cli->outbuf,1, 0,True);
76 CVAL(cli->outbuf,smb_com) = SMBunlink;
77 SSVAL(cli->outbuf,smb_tid,cli->cnum);
78 cli_setup_packet(cli);
80 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
82 p = smb_buf(cli->outbuf);
84 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
86 cli_setup_bcc(cli, p);
88 if (!cli_receive_smb(cli)) {
92 if (cli_is_error(cli)) {
99 /****************************************************************************
101 ****************************************************************************/
103 BOOL cli_mkdir(struct cli_state *cli, const char *dname)
107 memset(cli->outbuf,'\0',smb_size);
108 memset(cli->inbuf,'\0',smb_size);
110 set_message(cli->outbuf,0, 0,True);
112 CVAL(cli->outbuf,smb_com) = SMBmkdir;
113 SSVAL(cli->outbuf,smb_tid,cli->cnum);
114 cli_setup_packet(cli);
116 p = smb_buf(cli->outbuf);
118 p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
120 cli_setup_bcc(cli, p);
123 if (!cli_receive_smb(cli)) {
127 if (cli_is_error(cli)) {
134 /****************************************************************************
136 ****************************************************************************/
138 BOOL cli_rmdir(struct cli_state *cli, const char *dname)
142 memset(cli->outbuf,'\0',smb_size);
143 memset(cli->inbuf,'\0',smb_size);
145 set_message(cli->outbuf,0, 0, True);
147 CVAL(cli->outbuf,smb_com) = SMBrmdir;
148 SSVAL(cli->outbuf,smb_tid,cli->cnum);
149 cli_setup_packet(cli);
151 p = smb_buf(cli->outbuf);
153 p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
155 cli_setup_bcc(cli, p);
158 if (!cli_receive_smb(cli)) {
162 if (cli_is_error(cli)) {
169 /****************************************************************************
170 Set or clear the delete on close flag.
171 ****************************************************************************/
173 int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
177 uint16 setup = TRANSACT2_SETFILEINFO;
180 char *rparam=NULL, *rdata=NULL;
182 memset(param, 0, param_len);
184 SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
188 if (!cli_send_trans(cli, SMBtrans2,
190 -1, 0, /* fid, flags */
191 &setup, 1, 0, /* setup, length, max */
192 param, param_len, 2, /* param, length, max */
193 (char *)&data, data_len, cli->max_xmit /* data, length, max */
198 if (!cli_receive_trans(cli, SMBtrans2,
200 &rdata, &data_len)) {
210 /****************************************************************************
211 Open a file - exposing the full horror of the NT API :-).
213 ****************************************************************************/
215 int cli_nt_create_full(struct cli_state *cli, const char *fname, uint32 DesiredAccess,
216 uint32 FileAttributes, uint32 ShareAccess,
217 uint32 CreateDisposition, uint32 CreateOptions)
222 memset(cli->outbuf,'\0',smb_size);
223 memset(cli->inbuf,'\0',smb_size);
225 set_message(cli->outbuf,24,0,True);
227 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
228 SSVAL(cli->outbuf,smb_tid,cli->cnum);
229 cli_setup_packet(cli);
231 SSVAL(cli->outbuf,smb_vwv0,0xFF);
232 if (cli->use_oplocks)
233 SIVAL(cli->outbuf,smb_ntcreate_Flags, REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
235 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0);
236 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
237 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
238 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
239 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
240 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
241 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
242 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
244 p = smb_buf(cli->outbuf);
245 /* this alignment and termination is critical for netapp filers. Don't change */
246 p += clistr_align_out(cli, p, 0);
247 len = clistr_push(cli, p, fname, -1, 0);
249 SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
250 /* sigh. this copes with broken netapp filer behaviour */
251 p += clistr_push(cli, p, "", -1, STR_TERMINATE);
253 cli_setup_bcc(cli, p);
256 if (!cli_receive_smb(cli)) {
260 if (cli_is_error(cli)) {
264 return SVAL(cli->inbuf,smb_vwv2 + 1);
267 /****************************************************************************
269 ****************************************************************************/
271 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
273 return cli_nt_create_full(cli, fname, DesiredAccess, 0,
274 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0);
277 /****************************************************************************
279 WARNING: if you open with O_WRONLY then getattrE won't work!
280 ****************************************************************************/
282 int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
286 unsigned accessmode=0;
290 if (!(flags & O_EXCL)) {
297 accessmode = (share_mode<<4);
299 if ((flags & O_ACCMODE) == O_RDWR) {
301 } else if ((flags & O_ACCMODE) == O_WRONLY) {
306 if ((flags & O_SYNC) == O_SYNC) {
307 accessmode |= (1<<14);
311 if (share_mode == DENY_FCB) {
315 memset(cli->outbuf,'\0',smb_size);
316 memset(cli->inbuf,'\0',smb_size);
318 set_message(cli->outbuf,15,0,True);
320 CVAL(cli->outbuf,smb_com) = SMBopenX;
321 SSVAL(cli->outbuf,smb_tid,cli->cnum);
322 cli_setup_packet(cli);
324 SSVAL(cli->outbuf,smb_vwv0,0xFF);
325 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
326 SSVAL(cli->outbuf,smb_vwv3,accessmode);
327 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
328 SSVAL(cli->outbuf,smb_vwv5,0);
329 SSVAL(cli->outbuf,smb_vwv8,openfn);
331 if (cli->use_oplocks) {
332 /* if using oplocks then ask for a batch oplock via
333 core and extended methods */
334 CVAL(cli->outbuf,smb_flg) |=
335 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
336 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
339 p = smb_buf(cli->outbuf);
340 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
342 cli_setup_bcc(cli, p);
345 if (!cli_receive_smb(cli)) {
349 if (cli_is_error(cli)) {
353 return SVAL(cli->inbuf,smb_vwv2);
356 /****************************************************************************
358 ****************************************************************************/
360 BOOL cli_close(struct cli_state *cli, int fnum)
362 memset(cli->outbuf,'\0',smb_size);
363 memset(cli->inbuf,'\0',smb_size);
365 set_message(cli->outbuf,3,0,True);
367 CVAL(cli->outbuf,smb_com) = SMBclose;
368 SSVAL(cli->outbuf,smb_tid,cli->cnum);
369 cli_setup_packet(cli);
371 SSVAL(cli->outbuf,smb_vwv0,fnum);
372 SIVALS(cli->outbuf,smb_vwv1,-1);
375 if (!cli_receive_smb(cli)) {
379 return !cli_is_error(cli);
382 /****************************************************************************
384 ****************************************************************************/
386 BOOL cli_lock(struct cli_state *cli, int fnum,
387 uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
390 int saved_timeout = cli->timeout;
392 memset(cli->outbuf,'\0',smb_size);
393 memset(cli->inbuf,'\0', smb_size);
395 set_message(cli->outbuf,8,0,True);
397 CVAL(cli->outbuf,smb_com) = SMBlockingX;
398 SSVAL(cli->outbuf,smb_tid,cli->cnum);
399 cli_setup_packet(cli);
401 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
402 SSVAL(cli->outbuf,smb_vwv2,fnum);
403 CVAL(cli->outbuf,smb_vwv3) = (lock_type == READ_LOCK? 1 : 0);
404 SIVALS(cli->outbuf, smb_vwv4, timeout);
405 SSVAL(cli->outbuf,smb_vwv6,0);
406 SSVAL(cli->outbuf,smb_vwv7,1);
408 p = smb_buf(cli->outbuf);
409 SSVAL(p, 0, cli->pid);
415 cli_setup_bcc(cli, p);
419 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
421 if (!cli_receive_smb(cli)) {
422 cli->timeout = saved_timeout;
426 cli->timeout = saved_timeout;
428 if (cli_is_error(cli)) {
435 /****************************************************************************
437 ****************************************************************************/
439 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
443 memset(cli->outbuf,'\0',smb_size);
444 memset(cli->inbuf,'\0',smb_size);
446 set_message(cli->outbuf,8,0,True);
448 CVAL(cli->outbuf,smb_com) = SMBlockingX;
449 SSVAL(cli->outbuf,smb_tid,cli->cnum);
450 cli_setup_packet(cli);
452 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
453 SSVAL(cli->outbuf,smb_vwv2,fnum);
454 CVAL(cli->outbuf,smb_vwv3) = 0;
455 SIVALS(cli->outbuf, smb_vwv4, 0);
456 SSVAL(cli->outbuf,smb_vwv6,1);
457 SSVAL(cli->outbuf,smb_vwv7,0);
459 p = smb_buf(cli->outbuf);
460 SSVAL(p, 0, cli->pid);
464 cli_setup_bcc(cli, p);
466 if (!cli_receive_smb(cli)) {
470 if (cli_is_error(cli)) {
477 /****************************************************************************
478 Lock a file with 64 bit offsets.
479 ****************************************************************************/
481 BOOL cli_lock64(struct cli_state *cli, int fnum,
482 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
485 int saved_timeout = cli->timeout;
488 if (! (cli->capabilities & CAP_LARGE_FILES)) {
489 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
492 ltype = (lock_type == READ_LOCK? 1 : 0);
493 ltype |= LOCKING_ANDX_LARGE_FILES;
495 memset(cli->outbuf,'\0',smb_size);
496 memset(cli->inbuf,'\0', smb_size);
498 set_message(cli->outbuf,8,0,True);
500 CVAL(cli->outbuf,smb_com) = SMBlockingX;
501 SSVAL(cli->outbuf,smb_tid,cli->cnum);
502 cli_setup_packet(cli);
504 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
505 SSVAL(cli->outbuf,smb_vwv2,fnum);
506 CVAL(cli->outbuf,smb_vwv3) = ltype;
507 SIVALS(cli->outbuf, smb_vwv4, timeout);
508 SSVAL(cli->outbuf,smb_vwv6,0);
509 SSVAL(cli->outbuf,smb_vwv7,1);
511 p = smb_buf(cli->outbuf);
512 SIVAL(p, 0, cli->pid);
513 SOFF_T_R(p, 4, offset);
514 SOFF_T_R(p, 12, len);
517 cli_setup_bcc(cli, p);
520 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
522 if (!cli_receive_smb(cli)) {
523 cli->timeout = saved_timeout;
527 cli->timeout = saved_timeout;
529 if (cli_is_error(cli)) {
536 /****************************************************************************
537 Unlock a file with 64 bit offsets.
538 ****************************************************************************/
540 BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
544 if (! (cli->capabilities & CAP_LARGE_FILES)) {
545 return cli_unlock(cli, fnum, offset, len);
548 memset(cli->outbuf,'\0',smb_size);
549 memset(cli->inbuf,'\0',smb_size);
551 set_message(cli->outbuf,8,0,True);
553 CVAL(cli->outbuf,smb_com) = SMBlockingX;
554 SSVAL(cli->outbuf,smb_tid,cli->cnum);
555 cli_setup_packet(cli);
557 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
558 SSVAL(cli->outbuf,smb_vwv2,fnum);
559 CVAL(cli->outbuf,smb_vwv3) = LOCKING_ANDX_LARGE_FILES;
560 SIVALS(cli->outbuf, smb_vwv4, 0);
561 SSVAL(cli->outbuf,smb_vwv6,1);
562 SSVAL(cli->outbuf,smb_vwv7,0);
564 p = smb_buf(cli->outbuf);
565 SIVAL(p, 0, cli->pid);
566 SOFF_T_R(p, 4, offset);
567 SOFF_T_R(p, 12, len);
569 cli_setup_bcc(cli, p);
571 if (!cli_receive_smb(cli)) {
575 if (cli_is_error(cli)) {
582 /****************************************************************************
583 Do a SMBgetattrE call.
584 ****************************************************************************/
586 BOOL cli_getattrE(struct cli_state *cli, int fd,
587 uint16 *attr, size_t *size,
588 time_t *c_time, time_t *a_time, time_t *m_time)
590 memset(cli->outbuf,'\0',smb_size);
591 memset(cli->inbuf,'\0',smb_size);
593 set_message(cli->outbuf,1,0,True);
595 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
596 SSVAL(cli->outbuf,smb_tid,cli->cnum);
597 cli_setup_packet(cli);
599 SSVAL(cli->outbuf,smb_vwv0,fd);
602 if (!cli_receive_smb(cli)) {
606 if (cli_is_error(cli)) {
611 *size = IVAL(cli->inbuf, smb_vwv6);
615 *attr = SVAL(cli->inbuf,smb_vwv10);
619 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
623 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
627 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
633 /****************************************************************************
635 ****************************************************************************/
637 BOOL cli_getatr(struct cli_state *cli, const char *fname,
638 uint16 *attr, size_t *size, time_t *t)
642 memset(cli->outbuf,'\0',smb_size);
643 memset(cli->inbuf,'\0',smb_size);
645 set_message(cli->outbuf,0,0,True);
647 CVAL(cli->outbuf,smb_com) = SMBgetatr;
648 SSVAL(cli->outbuf,smb_tid,cli->cnum);
649 cli_setup_packet(cli);
651 p = smb_buf(cli->outbuf);
653 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
655 cli_setup_bcc(cli, p);
658 if (!cli_receive_smb(cli)) {
662 if (cli_is_error(cli)) {
667 *size = IVAL(cli->inbuf, smb_vwv3);
671 *t = make_unix_date3(cli->inbuf+smb_vwv1);
675 *attr = SVAL(cli->inbuf,smb_vwv0);
682 /****************************************************************************
684 ****************************************************************************/
686 BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
690 memset(cli->outbuf,'\0',smb_size);
691 memset(cli->inbuf,'\0',smb_size);
693 set_message(cli->outbuf,8,0,True);
695 CVAL(cli->outbuf,smb_com) = SMBsetatr;
696 SSVAL(cli->outbuf,smb_tid,cli->cnum);
697 cli_setup_packet(cli);
699 SSVAL(cli->outbuf,smb_vwv0, attr);
700 put_dos_date3(cli->outbuf,smb_vwv1, t);
702 p = smb_buf(cli->outbuf);
704 p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
707 cli_setup_bcc(cli, p);
710 if (!cli_receive_smb(cli)) {
714 if (cli_is_error(cli)) {
721 /****************************************************************************
722 Check for existance of a dir.
723 ****************************************************************************/
725 BOOL cli_chkpath(struct cli_state *cli, const char *path)
730 safe_strcpy(path2,path,sizeof(pstring));
731 trim_string(path2,NULL,"\\");
732 if (!*path2) *path2 = '\\';
734 memset(cli->outbuf,'\0',smb_size);
735 set_message(cli->outbuf,0,0,True);
736 SCVAL(cli->outbuf,smb_com,SMBchkpth);
737 SSVAL(cli->outbuf,smb_tid,cli->cnum);
738 cli_setup_packet(cli);
739 p = smb_buf(cli->outbuf);
741 p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
743 cli_setup_bcc(cli, p);
746 if (!cli_receive_smb(cli)) {
750 if (cli_is_error(cli)) return False;
755 /****************************************************************************
757 ****************************************************************************/
759 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
761 memset(cli->outbuf,'\0',smb_size);
762 set_message(cli->outbuf,0,0,True);
763 CVAL(cli->outbuf,smb_com) = SMBdskattr;
764 SSVAL(cli->outbuf,smb_tid,cli->cnum);
765 cli_setup_packet(cli);
768 if (!cli_receive_smb(cli)) {
772 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
773 *total = SVAL(cli->inbuf,smb_vwv0);
774 *avail = SVAL(cli->inbuf,smb_vwv3);
779 /****************************************************************************
780 Create and open a temporary file.
781 ****************************************************************************/
783 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
788 memset(cli->outbuf,'\0',smb_size);
789 memset(cli->inbuf,'\0',smb_size);
791 set_message(cli->outbuf,3,0,True);
793 CVAL(cli->outbuf,smb_com) = SMBctemp;
794 SSVAL(cli->outbuf,smb_tid,cli->cnum);
795 cli_setup_packet(cli);
797 SSVAL(cli->outbuf,smb_vwv0,0);
798 SIVALS(cli->outbuf,smb_vwv1,-1);
800 p = smb_buf(cli->outbuf);
802 p += clistr_push(cli, p, path, -1, STR_TERMINATE);
804 cli_setup_bcc(cli, p);
807 if (!cli_receive_smb(cli)) {
811 if (cli_is_error(cli)) {
815 /* despite the spec, the result has a -1, followed by
816 length, followed by name */
817 p = smb_buf(cli->inbuf);
819 len = smb_buflen(cli->inbuf) - 4;
820 if (len <= 0) return -1;
824 clistr_pull(cli, path2, p,
825 sizeof(path2), len, STR_ASCII);
826 *tmp_path = strdup(path2);
829 return SVAL(cli->inbuf,smb_vwv0);