Minor comment updates ...
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob3752507493073a520a6fd4aaeae5dc24c7a28bc9
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 NTSTATUS nterr = NT_STATUS_OK;
3017 if(errno == ENOENT) {
3018 unix_ERR_class = ERRDOS;
3019 if (bad_path) {
3020 unix_ERR_code = ERRbadpath;
3021 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
3022 } else {
3023 unix_ERR_code = ERRbadfile;
3024 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3027 if (!NT_STATUS_IS_OK(nterr))
3028 return nterr;
3029 return map_nt_error_from_unix(errno);
3032 return NT_STATUS_OK;
3035 /****************************************************************************
3036 Reply to a mkdir.
3037 ****************************************************************************/
3039 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3041 pstring directory;
3042 int outsize;
3043 NTSTATUS status;
3044 START_PROFILE(SMBmkdir);
3046 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 END_PROFILE(SMBmkdir);
3049 return ERROR_NT(status);
3052 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3054 status = mkdir_internal(conn, directory);
3055 if (!NT_STATUS_IS_OK(status)) {
3056 END_PROFILE(SMBmkdir);
3057 return ERROR_NT(status);
3060 outsize = set_message(outbuf,0,0,True);
3062 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3064 END_PROFILE(SMBmkdir);
3065 return(outsize);
3068 /****************************************************************************
3069 Static function used by reply_rmdir to delete an entire directory
3070 tree recursively. Return False on ok, True on fail.
3071 ****************************************************************************/
3073 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3075 const char *dname = NULL;
3076 BOOL ret = False;
3077 void *dirptr = OpenDir(conn, directory, False);
3079 if(dirptr == NULL)
3080 return True;
3082 while((dname = ReadDirName(dirptr))) {
3083 pstring fullname;
3084 SMB_STRUCT_STAT st;
3086 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3087 continue;
3089 /* Construct the full name. */
3090 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3091 errno = ENOMEM;
3092 ret = True;
3093 break;
3096 pstrcpy(fullname, directory);
3097 pstrcat(fullname, "/");
3098 pstrcat(fullname, dname);
3100 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3101 ret = True;
3102 break;
3105 if(st.st_mode & S_IFDIR) {
3106 if(recursive_rmdir(conn, fullname)!=0) {
3107 ret = True;
3108 break;
3110 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3111 ret = True;
3112 break;
3114 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3115 ret = True;
3116 break;
3119 CloseDir(dirptr);
3120 return ret;
3123 /****************************************************************************
3124 The internals of the rmdir code - called elsewhere.
3125 ****************************************************************************/
3127 BOOL rmdir_internals(connection_struct *conn, char *directory)
3129 BOOL ok;
3131 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3132 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3134 * Check to see if the only thing in this directory are
3135 * vetoed files/directories. If so then delete them and
3136 * retry. If we fail to delete any of them (and we *don't*
3137 * do a recursive delete) then fail the rmdir.
3139 BOOL all_veto_files = True;
3140 const char *dname;
3141 void *dirptr = OpenDir(conn, directory, False);
3143 if(dirptr != NULL) {
3144 int dirpos = TellDir(dirptr);
3145 while ((dname = ReadDirName(dirptr))) {
3146 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3147 continue;
3148 if(!IS_VETO_PATH(conn, dname)) {
3149 all_veto_files = False;
3150 break;
3154 if(all_veto_files) {
3155 SeekDir(dirptr,dirpos);
3156 while ((dname = ReadDirName(dirptr))) {
3157 pstring fullname;
3158 SMB_STRUCT_STAT st;
3160 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3161 continue;
3163 /* Construct the full name. */
3164 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3165 errno = ENOMEM;
3166 break;
3169 pstrcpy(fullname, directory);
3170 pstrcat(fullname, "/");
3171 pstrcat(fullname, dname);
3173 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3174 break;
3175 if(st.st_mode & S_IFDIR) {
3176 if(lp_recursive_veto_delete(SNUM(conn))) {
3177 if(recursive_rmdir(conn, fullname) != 0)
3178 break;
3180 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3181 break;
3182 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3183 break;
3185 CloseDir(dirptr);
3186 /* Retry the rmdir */
3187 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3188 } else {
3189 CloseDir(dirptr);
3191 } else {
3192 errno = ENOTEMPTY;
3196 if (!ok)
3197 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3199 return ok;
3202 /****************************************************************************
3203 Reply to a rmdir.
3204 ****************************************************************************/
3206 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3208 pstring directory;
3209 int outsize = 0;
3210 BOOL ok = False;
3211 BOOL bad_path = False;
3212 SMB_STRUCT_STAT sbuf;
3213 NTSTATUS status;
3214 START_PROFILE(SMBrmdir);
3216 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 END_PROFILE(SMBrmdir);
3219 return ERROR_NT(status);
3222 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3224 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3226 if (check_name(directory,conn)) {
3227 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3228 ok = rmdir_internals(conn, directory);
3231 if (!ok) {
3232 END_PROFILE(SMBrmdir);
3233 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3236 outsize = set_message(outbuf,0,0,True);
3238 DEBUG( 3, ( "rmdir %s\n", directory ) );
3240 END_PROFILE(SMBrmdir);
3241 return(outsize);
3244 /*******************************************************************
3245 Resolve wildcards in a filename rename.
3246 ********************************************************************/
3248 static BOOL resolve_wildcards(const char *name1, char *name2)
3250 fstring root1,root2;
3251 fstring ext1,ext2;
3252 char *p,*p2, *pname1, *pname2;
3253 int available_space;
3256 pname1 = strrchr_m(name1,'/');
3257 pname2 = strrchr_m(name2,'/');
3259 if (!pname1 || !pname2)
3260 return(False);
3262 fstrcpy(root1,pname1);
3263 fstrcpy(root2,pname2);
3264 p = strrchr_m(root1,'.');
3265 if (p) {
3266 *p = 0;
3267 fstrcpy(ext1,p+1);
3268 } else {
3269 fstrcpy(ext1,"");
3271 p = strrchr_m(root2,'.');
3272 if (p) {
3273 *p = 0;
3274 fstrcpy(ext2,p+1);
3275 } else {
3276 fstrcpy(ext2,"");
3279 p = root1;
3280 p2 = root2;
3281 while (*p2) {
3282 if (*p2 == '?') {
3283 *p2 = *p;
3284 p2++;
3285 } else {
3286 p2++;
3288 if (*p)
3289 p++;
3292 p = ext1;
3293 p2 = ext2;
3294 while (*p2) {
3295 if (*p2 == '?') {
3296 *p2 = *p;
3297 p2++;
3298 } else {
3299 p2++;
3301 if (*p)
3302 p++;
3305 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3307 if (ext2[0]) {
3308 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3309 } else {
3310 pstrcpy_base(pname2, root2, name2);
3313 return(True);
3316 /****************************************************************************
3317 Ensure open files have their names updates.
3318 ****************************************************************************/
3320 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3322 files_struct *fsp;
3323 BOOL did_rename = False;
3325 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3326 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3327 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3328 fsp->fsp_name, newname ));
3329 string_set(&fsp->fsp_name, newname);
3330 did_rename = True;
3333 if (!did_rename)
3334 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3335 (unsigned int)dev, (double)inode, newname ));
3338 /****************************************************************************
3339 Rename an open file - given an fsp.
3340 ****************************************************************************/
3342 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3344 SMB_STRUCT_STAT sbuf;
3345 BOOL bad_path = False;
3346 pstring newname_last_component;
3347 NTSTATUS error = NT_STATUS_OK;
3348 BOOL dest_exists;
3350 ZERO_STRUCT(sbuf);
3351 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3353 /* Ensure newname contains a '/' */
3354 if(strrchr_m(newname,'/') == 0) {
3355 pstring tmpstr;
3357 pstrcpy(tmpstr, "./");
3358 pstrcat(tmpstr, newname);
3359 pstrcpy(newname, tmpstr);
3363 * Check for special case with case preserving and not
3364 * case sensitive. If the old last component differs from the original
3365 * last component only by case, then we should allow
3366 * the rename (user is trying to change the case of the
3367 * filename).
3370 if((case_sensitive == False) && (case_preserve == True) &&
3371 strequal(newname, fsp->fsp_name)) {
3372 char *p;
3373 pstring newname_modified_last_component;
3376 * Get the last component of the modified name.
3377 * Note that we guarantee that newname contains a '/'
3378 * character above.
3380 p = strrchr_m(newname,'/');
3381 pstrcpy(newname_modified_last_component,p+1);
3383 if(strcsequal(newname_modified_last_component,
3384 newname_last_component) == False) {
3386 * Replace the modified last component with
3387 * the original.
3389 pstrcpy(p+1, newname_last_component);
3394 * If the src and dest names are identical - including case,
3395 * don't do the rename, just return success.
3398 if (strcsequal(fsp->fsp_name, newname)) {
3399 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3400 newname));
3401 return NT_STATUS_OK;
3404 dest_exists = vfs_object_exist(conn,newname,NULL);
3406 if(!replace_if_exists && dest_exists) {
3407 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3408 fsp->fsp_name,newname));
3409 return NT_STATUS_OBJECT_NAME_COLLISION;
3412 error = can_rename(newname,conn,&sbuf);
3414 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3415 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3416 nt_errstr(error), fsp->fsp_name,newname));
3417 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3418 error = NT_STATUS_ACCESS_DENIED;
3419 return error;
3422 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3423 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3424 fsp->fsp_name,newname));
3425 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3426 return NT_STATUS_OK;
3429 if (errno == ENOTDIR || errno == EISDIR)
3430 error = NT_STATUS_OBJECT_NAME_COLLISION;
3431 else
3432 error = map_nt_error_from_unix(errno);
3434 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3435 nt_errstr(error), fsp->fsp_name,newname));
3437 return error;
3440 /****************************************************************************
3441 The guts of the rename command, split out so it may be called by the NT SMB
3442 code.
3443 ****************************************************************************/
3445 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3447 pstring directory;
3448 pstring mask;
3449 pstring newname_last_component;
3450 char *p;
3451 BOOL has_wild;
3452 BOOL bad_path1 = False;
3453 BOOL bad_path2 = False;
3454 int count=0;
3455 NTSTATUS error = NT_STATUS_OK;
3456 BOOL rc = True;
3457 SMB_STRUCT_STAT sbuf1, sbuf2;
3459 *directory = *mask = 0;
3461 ZERO_STRUCT(sbuf1);
3462 ZERO_STRUCT(sbuf2);
3463 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3464 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3467 * Split the old name into directory and last component
3468 * strings. Note that unix_convert may have stripped off a
3469 * leading ./ from both name and newname if the rename is
3470 * at the root of the share. We need to make sure either both
3471 * name and newname contain a / character or neither of them do
3472 * as this is checked in resolve_wildcards().
3475 p = strrchr_m(name,'/');
3476 if (!p) {
3477 pstrcpy(directory,".");
3478 pstrcpy(mask,name);
3479 } else {
3480 *p = 0;
3481 pstrcpy(directory,name);
3482 pstrcpy(mask,p+1);
3483 *p = '/'; /* Replace needed for exceptional test below. */
3487 * We should only check the mangled cache
3488 * here if unix_convert failed. This means
3489 * that the path in 'mask' doesn't exist
3490 * on the file system and so we need to look
3491 * for a possible mangle. This patch from
3492 * Tine Smukavec <valentin.smukavec@hermes.si>.
3495 if (!rc && mangle_is_mangled(mask))
3496 mangle_check_cache( mask );
3498 has_wild = ms_has_wild(mask);
3500 if (!has_wild) {
3502 * No wildcards - just process the one file.
3504 BOOL is_short_name = mangle_is_8_3(name, True);
3506 /* Add a terminating '/' to the directory name. */
3507 pstrcat(directory,"/");
3508 pstrcat(directory,mask);
3510 /* Ensure newname contains a '/' also */
3511 if(strrchr_m(newname,'/') == 0) {
3512 pstring tmpstr;
3514 pstrcpy(tmpstr, "./");
3515 pstrcat(tmpstr, newname);
3516 pstrcpy(newname, tmpstr);
3519 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3520 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3521 case_sensitive, case_preserve, short_case_preserve, directory,
3522 newname, newname_last_component, is_short_name));
3525 * Check for special case with case preserving and not
3526 * case sensitive, if directory and newname are identical,
3527 * and the old last component differs from the original
3528 * last component only by case, then we should allow
3529 * the rename (user is trying to change the case of the
3530 * filename).
3532 if((case_sensitive == False) &&
3533 (((case_preserve == True) &&
3534 (is_short_name == False)) ||
3535 ((short_case_preserve == True) &&
3536 (is_short_name == True))) &&
3537 strcsequal(directory, newname)) {
3538 pstring newname_modified_last_component;
3541 * Get the last component of the modified name.
3542 * Note that we guarantee that newname contains a '/'
3543 * character above.
3545 p = strrchr_m(newname,'/');
3546 pstrcpy(newname_modified_last_component,p+1);
3548 if(strcsequal(newname_modified_last_component,
3549 newname_last_component) == False) {
3551 * Replace the modified last component with
3552 * the original.
3554 pstrcpy(p+1, newname_last_component);
3558 resolve_wildcards(directory,newname);
3561 * The source object must exist.
3564 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3565 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3566 directory,newname));
3568 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3570 * Must return different errors depending on whether the parent
3571 * directory existed or not.
3574 p = strrchr_m(directory, '/');
3575 if (!p)
3576 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3577 *p = '\0';
3578 if (vfs_object_exist(conn, directory, NULL))
3579 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3580 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3582 error = map_nt_error_from_unix(errno);
3583 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3584 nt_errstr(error), directory,newname));
3586 return error;
3589 error = can_rename(directory,conn,&sbuf1);
3591 if (!NT_STATUS_IS_OK(error)) {
3592 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3593 nt_errstr(error), directory,newname));
3594 return error;
3598 * If the src and dest names are identical - including case,
3599 * don't do the rename, just return success.
3602 if (strcsequal(directory, newname)) {
3603 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3604 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3605 return NT_STATUS_OK;
3608 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3609 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3610 directory,newname));
3611 return NT_STATUS_OBJECT_NAME_COLLISION;
3614 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3615 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3616 directory,newname));
3617 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3618 return NT_STATUS_OK;
3621 if (errno == ENOTDIR || errno == EISDIR)
3622 error = NT_STATUS_OBJECT_NAME_COLLISION;
3623 else
3624 error = map_nt_error_from_unix(errno);
3626 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3627 nt_errstr(error), directory,newname));
3629 return error;
3630 } else {
3632 * Wildcards - process each file that matches.
3634 void *dirptr = NULL;
3635 const char *dname;
3636 pstring destname;
3638 if (check_name(directory,conn))
3639 dirptr = OpenDir(conn, directory, True);
3641 if (dirptr) {
3642 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3644 if (strequal(mask,"????????.???"))
3645 pstrcpy(mask,"*");
3647 while ((dname = ReadDirName(dirptr))) {
3648 pstring fname;
3650 pstrcpy(fname,dname);
3652 if(!mask_match(fname, mask, case_sensitive))
3653 continue;
3655 error = NT_STATUS_ACCESS_DENIED;
3656 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3657 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3658 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3659 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3660 continue;
3662 error = can_rename(fname,conn,&sbuf1);
3663 if (!NT_STATUS_IS_OK(error)) {
3664 DEBUG(6,("rename %s refused\n", fname));
3665 continue;
3667 pstrcpy(destname,newname);
3669 if (!resolve_wildcards(fname,destname)) {
3670 DEBUG(6,("resolve_wildcards %s %s failed\n",
3671 fname, destname));
3672 continue;
3675 if (!replace_if_exists &&
3676 vfs_file_exist(conn,destname, NULL)) {
3677 DEBUG(6,("file_exist %s\n", destname));
3678 error = NT_STATUS_OBJECT_NAME_COLLISION;
3679 continue;
3682 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3683 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3684 count++;
3686 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3688 CloseDir(dirptr);
3692 if (count == 0 && NT_STATUS_IS_OK(error)) {
3693 error = map_nt_error_from_unix(errno);
3696 return error;
3699 /****************************************************************************
3700 Reply to a mv.
3701 ****************************************************************************/
3703 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3704 int dum_buffsize)
3706 int outsize = 0;
3707 pstring name;
3708 pstring newname;
3709 char *p;
3710 NTSTATUS status;
3712 START_PROFILE(SMBmv);
3714 p = smb_buf(inbuf) + 1;
3715 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 END_PROFILE(SMBmv);
3718 return ERROR_NT(status);
3720 p++;
3721 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3722 if (!NT_STATUS_IS_OK(status)) {
3723 END_PROFILE(SMBmv);
3724 return ERROR_NT(status);
3727 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3728 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3730 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3732 status = rename_internals(conn, name, newname, False);
3733 if (!NT_STATUS_IS_OK(status)) {
3734 END_PROFILE(SMBmv);
3735 return ERROR_NT(status);
3739 * Win2k needs a changenotify request response before it will
3740 * update after a rename..
3742 process_pending_change_notify_queue((time_t)0);
3743 outsize = set_message(outbuf,0,0,True);
3745 END_PROFILE(SMBmv);
3746 return(outsize);
3749 /*******************************************************************
3750 Copy a file as part of a reply_copy.
3751 ******************************************************************/
3753 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3754 int count,BOOL target_is_directory, int *err_ret)
3756 int Access,action;
3757 SMB_STRUCT_STAT src_sbuf, sbuf2;
3758 SMB_OFF_T ret=-1;
3759 files_struct *fsp1,*fsp2;
3760 pstring dest;
3762 *err_ret = 0;
3764 pstrcpy(dest,dest1);
3765 if (target_is_directory) {
3766 char *p = strrchr_m(src,'/');
3767 if (p)
3768 p++;
3769 else
3770 p = src;
3771 pstrcat(dest,"/");
3772 pstrcat(dest,p);
3775 if (!vfs_file_exist(conn,src,&src_sbuf))
3776 return(False);
3778 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3779 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3781 if (!fsp1)
3782 return(False);
3784 if (!target_is_directory && count)
3785 ofun = FILE_EXISTS_OPEN;
3787 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3788 ZERO_STRUCTP(&sbuf2);
3790 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3791 ofun,src_sbuf.st_mode,0,&Access,&action);
3793 if (!fsp2) {
3794 close_file(fsp1,False);
3795 return(False);
3798 if ((ofun&3) == 1) {
3799 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3800 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3802 * Stop the copy from occurring.
3804 ret = -1;
3805 src_sbuf.st_size = 0;
3809 if (src_sbuf.st_size)
3810 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3812 close_file(fsp1,False);
3814 /* Ensure the modtime is set correctly on the destination file. */
3815 fsp2->pending_modtime = src_sbuf.st_mtime;
3818 * As we are opening fsp1 read-only we only expect
3819 * an error on close on fsp2 if we are out of space.
3820 * Thus we don't look at the error return from the
3821 * close of fsp1.
3823 *err_ret = close_file(fsp2,False);
3825 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3828 /****************************************************************************
3829 Reply to a file copy.
3830 ****************************************************************************/
3832 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3834 int outsize = 0;
3835 pstring name;
3836 pstring directory;
3837 pstring mask,newname;
3838 char *p;
3839 int count=0;
3840 int error = ERRnoaccess;
3841 int err = 0;
3842 BOOL has_wild;
3843 BOOL exists=False;
3844 int tid2 = SVAL(inbuf,smb_vwv0);
3845 int ofun = SVAL(inbuf,smb_vwv1);
3846 int flags = SVAL(inbuf,smb_vwv2);
3847 BOOL target_is_directory=False;
3848 BOOL bad_path1 = False;
3849 BOOL bad_path2 = False;
3850 BOOL rc = True;
3851 SMB_STRUCT_STAT sbuf1, sbuf2;
3852 NTSTATUS status;
3854 START_PROFILE(SMBcopy);
3856 *directory = *mask = 0;
3858 p = smb_buf(inbuf);
3859 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 END_PROFILE(SMBcopy);
3862 return ERROR_NT(status);
3864 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3865 if (!NT_STATUS_IS_OK(status)) {
3866 END_PROFILE(SMBcopy);
3867 return ERROR_NT(status);
3870 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3872 if (tid2 != conn->cnum) {
3873 /* can't currently handle inter share copies XXXX */
3874 DEBUG(3,("Rejecting inter-share copy\n"));
3875 END_PROFILE(SMBcopy);
3876 return ERROR_DOS(ERRSRV,ERRinvdevice);
3879 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3880 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3882 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3883 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3885 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3887 if ((flags&1) && target_is_directory) {
3888 END_PROFILE(SMBcopy);
3889 return ERROR_DOS(ERRDOS,ERRbadfile);
3892 if ((flags&2) && !target_is_directory) {
3893 END_PROFILE(SMBcopy);
3894 return ERROR_DOS(ERRDOS,ERRbadpath);
3897 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3898 /* wants a tree copy! XXXX */
3899 DEBUG(3,("Rejecting tree copy\n"));
3900 END_PROFILE(SMBcopy);
3901 return ERROR_DOS(ERRSRV,ERRerror);
3904 p = strrchr_m(name,'/');
3905 if (!p) {
3906 pstrcpy(directory,"./");
3907 pstrcpy(mask,name);
3908 } else {
3909 *p = 0;
3910 pstrcpy(directory,name);
3911 pstrcpy(mask,p+1);
3915 * We should only check the mangled cache
3916 * here if unix_convert failed. This means
3917 * that the path in 'mask' doesn't exist
3918 * on the file system and so we need to look
3919 * for a possible mangle. This patch from
3920 * Tine Smukavec <valentin.smukavec@hermes.si>.
3923 if (!rc && mangle_is_mangled(mask))
3924 mangle_check_cache( mask );
3926 has_wild = ms_has_wild(mask);
3928 if (!has_wild) {
3929 pstrcat(directory,"/");
3930 pstrcat(directory,mask);
3931 if (resolve_wildcards(directory,newname) &&
3932 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3933 count++;
3934 if(!count && err) {
3935 errno = err;
3936 END_PROFILE(SMBcopy);
3937 return(UNIXERROR(ERRHRD,ERRgeneral));
3939 if (!count) {
3940 exists = vfs_file_exist(conn,directory,NULL);
3942 } else {
3943 void *dirptr = NULL;
3944 const char *dname;
3945 pstring destname;
3947 if (check_name(directory,conn))
3948 dirptr = OpenDir(conn, directory, True);
3950 if (dirptr) {
3951 error = ERRbadfile;
3953 if (strequal(mask,"????????.???"))
3954 pstrcpy(mask,"*");
3956 while ((dname = ReadDirName(dirptr))) {
3957 pstring fname;
3958 pstrcpy(fname,dname);
3960 if(!mask_match(fname, mask, case_sensitive))
3961 continue;
3963 error = ERRnoaccess;
3964 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3965 pstrcpy(destname,newname);
3966 if (resolve_wildcards(fname,destname) &&
3967 copy_file(fname,destname,conn,ofun,
3968 count,target_is_directory,&err))
3969 count++;
3970 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3972 CloseDir(dirptr);
3976 if (count == 0) {
3977 if(err) {
3978 /* Error on close... */
3979 errno = err;
3980 END_PROFILE(SMBcopy);
3981 return(UNIXERROR(ERRHRD,ERRgeneral));
3984 if (exists) {
3985 END_PROFILE(SMBcopy);
3986 return ERROR_DOS(ERRDOS,error);
3987 } else {
3988 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3989 unix_ERR_class = ERRDOS;
3990 unix_ERR_code = ERRbadpath;
3992 END_PROFILE(SMBcopy);
3993 return(UNIXERROR(ERRDOS,error));
3997 outsize = set_message(outbuf,1,0,True);
3998 SSVAL(outbuf,smb_vwv0,count);
4000 END_PROFILE(SMBcopy);
4001 return(outsize);
4004 /****************************************************************************
4005 Reply to a setdir.
4006 ****************************************************************************/
4008 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4010 int snum;
4011 int outsize = 0;
4012 BOOL ok = False;
4013 pstring newdir;
4014 NTSTATUS status;
4016 START_PROFILE(pathworks_setdir);
4018 snum = SNUM(conn);
4019 if (!CAN_SETDIR(snum)) {
4020 END_PROFILE(pathworks_setdir);
4021 return ERROR_DOS(ERRDOS,ERRnoaccess);
4024 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 END_PROFILE(pathworks_setdir);
4027 return ERROR_NT(status);
4030 if (strlen(newdir) == 0) {
4031 ok = True;
4032 } else {
4033 ok = vfs_directory_exist(conn,newdir,NULL);
4034 if (ok)
4035 string_set(&conn->connectpath,newdir);
4038 if (!ok) {
4039 END_PROFILE(pathworks_setdir);
4040 return ERROR_DOS(ERRDOS,ERRbadpath);
4043 outsize = set_message(outbuf,0,0,True);
4044 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4046 DEBUG(3,("setdir %s\n", newdir));
4048 END_PROFILE(pathworks_setdir);
4049 return(outsize);
4052 /****************************************************************************
4053 Get a lock pid, dealing with large count requests.
4054 ****************************************************************************/
4056 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4058 if(!large_file_format)
4059 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4060 else
4061 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4064 /****************************************************************************
4065 Get a lock count, dealing with large count requests.
4066 ****************************************************************************/
4068 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4070 SMB_BIG_UINT count = 0;
4072 if(!large_file_format) {
4073 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4074 } else {
4076 #if defined(HAVE_LONGLONG)
4077 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4078 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4079 #else /* HAVE_LONGLONG */
4082 * NT4.x seems to be broken in that it sends large file (64 bit)
4083 * lockingX calls even if the CAP_LARGE_FILES was *not*
4084 * negotiated. For boxes without large unsigned ints truncate the
4085 * lock count by dropping the top 32 bits.
4088 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4089 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4090 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4091 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4092 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4095 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4096 #endif /* HAVE_LONGLONG */
4099 return count;
4102 #if !defined(HAVE_LONGLONG)
4103 /****************************************************************************
4104 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4105 ****************************************************************************/
4107 static uint32 map_lock_offset(uint32 high, uint32 low)
4109 unsigned int i;
4110 uint32 mask = 0;
4111 uint32 highcopy = high;
4114 * Try and find out how many significant bits there are in high.
4117 for(i = 0; highcopy; i++)
4118 highcopy >>= 1;
4121 * We use 31 bits not 32 here as POSIX
4122 * lock offsets may not be negative.
4125 mask = (~0) << (31 - i);
4127 if(low & mask)
4128 return 0; /* Fail. */
4130 high <<= (31 - i);
4132 return (high|low);
4134 #endif /* !defined(HAVE_LONGLONG) */
4136 /****************************************************************************
4137 Get a lock offset, dealing with large offset requests.
4138 ****************************************************************************/
4140 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4142 SMB_BIG_UINT offset = 0;
4144 *err = False;
4146 if(!large_file_format) {
4147 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4148 } else {
4150 #if defined(HAVE_LONGLONG)
4151 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4152 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4153 #else /* HAVE_LONGLONG */
4156 * NT4.x seems to be broken in that it sends large file (64 bit)
4157 * lockingX calls even if the CAP_LARGE_FILES was *not*
4158 * negotiated. For boxes without large unsigned ints mangle the
4159 * lock offset by mapping the top 32 bits onto the lower 32.
4162 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4163 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4164 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4165 uint32 new_low = 0;
4167 if((new_low = map_lock_offset(high, low)) == 0) {
4168 *err = True;
4169 return (SMB_BIG_UINT)-1;
4172 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4173 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4174 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4175 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4178 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4179 #endif /* HAVE_LONGLONG */
4182 return offset;
4185 /****************************************************************************
4186 Reply to a lockingX request.
4187 ****************************************************************************/
4189 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4191 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4192 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4193 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4194 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4195 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4196 SMB_BIG_UINT count = 0, offset = 0;
4197 uint16 lock_pid;
4198 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4199 int i;
4200 char *data;
4201 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4202 BOOL err;
4203 BOOL my_lock_ctx = False;
4204 NTSTATUS status;
4206 START_PROFILE(SMBlockingX);
4208 CHECK_FSP(fsp,conn);
4210 data = smb_buf(inbuf);
4212 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4213 /* we don't support these - and CANCEL_LOCK makes w2k
4214 and XP reboot so I don't really want to be
4215 compatible! (tridge) */
4216 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4219 /* Check if this is an oplock break on a file
4220 we have granted an oplock on.
4222 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4223 /* Client can insist on breaking to none. */
4224 BOOL break_to_none = (oplocklevel == 0);
4226 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4227 (unsigned int)oplocklevel, fsp->fnum ));
4230 * Make sure we have granted an exclusive or batch oplock on this file.
4233 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4234 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4235 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4237 /* if this is a pure oplock break request then don't send a reply */
4238 if (num_locks == 0 && num_ulocks == 0) {
4239 END_PROFILE(SMBlockingX);
4240 return -1;
4241 } else {
4242 END_PROFILE(SMBlockingX);
4243 return ERROR_DOS(ERRDOS,ERRlock);
4247 if (remove_oplock(fsp, break_to_none) == False) {
4248 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4249 fsp->fsp_name ));
4252 /* if this is a pure oplock break request then don't send a reply */
4253 if (num_locks == 0 && num_ulocks == 0) {
4254 /* Sanity check - ensure a pure oplock break is not a
4255 chained request. */
4256 if(CVAL(inbuf,smb_vwv0) != 0xff)
4257 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4258 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4259 END_PROFILE(SMBlockingX);
4260 return -1;
4265 * We do this check *after* we have checked this is not a oplock break
4266 * response message. JRA.
4269 release_level_2_oplocks_on_change(fsp);
4271 /* Data now points at the beginning of the list
4272 of smb_unlkrng structs */
4273 for(i = 0; i < (int)num_ulocks; i++) {
4274 lock_pid = get_lock_pid( data, i, large_file_format);
4275 count = get_lock_count( data, i, large_file_format);
4276 offset = get_lock_offset( data, i, large_file_format, &err);
4279 * There is no error code marked "stupid client bug".... :-).
4281 if(err) {
4282 END_PROFILE(SMBlockingX);
4283 return ERROR_DOS(ERRDOS,ERRnoaccess);
4286 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4287 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4289 status = do_unlock(fsp,conn,lock_pid,count,offset);
4290 if (NT_STATUS_V(status)) {
4291 END_PROFILE(SMBlockingX);
4292 return ERROR_NT(status);
4296 /* Setup the timeout in seconds. */
4298 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4300 /* Now do any requested locks */
4301 data += ((large_file_format ? 20 : 10)*num_ulocks);
4303 /* Data now points at the beginning of the list
4304 of smb_lkrng structs */
4306 for(i = 0; i < (int)num_locks; i++) {
4307 lock_pid = get_lock_pid( data, i, large_file_format);
4308 count = get_lock_count( data, i, large_file_format);
4309 offset = get_lock_offset( data, i, large_file_format, &err);
4312 * There is no error code marked "stupid client bug".... :-).
4314 if(err) {
4315 END_PROFILE(SMBlockingX);
4316 return ERROR_DOS(ERRDOS,ERRnoaccess);
4319 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4320 (double)offset, (double)count, (unsigned int)lock_pid,
4321 fsp->fsp_name, (int)lock_timeout ));
4323 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4324 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4325 if (NT_STATUS_V(status)) {
4326 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4328 * A blocking lock was requested. Package up
4329 * this smb into a queued request and push it
4330 * onto the blocking lock queue.
4332 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4333 END_PROFILE(SMBlockingX);
4334 return -1;
4337 break;
4341 /* If any of the above locks failed, then we must unlock
4342 all of the previous locks (X/Open spec). */
4343 if (i != num_locks && num_locks != 0) {
4345 * Ensure we don't do a remove on the lock that just failed,
4346 * as under POSIX rules, if we have a lock already there, we
4347 * will delete it (and we shouldn't) .....
4349 for(i--; i >= 0; i--) {
4350 lock_pid = get_lock_pid( data, i, large_file_format);
4351 count = get_lock_count( data, i, large_file_format);
4352 offset = get_lock_offset( data, i, large_file_format, &err);
4355 * There is no error code marked "stupid client bug".... :-).
4357 if(err) {
4358 END_PROFILE(SMBlockingX);
4359 return ERROR_DOS(ERRDOS,ERRnoaccess);
4362 do_unlock(fsp,conn,lock_pid,count,offset);
4364 END_PROFILE(SMBlockingX);
4365 return ERROR_NT(status);
4368 set_message(outbuf,2,0,True);
4370 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4371 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4373 END_PROFILE(SMBlockingX);
4374 return chain_reply(inbuf,outbuf,length,bufsize);
4377 /****************************************************************************
4378 Reply to a SMBreadbmpx (read block multiplex) request.
4379 ****************************************************************************/
4381 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4383 ssize_t nread = -1;
4384 ssize_t total_read;
4385 char *data;
4386 SMB_OFF_T startpos;
4387 int outsize;
4388 size_t maxcount;
4389 int max_per_packet;
4390 size_t tcount;
4391 int pad;
4392 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4393 START_PROFILE(SMBreadBmpx);
4395 /* this function doesn't seem to work - disable by default */
4396 if (!lp_readbmpx()) {
4397 END_PROFILE(SMBreadBmpx);
4398 return ERROR_DOS(ERRSRV,ERRuseSTD);
4401 outsize = set_message(outbuf,8,0,True);
4403 CHECK_FSP(fsp,conn);
4404 CHECK_READ(fsp);
4406 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4407 maxcount = SVAL(inbuf,smb_vwv3);
4409 data = smb_buf(outbuf);
4410 pad = ((long)data)%4;
4411 if (pad)
4412 pad = 4 - pad;
4413 data += pad;
4415 max_per_packet = bufsize-(outsize+pad);
4416 tcount = maxcount;
4417 total_read = 0;
4419 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4420 END_PROFILE(SMBreadBmpx);
4421 return ERROR_DOS(ERRDOS,ERRlock);
4424 do {
4425 size_t N = MIN(max_per_packet,tcount-total_read);
4427 nread = read_file(fsp,data,startpos,N);
4429 if (nread <= 0)
4430 nread = 0;
4432 if (nread < (ssize_t)N)
4433 tcount = total_read + nread;
4435 set_message(outbuf,8,nread,False);
4436 SIVAL(outbuf,smb_vwv0,startpos);
4437 SSVAL(outbuf,smb_vwv2,tcount);
4438 SSVAL(outbuf,smb_vwv6,nread);
4439 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4441 if (!send_smb(smbd_server_fd(),outbuf))
4442 exit_server("reply_readbmpx: send_smb failed.");
4444 total_read += nread;
4445 startpos += nread;
4446 } while (total_read < (ssize_t)tcount);
4448 END_PROFILE(SMBreadBmpx);
4449 return(-1);
4452 /****************************************************************************
4453 Reply to a SMBsetattrE.
4454 ****************************************************************************/
4456 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4458 struct utimbuf unix_times;
4459 int outsize = 0;
4460 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4461 START_PROFILE(SMBsetattrE);
4463 outsize = set_message(outbuf,0,0,True);
4465 if(!fsp || (fsp->conn != conn)) {
4466 END_PROFILE(SMBgetattrE);
4467 return ERROR_DOS(ERRDOS,ERRbadfid);
4471 * Convert the DOS times into unix times. Ignore create
4472 * time as UNIX can't set this.
4475 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4476 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4479 * Patch from Ray Frush <frush@engr.colostate.edu>
4480 * Sometimes times are sent as zero - ignore them.
4483 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4484 /* Ignore request */
4485 if( DEBUGLVL( 3 ) ) {
4486 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4487 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4489 END_PROFILE(SMBsetattrE);
4490 return(outsize);
4491 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4492 /* set modify time = to access time if modify time was 0 */
4493 unix_times.modtime = unix_times.actime;
4496 /* Set the date on this file */
4497 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4498 END_PROFILE(SMBsetattrE);
4499 return ERROR_DOS(ERRDOS,ERRnoaccess);
4502 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4503 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4505 END_PROFILE(SMBsetattrE);
4506 return(outsize);
4510 /* Back from the dead for OS/2..... JRA. */
4512 /****************************************************************************
4513 Reply to a SMBwritebmpx (write block multiplex primary) request.
4514 ****************************************************************************/
4516 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4518 size_t numtowrite;
4519 ssize_t nwritten = -1;
4520 int outsize = 0;
4521 SMB_OFF_T startpos;
4522 size_t tcount;
4523 BOOL write_through;
4524 int smb_doff;
4525 char *data;
4526 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4527 START_PROFILE(SMBwriteBmpx);
4529 CHECK_FSP(fsp,conn);
4530 CHECK_WRITE(fsp);
4531 CHECK_ERROR(fsp);
4533 tcount = SVAL(inbuf,smb_vwv1);
4534 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4535 write_through = BITSETW(inbuf+smb_vwv7,0);
4536 numtowrite = SVAL(inbuf,smb_vwv10);
4537 smb_doff = SVAL(inbuf,smb_vwv11);
4539 data = smb_base(inbuf) + smb_doff;
4541 /* If this fails we need to send an SMBwriteC response,
4542 not an SMBwritebmpx - set this up now so we don't forget */
4543 SCVAL(outbuf,smb_com,SMBwritec);
4545 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4546 END_PROFILE(SMBwriteBmpx);
4547 return(ERROR_DOS(ERRDOS,ERRlock));
4550 nwritten = write_file(fsp,data,startpos,numtowrite);
4552 if(lp_syncalways(SNUM(conn)) || write_through)
4553 sync_file(conn,fsp);
4555 if(nwritten < (ssize_t)numtowrite) {
4556 END_PROFILE(SMBwriteBmpx);
4557 return(UNIXERROR(ERRHRD,ERRdiskfull));
4560 /* If the maximum to be written to this file
4561 is greater than what we just wrote then set
4562 up a secondary struct to be attached to this
4563 fd, we will use this to cache error messages etc. */
4565 if((ssize_t)tcount > nwritten) {
4566 write_bmpx_struct *wbms;
4567 if(fsp->wbmpx_ptr != NULL)
4568 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4569 else
4570 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4571 if(!wbms) {
4572 DEBUG(0,("Out of memory in reply_readmpx\n"));
4573 END_PROFILE(SMBwriteBmpx);
4574 return(ERROR_DOS(ERRSRV,ERRnoresource));
4576 wbms->wr_mode = write_through;
4577 wbms->wr_discard = False; /* No errors yet */
4578 wbms->wr_total_written = nwritten;
4579 wbms->wr_errclass = 0;
4580 wbms->wr_error = 0;
4581 fsp->wbmpx_ptr = wbms;
4584 /* We are returning successfully, set the message type back to
4585 SMBwritebmpx */
4586 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4588 outsize = set_message(outbuf,1,0,True);
4590 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4592 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4593 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4595 if (write_through && tcount==nwritten) {
4596 /* We need to send both a primary and a secondary response */
4597 smb_setlen(outbuf,outsize - 4);
4598 if (!send_smb(smbd_server_fd(),outbuf))
4599 exit_server("reply_writebmpx: send_smb failed.");
4601 /* Now the secondary */
4602 outsize = set_message(outbuf,1,0,True);
4603 SCVAL(outbuf,smb_com,SMBwritec);
4604 SSVAL(outbuf,smb_vwv0,nwritten);
4607 END_PROFILE(SMBwriteBmpx);
4608 return(outsize);
4611 /****************************************************************************
4612 Reply to a SMBwritebs (write block multiplex secondary) request.
4613 ****************************************************************************/
4615 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4617 size_t numtowrite;
4618 ssize_t nwritten = -1;
4619 int outsize = 0;
4620 SMB_OFF_T startpos;
4621 size_t tcount;
4622 BOOL write_through;
4623 int smb_doff;
4624 char *data;
4625 write_bmpx_struct *wbms;
4626 BOOL send_response = False;
4627 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4628 START_PROFILE(SMBwriteBs);
4630 CHECK_FSP(fsp,conn);
4631 CHECK_WRITE(fsp);
4633 tcount = SVAL(inbuf,smb_vwv1);
4634 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4635 numtowrite = SVAL(inbuf,smb_vwv6);
4636 smb_doff = SVAL(inbuf,smb_vwv7);
4638 data = smb_base(inbuf) + smb_doff;
4640 /* We need to send an SMBwriteC response, not an SMBwritebs */
4641 SCVAL(outbuf,smb_com,SMBwritec);
4643 /* This fd should have an auxiliary struct attached,
4644 check that it does */
4645 wbms = fsp->wbmpx_ptr;
4646 if(!wbms) {
4647 END_PROFILE(SMBwriteBs);
4648 return(-1);
4651 /* If write through is set we can return errors, else we must cache them */
4652 write_through = wbms->wr_mode;
4654 /* Check for an earlier error */
4655 if(wbms->wr_discard) {
4656 END_PROFILE(SMBwriteBs);
4657 return -1; /* Just discard the packet */
4660 nwritten = write_file(fsp,data,startpos,numtowrite);
4662 if(lp_syncalways(SNUM(conn)) || write_through)
4663 sync_file(conn,fsp);
4665 if (nwritten < (ssize_t)numtowrite) {
4666 if(write_through) {
4667 /* We are returning an error - we can delete the aux struct */
4668 if (wbms)
4669 free((char *)wbms);
4670 fsp->wbmpx_ptr = NULL;
4671 END_PROFILE(SMBwriteBs);
4672 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4674 END_PROFILE(SMBwriteBs);
4675 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4678 /* Increment the total written, if this matches tcount
4679 we can discard the auxiliary struct (hurrah !) and return a writeC */
4680 wbms->wr_total_written += nwritten;
4681 if(wbms->wr_total_written >= tcount) {
4682 if (write_through) {
4683 outsize = set_message(outbuf,1,0,True);
4684 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4685 send_response = True;
4688 free((char *)wbms);
4689 fsp->wbmpx_ptr = NULL;
4692 if(send_response) {
4693 END_PROFILE(SMBwriteBs);
4694 return(outsize);
4697 END_PROFILE(SMBwriteBs);
4698 return(-1);
4701 /****************************************************************************
4702 Reply to a SMBgetattrE.
4703 ****************************************************************************/
4705 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4707 SMB_STRUCT_STAT sbuf;
4708 int outsize = 0;
4709 int mode;
4710 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4711 START_PROFILE(SMBgetattrE);
4713 outsize = set_message(outbuf,11,0,True);
4715 if(!fsp || (fsp->conn != conn)) {
4716 END_PROFILE(SMBgetattrE);
4717 return ERROR_DOS(ERRDOS,ERRbadfid);
4720 /* Do an fstat on this file */
4721 if(fsp_stat(fsp, &sbuf)) {
4722 END_PROFILE(SMBgetattrE);
4723 return(UNIXERROR(ERRDOS,ERRnoaccess));
4726 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4729 * Convert the times into dos times. Set create
4730 * date to be last modify date as UNIX doesn't save
4731 * this.
4734 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4735 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4736 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4738 if (mode & aDIR) {
4739 SIVAL(outbuf,smb_vwv6,0);
4740 SIVAL(outbuf,smb_vwv8,0);
4741 } else {
4742 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4743 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4744 SIVAL(outbuf,smb_vwv8,allocation_size);
4746 SSVAL(outbuf,smb_vwv10, mode);
4748 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4750 END_PROFILE(SMBgetattrE);
4751 return(outsize);