Enable checking/resetting of account lockout and bad password based on policy
[Samba/gebeck_regimport.git] / source / smbd / reply.c
blobc4ff77bd8664a8fece6c5fb4cf24141e8d2711ff
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
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.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
26 #include "includes.h"
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K.
43 ****************************************************************************/
45 NTSTATUS check_path_syntax(const char *name)
47 while (*name == '\\' || *name == '/')
48 name++;
49 if (name[0] == '.' && name[1] == '\0')
50 return NT_STATUS_OBJECT_NAME_INVALID;
51 else if (name[0] == '.' && name[1] == '.' &&
52 (name[2] == '\\' || name [2] == '/' || name[2] == '\0'))
53 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
54 return NT_STATUS_OK;
57 /****************************************************************************
58 Pull a string and check the path - provide for error return.
59 ****************************************************************************/
61 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err)
63 size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
64 *err = check_path_syntax(dest);
65 return ret;
68 /****************************************************************************
69 Reply to a special message.
70 ****************************************************************************/
72 int reply_special(char *inbuf,char *outbuf)
74 int outsize = 4;
75 int msg_type = CVAL(inbuf,0);
76 int msg_flags = CVAL(inbuf,1);
77 pstring name1,name2;
78 char name_type = 0;
80 static BOOL already_got_session = False;
82 *name1 = *name2 = 0;
84 memset(outbuf,'\0',smb_size);
86 smb_setlen(outbuf,0);
88 switch (msg_type) {
89 case 0x81: /* session request */
91 if (already_got_session) {
92 exit_server("multiple session request not permitted");
95 SCVAL(outbuf,0,0x82);
96 SCVAL(outbuf,3,0);
97 if (name_len(inbuf+4) > 50 ||
98 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
99 DEBUG(0,("Invalid name length in session request\n"));
100 return(0);
102 name_extract(inbuf,4,name1);
103 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
104 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
105 name1,name2));
107 set_local_machine_name(name1, True);
108 set_remote_machine_name(name2, True);
110 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
111 get_local_machine_name(), get_remote_machine_name(),
112 name_type));
114 if (name_type == 'R') {
115 /* We are being asked for a pathworks session ---
116 no thanks! */
117 SCVAL(outbuf, 0,0x83);
118 break;
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE) {
125 add_session_user(get_remote_machine_name());
128 reload_services(True);
129 reopen_logs();
131 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
133 already_got_session = True;
134 break;
136 case 0x89: /* session keepalive request
137 (some old clients produce this?) */
138 SCVAL(outbuf,0,SMBkeepalive);
139 SCVAL(outbuf,3,0);
140 break;
142 case 0x82: /* positive session response */
143 case 0x83: /* negative session response */
144 case 0x84: /* retarget session response */
145 DEBUG(0,("Unexpected session response\n"));
146 break;
148 case SMBkeepalive: /* session keepalive */
149 default:
150 return(0);
153 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
154 msg_type, msg_flags));
156 return(outsize);
159 /****************************************************************************
160 Reply to a tcon.
161 ****************************************************************************/
163 int reply_tcon(connection_struct *conn,
164 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
166 const char *service;
167 pstring service_buf;
168 pstring password;
169 pstring dev;
170 int outsize = 0;
171 uint16 vuid = SVAL(inbuf,smb_uid);
172 int pwlen=0;
173 NTSTATUS nt_status;
174 char *p;
175 DATA_BLOB password_blob;
177 START_PROFILE(SMBtcon);
179 *service_buf = *password = *dev = 0;
181 p = smb_buf(inbuf)+1;
182 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
183 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
184 p += pwlen;
185 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
187 p = strrchr_m(service_buf,'\\');
188 if (p) {
189 service = p+1;
190 } else {
191 service = service_buf;
194 password_blob = data_blob(password, pwlen+1);
196 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
198 data_blob_clear_free(&password_blob);
200 if (!conn) {
201 END_PROFILE(SMBtcon);
202 return ERROR_NT(nt_status);
205 outsize = set_message(outbuf,2,0,True);
206 SSVAL(outbuf,smb_vwv0,max_recv);
207 SSVAL(outbuf,smb_vwv1,conn->cnum);
208 SSVAL(outbuf,smb_tid,conn->cnum);
210 DEBUG(3,("tcon service=%s cnum=%d\n",
211 service, conn->cnum));
213 END_PROFILE(SMBtcon);
214 return(outsize);
217 /****************************************************************************
218 Reply to a tcon and X.
219 ****************************************************************************/
221 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
223 fstring service;
224 DATA_BLOB password;
226 /* what the cleint thinks the device is */
227 fstring client_devicetype;
228 /* what the server tells the client the share represents */
229 const char *server_devicetype;
230 NTSTATUS nt_status;
231 uint16 vuid = SVAL(inbuf,smb_uid);
232 int passlen = SVAL(inbuf,smb_vwv3);
233 pstring path;
234 char *p, *q;
235 extern BOOL global_encrypted_passwords_negotiated;
237 START_PROFILE(SMBtconX);
239 *service = *client_devicetype = 0;
241 /* we might have to close an old one */
242 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
243 close_cnum(conn,vuid);
246 if (passlen > MAX_PASS_LEN) {
247 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
250 if (global_encrypted_passwords_negotiated) {
251 password = data_blob(smb_buf(inbuf),passlen);
252 } else {
253 password = data_blob(smb_buf(inbuf),passlen+1);
254 /* Ensure correct termination */
255 password.data[passlen]=0;
258 p = smb_buf(inbuf) + passlen;
259 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
262 * the service name can be either: \\server\share
263 * or share directly like on the DELL PowerVault 705
265 if (*path=='\\') {
266 q = strchr_m(path+2,'\\');
267 if (!q) {
268 END_PROFILE(SMBtconX);
269 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
271 fstrcpy(service,q+1);
273 else
274 fstrcpy(service,path);
276 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
278 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
280 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
282 data_blob_clear_free(&password);
284 if (!conn) {
285 END_PROFILE(SMBtconX);
286 return ERROR_NT(nt_status);
289 if ( IS_IPC(conn) )
290 server_devicetype = "IPC";
291 else if ( IS_PRINT(conn) )
292 server_devicetype = "LPT1:";
293 else
294 server_devicetype = "A:";
296 if (Protocol < PROTOCOL_NT1) {
297 set_message(outbuf,2,0,True);
298 p = smb_buf(outbuf);
299 p += srvstr_push(outbuf, p, server_devicetype, -1,
300 STR_TERMINATE|STR_ASCII);
301 set_message_end(outbuf,p);
302 } else {
303 /* NT sets the fstype of IPC$ to the null string */
304 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
306 set_message(outbuf,3,0,True);
308 p = smb_buf(outbuf);
309 p += srvstr_push(outbuf, p, server_devicetype, -1,
310 STR_TERMINATE|STR_ASCII);
311 p += srvstr_push(outbuf, p, fstype, -1,
312 STR_TERMINATE);
314 set_message_end(outbuf,p);
316 /* what does setting this bit do? It is set by NT4 and
317 may affect the ability to autorun mounted cdroms */
318 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
319 (lp_csc_policy(SNUM(conn)) << 2));
321 init_dfsroot(conn, inbuf, outbuf);
325 DEBUG(3,("tconX service=%s \n",
326 service));
328 /* set the incoming and outgoing tid to the just created one */
329 SSVAL(inbuf,smb_tid,conn->cnum);
330 SSVAL(outbuf,smb_tid,conn->cnum);
332 END_PROFILE(SMBtconX);
333 return chain_reply(inbuf,outbuf,length,bufsize);
336 /****************************************************************************
337 Reply to an unknown type.
338 ****************************************************************************/
340 int reply_unknown(char *inbuf,char *outbuf)
342 int type;
343 type = CVAL(inbuf,smb_com);
345 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
346 smb_fn_name(type), type, type));
348 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
351 /****************************************************************************
352 Reply to an ioctl.
353 ****************************************************************************/
355 int reply_ioctl(connection_struct *conn,
356 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
358 uint16 device = SVAL(inbuf,smb_vwv1);
359 uint16 function = SVAL(inbuf,smb_vwv2);
360 uint32 ioctl_code = (device << 16) + function;
361 int replysize, outsize;
362 char *p;
363 START_PROFILE(SMBioctl);
365 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
367 switch (ioctl_code) {
368 case IOCTL_QUERY_JOB_INFO:
369 replysize = 32;
370 break;
371 default:
372 END_PROFILE(SMBioctl);
373 return(ERROR_DOS(ERRSRV,ERRnosupport));
376 outsize = set_message(outbuf,8,replysize+1,True);
377 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
378 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
379 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
380 p = smb_buf(outbuf) + 1; /* Allow for alignment */
382 switch (ioctl_code) {
383 case IOCTL_QUERY_JOB_INFO:
385 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
386 if (!fsp) {
387 END_PROFILE(SMBioctl);
388 return(UNIXERROR(ERRDOS,ERRbadfid));
390 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
391 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
392 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
393 break;
397 END_PROFILE(SMBioctl);
398 return outsize;
401 /****************************************************************************
402 Reply to a chkpth.
403 ****************************************************************************/
405 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
407 int outsize = 0;
408 int mode;
409 pstring name;
410 BOOL ok = False;
411 BOOL bad_path = False;
412 SMB_STRUCT_STAT sbuf;
413 NTSTATUS status;
415 START_PROFILE(SMBchkpth);
417 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status);
418 if (!NT_STATUS_IS_OK(status)) {
419 END_PROFILE(SMBchkpth);
420 return ERROR_NT(status);
423 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
425 unix_convert(name,conn,0,&bad_path,&sbuf);
427 mode = SVAL(inbuf,smb_vwv0);
429 if (check_name(name,conn)) {
430 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
431 if (!(ok = S_ISDIR(sbuf.st_mode))) {
432 END_PROFILE(SMBchkpth);
433 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
437 if (!ok) {
438 /* We special case this - as when a Windows machine
439 is parsing a path is steps through the components
440 one at a time - if a component fails it expects
441 ERRbadpath, not ERRbadfile.
443 if(errno == ENOENT) {
445 * Windows returns different error codes if
446 * the parent directory is valid but not the
447 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
448 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
449 * if the path is invalid.
451 if (bad_path) {
452 END_PROFILE(SMBchkpth);
453 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
454 } else {
455 END_PROFILE(SMBchkpth);
456 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
458 } else if (errno == ENOTDIR) {
459 END_PROFILE(SMBchkpth);
460 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
463 END_PROFILE(SMBchkpth);
464 return(UNIXERROR(ERRDOS,ERRbadpath));
467 outsize = set_message(outbuf,0,0,True);
469 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
471 END_PROFILE(SMBchkpth);
472 return(outsize);
475 /****************************************************************************
476 Reply to a getatr.
477 ****************************************************************************/
479 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
481 pstring fname;
482 int outsize = 0;
483 SMB_STRUCT_STAT sbuf;
484 BOOL ok = False;
485 int mode=0;
486 SMB_OFF_T size=0;
487 time_t mtime=0;
488 BOOL bad_path = False;
489 char *p;
490 NTSTATUS status;
492 START_PROFILE(SMBgetatr);
494 p = smb_buf(inbuf) + 1;
495 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
496 if (!NT_STATUS_IS_OK(status)) {
497 END_PROFILE(SMBgetatr);
498 return ERROR_NT(status);
501 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
503 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
504 under WfWg - weird! */
505 if (! (*fname)) {
506 mode = aHIDDEN | aDIR;
507 if (!CAN_WRITE(conn))
508 mode |= aRONLY;
509 size = 0;
510 mtime = 0;
511 ok = True;
512 } else {
513 unix_convert(fname,conn,0,&bad_path,&sbuf);
514 if (check_name(fname,conn)) {
515 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
516 mode = dos_mode(conn,fname,&sbuf);
517 size = sbuf.st_size;
518 mtime = sbuf.st_mtime;
519 if (mode & aDIR)
520 size = 0;
521 ok = True;
522 } else {
523 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
528 if (!ok) {
529 END_PROFILE(SMBgetatr);
530 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
533 outsize = set_message(outbuf,10,0,True);
535 SSVAL(outbuf,smb_vwv0,mode);
536 if(lp_dos_filetime_resolution(SNUM(conn)) )
537 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
538 else
539 put_dos_date3(outbuf,smb_vwv1,mtime);
540 SIVAL(outbuf,smb_vwv3,(uint32)size);
542 if (Protocol >= PROTOCOL_NT1)
543 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
545 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
547 END_PROFILE(SMBgetatr);
548 return(outsize);
551 /****************************************************************************
552 Reply to a setatr.
553 ****************************************************************************/
555 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
557 pstring fname;
558 int outsize = 0;
559 BOOL ok=False;
560 int mode;
561 time_t mtime;
562 SMB_STRUCT_STAT sbuf;
563 BOOL bad_path = False;
564 char *p;
565 NTSTATUS status;
567 START_PROFILE(SMBsetatr);
569 p = smb_buf(inbuf) + 1;
570 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
571 if (!NT_STATUS_IS_OK(status)) {
572 END_PROFILE(SMBsetatr);
573 return ERROR_NT(status);
576 unix_convert(fname,conn,0,&bad_path,&sbuf);
578 mode = SVAL(inbuf,smb_vwv0);
579 mtime = make_unix_date3(inbuf+smb_vwv1);
581 if (mode != FILE_ATTRIBUTE_NORMAL) {
582 if (VALID_STAT_OF_DIR(sbuf))
583 mode |= aDIR;
584 else
585 mode &= ~aDIR;
587 if (check_name(fname,conn))
588 ok = (file_chmod(conn,fname,mode,NULL) == 0);
589 } else {
590 ok = True;
593 if (ok)
594 ok = set_filetime(conn,fname,mtime);
596 if (!ok) {
597 END_PROFILE(SMBsetatr);
598 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
601 outsize = set_message(outbuf,0,0,True);
603 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
605 END_PROFILE(SMBsetatr);
606 return(outsize);
609 /****************************************************************************
610 Reply to a dskattr.
611 ****************************************************************************/
613 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
615 int outsize = 0;
616 SMB_BIG_UINT dfree,dsize,bsize;
617 START_PROFILE(SMBdskattr);
619 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
621 outsize = set_message(outbuf,5,0,True);
623 if (Protocol <= PROTOCOL_LANMAN2) {
624 double total_space, free_space;
625 /* we need to scale this to a number that DOS6 can handle. We
626 use floating point so we can handle large drives on systems
627 that don't have 64 bit integers
629 we end up displaying a maximum of 2G to DOS systems
631 total_space = dsize * (double)bsize;
632 free_space = dfree * (double)bsize;
634 dsize = (total_space+63*512) / (64*512);
635 dfree = (free_space+63*512) / (64*512);
637 if (dsize > 0xFFFF) dsize = 0xFFFF;
638 if (dfree > 0xFFFF) dfree = 0xFFFF;
640 SSVAL(outbuf,smb_vwv0,dsize);
641 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
642 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
643 SSVAL(outbuf,smb_vwv3,dfree);
644 } else {
645 SSVAL(outbuf,smb_vwv0,dsize);
646 SSVAL(outbuf,smb_vwv1,bsize/512);
647 SSVAL(outbuf,smb_vwv2,512);
648 SSVAL(outbuf,smb_vwv3,dfree);
651 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
653 END_PROFILE(SMBdskattr);
654 return(outsize);
657 /****************************************************************************
658 Reply to a search.
659 Can be called from SMBsearch, SMBffirst or SMBfunique.
660 ****************************************************************************/
662 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
664 pstring mask;
665 pstring directory;
666 pstring fname;
667 SMB_OFF_T size;
668 int mode;
669 time_t date;
670 int dirtype;
671 int outsize = 0;
672 unsigned int numentries = 0;
673 unsigned int maxentries = 0;
674 BOOL finished = False;
675 char *p;
676 BOOL ok = False;
677 int status_len;
678 pstring path;
679 char status[21];
680 int dptr_num= -1;
681 BOOL check_descend = False;
682 BOOL expect_close = False;
683 BOOL can_open = True;
684 BOOL bad_path = False;
685 NTSTATUS nt_status;
686 START_PROFILE(SMBsearch);
688 *mask = *directory = *fname = 0;
690 /* If we were called as SMBffirst then we must expect close. */
691 if(CVAL(inbuf,smb_com) == SMBffirst)
692 expect_close = True;
694 outsize = set_message(outbuf,1,3,True);
695 maxentries = SVAL(inbuf,smb_vwv0);
696 dirtype = SVAL(inbuf,smb_vwv1);
697 p = smb_buf(inbuf) + 1;
698 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status);
699 if (!NT_STATUS_IS_OK(nt_status)) {
700 END_PROFILE(SMBsearch);
701 return ERROR_NT(nt_status);
703 p++;
704 status_len = SVAL(p, 0);
705 p += 2;
707 /* dirtype &= ~aDIR; */
709 if (status_len == 0) {
710 SMB_STRUCT_STAT sbuf;
711 pstring dir2;
713 pstrcpy(directory,path);
714 pstrcpy(dir2,path);
715 unix_convert(directory,conn,0,&bad_path,&sbuf);
716 unix_format(dir2);
718 if (!check_name(directory,conn))
719 can_open = False;
721 p = strrchr_m(dir2,'/');
722 if (p == NULL) {
723 pstrcpy(mask,dir2);
724 *dir2 = 0;
725 } else {
726 *p = 0;
727 pstrcpy(mask,p+1);
730 p = strrchr_m(directory,'/');
731 if (!p)
732 *directory = 0;
733 else
734 *p = 0;
736 if (strlen(directory) == 0)
737 pstrcpy(directory,".");
738 memset((char *)status,'\0',21);
739 SCVAL(status,0,(dirtype & 0x1F));
740 } else {
741 int status_dirtype;
743 memcpy(status,p,21);
744 status_dirtype = CVAL(status,0) & 0x1F;
745 if (status_dirtype != (dirtype & 0x1F))
746 dirtype = status_dirtype;
748 conn->dirptr = dptr_fetch(status+12,&dptr_num);
749 if (!conn->dirptr)
750 goto SearchEmpty;
751 string_set(&conn->dirpath,dptr_path(dptr_num));
752 pstrcpy(mask, dptr_wcard(dptr_num));
755 if (can_open) {
756 p = smb_buf(outbuf) + 3;
757 ok = True;
759 if (status_len == 0) {
760 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
761 if (dptr_num < 0) {
762 if(dptr_num == -2) {
763 END_PROFILE(SMBsearch);
764 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
766 END_PROFILE(SMBsearch);
767 return ERROR_DOS(ERRDOS,ERRnofids);
769 dptr_set_wcard(dptr_num, strdup(mask));
770 dptr_set_attr(dptr_num, dirtype);
771 } else {
772 dirtype = dptr_attr(dptr_num);
775 DEBUG(4,("dptr_num is %d\n",dptr_num));
777 if (ok) {
778 if ((dirtype&0x1F) == aVOLID) {
779 memcpy(p,status,21);
780 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
781 dptr_fill(p+12,dptr_num);
782 if (dptr_zero(p+12) && (status_len==0))
783 numentries = 1;
784 else
785 numentries = 0;
786 p += DIR_STRUCT_SIZE;
787 } else {
788 unsigned int i;
789 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
791 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
792 conn->dirpath,lp_dontdescend(SNUM(conn))));
793 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
794 check_descend = True;
796 for (i=numentries;(i<maxentries) && !finished;i++) {
797 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
798 if (!finished) {
799 memcpy(p,status,21);
800 make_dir_struct(p,mask,fname,size,mode,date);
801 dptr_fill(p+12,dptr_num);
802 numentries++;
804 p += DIR_STRUCT_SIZE;
807 } /* if (ok ) */
811 SearchEmpty:
813 /* If we were called as SMBffirst with smb_search_id == NULL
814 and no entries were found then return error and close dirptr
815 (X/Open spec) */
817 if(ok && expect_close && numentries == 0 && status_len == 0) {
818 if (Protocol < PROTOCOL_NT1) {
819 SCVAL(outbuf,smb_rcls,ERRDOS);
820 SSVAL(outbuf,smb_err,ERRnofiles);
822 /* Also close the dptr - we know it's gone */
823 dptr_close(&dptr_num);
824 } else if (numentries == 0 || !ok) {
825 if (Protocol < PROTOCOL_NT1) {
826 SCVAL(outbuf,smb_rcls,ERRDOS);
827 SSVAL(outbuf,smb_err,ERRnofiles);
829 dptr_close(&dptr_num);
832 /* If we were called as SMBfunique, then we can close the dirptr now ! */
833 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
834 dptr_close(&dptr_num);
836 SSVAL(outbuf,smb_vwv0,numentries);
837 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
838 SCVAL(smb_buf(outbuf),0,5);
839 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
841 if (Protocol >= PROTOCOL_NT1)
842 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
844 outsize += DIR_STRUCT_SIZE*numentries;
845 smb_setlen(outbuf,outsize - 4);
847 if ((! *directory) && dptr_path(dptr_num))
848 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
850 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
851 smb_fn_name(CVAL(inbuf,smb_com)),
852 mask, directory, dirtype, numentries, maxentries ) );
854 END_PROFILE(SMBsearch);
855 return(outsize);
858 /****************************************************************************
859 Reply to a fclose (stop directory search).
860 ****************************************************************************/
862 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
864 int outsize = 0;
865 int status_len;
866 pstring path;
867 char status[21];
868 int dptr_num= -2;
869 char *p;
870 NTSTATUS err;
872 START_PROFILE(SMBfclose);
874 outsize = set_message(outbuf,1,0,True);
875 p = smb_buf(inbuf) + 1;
876 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err);
877 if (!NT_STATUS_IS_OK(err)) {
878 END_PROFILE(SMBfclose);
879 return ERROR_NT(err);
881 p++;
882 status_len = SVAL(p,0);
883 p += 2;
885 if (status_len == 0) {
886 END_PROFILE(SMBfclose);
887 return ERROR_DOS(ERRSRV,ERRsrverror);
890 memcpy(status,p,21);
892 if(dptr_fetch(status+12,&dptr_num)) {
893 /* Close the dptr - we know it's gone */
894 dptr_close(&dptr_num);
897 SSVAL(outbuf,smb_vwv0,0);
899 DEBUG(3,("search close\n"));
901 END_PROFILE(SMBfclose);
902 return(outsize);
905 /****************************************************************************
906 Reply to an open.
907 ****************************************************************************/
909 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
911 pstring fname;
912 int outsize = 0;
913 int fmode=0;
914 int share_mode;
915 SMB_OFF_T size = 0;
916 time_t mtime=0;
917 mode_t unixmode;
918 int rmode=0;
919 SMB_STRUCT_STAT sbuf;
920 BOOL bad_path = False;
921 files_struct *fsp;
922 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
923 NTSTATUS status;
924 START_PROFILE(SMBopen);
926 share_mode = SVAL(inbuf,smb_vwv0);
928 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
929 if (!NT_STATUS_IS_OK(status)) {
930 END_PROFILE(SMBopen);
931 return ERROR_NT(status);
934 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
936 unix_convert(fname,conn,0,&bad_path,&sbuf);
938 unixmode = unix_mode(conn,aARCH,fname);
940 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
941 unixmode, oplock_request,&rmode,NULL);
943 if (!fsp) {
944 END_PROFILE(SMBopen);
945 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
948 size = sbuf.st_size;
949 fmode = dos_mode(conn,fname,&sbuf);
950 mtime = sbuf.st_mtime;
952 if (fmode & aDIR) {
953 DEBUG(3,("attempt to open a directory %s\n",fname));
954 close_file(fsp,False);
955 END_PROFILE(SMBopen);
956 return ERROR_DOS(ERRDOS,ERRnoaccess);
959 outsize = set_message(outbuf,7,0,True);
960 SSVAL(outbuf,smb_vwv0,fsp->fnum);
961 SSVAL(outbuf,smb_vwv1,fmode);
962 if(lp_dos_filetime_resolution(SNUM(conn)) )
963 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
964 else
965 put_dos_date3(outbuf,smb_vwv2,mtime);
966 SIVAL(outbuf,smb_vwv4,(uint32)size);
967 SSVAL(outbuf,smb_vwv6,rmode);
969 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
970 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
972 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
973 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
974 END_PROFILE(SMBopen);
975 return(outsize);
978 /****************************************************************************
979 Reply to an open and X.
980 ****************************************************************************/
982 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
984 pstring fname;
985 int smb_mode = SVAL(inbuf,smb_vwv3);
986 int smb_attr = SVAL(inbuf,smb_vwv5);
987 /* Breakout the oplock request bits so we can set the
988 reply bits separately. */
989 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
990 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
991 BOOL oplock_request = ex_oplock_request | core_oplock_request;
992 #if 0
993 int open_flags = SVAL(inbuf,smb_vwv2);
994 int smb_sattr = SVAL(inbuf,smb_vwv4);
995 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
996 #endif
997 int smb_ofun = SVAL(inbuf,smb_vwv8);
998 mode_t unixmode;
999 SMB_OFF_T size=0;
1000 int fmode=0,mtime=0,rmode=0;
1001 SMB_STRUCT_STAT sbuf;
1002 int smb_action = 0;
1003 BOOL bad_path = False;
1004 files_struct *fsp;
1005 NTSTATUS status;
1006 START_PROFILE(SMBopenX);
1008 /* If it's an IPC, pass off the pipe handler. */
1009 if (IS_IPC(conn)) {
1010 if (lp_nt_pipe_support()) {
1011 END_PROFILE(SMBopenX);
1012 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1013 } else {
1014 END_PROFILE(SMBopenX);
1015 return ERROR_DOS(ERRSRV,ERRaccess);
1019 /* XXXX we need to handle passed times, sattr and flags */
1020 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 END_PROFILE(SMBopenX);
1023 return ERROR_NT(status);
1026 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1028 unix_convert(fname,conn,0,&bad_path,&sbuf);
1030 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1032 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1033 oplock_request, &rmode,&smb_action);
1035 if (!fsp) {
1036 END_PROFILE(SMBopenX);
1037 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1040 size = sbuf.st_size;
1041 fmode = dos_mode(conn,fname,&sbuf);
1042 mtime = sbuf.st_mtime;
1043 if (fmode & aDIR) {
1044 close_file(fsp,False);
1045 END_PROFILE(SMBopenX);
1046 return ERROR_DOS(ERRDOS,ERRnoaccess);
1049 /* If the caller set the extended oplock request bit
1050 and we granted one (by whatever means) - set the
1051 correct bit for extended oplock reply.
1054 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1055 smb_action |= EXTENDED_OPLOCK_GRANTED;
1057 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1058 smb_action |= EXTENDED_OPLOCK_GRANTED;
1060 /* If the caller set the core oplock request bit
1061 and we granted one (by whatever means) - set the
1062 correct bit for core oplock reply.
1065 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1066 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1068 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1069 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1071 set_message(outbuf,15,0,True);
1072 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1073 SSVAL(outbuf,smb_vwv3,fmode);
1074 if(lp_dos_filetime_resolution(SNUM(conn)) )
1075 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1076 else
1077 put_dos_date3(outbuf,smb_vwv4,mtime);
1078 SIVAL(outbuf,smb_vwv6,(uint32)size);
1079 SSVAL(outbuf,smb_vwv8,rmode);
1080 SSVAL(outbuf,smb_vwv11,smb_action);
1082 END_PROFILE(SMBopenX);
1083 return chain_reply(inbuf,outbuf,length,bufsize);
1086 /****************************************************************************
1087 Reply to a SMBulogoffX.
1088 ****************************************************************************/
1090 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1092 uint16 vuid = SVAL(inbuf,smb_uid);
1093 user_struct *vuser = get_valid_user_struct(vuid);
1094 START_PROFILE(SMBulogoffX);
1096 if(vuser == 0)
1097 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1099 /* in user level security we are supposed to close any files
1100 open by this user */
1101 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1102 file_close_user(vuid);
1104 invalidate_vuid(vuid);
1106 set_message(outbuf,2,0,True);
1108 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1110 END_PROFILE(SMBulogoffX);
1111 return chain_reply(inbuf,outbuf,length,bufsize);
1114 /****************************************************************************
1115 Reply to a mknew or a create.
1116 ****************************************************************************/
1118 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1120 pstring fname;
1121 int com;
1122 int outsize = 0;
1123 int createmode;
1124 mode_t unixmode;
1125 int ofun = 0;
1126 BOOL bad_path = False;
1127 files_struct *fsp;
1128 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1129 SMB_STRUCT_STAT sbuf;
1130 NTSTATUS status;
1131 START_PROFILE(SMBcreate);
1133 com = SVAL(inbuf,smb_com);
1135 createmode = SVAL(inbuf,smb_vwv0);
1136 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status);
1137 if (!NT_STATUS_IS_OK(status)) {
1138 END_PROFILE(SMBcreate);
1139 return ERROR_NT(status);
1142 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1144 unix_convert(fname,conn,0,&bad_path,&sbuf);
1146 if (createmode & aVOLID)
1147 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1149 unixmode = unix_mode(conn,createmode,fname);
1151 if(com == SMBmknew) {
1152 /* We should fail if file exists. */
1153 ofun = FILE_CREATE_IF_NOT_EXIST;
1154 } else {
1155 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1156 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1159 /* Open file in dos compatibility share mode. */
1160 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1161 ofun, unixmode, oplock_request, NULL, NULL);
1163 if (!fsp) {
1164 END_PROFILE(SMBcreate);
1165 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1168 outsize = set_message(outbuf,1,0,True);
1169 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1171 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1172 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1174 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1175 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1177 DEBUG( 2, ( "new file %s\n", fname ) );
1178 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1180 END_PROFILE(SMBcreate);
1181 return(outsize);
1184 /****************************************************************************
1185 Reply to a create temporary file.
1186 ****************************************************************************/
1188 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1190 pstring fname;
1191 int outsize = 0;
1192 int createmode;
1193 mode_t unixmode;
1194 BOOL bad_path = False;
1195 files_struct *fsp;
1196 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1197 int tmpfd;
1198 SMB_STRUCT_STAT sbuf;
1199 char *p, *s;
1200 NTSTATUS status;
1202 START_PROFILE(SMBctemp);
1204 createmode = SVAL(inbuf,smb_vwv0);
1205 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 END_PROFILE(SMBctemp);
1208 return ERROR_NT(status);
1210 pstrcat(fname,"\\TMXXXXXX");
1212 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1214 unix_convert(fname,conn,0,&bad_path,&sbuf);
1216 unixmode = unix_mode(conn,createmode,fname);
1218 tmpfd = smb_mkstemp(fname);
1219 if (tmpfd == -1) {
1220 END_PROFILE(SMBctemp);
1221 return(UNIXERROR(ERRDOS,ERRnoaccess));
1224 SMB_VFS_STAT(conn,fname,&sbuf);
1226 /* Open file in dos compatibility share mode. */
1227 /* We should fail if file does not exist. */
1228 fsp = open_file_shared(conn,fname,&sbuf,
1229 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1230 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1231 unixmode, oplock_request, NULL, NULL);
1233 /* close fd from smb_mkstemp() */
1234 close(tmpfd);
1236 if (!fsp) {
1237 END_PROFILE(SMBctemp);
1238 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1241 outsize = set_message(outbuf,1,0,True);
1242 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1244 /* the returned filename is relative to the directory */
1245 s = strrchr_m(fname, '/');
1246 if (!s)
1247 s = fname;
1248 else
1249 s++;
1251 p = smb_buf(outbuf);
1252 SSVALS(p, 0, -1); /* what is this? not in spec */
1253 SSVAL(p, 2, strlen(s));
1254 p += 4;
1255 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1256 outsize = set_message_end(outbuf, p);
1258 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1259 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1261 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1262 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1264 DEBUG( 2, ( "created temp file %s\n", fname ) );
1265 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1266 fname, fsp->fd, createmode, (int)unixmode ) );
1268 END_PROFILE(SMBctemp);
1269 return(outsize);
1272 /*******************************************************************
1273 Check if a user is allowed to rename a file.
1274 ********************************************************************/
1276 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1278 int smb_action;
1279 int access_mode;
1280 files_struct *fsp;
1282 if (!CAN_WRITE(conn))
1283 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1285 if (S_ISDIR(pst->st_mode))
1286 return NT_STATUS_OK;
1288 /* We need a better way to return NT status codes from open... */
1289 unix_ERR_class = 0;
1290 unix_ERR_code = 0;
1292 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1293 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1295 if (!fsp) {
1296 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1297 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1298 ret = NT_STATUS_SHARING_VIOLATION;
1299 unix_ERR_class = 0;
1300 unix_ERR_code = 0;
1301 unix_ERR_ntstatus = NT_STATUS_OK;
1302 return ret;
1304 close_file(fsp,False);
1305 return NT_STATUS_OK;
1308 /*******************************************************************
1309 Check if a user is allowed to delete a file.
1310 ********************************************************************/
1312 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1314 SMB_STRUCT_STAT sbuf;
1315 int fmode;
1316 int smb_action;
1317 int access_mode;
1318 files_struct *fsp;
1320 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1321 fname, dirtype ));
1323 if (!CAN_WRITE(conn))
1324 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1326 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1327 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1329 fmode = dos_mode(conn,fname,&sbuf);
1331 /* Can't delete a directory. */
1332 if (fmode & aDIR)
1333 return NT_STATUS_FILE_IS_A_DIRECTORY;
1334 #if 0 /* JRATEST */
1335 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1336 return NT_STATUS_OBJECT_NAME_INVALID;
1337 #endif /* JRATEST */
1339 if (!lp_delete_readonly(SNUM(conn))) {
1340 if (fmode & aRONLY)
1341 return NT_STATUS_CANNOT_DELETE;
1343 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1344 return NT_STATUS_NO_SUCH_FILE;
1346 /* We need a better way to return NT status codes from open... */
1347 unix_ERR_class = 0;
1348 unix_ERR_code = 0;
1350 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1351 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1353 if (!fsp) {
1354 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1355 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1356 ret = unix_ERR_ntstatus;
1357 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1358 ret = NT_STATUS_SHARING_VIOLATION;
1359 unix_ERR_class = 0;
1360 unix_ERR_code = 0;
1361 unix_ERR_ntstatus = NT_STATUS_OK;
1362 return ret;
1364 close_file(fsp,False);
1365 return NT_STATUS_OK;
1368 /****************************************************************************
1369 The guts of the unlink command, split out so it may be called by the NT SMB
1370 code.
1371 ****************************************************************************/
1373 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1375 pstring directory;
1376 pstring mask;
1377 char *p;
1378 int count=0;
1379 NTSTATUS error = NT_STATUS_OK;
1380 BOOL has_wild;
1381 BOOL bad_path = False;
1382 BOOL rc = True;
1383 SMB_STRUCT_STAT sbuf;
1385 *directory = *mask = 0;
1387 /* We must check for wildcards in the name given
1388 * directly by the client - before any unmangling.
1389 * This prevents an unmangling of a UNIX name containing
1390 * a DOS wildcard like '*' or '?' from unmangling into
1391 * a wildcard delete which was not intended.
1392 * FIX for #226. JRA.
1395 has_wild = ms_has_wild(name);
1397 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1399 p = strrchr_m(name,'/');
1400 if (!p) {
1401 pstrcpy(directory,".");
1402 pstrcpy(mask,name);
1403 } else {
1404 *p = 0;
1405 pstrcpy(directory,name);
1406 pstrcpy(mask,p+1);
1410 * We should only check the mangled cache
1411 * here if unix_convert failed. This means
1412 * that the path in 'mask' doesn't exist
1413 * on the file system and so we need to look
1414 * for a possible mangle. This patch from
1415 * Tine Smukavec <valentin.smukavec@hermes.si>.
1418 if (!rc && mangle_is_mangled(mask))
1419 mangle_check_cache( mask );
1421 if (!has_wild) {
1422 pstrcat(directory,"/");
1423 pstrcat(directory,mask);
1424 error = can_delete(directory,conn,dirtype);
1425 if (!NT_STATUS_IS_OK(error))
1426 return error;
1428 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1429 count++;
1431 } else {
1432 void *dirptr = NULL;
1433 const char *dname;
1435 if (check_name(directory,conn))
1436 dirptr = OpenDir(conn, directory, True);
1438 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1439 the pattern matches against the long name, otherwise the short name
1440 We don't implement this yet XXXX
1443 if (dirptr) {
1444 error = NT_STATUS_NO_SUCH_FILE;
1446 if (strequal(mask,"????????.???"))
1447 pstrcpy(mask,"*");
1449 while ((dname = ReadDirName(dirptr))) {
1450 pstring fname;
1451 pstrcpy(fname,dname);
1453 if(!mask_match(fname, mask, case_sensitive))
1454 continue;
1456 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1457 error = can_delete(fname,conn,dirtype);
1458 if (!NT_STATUS_IS_OK(error))
1459 continue;
1460 if (SMB_VFS_UNLINK(conn,fname) == 0)
1461 count++;
1462 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1464 CloseDir(dirptr);
1468 if (count == 0 && NT_STATUS_IS_OK(error)) {
1469 error = map_nt_error_from_unix(errno);
1472 return error;
1475 /****************************************************************************
1476 Reply to a unlink
1477 ****************************************************************************/
1479 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1480 int dum_buffsize)
1482 int outsize = 0;
1483 pstring name;
1484 int dirtype;
1485 NTSTATUS status;
1486 START_PROFILE(SMBunlink);
1488 dirtype = SVAL(inbuf,smb_vwv0);
1490 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 END_PROFILE(SMBunlink);
1493 return ERROR_NT(status);
1496 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1498 DEBUG(3,("reply_unlink : %s\n",name));
1500 status = unlink_internals(conn, dirtype, name);
1501 if (!NT_STATUS_IS_OK(status))
1502 return ERROR_NT(status);
1505 * Win2k needs a changenotify request response before it will
1506 * update after a rename..
1508 process_pending_change_notify_queue((time_t)0);
1510 outsize = set_message(outbuf,0,0,True);
1512 END_PROFILE(SMBunlink);
1513 return outsize;
1516 /****************************************************************************
1517 Fail for readbraw.
1518 ****************************************************************************/
1520 void fail_readraw(void)
1522 pstring errstr;
1523 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1524 strerror(errno) );
1525 exit_server(errstr);
1528 /****************************************************************************
1529 Use sendfile in readbraw.
1530 ****************************************************************************/
1532 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1533 ssize_t mincount, char *outbuf)
1535 ssize_t ret=0;
1537 #if defined(WITH_SENDFILE)
1539 * We can only use sendfile on a non-chained packet and on a file
1540 * that is exclusively oplocked. reply_readbraw has already checked the length.
1543 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1544 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1545 DATA_BLOB header;
1547 _smb_setlen(outbuf,nread);
1548 header.data = outbuf;
1549 header.length = 4;
1550 header.free = NULL;
1552 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1554 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1555 * return ENOSYS then pretend we just got a normal read.
1557 if (errno == ENOSYS)
1558 goto normal_read;
1560 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1561 fsp->fsp_name, strerror(errno) ));
1562 exit_server("send_file_readbraw sendfile failed");
1567 normal_read:
1568 #endif
1570 if (nread > 0) {
1571 ret = read_file(fsp,outbuf+4,startpos,nread);
1572 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1573 if (ret < mincount)
1574 ret = 0;
1575 #else
1576 if (ret < nread)
1577 ret = 0;
1578 #endif
1581 _smb_setlen(outbuf,ret);
1582 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1583 fail_readraw();
1586 /****************************************************************************
1587 Reply to a readbraw (core+ protocol).
1588 ****************************************************************************/
1590 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1592 extern struct current_user current_user;
1593 ssize_t maxcount,mincount;
1594 size_t nread = 0;
1595 SMB_OFF_T startpos;
1596 char *header = outbuf;
1597 files_struct *fsp;
1598 START_PROFILE(SMBreadbraw);
1600 if (srv_is_signing_active()) {
1601 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1605 * Special check if an oplock break has been issued
1606 * and the readraw request croses on the wire, we must
1607 * return a zero length response here.
1610 if(global_oplock_break) {
1611 _smb_setlen(header,0);
1612 if (write_data(smbd_server_fd(),header,4) != 4)
1613 fail_readraw();
1614 DEBUG(5,("readbraw - oplock break finished\n"));
1615 END_PROFILE(SMBreadbraw);
1616 return -1;
1619 fsp = file_fsp(inbuf,smb_vwv0);
1621 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1623 * fsp could be NULL here so use the value from the packet. JRA.
1625 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1626 _smb_setlen(header,0);
1627 if (write_data(smbd_server_fd(),header,4) != 4)
1628 fail_readraw();
1629 END_PROFILE(SMBreadbraw);
1630 return(-1);
1633 CHECK_FSP(fsp,conn);
1635 flush_write_cache(fsp, READRAW_FLUSH);
1637 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1638 if(CVAL(inbuf,smb_wct) == 10) {
1640 * This is a large offset (64 bit) read.
1642 #ifdef LARGE_SMB_OFF_T
1644 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1646 #else /* !LARGE_SMB_OFF_T */
1649 * Ensure we haven't been sent a >32 bit offset.
1652 if(IVAL(inbuf,smb_vwv8) != 0) {
1653 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1654 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1655 _smb_setlen(header,0);
1656 if (write_data(smbd_server_fd(),header,4) != 4)
1657 fail_readraw();
1658 END_PROFILE(SMBreadbraw);
1659 return(-1);
1662 #endif /* LARGE_SMB_OFF_T */
1664 if(startpos < 0) {
1665 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1666 _smb_setlen(header,0);
1667 if (write_data(smbd_server_fd(),header,4) != 4)
1668 fail_readraw();
1669 END_PROFILE(SMBreadbraw);
1670 return(-1);
1673 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1674 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1676 /* ensure we don't overrun the packet size */
1677 maxcount = MIN(65535,maxcount);
1679 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1680 SMB_OFF_T size = fsp->size;
1681 SMB_OFF_T sizeneeded = startpos + maxcount;
1683 if (size < sizeneeded) {
1684 SMB_STRUCT_STAT st;
1685 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1686 size = st.st_size;
1687 if (!fsp->can_write)
1688 fsp->size = size;
1691 if (startpos >= size)
1692 nread = 0;
1693 else
1694 nread = MIN(maxcount,(size - startpos));
1697 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1698 if (nread < mincount)
1699 nread = 0;
1700 #endif
1702 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1703 (int)maxcount, (int)mincount, (int)nread ) );
1705 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1707 DEBUG(5,("readbraw finished\n"));
1708 END_PROFILE(SMBreadbraw);
1709 return -1;
1712 /****************************************************************************
1713 Reply to a lockread (core+ protocol).
1714 ****************************************************************************/
1716 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1718 ssize_t nread = -1;
1719 char *data;
1720 int outsize = 0;
1721 SMB_OFF_T startpos;
1722 size_t numtoread;
1723 NTSTATUS status;
1724 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1725 BOOL my_lock_ctx = False;
1726 START_PROFILE(SMBlockread);
1728 CHECK_FSP(fsp,conn);
1729 CHECK_READ(fsp);
1731 release_level_2_oplocks_on_change(fsp);
1733 numtoread = SVAL(inbuf,smb_vwv1);
1734 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1736 outsize = set_message(outbuf,5,3,True);
1737 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1738 data = smb_buf(outbuf) + 3;
1741 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1742 * protocol request that predates the read/write lock concept.
1743 * Thus instead of asking for a read lock here we need to ask
1744 * for a write lock. JRA.
1745 * Note that the requested lock size is unaffected by max_recv.
1748 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1749 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1751 if (NT_STATUS_V(status)) {
1752 #if 0
1754 * We used to make lockread a blocking lock. It turns out
1755 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1756 * tester. JRA.
1759 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1761 * A blocking lock was requested. Package up
1762 * this smb into a queued request and push it
1763 * onto the blocking lock queue.
1765 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1766 (SMB_BIG_UINT)numtoread)) {
1767 END_PROFILE(SMBlockread);
1768 return -1;
1771 #endif
1772 END_PROFILE(SMBlockread);
1773 return ERROR_NT(status);
1777 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1780 if (numtoread > max_recv) {
1781 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1782 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1783 (unsigned int)numtoread, (unsigned int)max_recv ));
1784 numtoread = MIN(numtoread,max_recv);
1786 nread = read_file(fsp,data,startpos,numtoread);
1788 if (nread < 0) {
1789 END_PROFILE(SMBlockread);
1790 return(UNIXERROR(ERRDOS,ERRnoaccess));
1793 outsize += nread;
1794 SSVAL(outbuf,smb_vwv0,nread);
1795 SSVAL(outbuf,smb_vwv5,nread+3);
1796 SSVAL(smb_buf(outbuf),1,nread);
1798 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1799 fsp->fnum, (int)numtoread, (int)nread));
1801 END_PROFILE(SMBlockread);
1802 return(outsize);
1805 /****************************************************************************
1806 Reply to a read.
1807 ****************************************************************************/
1809 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1811 size_t numtoread;
1812 ssize_t nread = 0;
1813 char *data;
1814 SMB_OFF_T startpos;
1815 int outsize = 0;
1816 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1817 START_PROFILE(SMBread);
1819 CHECK_FSP(fsp,conn);
1820 CHECK_READ(fsp);
1822 numtoread = SVAL(inbuf,smb_vwv1);
1823 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1825 outsize = set_message(outbuf,5,3,True);
1826 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1828 * The requested read size cannot be greater than max_recv. JRA.
1830 if (numtoread > max_recv) {
1831 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1832 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1833 (unsigned int)numtoread, (unsigned int)max_recv ));
1834 numtoread = MIN(numtoread,max_recv);
1837 data = smb_buf(outbuf) + 3;
1839 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1840 END_PROFILE(SMBread);
1841 return ERROR_DOS(ERRDOS,ERRlock);
1844 if (numtoread > 0)
1845 nread = read_file(fsp,data,startpos,numtoread);
1847 if (nread < 0) {
1848 END_PROFILE(SMBread);
1849 return(UNIXERROR(ERRDOS,ERRnoaccess));
1852 outsize += nread;
1853 SSVAL(outbuf,smb_vwv0,nread);
1854 SSVAL(outbuf,smb_vwv5,nread+3);
1855 SCVAL(smb_buf(outbuf),0,1);
1856 SSVAL(smb_buf(outbuf),1,nread);
1858 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1859 fsp->fnum, (int)numtoread, (int)nread ) );
1861 END_PROFILE(SMBread);
1862 return(outsize);
1865 /****************************************************************************
1866 Reply to a read and X - possibly using sendfile.
1867 ****************************************************************************/
1869 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1870 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1872 ssize_t nread = -1;
1873 char *data = smb_buf(outbuf);
1875 #if defined(WITH_SENDFILE)
1877 * We can only use sendfile on a non-chained packet and on a file
1878 * that is exclusively oplocked.
1881 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1882 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1883 SMB_STRUCT_STAT sbuf;
1884 DATA_BLOB header;
1886 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1887 return(UNIXERROR(ERRDOS,ERRnoaccess));
1889 if (startpos > sbuf.st_size)
1890 goto normal_read;
1892 if (smb_maxcnt > (sbuf.st_size - startpos))
1893 smb_maxcnt = (sbuf.st_size - startpos);
1895 if (smb_maxcnt == 0)
1896 goto normal_read;
1899 * Set up the packet header before send. We
1900 * assume here the sendfile will work (get the
1901 * correct amount of data).
1904 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1905 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1906 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1907 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1908 SCVAL(outbuf,smb_vwv0,0xFF);
1909 set_message(outbuf,12,smb_maxcnt,False);
1910 header.data = outbuf;
1911 header.length = data - outbuf;
1912 header.free = NULL;
1914 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1916 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1917 * return ENOSYS then pretend we just got a normal read.
1919 if (errno == ENOSYS)
1920 goto normal_read;
1922 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1923 fsp->fsp_name, strerror(errno) ));
1924 exit_server("send_file_readX sendfile failed");
1927 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1928 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1929 return -1;
1932 normal_read:
1934 #endif
1936 nread = read_file(fsp,data,startpos,smb_maxcnt);
1938 if (nread < 0) {
1939 END_PROFILE(SMBreadX);
1940 return(UNIXERROR(ERRDOS,ERRnoaccess));
1943 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1944 SSVAL(outbuf,smb_vwv5,nread);
1945 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1946 SSVAL(smb_buf(outbuf),-2,nread);
1948 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1949 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1951 return nread;
1954 /****************************************************************************
1955 Reply to a read and X.
1956 ****************************************************************************/
1958 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1960 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1961 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1962 ssize_t nread = -1;
1963 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1964 #if 0
1965 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1966 #endif
1968 START_PROFILE(SMBreadX);
1970 /* If it's an IPC, pass off the pipe handler. */
1971 if (IS_IPC(conn)) {
1972 END_PROFILE(SMBreadX);
1973 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1976 CHECK_FSP(fsp,conn);
1977 CHECK_READ(fsp);
1979 set_message(outbuf,12,0,True);
1981 if(CVAL(inbuf,smb_wct) == 12) {
1982 #ifdef LARGE_SMB_OFF_T
1984 * This is a large offset (64 bit) read.
1986 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1988 #else /* !LARGE_SMB_OFF_T */
1991 * Ensure we haven't been sent a >32 bit offset.
1994 if(IVAL(inbuf,smb_vwv10) != 0) {
1995 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1996 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1997 END_PROFILE(SMBreadX);
1998 return ERROR_DOS(ERRDOS,ERRbadaccess);
2001 #endif /* LARGE_SMB_OFF_T */
2005 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2006 END_PROFILE(SMBreadX);
2007 return ERROR_DOS(ERRDOS,ERRlock);
2010 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2011 if (nread != -1)
2012 nread = chain_reply(inbuf,outbuf,length,bufsize);
2014 END_PROFILE(SMBreadX);
2015 return nread;
2018 /****************************************************************************
2019 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2020 ****************************************************************************/
2022 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2024 ssize_t nwritten=0;
2025 ssize_t total_written=0;
2026 size_t numtowrite=0;
2027 size_t tcount;
2028 SMB_OFF_T startpos;
2029 char *data=NULL;
2030 BOOL write_through;
2031 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2032 int outsize = 0;
2033 START_PROFILE(SMBwritebraw);
2035 if (srv_is_signing_active()) {
2036 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2039 CHECK_FSP(fsp,conn);
2040 CHECK_WRITE(fsp);
2042 tcount = IVAL(inbuf,smb_vwv1);
2043 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2044 write_through = BITSETW(inbuf+smb_vwv7,0);
2046 /* We have to deal with slightly different formats depending
2047 on whether we are using the core+ or lanman1.0 protocol */
2049 if(Protocol <= PROTOCOL_COREPLUS) {
2050 numtowrite = SVAL(smb_buf(inbuf),-2);
2051 data = smb_buf(inbuf);
2052 } else {
2053 numtowrite = SVAL(inbuf,smb_vwv10);
2054 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2057 /* force the error type */
2058 SCVAL(inbuf,smb_com,SMBwritec);
2059 SCVAL(outbuf,smb_com,SMBwritec);
2061 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2062 END_PROFILE(SMBwritebraw);
2063 return(ERROR_DOS(ERRDOS,ERRlock));
2066 if (numtowrite>0)
2067 nwritten = write_file(fsp,data,startpos,numtowrite);
2069 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2070 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2072 if (nwritten < (ssize_t)numtowrite) {
2073 END_PROFILE(SMBwritebraw);
2074 return(UNIXERROR(ERRHRD,ERRdiskfull));
2077 total_written = nwritten;
2079 /* Return a message to the redirector to tell it to send more bytes */
2080 SCVAL(outbuf,smb_com,SMBwritebraw);
2081 SSVALS(outbuf,smb_vwv0,-1);
2082 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2083 if (!send_smb(smbd_server_fd(),outbuf))
2084 exit_server("reply_writebraw: send_smb failed.");
2086 /* Now read the raw data into the buffer and write it */
2087 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2088 exit_server("secondary writebraw failed");
2091 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2092 numtowrite = smb_len(inbuf);
2094 /* Set up outbuf to return the correct return */
2095 outsize = set_message(outbuf,1,0,True);
2096 SCVAL(outbuf,smb_com,SMBwritec);
2097 SSVAL(outbuf,smb_vwv0,total_written);
2099 if (numtowrite != 0) {
2101 if (numtowrite > BUFFER_SIZE) {
2102 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2103 (unsigned int)numtowrite ));
2104 exit_server("secondary writebraw failed");
2107 if (tcount > nwritten+numtowrite) {
2108 DEBUG(3,("Client overestimated the write %d %d %d\n",
2109 (int)tcount,(int)nwritten,(int)numtowrite));
2112 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2113 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2114 strerror(errno) ));
2115 exit_server("secondary writebraw failed");
2118 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2120 if (nwritten < (ssize_t)numtowrite) {
2121 SCVAL(outbuf,smb_rcls,ERRHRD);
2122 SSVAL(outbuf,smb_err,ERRdiskfull);
2125 if (nwritten > 0)
2126 total_written += nwritten;
2129 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2130 sync_file(conn,fsp);
2132 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2133 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2135 /* we won't return a status if write through is not selected - this follows what WfWg does */
2136 END_PROFILE(SMBwritebraw);
2137 if (!write_through && total_written==tcount) {
2139 #if RABBIT_PELLET_FIX
2141 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2142 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2144 if (!send_keepalive(smbd_server_fd()))
2145 exit_server("reply_writebraw: send of keepalive failed");
2146 #endif
2147 return(-1);
2150 return(outsize);
2153 /****************************************************************************
2154 Reply to a writeunlock (core+).
2155 ****************************************************************************/
2157 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2158 int size, int dum_buffsize)
2160 ssize_t nwritten = -1;
2161 size_t numtowrite;
2162 SMB_OFF_T startpos;
2163 char *data;
2164 NTSTATUS status = NT_STATUS_OK;
2165 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2166 int outsize = 0;
2167 START_PROFILE(SMBwriteunlock);
2169 CHECK_FSP(fsp,conn);
2170 CHECK_WRITE(fsp);
2172 numtowrite = SVAL(inbuf,smb_vwv1);
2173 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2174 data = smb_buf(inbuf) + 3;
2176 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2177 WRITE_LOCK,False)) {
2178 END_PROFILE(SMBwriteunlock);
2179 return ERROR_DOS(ERRDOS,ERRlock);
2182 /* The special X/Open SMB protocol handling of
2183 zero length writes is *NOT* done for
2184 this call */
2185 if(numtowrite == 0)
2186 nwritten = 0;
2187 else
2188 nwritten = write_file(fsp,data,startpos,numtowrite);
2190 if (lp_syncalways(SNUM(conn)))
2191 sync_file(conn,fsp);
2193 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2194 END_PROFILE(SMBwriteunlock);
2195 return(UNIXERROR(ERRHRD,ERRdiskfull));
2198 if (numtowrite) {
2199 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2200 (SMB_BIG_UINT)startpos);
2201 if (NT_STATUS_V(status)) {
2202 END_PROFILE(SMBwriteunlock);
2203 return ERROR_NT(status);
2207 outsize = set_message(outbuf,1,0,True);
2209 SSVAL(outbuf,smb_vwv0,nwritten);
2211 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2212 fsp->fnum, (int)numtowrite, (int)nwritten));
2214 END_PROFILE(SMBwriteunlock);
2215 return outsize;
2218 /****************************************************************************
2219 Reply to a write.
2220 ****************************************************************************/
2222 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2224 size_t numtowrite;
2225 ssize_t nwritten = -1;
2226 SMB_OFF_T startpos;
2227 char *data;
2228 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2229 int outsize = 0;
2230 START_PROFILE(SMBwrite);
2232 /* If it's an IPC, pass off the pipe handler. */
2233 if (IS_IPC(conn)) {
2234 END_PROFILE(SMBwrite);
2235 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2238 CHECK_FSP(fsp,conn);
2239 CHECK_WRITE(fsp);
2241 numtowrite = SVAL(inbuf,smb_vwv1);
2242 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2243 data = smb_buf(inbuf) + 3;
2245 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2246 END_PROFILE(SMBwrite);
2247 return ERROR_DOS(ERRDOS,ERRlock);
2251 * X/Open SMB protocol says that if smb_vwv1 is
2252 * zero then the file size should be extended or
2253 * truncated to the size given in smb_vwv[2-3].
2256 if(numtowrite == 0) {
2258 * This is actually an allocate call, and set EOF. JRA.
2260 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2261 if (nwritten < 0) {
2262 END_PROFILE(SMBwrite);
2263 return ERROR_NT(NT_STATUS_DISK_FULL);
2265 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2266 if (nwritten < 0) {
2267 END_PROFILE(SMBwrite);
2268 return ERROR_NT(NT_STATUS_DISK_FULL);
2270 } else
2271 nwritten = write_file(fsp,data,startpos,numtowrite);
2273 if (lp_syncalways(SNUM(conn)))
2274 sync_file(conn,fsp);
2276 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2277 END_PROFILE(SMBwrite);
2278 return(UNIXERROR(ERRHRD,ERRdiskfull));
2281 outsize = set_message(outbuf,1,0,True);
2283 SSVAL(outbuf,smb_vwv0,nwritten);
2285 if (nwritten < (ssize_t)numtowrite) {
2286 SCVAL(outbuf,smb_rcls,ERRHRD);
2287 SSVAL(outbuf,smb_err,ERRdiskfull);
2290 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2292 END_PROFILE(SMBwrite);
2293 return(outsize);
2296 /****************************************************************************
2297 Reply to a write and X.
2298 ****************************************************************************/
2300 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2302 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2303 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2304 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2305 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2306 ssize_t nwritten = -1;
2307 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2308 unsigned int smblen = smb_len(inbuf);
2309 char *data;
2310 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2311 START_PROFILE(SMBwriteX);
2313 /* If it's an IPC, pass off the pipe handler. */
2314 if (IS_IPC(conn)) {
2315 END_PROFILE(SMBwriteX);
2316 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2319 CHECK_FSP(fsp,conn);
2320 CHECK_WRITE(fsp);
2322 /* Deal with possible LARGE_WRITEX */
2323 if (large_writeX)
2324 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2326 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2327 END_PROFILE(SMBwriteX);
2328 return ERROR_DOS(ERRDOS,ERRbadmem);
2331 data = smb_base(inbuf) + smb_doff;
2333 if(CVAL(inbuf,smb_wct) == 14) {
2334 #ifdef LARGE_SMB_OFF_T
2336 * This is a large offset (64 bit) write.
2338 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2340 #else /* !LARGE_SMB_OFF_T */
2343 * Ensure we haven't been sent a >32 bit offset.
2346 if(IVAL(inbuf,smb_vwv12) != 0) {
2347 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2348 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2349 END_PROFILE(SMBwriteX);
2350 return ERROR_DOS(ERRDOS,ERRbadaccess);
2353 #endif /* LARGE_SMB_OFF_T */
2356 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2357 END_PROFILE(SMBwriteX);
2358 return ERROR_DOS(ERRDOS,ERRlock);
2361 /* X/Open SMB protocol says that, unlike SMBwrite
2362 if the length is zero then NO truncation is
2363 done, just a write of zero. To truncate a file,
2364 use SMBwrite. */
2366 if(numtowrite == 0)
2367 nwritten = 0;
2368 else
2369 nwritten = write_file(fsp,data,startpos,numtowrite);
2371 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2372 END_PROFILE(SMBwriteX);
2373 return(UNIXERROR(ERRHRD,ERRdiskfull));
2376 set_message(outbuf,6,0,True);
2378 SSVAL(outbuf,smb_vwv2,nwritten);
2379 if (large_writeX)
2380 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2382 if (nwritten < (ssize_t)numtowrite) {
2383 SCVAL(outbuf,smb_rcls,ERRHRD);
2384 SSVAL(outbuf,smb_err,ERRdiskfull);
2387 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2388 fsp->fnum, (int)numtowrite, (int)nwritten));
2390 if (lp_syncalways(SNUM(conn)) || write_through)
2391 sync_file(conn,fsp);
2393 END_PROFILE(SMBwriteX);
2394 return chain_reply(inbuf,outbuf,length,bufsize);
2397 /****************************************************************************
2398 Reply to a lseek.
2399 ****************************************************************************/
2401 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2403 SMB_OFF_T startpos;
2404 SMB_OFF_T res= -1;
2405 int mode,umode;
2406 int outsize = 0;
2407 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2408 START_PROFILE(SMBlseek);
2410 CHECK_FSP(fsp,conn);
2412 flush_write_cache(fsp, SEEK_FLUSH);
2414 mode = SVAL(inbuf,smb_vwv1) & 3;
2415 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2416 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2418 switch (mode) {
2419 case 0:
2420 umode = SEEK_SET;
2421 res = startpos;
2422 break;
2423 case 1:
2424 umode = SEEK_CUR;
2425 res = fsp->pos + startpos;
2426 break;
2427 case 2:
2428 umode = SEEK_END;
2429 break;
2430 default:
2431 umode = SEEK_SET;
2432 res = startpos;
2433 break;
2436 if (umode == SEEK_END) {
2437 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2438 if(errno == EINVAL) {
2439 SMB_OFF_T current_pos = startpos;
2440 SMB_STRUCT_STAT sbuf;
2442 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2443 END_PROFILE(SMBlseek);
2444 return(UNIXERROR(ERRDOS,ERRnoaccess));
2447 current_pos += sbuf.st_size;
2448 if(current_pos < 0)
2449 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2453 if(res == -1) {
2454 END_PROFILE(SMBlseek);
2455 return(UNIXERROR(ERRDOS,ERRnoaccess));
2459 fsp->pos = res;
2461 outsize = set_message(outbuf,2,0,True);
2462 SIVAL(outbuf,smb_vwv0,res);
2464 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2465 fsp->fnum, (double)startpos, (double)res, mode));
2467 END_PROFILE(SMBlseek);
2468 return(outsize);
2471 /****************************************************************************
2472 Reply to a flush.
2473 ****************************************************************************/
2475 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2477 int outsize = set_message(outbuf,0,0,True);
2478 uint16 fnum = SVAL(inbuf,smb_vwv0);
2479 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2480 START_PROFILE(SMBflush);
2482 if (fnum != 0xFFFF)
2483 CHECK_FSP(fsp,conn);
2485 if (!fsp) {
2486 file_sync_all(conn);
2487 } else {
2488 sync_file(conn,fsp);
2491 DEBUG(3,("flush\n"));
2492 END_PROFILE(SMBflush);
2493 return(outsize);
2496 /****************************************************************************
2497 Reply to a exit.
2498 ****************************************************************************/
2500 int reply_exit(connection_struct *conn,
2501 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2503 int outsize;
2504 START_PROFILE(SMBexit);
2506 file_close_pid(SVAL(inbuf,smb_pid));
2508 outsize = set_message(outbuf,0,0,True);
2510 DEBUG(3,("exit\n"));
2512 END_PROFILE(SMBexit);
2513 return(outsize);
2516 /****************************************************************************
2517 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2518 ****************************************************************************/
2520 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2521 int dum_buffsize)
2523 extern struct current_user current_user;
2524 int outsize = 0;
2525 time_t mtime;
2526 int32 eclass = 0, err = 0;
2527 files_struct *fsp = NULL;
2528 START_PROFILE(SMBclose);
2530 outsize = set_message(outbuf,0,0,True);
2532 /* If it's an IPC, pass off to the pipe handler. */
2533 if (IS_IPC(conn)) {
2534 END_PROFILE(SMBclose);
2535 return reply_pipe_close(conn, inbuf,outbuf);
2538 fsp = file_fsp(inbuf,smb_vwv0);
2541 * We can only use CHECK_FSP if we know it's not a directory.
2544 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2545 END_PROFILE(SMBclose);
2546 return ERROR_DOS(ERRDOS,ERRbadfid);
2549 if(fsp->is_directory) {
2551 * Special case - close NT SMB directory handle.
2553 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2554 close_file(fsp,True);
2555 } else {
2557 * Close ordinary file.
2559 int close_err;
2560 pstring file_name;
2562 /* Save the name for time set in close. */
2563 pstrcpy( file_name, fsp->fsp_name);
2565 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2566 fsp->fd, fsp->fnum,
2567 conn->num_files_open));
2570 * close_file() returns the unix errno if an error
2571 * was detected on close - normally this is due to
2572 * a disk full error. If not then it was probably an I/O error.
2575 if((close_err = close_file(fsp,True)) != 0) {
2576 errno = close_err;
2577 END_PROFILE(SMBclose);
2578 return (UNIXERROR(ERRHRD,ERRgeneral));
2582 * Now take care of any time sent in the close.
2585 mtime = make_unix_date3(inbuf+smb_vwv1);
2587 /* try and set the date */
2588 set_filetime(conn, file_name, mtime);
2592 /* We have a cached error */
2593 if(eclass || err) {
2594 END_PROFILE(SMBclose);
2595 return ERROR_DOS(eclass,err);
2598 END_PROFILE(SMBclose);
2599 return(outsize);
2602 /****************************************************************************
2603 Reply to a writeclose (Core+ protocol).
2604 ****************************************************************************/
2606 int reply_writeclose(connection_struct *conn,
2607 char *inbuf,char *outbuf, int size, int dum_buffsize)
2609 size_t numtowrite;
2610 ssize_t nwritten = -1;
2611 int outsize = 0;
2612 int close_err = 0;
2613 SMB_OFF_T startpos;
2614 char *data;
2615 time_t mtime;
2616 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2617 START_PROFILE(SMBwriteclose);
2619 CHECK_FSP(fsp,conn);
2620 CHECK_WRITE(fsp);
2622 numtowrite = SVAL(inbuf,smb_vwv1);
2623 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2624 mtime = make_unix_date3(inbuf+smb_vwv4);
2625 data = smb_buf(inbuf) + 1;
2627 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2628 END_PROFILE(SMBwriteclose);
2629 return ERROR_DOS(ERRDOS,ERRlock);
2632 nwritten = write_file(fsp,data,startpos,numtowrite);
2634 set_filetime(conn, fsp->fsp_name,mtime);
2637 * More insanity. W2K only closes the file if writelen > 0.
2638 * JRA.
2641 if (numtowrite) {
2642 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2643 fsp->fsp_name ));
2644 close_err = close_file(fsp,True);
2647 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2648 fsp->fnum, (int)numtowrite, (int)nwritten,
2649 conn->num_files_open));
2651 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2652 END_PROFILE(SMBwriteclose);
2653 return(UNIXERROR(ERRHRD,ERRdiskfull));
2656 if(close_err != 0) {
2657 errno = close_err;
2658 END_PROFILE(SMBwriteclose);
2659 return(UNIXERROR(ERRHRD,ERRgeneral));
2662 outsize = set_message(outbuf,1,0,True);
2664 SSVAL(outbuf,smb_vwv0,nwritten);
2665 END_PROFILE(SMBwriteclose);
2666 return(outsize);
2669 /****************************************************************************
2670 Reply to a lock.
2671 ****************************************************************************/
2673 int reply_lock(connection_struct *conn,
2674 char *inbuf,char *outbuf, int length, int dum_buffsize)
2676 int outsize = set_message(outbuf,0,0,True);
2677 SMB_BIG_UINT count,offset;
2678 NTSTATUS status;
2679 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2680 BOOL my_lock_ctx = False;
2682 START_PROFILE(SMBlock);
2684 CHECK_FSP(fsp,conn);
2686 release_level_2_oplocks_on_change(fsp);
2688 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2689 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2691 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2692 fsp->fd, fsp->fnum, (double)offset, (double)count));
2694 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2695 if (NT_STATUS_V(status)) {
2696 #if 0
2697 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2698 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2700 * A blocking lock was requested. Package up
2701 * this smb into a queued request and push it
2702 * onto the blocking lock queue.
2704 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2705 END_PROFILE(SMBlock);
2706 return -1;
2709 #endif
2710 END_PROFILE(SMBlock);
2711 return ERROR_NT(status);
2714 END_PROFILE(SMBlock);
2715 return(outsize);
2718 /****************************************************************************
2719 Reply to a unlock.
2720 ****************************************************************************/
2722 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2723 int dum_buffsize)
2725 int outsize = set_message(outbuf,0,0,True);
2726 SMB_BIG_UINT count,offset;
2727 NTSTATUS status;
2728 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2729 START_PROFILE(SMBunlock);
2731 CHECK_FSP(fsp,conn);
2733 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2734 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2736 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2737 if (NT_STATUS_V(status)) {
2738 END_PROFILE(SMBunlock);
2739 return ERROR_NT(status);
2742 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2743 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2745 END_PROFILE(SMBunlock);
2746 return(outsize);
2749 /****************************************************************************
2750 Reply to a tdis.
2751 ****************************************************************************/
2753 int reply_tdis(connection_struct *conn,
2754 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2756 int outsize = set_message(outbuf,0,0,True);
2757 uint16 vuid;
2758 START_PROFILE(SMBtdis);
2760 vuid = SVAL(inbuf,smb_uid);
2762 if (!conn) {
2763 DEBUG(4,("Invalid connection in tdis\n"));
2764 END_PROFILE(SMBtdis);
2765 return ERROR_DOS(ERRSRV,ERRinvnid);
2768 conn->used = False;
2770 close_cnum(conn,vuid);
2772 END_PROFILE(SMBtdis);
2773 return outsize;
2776 /****************************************************************************
2777 Reply to a echo.
2778 ****************************************************************************/
2780 int reply_echo(connection_struct *conn,
2781 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2783 int smb_reverb = SVAL(inbuf,smb_vwv0);
2784 int seq_num;
2785 unsigned int data_len = smb_buflen(inbuf);
2786 int outsize = set_message(outbuf,1,data_len,True);
2787 START_PROFILE(SMBecho);
2789 if (data_len > BUFFER_SIZE) {
2790 DEBUG(0,("reply_echo: data_len too large.\n"));
2791 END_PROFILE(SMBecho);
2792 return -1;
2795 /* copy any incoming data back out */
2796 if (data_len > 0)
2797 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2799 if (smb_reverb > 100) {
2800 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2801 smb_reverb = 100;
2804 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2805 SSVAL(outbuf,smb_vwv0,seq_num);
2807 smb_setlen(outbuf,outsize - 4);
2809 if (!send_smb(smbd_server_fd(),outbuf))
2810 exit_server("reply_echo: send_smb failed.");
2813 DEBUG(3,("echo %d times\n", smb_reverb));
2815 smb_echo_count++;
2817 END_PROFILE(SMBecho);
2818 return -1;
2821 /****************************************************************************
2822 Reply to a printopen.
2823 ****************************************************************************/
2825 int reply_printopen(connection_struct *conn,
2826 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2828 int outsize = 0;
2829 files_struct *fsp;
2830 START_PROFILE(SMBsplopen);
2832 if (!CAN_PRINT(conn)) {
2833 END_PROFILE(SMBsplopen);
2834 return ERROR_DOS(ERRDOS,ERRnoaccess);
2837 /* Open for exclusive use, write only. */
2838 fsp = print_fsp_open(conn, NULL);
2840 if (!fsp) {
2841 END_PROFILE(SMBsplopen);
2842 return(UNIXERROR(ERRDOS,ERRnoaccess));
2845 outsize = set_message(outbuf,1,0,True);
2846 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2848 DEBUG(3,("openprint fd=%d fnum=%d\n",
2849 fsp->fd, fsp->fnum));
2851 END_PROFILE(SMBsplopen);
2852 return(outsize);
2855 /****************************************************************************
2856 Reply to a printclose.
2857 ****************************************************************************/
2859 int reply_printclose(connection_struct *conn,
2860 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2862 int outsize = set_message(outbuf,0,0,True);
2863 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2864 int close_err = 0;
2865 START_PROFILE(SMBsplclose);
2867 CHECK_FSP(fsp,conn);
2869 if (!CAN_PRINT(conn)) {
2870 END_PROFILE(SMBsplclose);
2871 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2874 DEBUG(3,("printclose fd=%d fnum=%d\n",
2875 fsp->fd,fsp->fnum));
2877 close_err = close_file(fsp,True);
2879 if(close_err != 0) {
2880 errno = close_err;
2881 END_PROFILE(SMBsplclose);
2882 return(UNIXERROR(ERRHRD,ERRgeneral));
2885 END_PROFILE(SMBsplclose);
2886 return(outsize);
2889 /****************************************************************************
2890 Reply to a printqueue.
2891 ****************************************************************************/
2893 int reply_printqueue(connection_struct *conn,
2894 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2896 int outsize = set_message(outbuf,2,3,True);
2897 int max_count = SVAL(inbuf,smb_vwv0);
2898 int start_index = SVAL(inbuf,smb_vwv1);
2899 START_PROFILE(SMBsplretq);
2901 /* we used to allow the client to get the cnum wrong, but that
2902 is really quite gross and only worked when there was only
2903 one printer - I think we should now only accept it if they
2904 get it right (tridge) */
2905 if (!CAN_PRINT(conn)) {
2906 END_PROFILE(SMBsplretq);
2907 return ERROR_DOS(ERRDOS,ERRnoaccess);
2910 SSVAL(outbuf,smb_vwv0,0);
2911 SSVAL(outbuf,smb_vwv1,0);
2912 SCVAL(smb_buf(outbuf),0,1);
2913 SSVAL(smb_buf(outbuf),1,0);
2915 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2916 start_index, max_count));
2919 print_queue_struct *queue = NULL;
2920 print_status_struct status;
2921 char *p = smb_buf(outbuf) + 3;
2922 int count = print_queue_status(SNUM(conn), &queue, &status);
2923 int num_to_get = ABS(max_count);
2924 int first = (max_count>0?start_index:start_index+max_count+1);
2925 int i;
2927 if (first >= count)
2928 num_to_get = 0;
2929 else
2930 num_to_get = MIN(num_to_get,count-first);
2933 for (i=first;i<first+num_to_get;i++) {
2934 put_dos_date2(p,0,queue[i].time);
2935 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2936 SSVAL(p,5, queue[i].job);
2937 SIVAL(p,7,queue[i].size);
2938 SCVAL(p,11,0);
2939 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2940 p += 28;
2943 if (count > 0) {
2944 outsize = set_message(outbuf,2,28*count+3,False);
2945 SSVAL(outbuf,smb_vwv0,count);
2946 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2947 SCVAL(smb_buf(outbuf),0,1);
2948 SSVAL(smb_buf(outbuf),1,28*count);
2951 SAFE_FREE(queue);
2953 DEBUG(3,("%d entries returned in queue\n",count));
2956 END_PROFILE(SMBsplretq);
2957 return(outsize);
2960 /****************************************************************************
2961 Reply to a printwrite.
2962 ****************************************************************************/
2964 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2966 int numtowrite;
2967 int outsize = set_message(outbuf,0,0,True);
2968 char *data;
2969 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2971 START_PROFILE(SMBsplwr);
2973 if (!CAN_PRINT(conn)) {
2974 END_PROFILE(SMBsplwr);
2975 return ERROR_DOS(ERRDOS,ERRnoaccess);
2978 CHECK_FSP(fsp,conn);
2979 CHECK_WRITE(fsp);
2981 numtowrite = SVAL(smb_buf(inbuf),1);
2982 data = smb_buf(inbuf) + 3;
2984 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2985 END_PROFILE(SMBsplwr);
2986 return(UNIXERROR(ERRHRD,ERRdiskfull));
2989 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2991 END_PROFILE(SMBsplwr);
2992 return(outsize);
2995 /****************************************************************************
2996 The guts of the mkdir command, split out so it may be called by the NT SMB
2997 code.
2998 ****************************************************************************/
3000 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3002 BOOL bad_path = False;
3003 SMB_STRUCT_STAT sbuf;
3004 int ret= -1;
3006 unix_convert(directory,conn,0,&bad_path,&sbuf);
3008 if (ms_has_wild(directory)) {
3009 return NT_STATUS_OBJECT_NAME_INVALID;
3012 if (check_name(directory, conn))
3013 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3015 if (ret == -1) {
3016 if(errno == ENOENT) {
3017 if (bad_path)
3018 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3019 else
3020 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3022 return map_nt_error_from_unix(errno);
3025 return NT_STATUS_OK;
3028 /****************************************************************************
3029 Reply to a mkdir.
3030 ****************************************************************************/
3032 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3034 pstring directory;
3035 int outsize;
3036 NTSTATUS status;
3037 START_PROFILE(SMBmkdir);
3039 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3040 if (!NT_STATUS_IS_OK(status)) {
3041 END_PROFILE(SMBmkdir);
3042 return ERROR_NT(status);
3045 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3047 status = mkdir_internal(conn, directory);
3048 if (!NT_STATUS_IS_OK(status)) {
3049 END_PROFILE(SMBmkdir);
3050 return ERROR_NT(status);
3053 outsize = set_message(outbuf,0,0,True);
3055 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3057 END_PROFILE(SMBmkdir);
3058 return(outsize);
3061 /****************************************************************************
3062 Static function used by reply_rmdir to delete an entire directory
3063 tree recursively. Return False on ok, True on fail.
3064 ****************************************************************************/
3066 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3068 const char *dname = NULL;
3069 BOOL ret = False;
3070 void *dirptr = OpenDir(conn, directory, False);
3072 if(dirptr == NULL)
3073 return True;
3075 while((dname = ReadDirName(dirptr))) {
3076 pstring fullname;
3077 SMB_STRUCT_STAT st;
3079 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3080 continue;
3082 /* Construct the full name. */
3083 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3084 errno = ENOMEM;
3085 ret = True;
3086 break;
3089 pstrcpy(fullname, directory);
3090 pstrcat(fullname, "/");
3091 pstrcat(fullname, dname);
3093 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3094 ret = True;
3095 break;
3098 if(st.st_mode & S_IFDIR) {
3099 if(recursive_rmdir(conn, fullname)!=0) {
3100 ret = True;
3101 break;
3103 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3104 ret = True;
3105 break;
3107 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3108 ret = True;
3109 break;
3112 CloseDir(dirptr);
3113 return ret;
3116 /****************************************************************************
3117 The internals of the rmdir code - called elsewhere.
3118 ****************************************************************************/
3120 BOOL rmdir_internals(connection_struct *conn, char *directory)
3122 BOOL ok;
3124 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3125 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3127 * Check to see if the only thing in this directory are
3128 * vetoed files/directories. If so then delete them and
3129 * retry. If we fail to delete any of them (and we *don't*
3130 * do a recursive delete) then fail the rmdir.
3132 BOOL all_veto_files = True;
3133 const char *dname;
3134 void *dirptr = OpenDir(conn, directory, False);
3136 if(dirptr != NULL) {
3137 int dirpos = TellDir(dirptr);
3138 while ((dname = ReadDirName(dirptr))) {
3139 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3140 continue;
3141 if(!IS_VETO_PATH(conn, dname)) {
3142 all_veto_files = False;
3143 break;
3147 if(all_veto_files) {
3148 SeekDir(dirptr,dirpos);
3149 while ((dname = ReadDirName(dirptr))) {
3150 pstring fullname;
3151 SMB_STRUCT_STAT st;
3153 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3154 continue;
3156 /* Construct the full name. */
3157 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3158 errno = ENOMEM;
3159 break;
3162 pstrcpy(fullname, directory);
3163 pstrcat(fullname, "/");
3164 pstrcat(fullname, dname);
3166 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3167 break;
3168 if(st.st_mode & S_IFDIR) {
3169 if(lp_recursive_veto_delete(SNUM(conn))) {
3170 if(recursive_rmdir(conn, fullname) != 0)
3171 break;
3173 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3174 break;
3175 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3176 break;
3178 CloseDir(dirptr);
3179 /* Retry the rmdir */
3180 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3181 } else {
3182 CloseDir(dirptr);
3184 } else {
3185 errno = ENOTEMPTY;
3189 if (!ok)
3190 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3192 return ok;
3195 /****************************************************************************
3196 Reply to a rmdir.
3197 ****************************************************************************/
3199 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3201 pstring directory;
3202 int outsize = 0;
3203 BOOL ok = False;
3204 BOOL bad_path = False;
3205 SMB_STRUCT_STAT sbuf;
3206 NTSTATUS status;
3207 START_PROFILE(SMBrmdir);
3209 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3210 if (!NT_STATUS_IS_OK(status)) {
3211 END_PROFILE(SMBrmdir);
3212 return ERROR_NT(status);
3215 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3217 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3219 if (check_name(directory,conn)) {
3220 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3221 ok = rmdir_internals(conn, directory);
3224 if (!ok) {
3225 END_PROFILE(SMBrmdir);
3226 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3229 outsize = set_message(outbuf,0,0,True);
3231 DEBUG( 3, ( "rmdir %s\n", directory ) );
3233 END_PROFILE(SMBrmdir);
3234 return(outsize);
3237 /*******************************************************************
3238 Resolve wildcards in a filename rename.
3239 ********************************************************************/
3241 static BOOL resolve_wildcards(const char *name1, char *name2)
3243 fstring root1,root2;
3244 fstring ext1,ext2;
3245 char *p,*p2, *pname1, *pname2;
3246 int available_space;
3249 pname1 = strrchr_m(name1,'/');
3250 pname2 = strrchr_m(name2,'/');
3252 if (!pname1 || !pname2)
3253 return(False);
3255 fstrcpy(root1,pname1);
3256 fstrcpy(root2,pname2);
3257 p = strrchr_m(root1,'.');
3258 if (p) {
3259 *p = 0;
3260 fstrcpy(ext1,p+1);
3261 } else {
3262 fstrcpy(ext1,"");
3264 p = strrchr_m(root2,'.');
3265 if (p) {
3266 *p = 0;
3267 fstrcpy(ext2,p+1);
3268 } else {
3269 fstrcpy(ext2,"");
3272 p = root1;
3273 p2 = root2;
3274 while (*p2) {
3275 if (*p2 == '?') {
3276 *p2 = *p;
3277 p2++;
3278 } else {
3279 p2++;
3281 if (*p)
3282 p++;
3285 p = ext1;
3286 p2 = ext2;
3287 while (*p2) {
3288 if (*p2 == '?') {
3289 *p2 = *p;
3290 p2++;
3291 } else {
3292 p2++;
3294 if (*p)
3295 p++;
3298 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3300 if (ext2[0]) {
3301 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3302 } else {
3303 pstrcpy_base(pname2, root2, name2);
3306 return(True);
3309 /****************************************************************************
3310 Ensure open files have their names updates.
3311 ****************************************************************************/
3313 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3315 files_struct *fsp;
3316 BOOL did_rename = False;
3318 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3319 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3320 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3321 fsp->fsp_name, newname ));
3322 string_set(&fsp->fsp_name, newname);
3323 did_rename = True;
3326 if (!did_rename)
3327 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3328 (unsigned int)dev, (double)inode, newname ));
3331 /****************************************************************************
3332 Rename an open file - given an fsp.
3333 ****************************************************************************/
3335 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3337 SMB_STRUCT_STAT sbuf;
3338 BOOL bad_path = False;
3339 pstring newname_last_component;
3340 NTSTATUS error = NT_STATUS_OK;
3341 BOOL dest_exists;
3343 ZERO_STRUCT(sbuf);
3344 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3346 /* Ensure newname contains a '/' */
3347 if(strrchr_m(newname,'/') == 0) {
3348 pstring tmpstr;
3350 pstrcpy(tmpstr, "./");
3351 pstrcat(tmpstr, newname);
3352 pstrcpy(newname, tmpstr);
3356 * Check for special case with case preserving and not
3357 * case sensitive. If the old last component differs from the original
3358 * last component only by case, then we should allow
3359 * the rename (user is trying to change the case of the
3360 * filename).
3363 if((case_sensitive == False) && (case_preserve == True) &&
3364 strequal(newname, fsp->fsp_name)) {
3365 char *p;
3366 pstring newname_modified_last_component;
3369 * Get the last component of the modified name.
3370 * Note that we guarantee that newname contains a '/'
3371 * character above.
3373 p = strrchr_m(newname,'/');
3374 pstrcpy(newname_modified_last_component,p+1);
3376 if(strcsequal(newname_modified_last_component,
3377 newname_last_component) == False) {
3379 * Replace the modified last component with
3380 * the original.
3382 pstrcpy(p+1, newname_last_component);
3387 * If the src and dest names are identical - including case,
3388 * don't do the rename, just return success.
3391 if (strcsequal(fsp->fsp_name, newname)) {
3392 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3393 newname));
3394 return NT_STATUS_OK;
3397 dest_exists = vfs_object_exist(conn,newname,NULL);
3399 if(!replace_if_exists && dest_exists) {
3400 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3401 fsp->fsp_name,newname));
3402 return NT_STATUS_OBJECT_NAME_COLLISION;
3405 error = can_rename(newname,conn,&sbuf);
3407 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3408 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3409 nt_errstr(error), fsp->fsp_name,newname));
3410 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3411 error = NT_STATUS_ACCESS_DENIED;
3412 return error;
3415 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3416 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3417 fsp->fsp_name,newname));
3418 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3419 return NT_STATUS_OK;
3422 if (errno == ENOTDIR || errno == EISDIR)
3423 error = NT_STATUS_OBJECT_NAME_COLLISION;
3424 else
3425 error = map_nt_error_from_unix(errno);
3427 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3428 nt_errstr(error), fsp->fsp_name,newname));
3430 return error;
3433 /****************************************************************************
3434 The guts of the rename command, split out so it may be called by the NT SMB
3435 code.
3436 ****************************************************************************/
3438 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3440 pstring directory;
3441 pstring mask;
3442 pstring newname_last_component;
3443 char *p;
3444 BOOL has_wild;
3445 BOOL bad_path1 = False;
3446 BOOL bad_path2 = False;
3447 int count=0;
3448 NTSTATUS error = NT_STATUS_OK;
3449 BOOL rc = True;
3450 SMB_STRUCT_STAT sbuf1, sbuf2;
3452 *directory = *mask = 0;
3454 ZERO_STRUCT(sbuf1);
3455 ZERO_STRUCT(sbuf2);
3456 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3457 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3460 * Split the old name into directory and last component
3461 * strings. Note that unix_convert may have stripped off a
3462 * leading ./ from both name and newname if the rename is
3463 * at the root of the share. We need to make sure either both
3464 * name and newname contain a / character or neither of them do
3465 * as this is checked in resolve_wildcards().
3468 p = strrchr_m(name,'/');
3469 if (!p) {
3470 pstrcpy(directory,".");
3471 pstrcpy(mask,name);
3472 } else {
3473 *p = 0;
3474 pstrcpy(directory,name);
3475 pstrcpy(mask,p+1);
3476 *p = '/'; /* Replace needed for exceptional test below. */
3480 * We should only check the mangled cache
3481 * here if unix_convert failed. This means
3482 * that the path in 'mask' doesn't exist
3483 * on the file system and so we need to look
3484 * for a possible mangle. This patch from
3485 * Tine Smukavec <valentin.smukavec@hermes.si>.
3488 if (!rc && mangle_is_mangled(mask))
3489 mangle_check_cache( mask );
3491 has_wild = ms_has_wild(mask);
3493 if (!has_wild) {
3495 * No wildcards - just process the one file.
3497 BOOL is_short_name = mangle_is_8_3(name, True);
3499 /* Add a terminating '/' to the directory name. */
3500 pstrcat(directory,"/");
3501 pstrcat(directory,mask);
3503 /* Ensure newname contains a '/' also */
3504 if(strrchr_m(newname,'/') == 0) {
3505 pstring tmpstr;
3507 pstrcpy(tmpstr, "./");
3508 pstrcat(tmpstr, newname);
3509 pstrcpy(newname, tmpstr);
3512 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3513 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3514 case_sensitive, case_preserve, short_case_preserve, directory,
3515 newname, newname_last_component, is_short_name));
3518 * Check for special case with case preserving and not
3519 * case sensitive, if directory and newname are identical,
3520 * and the old last component differs from the original
3521 * last component only by case, then we should allow
3522 * the rename (user is trying to change the case of the
3523 * filename).
3525 if((case_sensitive == False) &&
3526 (((case_preserve == True) &&
3527 (is_short_name == False)) ||
3528 ((short_case_preserve == True) &&
3529 (is_short_name == True))) &&
3530 strcsequal(directory, newname)) {
3531 pstring newname_modified_last_component;
3534 * Get the last component of the modified name.
3535 * Note that we guarantee that newname contains a '/'
3536 * character above.
3538 p = strrchr_m(newname,'/');
3539 pstrcpy(newname_modified_last_component,p+1);
3541 if(strcsequal(newname_modified_last_component,
3542 newname_last_component) == False) {
3544 * Replace the modified last component with
3545 * the original.
3547 pstrcpy(p+1, newname_last_component);
3551 resolve_wildcards(directory,newname);
3554 * The source object must exist.
3557 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3558 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3559 directory,newname));
3561 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3563 * Must return different errors depending on whether the parent
3564 * directory existed or not.
3567 p = strrchr_m(directory, '/');
3568 if (!p)
3569 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3570 *p = '\0';
3571 if (vfs_object_exist(conn, directory, NULL))
3572 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3573 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3575 error = map_nt_error_from_unix(errno);
3576 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3577 nt_errstr(error), directory,newname));
3579 return error;
3582 error = can_rename(directory,conn,&sbuf1);
3584 if (!NT_STATUS_IS_OK(error)) {
3585 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3586 nt_errstr(error), directory,newname));
3587 return error;
3591 * If the src and dest names are identical - including case,
3592 * don't do the rename, just return success.
3595 if (strcsequal(directory, newname)) {
3596 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3597 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3598 return NT_STATUS_OK;
3601 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3602 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3603 directory,newname));
3604 return NT_STATUS_OBJECT_NAME_COLLISION;
3607 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3608 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3609 directory,newname));
3610 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3611 return NT_STATUS_OK;
3614 if (errno == ENOTDIR || errno == EISDIR)
3615 error = NT_STATUS_OBJECT_NAME_COLLISION;
3616 else
3617 error = map_nt_error_from_unix(errno);
3619 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3620 nt_errstr(error), directory,newname));
3622 return error;
3623 } else {
3625 * Wildcards - process each file that matches.
3627 void *dirptr = NULL;
3628 const char *dname;
3629 pstring destname;
3631 if (check_name(directory,conn))
3632 dirptr = OpenDir(conn, directory, True);
3634 if (dirptr) {
3635 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3637 if (strequal(mask,"????????.???"))
3638 pstrcpy(mask,"*");
3640 while ((dname = ReadDirName(dirptr))) {
3641 pstring fname;
3643 pstrcpy(fname,dname);
3645 if(!mask_match(fname, mask, case_sensitive))
3646 continue;
3648 error = NT_STATUS_ACCESS_DENIED;
3649 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3650 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3651 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3652 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3653 continue;
3655 error = can_rename(fname,conn,&sbuf1);
3656 if (!NT_STATUS_IS_OK(error)) {
3657 DEBUG(6,("rename %s refused\n", fname));
3658 continue;
3660 pstrcpy(destname,newname);
3662 if (!resolve_wildcards(fname,destname)) {
3663 DEBUG(6,("resolve_wildcards %s %s failed\n",
3664 fname, destname));
3665 continue;
3668 if (!replace_if_exists &&
3669 vfs_file_exist(conn,destname, NULL)) {
3670 DEBUG(6,("file_exist %s\n", destname));
3671 error = NT_STATUS_OBJECT_NAME_COLLISION;
3672 continue;
3675 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3676 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3677 count++;
3679 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3681 CloseDir(dirptr);
3685 if (count == 0 && NT_STATUS_IS_OK(error)) {
3686 error = map_nt_error_from_unix(errno);
3689 return error;
3692 /****************************************************************************
3693 Reply to a mv.
3694 ****************************************************************************/
3696 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3697 int dum_buffsize)
3699 int outsize = 0;
3700 pstring name;
3701 pstring newname;
3702 char *p;
3703 NTSTATUS status;
3705 START_PROFILE(SMBmv);
3707 p = smb_buf(inbuf) + 1;
3708 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3709 if (!NT_STATUS_IS_OK(status)) {
3710 END_PROFILE(SMBmv);
3711 return ERROR_NT(status);
3713 p++;
3714 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3715 if (!NT_STATUS_IS_OK(status)) {
3716 END_PROFILE(SMBmv);
3717 return ERROR_NT(status);
3720 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3721 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3723 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3725 status = rename_internals(conn, name, newname, False);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 END_PROFILE(SMBmv);
3728 return ERROR_NT(status);
3732 * Win2k needs a changenotify request response before it will
3733 * update after a rename..
3735 process_pending_change_notify_queue((time_t)0);
3736 outsize = set_message(outbuf,0,0,True);
3738 END_PROFILE(SMBmv);
3739 return(outsize);
3742 /*******************************************************************
3743 Copy a file as part of a reply_copy.
3744 ******************************************************************/
3746 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3747 int count,BOOL target_is_directory, int *err_ret)
3749 int Access,action;
3750 SMB_STRUCT_STAT src_sbuf, sbuf2;
3751 SMB_OFF_T ret=-1;
3752 files_struct *fsp1,*fsp2;
3753 pstring dest;
3755 *err_ret = 0;
3757 pstrcpy(dest,dest1);
3758 if (target_is_directory) {
3759 char *p = strrchr_m(src,'/');
3760 if (p)
3761 p++;
3762 else
3763 p = src;
3764 pstrcat(dest,"/");
3765 pstrcat(dest,p);
3768 if (!vfs_file_exist(conn,src,&src_sbuf))
3769 return(False);
3771 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3772 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3774 if (!fsp1)
3775 return(False);
3777 if (!target_is_directory && count)
3778 ofun = FILE_EXISTS_OPEN;
3780 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3781 ZERO_STRUCTP(&sbuf2);
3783 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3784 ofun,src_sbuf.st_mode,0,&Access,&action);
3786 if (!fsp2) {
3787 close_file(fsp1,False);
3788 return(False);
3791 if ((ofun&3) == 1) {
3792 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3793 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3795 * Stop the copy from occurring.
3797 ret = -1;
3798 src_sbuf.st_size = 0;
3802 if (src_sbuf.st_size)
3803 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3805 close_file(fsp1,False);
3807 /* Ensure the modtime is set correctly on the destination file. */
3808 fsp2->pending_modtime = src_sbuf.st_mtime;
3811 * As we are opening fsp1 read-only we only expect
3812 * an error on close on fsp2 if we are out of space.
3813 * Thus we don't look at the error return from the
3814 * close of fsp1.
3816 *err_ret = close_file(fsp2,False);
3818 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3821 /****************************************************************************
3822 Reply to a file copy.
3823 ****************************************************************************/
3825 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3827 int outsize = 0;
3828 pstring name;
3829 pstring directory;
3830 pstring mask,newname;
3831 char *p;
3832 int count=0;
3833 int error = ERRnoaccess;
3834 int err = 0;
3835 BOOL has_wild;
3836 BOOL exists=False;
3837 int tid2 = SVAL(inbuf,smb_vwv0);
3838 int ofun = SVAL(inbuf,smb_vwv1);
3839 int flags = SVAL(inbuf,smb_vwv2);
3840 BOOL target_is_directory=False;
3841 BOOL bad_path1 = False;
3842 BOOL bad_path2 = False;
3843 BOOL rc = True;
3844 SMB_STRUCT_STAT sbuf1, sbuf2;
3845 NTSTATUS status;
3847 START_PROFILE(SMBcopy);
3849 *directory = *mask = 0;
3851 p = smb_buf(inbuf);
3852 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3853 if (!NT_STATUS_IS_OK(status)) {
3854 END_PROFILE(SMBcopy);
3855 return ERROR_NT(status);
3857 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3858 if (!NT_STATUS_IS_OK(status)) {
3859 END_PROFILE(SMBcopy);
3860 return ERROR_NT(status);
3863 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3865 if (tid2 != conn->cnum) {
3866 /* can't currently handle inter share copies XXXX */
3867 DEBUG(3,("Rejecting inter-share copy\n"));
3868 END_PROFILE(SMBcopy);
3869 return ERROR_DOS(ERRSRV,ERRinvdevice);
3872 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3873 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3875 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3876 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3878 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3880 if ((flags&1) && target_is_directory) {
3881 END_PROFILE(SMBcopy);
3882 return ERROR_DOS(ERRDOS,ERRbadfile);
3885 if ((flags&2) && !target_is_directory) {
3886 END_PROFILE(SMBcopy);
3887 return ERROR_DOS(ERRDOS,ERRbadpath);
3890 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3891 /* wants a tree copy! XXXX */
3892 DEBUG(3,("Rejecting tree copy\n"));
3893 END_PROFILE(SMBcopy);
3894 return ERROR_DOS(ERRSRV,ERRerror);
3897 p = strrchr_m(name,'/');
3898 if (!p) {
3899 pstrcpy(directory,"./");
3900 pstrcpy(mask,name);
3901 } else {
3902 *p = 0;
3903 pstrcpy(directory,name);
3904 pstrcpy(mask,p+1);
3908 * We should only check the mangled cache
3909 * here if unix_convert failed. This means
3910 * that the path in 'mask' doesn't exist
3911 * on the file system and so we need to look
3912 * for a possible mangle. This patch from
3913 * Tine Smukavec <valentin.smukavec@hermes.si>.
3916 if (!rc && mangle_is_mangled(mask))
3917 mangle_check_cache( mask );
3919 has_wild = ms_has_wild(mask);
3921 if (!has_wild) {
3922 pstrcat(directory,"/");
3923 pstrcat(directory,mask);
3924 if (resolve_wildcards(directory,newname) &&
3925 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3926 count++;
3927 if(!count && err) {
3928 errno = err;
3929 END_PROFILE(SMBcopy);
3930 return(UNIXERROR(ERRHRD,ERRgeneral));
3932 if (!count) {
3933 exists = vfs_file_exist(conn,directory,NULL);
3935 } else {
3936 void *dirptr = NULL;
3937 const char *dname;
3938 pstring destname;
3940 if (check_name(directory,conn))
3941 dirptr = OpenDir(conn, directory, True);
3943 if (dirptr) {
3944 error = ERRbadfile;
3946 if (strequal(mask,"????????.???"))
3947 pstrcpy(mask,"*");
3949 while ((dname = ReadDirName(dirptr))) {
3950 pstring fname;
3951 pstrcpy(fname,dname);
3953 if(!mask_match(fname, mask, case_sensitive))
3954 continue;
3956 error = ERRnoaccess;
3957 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3958 pstrcpy(destname,newname);
3959 if (resolve_wildcards(fname,destname) &&
3960 copy_file(fname,destname,conn,ofun,
3961 count,target_is_directory,&err))
3962 count++;
3963 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3965 CloseDir(dirptr);
3969 if (count == 0) {
3970 if(err) {
3971 /* Error on close... */
3972 errno = err;
3973 END_PROFILE(SMBcopy);
3974 return(UNIXERROR(ERRHRD,ERRgeneral));
3977 if (exists) {
3978 END_PROFILE(SMBcopy);
3979 return ERROR_DOS(ERRDOS,error);
3980 } else {
3981 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3982 unix_ERR_class = ERRDOS;
3983 unix_ERR_code = ERRbadpath;
3985 END_PROFILE(SMBcopy);
3986 return(UNIXERROR(ERRDOS,error));
3990 outsize = set_message(outbuf,1,0,True);
3991 SSVAL(outbuf,smb_vwv0,count);
3993 END_PROFILE(SMBcopy);
3994 return(outsize);
3997 /****************************************************************************
3998 Reply to a setdir.
3999 ****************************************************************************/
4001 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4003 int snum;
4004 int outsize = 0;
4005 BOOL ok = False;
4006 pstring newdir;
4007 NTSTATUS status;
4009 START_PROFILE(pathworks_setdir);
4011 snum = SNUM(conn);
4012 if (!CAN_SETDIR(snum)) {
4013 END_PROFILE(pathworks_setdir);
4014 return ERROR_DOS(ERRDOS,ERRnoaccess);
4017 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4018 if (!NT_STATUS_IS_OK(status)) {
4019 END_PROFILE(pathworks_setdir);
4020 return ERROR_NT(status);
4023 if (strlen(newdir) == 0) {
4024 ok = True;
4025 } else {
4026 ok = vfs_directory_exist(conn,newdir,NULL);
4027 if (ok)
4028 string_set(&conn->connectpath,newdir);
4031 if (!ok) {
4032 END_PROFILE(pathworks_setdir);
4033 return ERROR_DOS(ERRDOS,ERRbadpath);
4036 outsize = set_message(outbuf,0,0,True);
4037 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4039 DEBUG(3,("setdir %s\n", newdir));
4041 END_PROFILE(pathworks_setdir);
4042 return(outsize);
4045 /****************************************************************************
4046 Get a lock pid, dealing with large count requests.
4047 ****************************************************************************/
4049 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4051 if(!large_file_format)
4052 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4053 else
4054 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4057 /****************************************************************************
4058 Get a lock count, dealing with large count requests.
4059 ****************************************************************************/
4061 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4063 SMB_BIG_UINT count = 0;
4065 if(!large_file_format) {
4066 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4067 } else {
4069 #if defined(HAVE_LONGLONG)
4070 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4071 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4072 #else /* HAVE_LONGLONG */
4075 * NT4.x seems to be broken in that it sends large file (64 bit)
4076 * lockingX calls even if the CAP_LARGE_FILES was *not*
4077 * negotiated. For boxes without large unsigned ints truncate the
4078 * lock count by dropping the top 32 bits.
4081 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4082 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4083 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4084 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4085 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4088 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4089 #endif /* HAVE_LONGLONG */
4092 return count;
4095 #if !defined(HAVE_LONGLONG)
4096 /****************************************************************************
4097 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4098 ****************************************************************************/
4100 static uint32 map_lock_offset(uint32 high, uint32 low)
4102 unsigned int i;
4103 uint32 mask = 0;
4104 uint32 highcopy = high;
4107 * Try and find out how many significant bits there are in high.
4110 for(i = 0; highcopy; i++)
4111 highcopy >>= 1;
4114 * We use 31 bits not 32 here as POSIX
4115 * lock offsets may not be negative.
4118 mask = (~0) << (31 - i);
4120 if(low & mask)
4121 return 0; /* Fail. */
4123 high <<= (31 - i);
4125 return (high|low);
4127 #endif /* !defined(HAVE_LONGLONG) */
4129 /****************************************************************************
4130 Get a lock offset, dealing with large offset requests.
4131 ****************************************************************************/
4133 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4135 SMB_BIG_UINT offset = 0;
4137 *err = False;
4139 if(!large_file_format) {
4140 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4141 } else {
4143 #if defined(HAVE_LONGLONG)
4144 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4145 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4146 #else /* HAVE_LONGLONG */
4149 * NT4.x seems to be broken in that it sends large file (64 bit)
4150 * lockingX calls even if the CAP_LARGE_FILES was *not*
4151 * negotiated. For boxes without large unsigned ints mangle the
4152 * lock offset by mapping the top 32 bits onto the lower 32.
4155 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4156 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4157 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4158 uint32 new_low = 0;
4160 if((new_low = map_lock_offset(high, low)) == 0) {
4161 *err = True;
4162 return (SMB_BIG_UINT)-1;
4165 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4166 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4167 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4168 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4171 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4172 #endif /* HAVE_LONGLONG */
4175 return offset;
4178 /****************************************************************************
4179 Reply to a lockingX request.
4180 ****************************************************************************/
4182 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4184 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4185 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4186 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4187 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4188 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4189 SMB_BIG_UINT count = 0, offset = 0;
4190 uint16 lock_pid;
4191 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4192 int i;
4193 char *data;
4194 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4195 BOOL err;
4196 BOOL my_lock_ctx = False;
4197 NTSTATUS status;
4199 START_PROFILE(SMBlockingX);
4201 CHECK_FSP(fsp,conn);
4203 data = smb_buf(inbuf);
4205 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4206 /* we don't support these - and CANCEL_LOCK makes w2k
4207 and XP reboot so I don't really want to be
4208 compatible! (tridge) */
4209 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4212 /* Check if this is an oplock break on a file
4213 we have granted an oplock on.
4215 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4216 /* Client can insist on breaking to none. */
4217 BOOL break_to_none = (oplocklevel == 0);
4219 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4220 (unsigned int)oplocklevel, fsp->fnum ));
4223 * Make sure we have granted an exclusive or batch oplock on this file.
4226 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4227 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4228 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4230 /* if this is a pure oplock break request then don't send a reply */
4231 if (num_locks == 0 && num_ulocks == 0) {
4232 END_PROFILE(SMBlockingX);
4233 return -1;
4234 } else {
4235 END_PROFILE(SMBlockingX);
4236 return ERROR_DOS(ERRDOS,ERRlock);
4240 if (remove_oplock(fsp, break_to_none) == False) {
4241 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4242 fsp->fsp_name ));
4245 /* if this is a pure oplock break request then don't send a reply */
4246 if (num_locks == 0 && num_ulocks == 0) {
4247 /* Sanity check - ensure a pure oplock break is not a
4248 chained request. */
4249 if(CVAL(inbuf,smb_vwv0) != 0xff)
4250 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4251 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4252 END_PROFILE(SMBlockingX);
4253 return -1;
4258 * We do this check *after* we have checked this is not a oplock break
4259 * response message. JRA.
4262 release_level_2_oplocks_on_change(fsp);
4264 /* Data now points at the beginning of the list
4265 of smb_unlkrng structs */
4266 for(i = 0; i < (int)num_ulocks; i++) {
4267 lock_pid = get_lock_pid( data, i, large_file_format);
4268 count = get_lock_count( data, i, large_file_format);
4269 offset = get_lock_offset( data, i, large_file_format, &err);
4272 * There is no error code marked "stupid client bug".... :-).
4274 if(err) {
4275 END_PROFILE(SMBlockingX);
4276 return ERROR_DOS(ERRDOS,ERRnoaccess);
4279 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4280 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4282 status = do_unlock(fsp,conn,lock_pid,count,offset);
4283 if (NT_STATUS_V(status)) {
4284 END_PROFILE(SMBlockingX);
4285 return ERROR_NT(status);
4289 /* Setup the timeout in seconds. */
4291 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4293 /* Now do any requested locks */
4294 data += ((large_file_format ? 20 : 10)*num_ulocks);
4296 /* Data now points at the beginning of the list
4297 of smb_lkrng structs */
4299 for(i = 0; i < (int)num_locks; i++) {
4300 lock_pid = get_lock_pid( data, i, large_file_format);
4301 count = get_lock_count( data, i, large_file_format);
4302 offset = get_lock_offset( data, i, large_file_format, &err);
4305 * There is no error code marked "stupid client bug".... :-).
4307 if(err) {
4308 END_PROFILE(SMBlockingX);
4309 return ERROR_DOS(ERRDOS,ERRnoaccess);
4312 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4313 (double)offset, (double)count, (unsigned int)lock_pid,
4314 fsp->fsp_name, (int)lock_timeout ));
4316 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4317 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4318 if (NT_STATUS_V(status)) {
4319 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4321 * A blocking lock was requested. Package up
4322 * this smb into a queued request and push it
4323 * onto the blocking lock queue.
4325 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4326 END_PROFILE(SMBlockingX);
4327 return -1;
4330 break;
4334 /* If any of the above locks failed, then we must unlock
4335 all of the previous locks (X/Open spec). */
4336 if (i != num_locks && num_locks != 0) {
4338 * Ensure we don't do a remove on the lock that just failed,
4339 * as under POSIX rules, if we have a lock already there, we
4340 * will delete it (and we shouldn't) .....
4342 for(i--; i >= 0; i--) {
4343 lock_pid = get_lock_pid( data, i, large_file_format);
4344 count = get_lock_count( data, i, large_file_format);
4345 offset = get_lock_offset( data, i, large_file_format, &err);
4348 * There is no error code marked "stupid client bug".... :-).
4350 if(err) {
4351 END_PROFILE(SMBlockingX);
4352 return ERROR_DOS(ERRDOS,ERRnoaccess);
4355 do_unlock(fsp,conn,lock_pid,count,offset);
4357 END_PROFILE(SMBlockingX);
4358 return ERROR_NT(status);
4361 set_message(outbuf,2,0,True);
4363 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4364 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4366 END_PROFILE(SMBlockingX);
4367 return chain_reply(inbuf,outbuf,length,bufsize);
4370 /****************************************************************************
4371 Reply to a SMBreadbmpx (read block multiplex) request.
4372 ****************************************************************************/
4374 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4376 ssize_t nread = -1;
4377 ssize_t total_read;
4378 char *data;
4379 SMB_OFF_T startpos;
4380 int outsize;
4381 size_t maxcount;
4382 int max_per_packet;
4383 size_t tcount;
4384 int pad;
4385 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4386 START_PROFILE(SMBreadBmpx);
4388 /* this function doesn't seem to work - disable by default */
4389 if (!lp_readbmpx()) {
4390 END_PROFILE(SMBreadBmpx);
4391 return ERROR_DOS(ERRSRV,ERRuseSTD);
4394 outsize = set_message(outbuf,8,0,True);
4396 CHECK_FSP(fsp,conn);
4397 CHECK_READ(fsp);
4399 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4400 maxcount = SVAL(inbuf,smb_vwv3);
4402 data = smb_buf(outbuf);
4403 pad = ((long)data)%4;
4404 if (pad)
4405 pad = 4 - pad;
4406 data += pad;
4408 max_per_packet = bufsize-(outsize+pad);
4409 tcount = maxcount;
4410 total_read = 0;
4412 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4413 END_PROFILE(SMBreadBmpx);
4414 return ERROR_DOS(ERRDOS,ERRlock);
4417 do {
4418 size_t N = MIN(max_per_packet,tcount-total_read);
4420 nread = read_file(fsp,data,startpos,N);
4422 if (nread <= 0)
4423 nread = 0;
4425 if (nread < (ssize_t)N)
4426 tcount = total_read + nread;
4428 set_message(outbuf,8,nread,False);
4429 SIVAL(outbuf,smb_vwv0,startpos);
4430 SSVAL(outbuf,smb_vwv2,tcount);
4431 SSVAL(outbuf,smb_vwv6,nread);
4432 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4434 if (!send_smb(smbd_server_fd(),outbuf))
4435 exit_server("reply_readbmpx: send_smb failed.");
4437 total_read += nread;
4438 startpos += nread;
4439 } while (total_read < (ssize_t)tcount);
4441 END_PROFILE(SMBreadBmpx);
4442 return(-1);
4445 /****************************************************************************
4446 Reply to a SMBsetattrE.
4447 ****************************************************************************/
4449 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4451 struct utimbuf unix_times;
4452 int outsize = 0;
4453 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4454 START_PROFILE(SMBsetattrE);
4456 outsize = set_message(outbuf,0,0,True);
4458 if(!fsp || (fsp->conn != conn)) {
4459 END_PROFILE(SMBgetattrE);
4460 return ERROR_DOS(ERRDOS,ERRbadfid);
4464 * Convert the DOS times into unix times. Ignore create
4465 * time as UNIX can't set this.
4468 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4469 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4472 * Patch from Ray Frush <frush@engr.colostate.edu>
4473 * Sometimes times are sent as zero - ignore them.
4476 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4477 /* Ignore request */
4478 if( DEBUGLVL( 3 ) ) {
4479 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4480 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4482 END_PROFILE(SMBsetattrE);
4483 return(outsize);
4484 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4485 /* set modify time = to access time if modify time was 0 */
4486 unix_times.modtime = unix_times.actime;
4489 /* Set the date on this file */
4490 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4491 END_PROFILE(SMBsetattrE);
4492 return ERROR_DOS(ERRDOS,ERRnoaccess);
4495 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4496 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4498 END_PROFILE(SMBsetattrE);
4499 return(outsize);
4503 /* Back from the dead for OS/2..... JRA. */
4505 /****************************************************************************
4506 Reply to a SMBwritebmpx (write block multiplex primary) request.
4507 ****************************************************************************/
4509 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4511 size_t numtowrite;
4512 ssize_t nwritten = -1;
4513 int outsize = 0;
4514 SMB_OFF_T startpos;
4515 size_t tcount;
4516 BOOL write_through;
4517 int smb_doff;
4518 char *data;
4519 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4520 START_PROFILE(SMBwriteBmpx);
4522 CHECK_FSP(fsp,conn);
4523 CHECK_WRITE(fsp);
4524 CHECK_ERROR(fsp);
4526 tcount = SVAL(inbuf,smb_vwv1);
4527 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4528 write_through = BITSETW(inbuf+smb_vwv7,0);
4529 numtowrite = SVAL(inbuf,smb_vwv10);
4530 smb_doff = SVAL(inbuf,smb_vwv11);
4532 data = smb_base(inbuf) + smb_doff;
4534 /* If this fails we need to send an SMBwriteC response,
4535 not an SMBwritebmpx - set this up now so we don't forget */
4536 SCVAL(outbuf,smb_com,SMBwritec);
4538 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4539 END_PROFILE(SMBwriteBmpx);
4540 return(ERROR_DOS(ERRDOS,ERRlock));
4543 nwritten = write_file(fsp,data,startpos,numtowrite);
4545 if(lp_syncalways(SNUM(conn)) || write_through)
4546 sync_file(conn,fsp);
4548 if(nwritten < (ssize_t)numtowrite) {
4549 END_PROFILE(SMBwriteBmpx);
4550 return(UNIXERROR(ERRHRD,ERRdiskfull));
4553 /* If the maximum to be written to this file
4554 is greater than what we just wrote then set
4555 up a secondary struct to be attached to this
4556 fd, we will use this to cache error messages etc. */
4558 if((ssize_t)tcount > nwritten) {
4559 write_bmpx_struct *wbms;
4560 if(fsp->wbmpx_ptr != NULL)
4561 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4562 else
4563 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4564 if(!wbms) {
4565 DEBUG(0,("Out of memory in reply_readmpx\n"));
4566 END_PROFILE(SMBwriteBmpx);
4567 return(ERROR_DOS(ERRSRV,ERRnoresource));
4569 wbms->wr_mode = write_through;
4570 wbms->wr_discard = False; /* No errors yet */
4571 wbms->wr_total_written = nwritten;
4572 wbms->wr_errclass = 0;
4573 wbms->wr_error = 0;
4574 fsp->wbmpx_ptr = wbms;
4577 /* We are returning successfully, set the message type back to
4578 SMBwritebmpx */
4579 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4581 outsize = set_message(outbuf,1,0,True);
4583 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4585 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4586 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4588 if (write_through && tcount==nwritten) {
4589 /* We need to send both a primary and a secondary response */
4590 smb_setlen(outbuf,outsize - 4);
4591 if (!send_smb(smbd_server_fd(),outbuf))
4592 exit_server("reply_writebmpx: send_smb failed.");
4594 /* Now the secondary */
4595 outsize = set_message(outbuf,1,0,True);
4596 SCVAL(outbuf,smb_com,SMBwritec);
4597 SSVAL(outbuf,smb_vwv0,nwritten);
4600 END_PROFILE(SMBwriteBmpx);
4601 return(outsize);
4604 /****************************************************************************
4605 Reply to a SMBwritebs (write block multiplex secondary) request.
4606 ****************************************************************************/
4608 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4610 size_t numtowrite;
4611 ssize_t nwritten = -1;
4612 int outsize = 0;
4613 SMB_OFF_T startpos;
4614 size_t tcount;
4615 BOOL write_through;
4616 int smb_doff;
4617 char *data;
4618 write_bmpx_struct *wbms;
4619 BOOL send_response = False;
4620 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4621 START_PROFILE(SMBwriteBs);
4623 CHECK_FSP(fsp,conn);
4624 CHECK_WRITE(fsp);
4626 tcount = SVAL(inbuf,smb_vwv1);
4627 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4628 numtowrite = SVAL(inbuf,smb_vwv6);
4629 smb_doff = SVAL(inbuf,smb_vwv7);
4631 data = smb_base(inbuf) + smb_doff;
4633 /* We need to send an SMBwriteC response, not an SMBwritebs */
4634 SCVAL(outbuf,smb_com,SMBwritec);
4636 /* This fd should have an auxiliary struct attached,
4637 check that it does */
4638 wbms = fsp->wbmpx_ptr;
4639 if(!wbms) {
4640 END_PROFILE(SMBwriteBs);
4641 return(-1);
4644 /* If write through is set we can return errors, else we must cache them */
4645 write_through = wbms->wr_mode;
4647 /* Check for an earlier error */
4648 if(wbms->wr_discard) {
4649 END_PROFILE(SMBwriteBs);
4650 return -1; /* Just discard the packet */
4653 nwritten = write_file(fsp,data,startpos,numtowrite);
4655 if(lp_syncalways(SNUM(conn)) || write_through)
4656 sync_file(conn,fsp);
4658 if (nwritten < (ssize_t)numtowrite) {
4659 if(write_through) {
4660 /* We are returning an error - we can delete the aux struct */
4661 if (wbms)
4662 free((char *)wbms);
4663 fsp->wbmpx_ptr = NULL;
4664 END_PROFILE(SMBwriteBs);
4665 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4667 END_PROFILE(SMBwriteBs);
4668 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4671 /* Increment the total written, if this matches tcount
4672 we can discard the auxiliary struct (hurrah !) and return a writeC */
4673 wbms->wr_total_written += nwritten;
4674 if(wbms->wr_total_written >= tcount) {
4675 if (write_through) {
4676 outsize = set_message(outbuf,1,0,True);
4677 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4678 send_response = True;
4681 free((char *)wbms);
4682 fsp->wbmpx_ptr = NULL;
4685 if(send_response) {
4686 END_PROFILE(SMBwriteBs);
4687 return(outsize);
4690 END_PROFILE(SMBwriteBs);
4691 return(-1);
4694 /****************************************************************************
4695 Reply to a SMBgetattrE.
4696 ****************************************************************************/
4698 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4700 SMB_STRUCT_STAT sbuf;
4701 int outsize = 0;
4702 int mode;
4703 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4704 START_PROFILE(SMBgetattrE);
4706 outsize = set_message(outbuf,11,0,True);
4708 if(!fsp || (fsp->conn != conn)) {
4709 END_PROFILE(SMBgetattrE);
4710 return ERROR_DOS(ERRDOS,ERRbadfid);
4713 /* Do an fstat on this file */
4714 if(fsp_stat(fsp, &sbuf)) {
4715 END_PROFILE(SMBgetattrE);
4716 return(UNIXERROR(ERRDOS,ERRnoaccess));
4719 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4722 * Convert the times into dos times. Set create
4723 * date to be last modify date as UNIX doesn't save
4724 * this.
4727 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4728 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4729 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4731 if (mode & aDIR) {
4732 SIVAL(outbuf,smb_vwv6,0);
4733 SIVAL(outbuf,smb_vwv8,0);
4734 } else {
4735 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4736 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4737 SIVAL(outbuf,smb_vwv8,allocation_size);
4739 SSVAL(outbuf,smb_vwv10, mode);
4741 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4743 END_PROFILE(SMBgetattrE);
4744 return(outsize);