Interesting fact found by IFSTEST /t LockOverlappedTest...
[Samba/gebeck_regimport.git] / source / smbd / reply.c
blob643b7c2d0810578f9a53c0d96fa6fd2a6955c0ba
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, BOOL bad_path)
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 if(errno == ENOENT) {
1328 if (bad_path)
1329 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1330 else
1331 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1333 return map_nt_error_from_unix(errno);
1336 fmode = dos_mode(conn,fname,&sbuf);
1338 /* Can't delete a directory. */
1339 if (fmode & aDIR)
1340 return NT_STATUS_FILE_IS_A_DIRECTORY;
1341 #if 0 /* JRATEST */
1342 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1343 return NT_STATUS_OBJECT_NAME_INVALID;
1344 #endif /* JRATEST */
1346 if (!lp_delete_readonly(SNUM(conn))) {
1347 if (fmode & aRONLY)
1348 return NT_STATUS_CANNOT_DELETE;
1350 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1351 return NT_STATUS_NO_SUCH_FILE;
1353 /* We need a better way to return NT status codes from open... */
1354 unix_ERR_class = 0;
1355 unix_ERR_code = 0;
1357 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1358 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1360 if (!fsp) {
1361 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1362 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1363 ret = unix_ERR_ntstatus;
1364 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1365 ret = NT_STATUS_SHARING_VIOLATION;
1366 unix_ERR_class = 0;
1367 unix_ERR_code = 0;
1368 unix_ERR_ntstatus = NT_STATUS_OK;
1369 return ret;
1371 close_file(fsp,False);
1372 return NT_STATUS_OK;
1375 /****************************************************************************
1376 The guts of the unlink command, split out so it may be called by the NT SMB
1377 code.
1378 ****************************************************************************/
1380 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1382 pstring directory;
1383 pstring mask;
1384 char *p;
1385 int count=0;
1386 NTSTATUS error = NT_STATUS_OK;
1387 BOOL has_wild;
1388 BOOL bad_path = False;
1389 BOOL rc = True;
1390 SMB_STRUCT_STAT sbuf;
1392 *directory = *mask = 0;
1394 /* We must check for wildcards in the name given
1395 * directly by the client - before any unmangling.
1396 * This prevents an unmangling of a UNIX name containing
1397 * a DOS wildcard like '*' or '?' from unmangling into
1398 * a wildcard delete which was not intended.
1399 * FIX for #226. JRA.
1402 has_wild = ms_has_wild(name);
1404 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1406 p = strrchr_m(name,'/');
1407 if (!p) {
1408 pstrcpy(directory,".");
1409 pstrcpy(mask,name);
1410 } else {
1411 *p = 0;
1412 pstrcpy(directory,name);
1413 pstrcpy(mask,p+1);
1417 * We should only check the mangled cache
1418 * here if unix_convert failed. This means
1419 * that the path in 'mask' doesn't exist
1420 * on the file system and so we need to look
1421 * for a possible mangle. This patch from
1422 * Tine Smukavec <valentin.smukavec@hermes.si>.
1425 if (!rc && mangle_is_mangled(mask))
1426 mangle_check_cache( mask );
1428 if (!has_wild) {
1429 pstrcat(directory,"/");
1430 pstrcat(directory,mask);
1431 error = can_delete(directory,conn,dirtype,bad_path);
1432 if (!NT_STATUS_IS_OK(error))
1433 return error;
1435 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1436 count++;
1438 } else {
1439 void *dirptr = NULL;
1440 const char *dname;
1442 if (check_name(directory,conn))
1443 dirptr = OpenDir(conn, directory, True);
1445 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1446 the pattern matches against the long name, otherwise the short name
1447 We don't implement this yet XXXX
1450 if (dirptr) {
1451 error = NT_STATUS_NO_SUCH_FILE;
1453 if (strequal(mask,"????????.???"))
1454 pstrcpy(mask,"*");
1456 while ((dname = ReadDirName(dirptr))) {
1457 pstring fname;
1458 pstrcpy(fname,dname);
1460 /* Quick check for "." and ".." */
1461 if (fname[0] == '.') {
1462 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1463 continue;
1467 if(!mask_match(fname, mask, case_sensitive))
1468 continue;
1470 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1471 error = can_delete(fname,conn,dirtype,bad_path);
1472 if (!NT_STATUS_IS_OK(error))
1473 continue;
1474 if (SMB_VFS_UNLINK(conn,fname) == 0)
1475 count++;
1476 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1478 CloseDir(dirptr);
1482 if (count == 0 && NT_STATUS_IS_OK(error)) {
1483 error = map_nt_error_from_unix(errno);
1486 return error;
1489 /****************************************************************************
1490 Reply to a unlink
1491 ****************************************************************************/
1493 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1494 int dum_buffsize)
1496 int outsize = 0;
1497 pstring name;
1498 int dirtype;
1499 NTSTATUS status;
1500 START_PROFILE(SMBunlink);
1502 dirtype = SVAL(inbuf,smb_vwv0);
1504 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 END_PROFILE(SMBunlink);
1507 return ERROR_NT(status);
1510 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1512 DEBUG(3,("reply_unlink : %s\n",name));
1514 status = unlink_internals(conn, dirtype, name);
1515 if (!NT_STATUS_IS_OK(status))
1516 return ERROR_NT(status);
1519 * Win2k needs a changenotify request response before it will
1520 * update after a rename..
1522 process_pending_change_notify_queue((time_t)0);
1524 outsize = set_message(outbuf,0,0,True);
1526 END_PROFILE(SMBunlink);
1527 return outsize;
1530 /****************************************************************************
1531 Fail for readbraw.
1532 ****************************************************************************/
1534 void fail_readraw(void)
1536 pstring errstr;
1537 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1538 strerror(errno) );
1539 exit_server(errstr);
1542 /****************************************************************************
1543 Use sendfile in readbraw.
1544 ****************************************************************************/
1546 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1547 ssize_t mincount, char *outbuf)
1549 ssize_t ret=0;
1551 #if defined(WITH_SENDFILE)
1553 * We can only use sendfile on a non-chained packet and on a file
1554 * that is exclusively oplocked. reply_readbraw has already checked the length.
1557 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1558 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1559 DATA_BLOB header;
1561 _smb_setlen(outbuf,nread);
1562 header.data = outbuf;
1563 header.length = 4;
1564 header.free = NULL;
1566 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1568 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1569 * return ENOSYS then pretend we just got a normal read.
1571 if (errno == ENOSYS)
1572 goto normal_read;
1574 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1575 fsp->fsp_name, strerror(errno) ));
1576 exit_server("send_file_readbraw sendfile failed");
1581 normal_read:
1582 #endif
1584 if (nread > 0) {
1585 ret = read_file(fsp,outbuf+4,startpos,nread);
1586 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1587 if (ret < mincount)
1588 ret = 0;
1589 #else
1590 if (ret < nread)
1591 ret = 0;
1592 #endif
1595 _smb_setlen(outbuf,ret);
1596 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1597 fail_readraw();
1600 /****************************************************************************
1601 Reply to a readbraw (core+ protocol).
1602 ****************************************************************************/
1604 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1606 extern struct current_user current_user;
1607 ssize_t maxcount,mincount;
1608 size_t nread = 0;
1609 SMB_OFF_T startpos;
1610 char *header = outbuf;
1611 files_struct *fsp;
1612 START_PROFILE(SMBreadbraw);
1614 if (srv_is_signing_active()) {
1615 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1619 * Special check if an oplock break has been issued
1620 * and the readraw request croses on the wire, we must
1621 * return a zero length response here.
1624 if(global_oplock_break) {
1625 _smb_setlen(header,0);
1626 if (write_data(smbd_server_fd(),header,4) != 4)
1627 fail_readraw();
1628 DEBUG(5,("readbraw - oplock break finished\n"));
1629 END_PROFILE(SMBreadbraw);
1630 return -1;
1633 fsp = file_fsp(inbuf,smb_vwv0);
1635 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1637 * fsp could be NULL here so use the value from the packet. JRA.
1639 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1640 _smb_setlen(header,0);
1641 if (write_data(smbd_server_fd(),header,4) != 4)
1642 fail_readraw();
1643 END_PROFILE(SMBreadbraw);
1644 return(-1);
1647 CHECK_FSP(fsp,conn);
1649 flush_write_cache(fsp, READRAW_FLUSH);
1651 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1652 if(CVAL(inbuf,smb_wct) == 10) {
1654 * This is a large offset (64 bit) read.
1656 #ifdef LARGE_SMB_OFF_T
1658 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1660 #else /* !LARGE_SMB_OFF_T */
1663 * Ensure we haven't been sent a >32 bit offset.
1666 if(IVAL(inbuf,smb_vwv8) != 0) {
1667 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1668 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1669 _smb_setlen(header,0);
1670 if (write_data(smbd_server_fd(),header,4) != 4)
1671 fail_readraw();
1672 END_PROFILE(SMBreadbraw);
1673 return(-1);
1676 #endif /* LARGE_SMB_OFF_T */
1678 if(startpos < 0) {
1679 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1680 _smb_setlen(header,0);
1681 if (write_data(smbd_server_fd(),header,4) != 4)
1682 fail_readraw();
1683 END_PROFILE(SMBreadbraw);
1684 return(-1);
1687 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1688 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1690 /* ensure we don't overrun the packet size */
1691 maxcount = MIN(65535,maxcount);
1693 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1694 SMB_OFF_T size = fsp->size;
1695 SMB_OFF_T sizeneeded = startpos + maxcount;
1697 if (size < sizeneeded) {
1698 SMB_STRUCT_STAT st;
1699 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1700 size = st.st_size;
1701 if (!fsp->can_write)
1702 fsp->size = size;
1705 if (startpos >= size)
1706 nread = 0;
1707 else
1708 nread = MIN(maxcount,(size - startpos));
1711 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1712 if (nread < mincount)
1713 nread = 0;
1714 #endif
1716 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1717 (int)maxcount, (int)mincount, (int)nread ) );
1719 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1721 DEBUG(5,("readbraw finished\n"));
1722 END_PROFILE(SMBreadbraw);
1723 return -1;
1726 /****************************************************************************
1727 Reply to a lockread (core+ protocol).
1728 ****************************************************************************/
1730 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1732 ssize_t nread = -1;
1733 char *data;
1734 int outsize = 0;
1735 SMB_OFF_T startpos;
1736 size_t numtoread;
1737 NTSTATUS status;
1738 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1739 BOOL my_lock_ctx = False;
1740 START_PROFILE(SMBlockread);
1742 CHECK_FSP(fsp,conn);
1743 CHECK_READ(fsp);
1745 release_level_2_oplocks_on_change(fsp);
1747 numtoread = SVAL(inbuf,smb_vwv1);
1748 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1750 outsize = set_message(outbuf,5,3,True);
1751 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1752 data = smb_buf(outbuf) + 3;
1755 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1756 * protocol request that predates the read/write lock concept.
1757 * Thus instead of asking for a read lock here we need to ask
1758 * for a write lock. JRA.
1759 * Note that the requested lock size is unaffected by max_recv.
1762 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1763 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1765 if (NT_STATUS_V(status)) {
1766 #if 0
1768 * We used to make lockread a blocking lock. It turns out
1769 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1770 * tester. JRA.
1773 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1775 * A blocking lock was requested. Package up
1776 * this smb into a queued request and push it
1777 * onto the blocking lock queue.
1779 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1780 (SMB_BIG_UINT)numtoread)) {
1781 END_PROFILE(SMBlockread);
1782 return -1;
1785 #endif
1786 END_PROFILE(SMBlockread);
1787 return ERROR_NT(status);
1791 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1794 if (numtoread > max_recv) {
1795 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1796 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1797 (unsigned int)numtoread, (unsigned int)max_recv ));
1798 numtoread = MIN(numtoread,max_recv);
1800 nread = read_file(fsp,data,startpos,numtoread);
1802 if (nread < 0) {
1803 END_PROFILE(SMBlockread);
1804 return(UNIXERROR(ERRDOS,ERRnoaccess));
1807 outsize += nread;
1808 SSVAL(outbuf,smb_vwv0,nread);
1809 SSVAL(outbuf,smb_vwv5,nread+3);
1810 SSVAL(smb_buf(outbuf),1,nread);
1812 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1813 fsp->fnum, (int)numtoread, (int)nread));
1815 END_PROFILE(SMBlockread);
1816 return(outsize);
1819 /****************************************************************************
1820 Reply to a read.
1821 ****************************************************************************/
1823 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1825 size_t numtoread;
1826 ssize_t nread = 0;
1827 char *data;
1828 SMB_OFF_T startpos;
1829 int outsize = 0;
1830 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1831 START_PROFILE(SMBread);
1833 CHECK_FSP(fsp,conn);
1834 CHECK_READ(fsp);
1836 numtoread = SVAL(inbuf,smb_vwv1);
1837 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1839 outsize = set_message(outbuf,5,3,True);
1840 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1842 * The requested read size cannot be greater than max_recv. JRA.
1844 if (numtoread > max_recv) {
1845 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1846 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1847 (unsigned int)numtoread, (unsigned int)max_recv ));
1848 numtoread = MIN(numtoread,max_recv);
1851 data = smb_buf(outbuf) + 3;
1853 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1854 END_PROFILE(SMBread);
1855 return ERROR_DOS(ERRDOS,ERRlock);
1858 if (numtoread > 0)
1859 nread = read_file(fsp,data,startpos,numtoread);
1861 if (nread < 0) {
1862 END_PROFILE(SMBread);
1863 return(UNIXERROR(ERRDOS,ERRnoaccess));
1866 outsize += nread;
1867 SSVAL(outbuf,smb_vwv0,nread);
1868 SSVAL(outbuf,smb_vwv5,nread+3);
1869 SCVAL(smb_buf(outbuf),0,1);
1870 SSVAL(smb_buf(outbuf),1,nread);
1872 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1873 fsp->fnum, (int)numtoread, (int)nread ) );
1875 END_PROFILE(SMBread);
1876 return(outsize);
1879 /****************************************************************************
1880 Reply to a read and X - possibly using sendfile.
1881 ****************************************************************************/
1883 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1884 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1886 ssize_t nread = -1;
1887 char *data = smb_buf(outbuf);
1889 #if defined(WITH_SENDFILE)
1891 * We can only use sendfile on a non-chained packet and on a file
1892 * that is exclusively oplocked.
1895 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1896 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1897 SMB_STRUCT_STAT sbuf;
1898 DATA_BLOB header;
1900 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1901 return(UNIXERROR(ERRDOS,ERRnoaccess));
1903 if (startpos > sbuf.st_size)
1904 goto normal_read;
1906 if (smb_maxcnt > (sbuf.st_size - startpos))
1907 smb_maxcnt = (sbuf.st_size - startpos);
1909 if (smb_maxcnt == 0)
1910 goto normal_read;
1913 * Set up the packet header before send. We
1914 * assume here the sendfile will work (get the
1915 * correct amount of data).
1918 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1919 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1920 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1921 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1922 SCVAL(outbuf,smb_vwv0,0xFF);
1923 set_message(outbuf,12,smb_maxcnt,False);
1924 header.data = outbuf;
1925 header.length = data - outbuf;
1926 header.free = NULL;
1928 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1930 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1931 * return ENOSYS then pretend we just got a normal read.
1933 if (errno == ENOSYS)
1934 goto normal_read;
1936 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1937 fsp->fsp_name, strerror(errno) ));
1938 exit_server("send_file_readX sendfile failed");
1941 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1942 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1943 return -1;
1946 normal_read:
1948 #endif
1950 nread = read_file(fsp,data,startpos,smb_maxcnt);
1952 if (nread < 0) {
1953 END_PROFILE(SMBreadX);
1954 return(UNIXERROR(ERRDOS,ERRnoaccess));
1957 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1958 SSVAL(outbuf,smb_vwv5,nread);
1959 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1960 SSVAL(smb_buf(outbuf),-2,nread);
1962 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1963 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1965 return nread;
1968 /****************************************************************************
1969 Reply to a read and X.
1970 ****************************************************************************/
1972 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1974 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1975 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1976 ssize_t nread = -1;
1977 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1978 #if 0
1979 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1980 #endif
1982 START_PROFILE(SMBreadX);
1984 /* If it's an IPC, pass off the pipe handler. */
1985 if (IS_IPC(conn)) {
1986 END_PROFILE(SMBreadX);
1987 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1990 CHECK_FSP(fsp,conn);
1991 CHECK_READ(fsp);
1993 set_message(outbuf,12,0,True);
1995 if(CVAL(inbuf,smb_wct) == 12) {
1996 #ifdef LARGE_SMB_OFF_T
1998 * This is a large offset (64 bit) read.
2000 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2002 #else /* !LARGE_SMB_OFF_T */
2005 * Ensure we haven't been sent a >32 bit offset.
2008 if(IVAL(inbuf,smb_vwv10) != 0) {
2009 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2010 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2011 END_PROFILE(SMBreadX);
2012 return ERROR_DOS(ERRDOS,ERRbadaccess);
2015 #endif /* LARGE_SMB_OFF_T */
2019 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2020 END_PROFILE(SMBreadX);
2021 return ERROR_DOS(ERRDOS,ERRlock);
2024 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2025 if (nread != -1)
2026 nread = chain_reply(inbuf,outbuf,length,bufsize);
2028 END_PROFILE(SMBreadX);
2029 return nread;
2032 /****************************************************************************
2033 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2034 ****************************************************************************/
2036 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2038 ssize_t nwritten=0;
2039 ssize_t total_written=0;
2040 size_t numtowrite=0;
2041 size_t tcount;
2042 SMB_OFF_T startpos;
2043 char *data=NULL;
2044 BOOL write_through;
2045 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2046 int outsize = 0;
2047 START_PROFILE(SMBwritebraw);
2049 if (srv_is_signing_active()) {
2050 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2053 CHECK_FSP(fsp,conn);
2054 CHECK_WRITE(fsp);
2056 tcount = IVAL(inbuf,smb_vwv1);
2057 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2058 write_through = BITSETW(inbuf+smb_vwv7,0);
2060 /* We have to deal with slightly different formats depending
2061 on whether we are using the core+ or lanman1.0 protocol */
2063 if(Protocol <= PROTOCOL_COREPLUS) {
2064 numtowrite = SVAL(smb_buf(inbuf),-2);
2065 data = smb_buf(inbuf);
2066 } else {
2067 numtowrite = SVAL(inbuf,smb_vwv10);
2068 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2071 /* force the error type */
2072 SCVAL(inbuf,smb_com,SMBwritec);
2073 SCVAL(outbuf,smb_com,SMBwritec);
2075 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2076 END_PROFILE(SMBwritebraw);
2077 return(ERROR_DOS(ERRDOS,ERRlock));
2080 if (numtowrite>0)
2081 nwritten = write_file(fsp,data,startpos,numtowrite);
2083 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2084 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2086 if (nwritten < (ssize_t)numtowrite) {
2087 END_PROFILE(SMBwritebraw);
2088 return(UNIXERROR(ERRHRD,ERRdiskfull));
2091 total_written = nwritten;
2093 /* Return a message to the redirector to tell it to send more bytes */
2094 SCVAL(outbuf,smb_com,SMBwritebraw);
2095 SSVALS(outbuf,smb_vwv0,-1);
2096 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2097 if (!send_smb(smbd_server_fd(),outbuf))
2098 exit_server("reply_writebraw: send_smb failed.");
2100 /* Now read the raw data into the buffer and write it */
2101 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2102 exit_server("secondary writebraw failed");
2105 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2106 numtowrite = smb_len(inbuf);
2108 /* Set up outbuf to return the correct return */
2109 outsize = set_message(outbuf,1,0,True);
2110 SCVAL(outbuf,smb_com,SMBwritec);
2111 SSVAL(outbuf,smb_vwv0,total_written);
2113 if (numtowrite != 0) {
2115 if (numtowrite > BUFFER_SIZE) {
2116 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2117 (unsigned int)numtowrite ));
2118 exit_server("secondary writebraw failed");
2121 if (tcount > nwritten+numtowrite) {
2122 DEBUG(3,("Client overestimated the write %d %d %d\n",
2123 (int)tcount,(int)nwritten,(int)numtowrite));
2126 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2127 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2128 strerror(errno) ));
2129 exit_server("secondary writebraw failed");
2132 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2134 if (nwritten < (ssize_t)numtowrite) {
2135 SCVAL(outbuf,smb_rcls,ERRHRD);
2136 SSVAL(outbuf,smb_err,ERRdiskfull);
2139 if (nwritten > 0)
2140 total_written += nwritten;
2143 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2144 sync_file(conn,fsp);
2146 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2147 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2149 /* we won't return a status if write through is not selected - this follows what WfWg does */
2150 END_PROFILE(SMBwritebraw);
2151 if (!write_through && total_written==tcount) {
2153 #if RABBIT_PELLET_FIX
2155 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2156 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2158 if (!send_keepalive(smbd_server_fd()))
2159 exit_server("reply_writebraw: send of keepalive failed");
2160 #endif
2161 return(-1);
2164 return(outsize);
2167 /****************************************************************************
2168 Reply to a writeunlock (core+).
2169 ****************************************************************************/
2171 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2172 int size, int dum_buffsize)
2174 ssize_t nwritten = -1;
2175 size_t numtowrite;
2176 SMB_OFF_T startpos;
2177 char *data;
2178 NTSTATUS status = NT_STATUS_OK;
2179 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2180 int outsize = 0;
2181 START_PROFILE(SMBwriteunlock);
2183 CHECK_FSP(fsp,conn);
2184 CHECK_WRITE(fsp);
2186 numtowrite = SVAL(inbuf,smb_vwv1);
2187 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2188 data = smb_buf(inbuf) + 3;
2190 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2191 WRITE_LOCK,False)) {
2192 END_PROFILE(SMBwriteunlock);
2193 return ERROR_DOS(ERRDOS,ERRlock);
2196 /* The special X/Open SMB protocol handling of
2197 zero length writes is *NOT* done for
2198 this call */
2199 if(numtowrite == 0)
2200 nwritten = 0;
2201 else
2202 nwritten = write_file(fsp,data,startpos,numtowrite);
2204 if (lp_syncalways(SNUM(conn)))
2205 sync_file(conn,fsp);
2207 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2208 END_PROFILE(SMBwriteunlock);
2209 return(UNIXERROR(ERRHRD,ERRdiskfull));
2212 if (numtowrite) {
2213 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2214 (SMB_BIG_UINT)startpos);
2215 if (NT_STATUS_V(status)) {
2216 END_PROFILE(SMBwriteunlock);
2217 return ERROR_NT(status);
2221 outsize = set_message(outbuf,1,0,True);
2223 SSVAL(outbuf,smb_vwv0,nwritten);
2225 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2226 fsp->fnum, (int)numtowrite, (int)nwritten));
2228 END_PROFILE(SMBwriteunlock);
2229 return outsize;
2232 /****************************************************************************
2233 Reply to a write.
2234 ****************************************************************************/
2236 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2238 size_t numtowrite;
2239 ssize_t nwritten = -1;
2240 SMB_OFF_T startpos;
2241 char *data;
2242 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2243 int outsize = 0;
2244 START_PROFILE(SMBwrite);
2246 /* If it's an IPC, pass off the pipe handler. */
2247 if (IS_IPC(conn)) {
2248 END_PROFILE(SMBwrite);
2249 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2252 CHECK_FSP(fsp,conn);
2253 CHECK_WRITE(fsp);
2255 numtowrite = SVAL(inbuf,smb_vwv1);
2256 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2257 data = smb_buf(inbuf) + 3;
2259 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2260 END_PROFILE(SMBwrite);
2261 return ERROR_DOS(ERRDOS,ERRlock);
2265 * X/Open SMB protocol says that if smb_vwv1 is
2266 * zero then the file size should be extended or
2267 * truncated to the size given in smb_vwv[2-3].
2270 if(numtowrite == 0) {
2272 * This is actually an allocate call, and set EOF. JRA.
2274 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2275 if (nwritten < 0) {
2276 END_PROFILE(SMBwrite);
2277 return ERROR_NT(NT_STATUS_DISK_FULL);
2279 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2280 if (nwritten < 0) {
2281 END_PROFILE(SMBwrite);
2282 return ERROR_NT(NT_STATUS_DISK_FULL);
2284 } else
2285 nwritten = write_file(fsp,data,startpos,numtowrite);
2287 if (lp_syncalways(SNUM(conn)))
2288 sync_file(conn,fsp);
2290 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2291 END_PROFILE(SMBwrite);
2292 return(UNIXERROR(ERRHRD,ERRdiskfull));
2295 outsize = set_message(outbuf,1,0,True);
2297 SSVAL(outbuf,smb_vwv0,nwritten);
2299 if (nwritten < (ssize_t)numtowrite) {
2300 SCVAL(outbuf,smb_rcls,ERRHRD);
2301 SSVAL(outbuf,smb_err,ERRdiskfull);
2304 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2306 END_PROFILE(SMBwrite);
2307 return(outsize);
2310 /****************************************************************************
2311 Reply to a write and X.
2312 ****************************************************************************/
2314 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2316 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2317 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2318 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2319 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2320 ssize_t nwritten = -1;
2321 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2322 unsigned int smblen = smb_len(inbuf);
2323 char *data;
2324 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2325 START_PROFILE(SMBwriteX);
2327 /* If it's an IPC, pass off the pipe handler. */
2328 if (IS_IPC(conn)) {
2329 END_PROFILE(SMBwriteX);
2330 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2333 CHECK_FSP(fsp,conn);
2334 CHECK_WRITE(fsp);
2336 /* Deal with possible LARGE_WRITEX */
2337 if (large_writeX)
2338 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2340 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2341 END_PROFILE(SMBwriteX);
2342 return ERROR_DOS(ERRDOS,ERRbadmem);
2345 data = smb_base(inbuf) + smb_doff;
2347 if(CVAL(inbuf,smb_wct) == 14) {
2348 #ifdef LARGE_SMB_OFF_T
2350 * This is a large offset (64 bit) write.
2352 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2354 #else /* !LARGE_SMB_OFF_T */
2357 * Ensure we haven't been sent a >32 bit offset.
2360 if(IVAL(inbuf,smb_vwv12) != 0) {
2361 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2362 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2363 END_PROFILE(SMBwriteX);
2364 return ERROR_DOS(ERRDOS,ERRbadaccess);
2367 #endif /* LARGE_SMB_OFF_T */
2370 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2371 END_PROFILE(SMBwriteX);
2372 return ERROR_DOS(ERRDOS,ERRlock);
2375 /* X/Open SMB protocol says that, unlike SMBwrite
2376 if the length is zero then NO truncation is
2377 done, just a write of zero. To truncate a file,
2378 use SMBwrite. */
2380 if(numtowrite == 0)
2381 nwritten = 0;
2382 else
2383 nwritten = write_file(fsp,data,startpos,numtowrite);
2385 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2386 END_PROFILE(SMBwriteX);
2387 return(UNIXERROR(ERRHRD,ERRdiskfull));
2390 set_message(outbuf,6,0,True);
2392 SSVAL(outbuf,smb_vwv2,nwritten);
2393 if (large_writeX)
2394 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2396 if (nwritten < (ssize_t)numtowrite) {
2397 SCVAL(outbuf,smb_rcls,ERRHRD);
2398 SSVAL(outbuf,smb_err,ERRdiskfull);
2401 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2402 fsp->fnum, (int)numtowrite, (int)nwritten));
2404 if (lp_syncalways(SNUM(conn)) || write_through)
2405 sync_file(conn,fsp);
2407 END_PROFILE(SMBwriteX);
2408 return chain_reply(inbuf,outbuf,length,bufsize);
2411 /****************************************************************************
2412 Reply to a lseek.
2413 ****************************************************************************/
2415 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2417 SMB_OFF_T startpos;
2418 SMB_OFF_T res= -1;
2419 int mode,umode;
2420 int outsize = 0;
2421 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2422 START_PROFILE(SMBlseek);
2424 CHECK_FSP(fsp,conn);
2426 flush_write_cache(fsp, SEEK_FLUSH);
2428 mode = SVAL(inbuf,smb_vwv1) & 3;
2429 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2430 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2432 switch (mode) {
2433 case 0:
2434 umode = SEEK_SET;
2435 res = startpos;
2436 break;
2437 case 1:
2438 umode = SEEK_CUR;
2439 res = fsp->pos + startpos;
2440 break;
2441 case 2:
2442 umode = SEEK_END;
2443 break;
2444 default:
2445 umode = SEEK_SET;
2446 res = startpos;
2447 break;
2450 if (umode == SEEK_END) {
2451 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2452 if(errno == EINVAL) {
2453 SMB_OFF_T current_pos = startpos;
2454 SMB_STRUCT_STAT sbuf;
2456 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2457 END_PROFILE(SMBlseek);
2458 return(UNIXERROR(ERRDOS,ERRnoaccess));
2461 current_pos += sbuf.st_size;
2462 if(current_pos < 0)
2463 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2467 if(res == -1) {
2468 END_PROFILE(SMBlseek);
2469 return(UNIXERROR(ERRDOS,ERRnoaccess));
2473 fsp->pos = res;
2475 outsize = set_message(outbuf,2,0,True);
2476 SIVAL(outbuf,smb_vwv0,res);
2478 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2479 fsp->fnum, (double)startpos, (double)res, mode));
2481 END_PROFILE(SMBlseek);
2482 return(outsize);
2485 /****************************************************************************
2486 Reply to a flush.
2487 ****************************************************************************/
2489 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2491 int outsize = set_message(outbuf,0,0,True);
2492 uint16 fnum = SVAL(inbuf,smb_vwv0);
2493 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2494 START_PROFILE(SMBflush);
2496 if (fnum != 0xFFFF)
2497 CHECK_FSP(fsp,conn);
2499 if (!fsp) {
2500 file_sync_all(conn);
2501 } else {
2502 sync_file(conn,fsp);
2505 DEBUG(3,("flush\n"));
2506 END_PROFILE(SMBflush);
2507 return(outsize);
2510 /****************************************************************************
2511 Reply to a exit.
2512 ****************************************************************************/
2514 int reply_exit(connection_struct *conn,
2515 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2517 int outsize;
2518 START_PROFILE(SMBexit);
2520 file_close_pid(SVAL(inbuf,smb_pid));
2522 outsize = set_message(outbuf,0,0,True);
2524 DEBUG(3,("exit\n"));
2526 END_PROFILE(SMBexit);
2527 return(outsize);
2530 /****************************************************************************
2531 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2532 ****************************************************************************/
2534 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2535 int dum_buffsize)
2537 extern struct current_user current_user;
2538 int outsize = 0;
2539 time_t mtime;
2540 int32 eclass = 0, err = 0;
2541 files_struct *fsp = NULL;
2542 START_PROFILE(SMBclose);
2544 outsize = set_message(outbuf,0,0,True);
2546 /* If it's an IPC, pass off to the pipe handler. */
2547 if (IS_IPC(conn)) {
2548 END_PROFILE(SMBclose);
2549 return reply_pipe_close(conn, inbuf,outbuf);
2552 fsp = file_fsp(inbuf,smb_vwv0);
2555 * We can only use CHECK_FSP if we know it's not a directory.
2558 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2559 END_PROFILE(SMBclose);
2560 return ERROR_DOS(ERRDOS,ERRbadfid);
2563 if(fsp->is_directory) {
2565 * Special case - close NT SMB directory handle.
2567 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2568 close_file(fsp,True);
2569 } else {
2571 * Close ordinary file.
2573 int close_err;
2574 pstring file_name;
2576 /* Save the name for time set in close. */
2577 pstrcpy( file_name, fsp->fsp_name);
2579 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2580 fsp->fd, fsp->fnum,
2581 conn->num_files_open));
2584 * close_file() returns the unix errno if an error
2585 * was detected on close - normally this is due to
2586 * a disk full error. If not then it was probably an I/O error.
2589 if((close_err = close_file(fsp,True)) != 0) {
2590 errno = close_err;
2591 END_PROFILE(SMBclose);
2592 return (UNIXERROR(ERRHRD,ERRgeneral));
2596 * Now take care of any time sent in the close.
2599 mtime = make_unix_date3(inbuf+smb_vwv1);
2601 /* try and set the date */
2602 set_filetime(conn, file_name, mtime);
2606 /* We have a cached error */
2607 if(eclass || err) {
2608 END_PROFILE(SMBclose);
2609 return ERROR_DOS(eclass,err);
2612 END_PROFILE(SMBclose);
2613 return(outsize);
2616 /****************************************************************************
2617 Reply to a writeclose (Core+ protocol).
2618 ****************************************************************************/
2620 int reply_writeclose(connection_struct *conn,
2621 char *inbuf,char *outbuf, int size, int dum_buffsize)
2623 size_t numtowrite;
2624 ssize_t nwritten = -1;
2625 int outsize = 0;
2626 int close_err = 0;
2627 SMB_OFF_T startpos;
2628 char *data;
2629 time_t mtime;
2630 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2631 START_PROFILE(SMBwriteclose);
2633 CHECK_FSP(fsp,conn);
2634 CHECK_WRITE(fsp);
2636 numtowrite = SVAL(inbuf,smb_vwv1);
2637 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2638 mtime = make_unix_date3(inbuf+smb_vwv4);
2639 data = smb_buf(inbuf) + 1;
2641 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2642 END_PROFILE(SMBwriteclose);
2643 return ERROR_DOS(ERRDOS,ERRlock);
2646 nwritten = write_file(fsp,data,startpos,numtowrite);
2648 set_filetime(conn, fsp->fsp_name,mtime);
2651 * More insanity. W2K only closes the file if writelen > 0.
2652 * JRA.
2655 if (numtowrite) {
2656 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2657 fsp->fsp_name ));
2658 close_err = close_file(fsp,True);
2661 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2662 fsp->fnum, (int)numtowrite, (int)nwritten,
2663 conn->num_files_open));
2665 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2666 END_PROFILE(SMBwriteclose);
2667 return(UNIXERROR(ERRHRD,ERRdiskfull));
2670 if(close_err != 0) {
2671 errno = close_err;
2672 END_PROFILE(SMBwriteclose);
2673 return(UNIXERROR(ERRHRD,ERRgeneral));
2676 outsize = set_message(outbuf,1,0,True);
2678 SSVAL(outbuf,smb_vwv0,nwritten);
2679 END_PROFILE(SMBwriteclose);
2680 return(outsize);
2683 /****************************************************************************
2684 Reply to a lock.
2685 ****************************************************************************/
2687 int reply_lock(connection_struct *conn,
2688 char *inbuf,char *outbuf, int length, int dum_buffsize)
2690 int outsize = set_message(outbuf,0,0,True);
2691 SMB_BIG_UINT count,offset;
2692 NTSTATUS status;
2693 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2694 BOOL my_lock_ctx = False;
2696 START_PROFILE(SMBlock);
2698 CHECK_FSP(fsp,conn);
2700 release_level_2_oplocks_on_change(fsp);
2702 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2703 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2705 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2706 fsp->fd, fsp->fnum, (double)offset, (double)count));
2708 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2709 if (NT_STATUS_V(status)) {
2710 #if 0
2711 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2712 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2714 * A blocking lock was requested. Package up
2715 * this smb into a queued request and push it
2716 * onto the blocking lock queue.
2718 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2719 END_PROFILE(SMBlock);
2720 return -1;
2723 #endif
2724 END_PROFILE(SMBlock);
2725 return ERROR_NT(status);
2728 END_PROFILE(SMBlock);
2729 return(outsize);
2732 /****************************************************************************
2733 Reply to a unlock.
2734 ****************************************************************************/
2736 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2737 int dum_buffsize)
2739 int outsize = set_message(outbuf,0,0,True);
2740 SMB_BIG_UINT count,offset;
2741 NTSTATUS status;
2742 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2743 START_PROFILE(SMBunlock);
2745 CHECK_FSP(fsp,conn);
2747 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2748 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2750 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2751 if (NT_STATUS_V(status)) {
2752 END_PROFILE(SMBunlock);
2753 return ERROR_NT(status);
2756 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2757 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2759 END_PROFILE(SMBunlock);
2760 return(outsize);
2763 /****************************************************************************
2764 Reply to a tdis.
2765 ****************************************************************************/
2767 int reply_tdis(connection_struct *conn,
2768 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2770 int outsize = set_message(outbuf,0,0,True);
2771 uint16 vuid;
2772 START_PROFILE(SMBtdis);
2774 vuid = SVAL(inbuf,smb_uid);
2776 if (!conn) {
2777 DEBUG(4,("Invalid connection in tdis\n"));
2778 END_PROFILE(SMBtdis);
2779 return ERROR_DOS(ERRSRV,ERRinvnid);
2782 conn->used = False;
2784 close_cnum(conn,vuid);
2786 END_PROFILE(SMBtdis);
2787 return outsize;
2790 /****************************************************************************
2791 Reply to a echo.
2792 ****************************************************************************/
2794 int reply_echo(connection_struct *conn,
2795 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2797 int smb_reverb = SVAL(inbuf,smb_vwv0);
2798 int seq_num;
2799 unsigned int data_len = smb_buflen(inbuf);
2800 int outsize = set_message(outbuf,1,data_len,True);
2801 START_PROFILE(SMBecho);
2803 if (data_len > BUFFER_SIZE) {
2804 DEBUG(0,("reply_echo: data_len too large.\n"));
2805 END_PROFILE(SMBecho);
2806 return -1;
2809 /* copy any incoming data back out */
2810 if (data_len > 0)
2811 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2813 if (smb_reverb > 100) {
2814 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2815 smb_reverb = 100;
2818 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2819 SSVAL(outbuf,smb_vwv0,seq_num);
2821 smb_setlen(outbuf,outsize - 4);
2823 if (!send_smb(smbd_server_fd(),outbuf))
2824 exit_server("reply_echo: send_smb failed.");
2827 DEBUG(3,("echo %d times\n", smb_reverb));
2829 smb_echo_count++;
2831 END_PROFILE(SMBecho);
2832 return -1;
2835 /****************************************************************************
2836 Reply to a printopen.
2837 ****************************************************************************/
2839 int reply_printopen(connection_struct *conn,
2840 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2842 int outsize = 0;
2843 files_struct *fsp;
2844 START_PROFILE(SMBsplopen);
2846 if (!CAN_PRINT(conn)) {
2847 END_PROFILE(SMBsplopen);
2848 return ERROR_DOS(ERRDOS,ERRnoaccess);
2851 /* Open for exclusive use, write only. */
2852 fsp = print_fsp_open(conn, NULL);
2854 if (!fsp) {
2855 END_PROFILE(SMBsplopen);
2856 return(UNIXERROR(ERRDOS,ERRnoaccess));
2859 outsize = set_message(outbuf,1,0,True);
2860 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2862 DEBUG(3,("openprint fd=%d fnum=%d\n",
2863 fsp->fd, fsp->fnum));
2865 END_PROFILE(SMBsplopen);
2866 return(outsize);
2869 /****************************************************************************
2870 Reply to a printclose.
2871 ****************************************************************************/
2873 int reply_printclose(connection_struct *conn,
2874 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2876 int outsize = set_message(outbuf,0,0,True);
2877 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2878 int close_err = 0;
2879 START_PROFILE(SMBsplclose);
2881 CHECK_FSP(fsp,conn);
2883 if (!CAN_PRINT(conn)) {
2884 END_PROFILE(SMBsplclose);
2885 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2888 DEBUG(3,("printclose fd=%d fnum=%d\n",
2889 fsp->fd,fsp->fnum));
2891 close_err = close_file(fsp,True);
2893 if(close_err != 0) {
2894 errno = close_err;
2895 END_PROFILE(SMBsplclose);
2896 return(UNIXERROR(ERRHRD,ERRgeneral));
2899 END_PROFILE(SMBsplclose);
2900 return(outsize);
2903 /****************************************************************************
2904 Reply to a printqueue.
2905 ****************************************************************************/
2907 int reply_printqueue(connection_struct *conn,
2908 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2910 int outsize = set_message(outbuf,2,3,True);
2911 int max_count = SVAL(inbuf,smb_vwv0);
2912 int start_index = SVAL(inbuf,smb_vwv1);
2913 START_PROFILE(SMBsplretq);
2915 /* we used to allow the client to get the cnum wrong, but that
2916 is really quite gross and only worked when there was only
2917 one printer - I think we should now only accept it if they
2918 get it right (tridge) */
2919 if (!CAN_PRINT(conn)) {
2920 END_PROFILE(SMBsplretq);
2921 return ERROR_DOS(ERRDOS,ERRnoaccess);
2924 SSVAL(outbuf,smb_vwv0,0);
2925 SSVAL(outbuf,smb_vwv1,0);
2926 SCVAL(smb_buf(outbuf),0,1);
2927 SSVAL(smb_buf(outbuf),1,0);
2929 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2930 start_index, max_count));
2933 print_queue_struct *queue = NULL;
2934 print_status_struct status;
2935 char *p = smb_buf(outbuf) + 3;
2936 int count = print_queue_status(SNUM(conn), &queue, &status);
2937 int num_to_get = ABS(max_count);
2938 int first = (max_count>0?start_index:start_index+max_count+1);
2939 int i;
2941 if (first >= count)
2942 num_to_get = 0;
2943 else
2944 num_to_get = MIN(num_to_get,count-first);
2947 for (i=first;i<first+num_to_get;i++) {
2948 put_dos_date2(p,0,queue[i].time);
2949 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2950 SSVAL(p,5, queue[i].job);
2951 SIVAL(p,7,queue[i].size);
2952 SCVAL(p,11,0);
2953 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2954 p += 28;
2957 if (count > 0) {
2958 outsize = set_message(outbuf,2,28*count+3,False);
2959 SSVAL(outbuf,smb_vwv0,count);
2960 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2961 SCVAL(smb_buf(outbuf),0,1);
2962 SSVAL(smb_buf(outbuf),1,28*count);
2965 SAFE_FREE(queue);
2967 DEBUG(3,("%d entries returned in queue\n",count));
2970 END_PROFILE(SMBsplretq);
2971 return(outsize);
2974 /****************************************************************************
2975 Reply to a printwrite.
2976 ****************************************************************************/
2978 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2980 int numtowrite;
2981 int outsize = set_message(outbuf,0,0,True);
2982 char *data;
2983 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2985 START_PROFILE(SMBsplwr);
2987 if (!CAN_PRINT(conn)) {
2988 END_PROFILE(SMBsplwr);
2989 return ERROR_DOS(ERRDOS,ERRnoaccess);
2992 CHECK_FSP(fsp,conn);
2993 CHECK_WRITE(fsp);
2995 numtowrite = SVAL(smb_buf(inbuf),1);
2996 data = smb_buf(inbuf) + 3;
2998 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2999 END_PROFILE(SMBsplwr);
3000 return(UNIXERROR(ERRHRD,ERRdiskfull));
3003 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3005 END_PROFILE(SMBsplwr);
3006 return(outsize);
3009 /****************************************************************************
3010 The guts of the mkdir command, split out so it may be called by the NT SMB
3011 code.
3012 ****************************************************************************/
3014 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3016 BOOL bad_path = False;
3017 SMB_STRUCT_STAT sbuf;
3018 int ret= -1;
3020 unix_convert(directory,conn,0,&bad_path,&sbuf);
3022 if( strchr_m(directory, ':')) {
3023 return NT_STATUS_NOT_A_DIRECTORY;
3026 if (ms_has_wild(directory)) {
3027 return NT_STATUS_OBJECT_NAME_INVALID;
3030 if (check_name(directory, conn))
3031 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3033 if (ret == -1) {
3034 if(errno == ENOENT) {
3035 if (bad_path)
3036 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3037 else
3038 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3040 return map_nt_error_from_unix(errno);
3043 return NT_STATUS_OK;
3046 /****************************************************************************
3047 Reply to a mkdir.
3048 ****************************************************************************/
3050 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3052 pstring directory;
3053 int outsize;
3054 NTSTATUS status;
3055 START_PROFILE(SMBmkdir);
3057 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3058 if (!NT_STATUS_IS_OK(status)) {
3059 END_PROFILE(SMBmkdir);
3060 return ERROR_NT(status);
3063 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3065 status = mkdir_internal(conn, directory);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 END_PROFILE(SMBmkdir);
3068 return ERROR_NT(status);
3071 outsize = set_message(outbuf,0,0,True);
3073 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3075 END_PROFILE(SMBmkdir);
3076 return(outsize);
3079 /****************************************************************************
3080 Static function used by reply_rmdir to delete an entire directory
3081 tree recursively. Return False on ok, True on fail.
3082 ****************************************************************************/
3084 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3086 const char *dname = NULL;
3087 BOOL ret = False;
3088 void *dirptr = OpenDir(conn, directory, False);
3090 if(dirptr == NULL)
3091 return True;
3093 while((dname = ReadDirName(dirptr))) {
3094 pstring fullname;
3095 SMB_STRUCT_STAT st;
3097 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3098 continue;
3100 /* Construct the full name. */
3101 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3102 errno = ENOMEM;
3103 ret = True;
3104 break;
3107 pstrcpy(fullname, directory);
3108 pstrcat(fullname, "/");
3109 pstrcat(fullname, dname);
3111 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3112 ret = True;
3113 break;
3116 if(st.st_mode & S_IFDIR) {
3117 if(recursive_rmdir(conn, fullname)!=0) {
3118 ret = True;
3119 break;
3121 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3122 ret = True;
3123 break;
3125 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3126 ret = True;
3127 break;
3130 CloseDir(dirptr);
3131 return ret;
3134 /****************************************************************************
3135 The internals of the rmdir code - called elsewhere.
3136 ****************************************************************************/
3138 BOOL rmdir_internals(connection_struct *conn, char *directory)
3140 BOOL ok;
3142 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3143 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3145 * Check to see if the only thing in this directory are
3146 * vetoed files/directories. If so then delete them and
3147 * retry. If we fail to delete any of them (and we *don't*
3148 * do a recursive delete) then fail the rmdir.
3150 BOOL all_veto_files = True;
3151 const char *dname;
3152 void *dirptr = OpenDir(conn, directory, False);
3154 if(dirptr != NULL) {
3155 int dirpos = TellDir(dirptr);
3156 while ((dname = ReadDirName(dirptr))) {
3157 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3158 continue;
3159 if(!IS_VETO_PATH(conn, dname)) {
3160 all_veto_files = False;
3161 break;
3165 if(all_veto_files) {
3166 SeekDir(dirptr,dirpos);
3167 while ((dname = ReadDirName(dirptr))) {
3168 pstring fullname;
3169 SMB_STRUCT_STAT st;
3171 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3172 continue;
3174 /* Construct the full name. */
3175 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3176 errno = ENOMEM;
3177 break;
3180 pstrcpy(fullname, directory);
3181 pstrcat(fullname, "/");
3182 pstrcat(fullname, dname);
3184 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3185 break;
3186 if(st.st_mode & S_IFDIR) {
3187 if(lp_recursive_veto_delete(SNUM(conn))) {
3188 if(recursive_rmdir(conn, fullname) != 0)
3189 break;
3191 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3192 break;
3193 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3194 break;
3196 CloseDir(dirptr);
3197 /* Retry the rmdir */
3198 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3199 } else {
3200 CloseDir(dirptr);
3202 } else {
3203 errno = ENOTEMPTY;
3207 if (!ok)
3208 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3210 return ok;
3213 /****************************************************************************
3214 Reply to a rmdir.
3215 ****************************************************************************/
3217 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3219 pstring directory;
3220 int outsize = 0;
3221 BOOL ok = False;
3222 BOOL bad_path = False;
3223 SMB_STRUCT_STAT sbuf;
3224 NTSTATUS status;
3225 START_PROFILE(SMBrmdir);
3227 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3228 if (!NT_STATUS_IS_OK(status)) {
3229 END_PROFILE(SMBrmdir);
3230 return ERROR_NT(status);
3233 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3235 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3237 if (check_name(directory,conn)) {
3238 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3239 ok = rmdir_internals(conn, directory);
3242 if (!ok) {
3243 END_PROFILE(SMBrmdir);
3244 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3247 outsize = set_message(outbuf,0,0,True);
3249 DEBUG( 3, ( "rmdir %s\n", directory ) );
3251 END_PROFILE(SMBrmdir);
3252 return(outsize);
3255 /*******************************************************************
3256 Resolve wildcards in a filename rename.
3257 ********************************************************************/
3259 static BOOL resolve_wildcards(const char *name1, char *name2)
3261 fstring root1,root2;
3262 fstring ext1,ext2;
3263 char *p,*p2, *pname1, *pname2;
3264 int available_space;
3267 pname1 = strrchr_m(name1,'/');
3268 pname2 = strrchr_m(name2,'/');
3270 if (!pname1 || !pname2)
3271 return(False);
3273 fstrcpy(root1,pname1);
3274 fstrcpy(root2,pname2);
3275 p = strrchr_m(root1,'.');
3276 if (p) {
3277 *p = 0;
3278 fstrcpy(ext1,p+1);
3279 } else {
3280 fstrcpy(ext1,"");
3282 p = strrchr_m(root2,'.');
3283 if (p) {
3284 *p = 0;
3285 fstrcpy(ext2,p+1);
3286 } else {
3287 fstrcpy(ext2,"");
3290 p = root1;
3291 p2 = root2;
3292 while (*p2) {
3293 if (*p2 == '?') {
3294 *p2 = *p;
3295 p2++;
3296 } else {
3297 p2++;
3299 if (*p)
3300 p++;
3303 p = ext1;
3304 p2 = ext2;
3305 while (*p2) {
3306 if (*p2 == '?') {
3307 *p2 = *p;
3308 p2++;
3309 } else {
3310 p2++;
3312 if (*p)
3313 p++;
3316 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3318 if (ext2[0]) {
3319 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3320 } else {
3321 pstrcpy_base(pname2, root2, name2);
3324 return(True);
3327 /****************************************************************************
3328 Ensure open files have their names updates.
3329 ****************************************************************************/
3331 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3333 files_struct *fsp;
3334 BOOL did_rename = False;
3336 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3337 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3338 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3339 fsp->fsp_name, newname ));
3340 string_set(&fsp->fsp_name, newname);
3341 did_rename = True;
3344 if (!did_rename)
3345 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3346 (unsigned int)dev, (double)inode, newname ));
3349 /****************************************************************************
3350 Rename an open file - given an fsp.
3351 ****************************************************************************/
3353 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3355 SMB_STRUCT_STAT sbuf;
3356 BOOL bad_path = False;
3357 pstring newname_last_component;
3358 NTSTATUS error = NT_STATUS_OK;
3359 BOOL dest_exists;
3361 ZERO_STRUCT(sbuf);
3362 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3364 /* Quick check for "." and ".." */
3365 if (newname_last_component[0] == '.') {
3366 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3367 return NT_STATUS_ACCESS_DENIED;
3371 /* Ensure newname contains a '/' */
3372 if(strrchr_m(newname,'/') == 0) {
3373 pstring tmpstr;
3375 pstrcpy(tmpstr, "./");
3376 pstrcat(tmpstr, newname);
3377 pstrcpy(newname, tmpstr);
3381 * Check for special case with case preserving and not
3382 * case sensitive. If the old last component differs from the original
3383 * last component only by case, then we should allow
3384 * the rename (user is trying to change the case of the
3385 * filename).
3388 if((case_sensitive == False) && (case_preserve == True) &&
3389 strequal(newname, fsp->fsp_name)) {
3390 char *p;
3391 pstring newname_modified_last_component;
3394 * Get the last component of the modified name.
3395 * Note that we guarantee that newname contains a '/'
3396 * character above.
3398 p = strrchr_m(newname,'/');
3399 pstrcpy(newname_modified_last_component,p+1);
3401 if(strcsequal(newname_modified_last_component,
3402 newname_last_component) == False) {
3404 * Replace the modified last component with
3405 * the original.
3407 pstrcpy(p+1, newname_last_component);
3412 * If the src and dest names are identical - including case,
3413 * don't do the rename, just return success.
3416 if (strcsequal(fsp->fsp_name, newname)) {
3417 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3418 newname));
3419 return NT_STATUS_OK;
3422 dest_exists = vfs_object_exist(conn,newname,NULL);
3424 if(!replace_if_exists && dest_exists) {
3425 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3426 fsp->fsp_name,newname));
3427 return NT_STATUS_OBJECT_NAME_COLLISION;
3430 error = can_rename(newname,conn,&sbuf);
3432 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3433 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3434 nt_errstr(error), fsp->fsp_name,newname));
3435 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3436 error = NT_STATUS_ACCESS_DENIED;
3437 return error;
3440 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3441 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3442 fsp->fsp_name,newname));
3443 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3444 return NT_STATUS_OK;
3447 if (errno == ENOTDIR || errno == EISDIR)
3448 error = NT_STATUS_OBJECT_NAME_COLLISION;
3449 else
3450 error = map_nt_error_from_unix(errno);
3452 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3453 nt_errstr(error), fsp->fsp_name,newname));
3455 return error;
3458 /****************************************************************************
3459 The guts of the rename command, split out so it may be called by the NT SMB
3460 code.
3461 ****************************************************************************/
3463 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3465 pstring directory;
3466 pstring mask;
3467 pstring newname_last_component;
3468 char *p;
3469 BOOL has_wild;
3470 BOOL bad_path1 = False;
3471 BOOL bad_path2 = False;
3472 int count=0;
3473 NTSTATUS error = NT_STATUS_OK;
3474 BOOL rc = True;
3475 SMB_STRUCT_STAT sbuf1, sbuf2;
3477 *directory = *mask = 0;
3479 ZERO_STRUCT(sbuf1);
3480 ZERO_STRUCT(sbuf2);
3481 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3482 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3484 /* Quick check for "." and ".." */
3485 if (!bad_path2 && newname_last_component[0] == '.') {
3486 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3487 DEBUG(10,("rename_internals: newname_last_component = '.' or '..'\n"));
3488 return NT_STATUS_ACCESS_DENIED;
3493 * Split the old name into directory and last component
3494 * strings. Note that unix_convert may have stripped off a
3495 * leading ./ from both name and newname if the rename is
3496 * at the root of the share. We need to make sure either both
3497 * name and newname contain a / character or neither of them do
3498 * as this is checked in resolve_wildcards().
3501 p = strrchr_m(name,'/');
3502 if (!p) {
3503 pstrcpy(directory,".");
3504 pstrcpy(mask,name);
3505 } else {
3506 *p = 0;
3507 pstrcpy(directory,name);
3508 pstrcpy(mask,p+1);
3509 *p = '/'; /* Replace needed for exceptional test below. */
3513 * We should only check the mangled cache
3514 * here if unix_convert failed. This means
3515 * that the path in 'mask' doesn't exist
3516 * on the file system and so we need to look
3517 * for a possible mangle. This patch from
3518 * Tine Smukavec <valentin.smukavec@hermes.si>.
3521 if (!rc && mangle_is_mangled(mask))
3522 mangle_check_cache( mask );
3524 has_wild = ms_has_wild(mask);
3526 if (!has_wild) {
3528 * No wildcards - just process the one file.
3530 BOOL is_short_name = mangle_is_8_3(name, True);
3532 /* Add a terminating '/' to the directory name. */
3533 pstrcat(directory,"/");
3534 pstrcat(directory,mask);
3536 /* Ensure newname contains a '/' also */
3537 if(strrchr_m(newname,'/') == 0) {
3538 pstring tmpstr;
3540 pstrcpy(tmpstr, "./");
3541 pstrcat(tmpstr, newname);
3542 pstrcpy(newname, tmpstr);
3545 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3546 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3547 case_sensitive, case_preserve, short_case_preserve, directory,
3548 newname, newname_last_component, is_short_name));
3551 * Check for special case with case preserving and not
3552 * case sensitive, if directory and newname are identical,
3553 * and the old last component differs from the original
3554 * last component only by case, then we should allow
3555 * the rename (user is trying to change the case of the
3556 * filename).
3558 if((case_sensitive == False) &&
3559 (((case_preserve == True) &&
3560 (is_short_name == False)) ||
3561 ((short_case_preserve == True) &&
3562 (is_short_name == True))) &&
3563 strcsequal(directory, newname)) {
3564 pstring newname_modified_last_component;
3567 * Get the last component of the modified name.
3568 * Note that we guarantee that newname contains a '/'
3569 * character above.
3571 p = strrchr_m(newname,'/');
3572 pstrcpy(newname_modified_last_component,p+1);
3574 if(strcsequal(newname_modified_last_component,
3575 newname_last_component) == False) {
3577 * Replace the modified last component with
3578 * the original.
3580 pstrcpy(p+1, newname_last_component);
3584 resolve_wildcards(directory,newname);
3587 * The source object must exist.
3590 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3591 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3592 directory,newname));
3594 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3596 * Must return different errors depending on whether the parent
3597 * directory existed or not.
3600 p = strrchr_m(directory, '/');
3601 if (!p)
3602 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3603 *p = '\0';
3604 if (vfs_object_exist(conn, directory, NULL))
3605 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3606 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3608 error = map_nt_error_from_unix(errno);
3609 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3610 nt_errstr(error), directory,newname));
3612 return error;
3615 error = can_rename(directory,conn,&sbuf1);
3617 if (!NT_STATUS_IS_OK(error)) {
3618 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3619 nt_errstr(error), directory,newname));
3620 return error;
3624 * If the src and dest names are identical - including case,
3625 * don't do the rename, just return success.
3628 if (strcsequal(directory, newname)) {
3629 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3630 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3631 return NT_STATUS_OK;
3634 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3635 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3636 directory,newname));
3637 return NT_STATUS_OBJECT_NAME_COLLISION;
3640 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3641 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3642 directory,newname));
3643 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3644 return NT_STATUS_OK;
3647 if (errno == ENOTDIR || errno == EISDIR)
3648 error = NT_STATUS_OBJECT_NAME_COLLISION;
3649 else
3650 error = map_nt_error_from_unix(errno);
3652 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3653 nt_errstr(error), directory,newname));
3655 return error;
3656 } else {
3658 * Wildcards - process each file that matches.
3660 void *dirptr = NULL;
3661 const char *dname;
3662 pstring destname;
3664 if (check_name(directory,conn))
3665 dirptr = OpenDir(conn, directory, True);
3667 if (dirptr) {
3668 error = NT_STATUS_NO_SUCH_FILE;
3669 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3671 if (strequal(mask,"????????.???"))
3672 pstrcpy(mask,"*");
3674 while ((dname = ReadDirName(dirptr))) {
3675 pstring fname;
3677 pstrcpy(fname,dname);
3679 /* Quick check for "." and ".." */
3680 if (fname[0] == '.') {
3681 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3682 continue;
3686 if(!mask_match(fname, mask, case_sensitive))
3687 continue;
3689 error = NT_STATUS_ACCESS_DENIED;
3690 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3691 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3692 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3693 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3694 continue;
3696 error = can_rename(fname,conn,&sbuf1);
3697 if (!NT_STATUS_IS_OK(error)) {
3698 DEBUG(6,("rename %s refused\n", fname));
3699 continue;
3701 pstrcpy(destname,newname);
3703 if (!resolve_wildcards(fname,destname)) {
3704 DEBUG(6,("resolve_wildcards %s %s failed\n",
3705 fname, destname));
3706 continue;
3709 if (!replace_if_exists &&
3710 vfs_file_exist(conn,destname, NULL)) {
3711 DEBUG(6,("file_exist %s\n", destname));
3712 error = NT_STATUS_OBJECT_NAME_COLLISION;
3713 continue;
3716 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3717 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3718 count++;
3720 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3722 CloseDir(dirptr);
3726 if (count == 0 && NT_STATUS_IS_OK(error)) {
3727 error = map_nt_error_from_unix(errno);
3730 return error;
3733 /****************************************************************************
3734 Reply to a mv.
3735 ****************************************************************************/
3737 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3738 int dum_buffsize)
3740 int outsize = 0;
3741 pstring name;
3742 pstring newname;
3743 char *p;
3744 NTSTATUS status;
3746 START_PROFILE(SMBmv);
3748 p = smb_buf(inbuf) + 1;
3749 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3750 if (!NT_STATUS_IS_OK(status)) {
3751 END_PROFILE(SMBmv);
3752 return ERROR_NT(status);
3754 p++;
3755 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3756 if (!NT_STATUS_IS_OK(status)) {
3757 END_PROFILE(SMBmv);
3758 return ERROR_NT(status);
3761 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3762 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3764 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3766 status = rename_internals(conn, name, newname, False);
3767 if (!NT_STATUS_IS_OK(status)) {
3768 END_PROFILE(SMBmv);
3769 return ERROR_NT(status);
3773 * Win2k needs a changenotify request response before it will
3774 * update after a rename..
3776 process_pending_change_notify_queue((time_t)0);
3777 outsize = set_message(outbuf,0,0,True);
3779 END_PROFILE(SMBmv);
3780 return(outsize);
3783 /*******************************************************************
3784 Copy a file as part of a reply_copy.
3785 ******************************************************************/
3787 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3788 int count,BOOL target_is_directory, int *err_ret)
3790 int Access,action;
3791 SMB_STRUCT_STAT src_sbuf, sbuf2;
3792 SMB_OFF_T ret=-1;
3793 files_struct *fsp1,*fsp2;
3794 pstring dest;
3796 *err_ret = 0;
3798 pstrcpy(dest,dest1);
3799 if (target_is_directory) {
3800 char *p = strrchr_m(src,'/');
3801 if (p)
3802 p++;
3803 else
3804 p = src;
3805 pstrcat(dest,"/");
3806 pstrcat(dest,p);
3809 if (!vfs_file_exist(conn,src,&src_sbuf))
3810 return(False);
3812 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3813 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3815 if (!fsp1)
3816 return(False);
3818 if (!target_is_directory && count)
3819 ofun = FILE_EXISTS_OPEN;
3821 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3822 ZERO_STRUCTP(&sbuf2);
3824 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3825 ofun,src_sbuf.st_mode,0,&Access,&action);
3827 if (!fsp2) {
3828 close_file(fsp1,False);
3829 return(False);
3832 if ((ofun&3) == 1) {
3833 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3834 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3836 * Stop the copy from occurring.
3838 ret = -1;
3839 src_sbuf.st_size = 0;
3843 if (src_sbuf.st_size)
3844 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3846 close_file(fsp1,False);
3848 /* Ensure the modtime is set correctly on the destination file. */
3849 fsp2->pending_modtime = src_sbuf.st_mtime;
3852 * As we are opening fsp1 read-only we only expect
3853 * an error on close on fsp2 if we are out of space.
3854 * Thus we don't look at the error return from the
3855 * close of fsp1.
3857 *err_ret = close_file(fsp2,False);
3859 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3862 /****************************************************************************
3863 Reply to a file copy.
3864 ****************************************************************************/
3866 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3868 int outsize = 0;
3869 pstring name;
3870 pstring directory;
3871 pstring mask,newname;
3872 char *p;
3873 int count=0;
3874 int error = ERRnoaccess;
3875 int err = 0;
3876 BOOL has_wild;
3877 BOOL exists=False;
3878 int tid2 = SVAL(inbuf,smb_vwv0);
3879 int ofun = SVAL(inbuf,smb_vwv1);
3880 int flags = SVAL(inbuf,smb_vwv2);
3881 BOOL target_is_directory=False;
3882 BOOL bad_path1 = False;
3883 BOOL bad_path2 = False;
3884 BOOL rc = True;
3885 SMB_STRUCT_STAT sbuf1, sbuf2;
3886 NTSTATUS status;
3888 START_PROFILE(SMBcopy);
3890 *directory = *mask = 0;
3892 p = smb_buf(inbuf);
3893 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 END_PROFILE(SMBcopy);
3896 return ERROR_NT(status);
3898 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3899 if (!NT_STATUS_IS_OK(status)) {
3900 END_PROFILE(SMBcopy);
3901 return ERROR_NT(status);
3904 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3906 if (tid2 != conn->cnum) {
3907 /* can't currently handle inter share copies XXXX */
3908 DEBUG(3,("Rejecting inter-share copy\n"));
3909 END_PROFILE(SMBcopy);
3910 return ERROR_DOS(ERRSRV,ERRinvdevice);
3913 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3914 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3916 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3917 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3919 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3921 if ((flags&1) && target_is_directory) {
3922 END_PROFILE(SMBcopy);
3923 return ERROR_DOS(ERRDOS,ERRbadfile);
3926 if ((flags&2) && !target_is_directory) {
3927 END_PROFILE(SMBcopy);
3928 return ERROR_DOS(ERRDOS,ERRbadpath);
3931 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3932 /* wants a tree copy! XXXX */
3933 DEBUG(3,("Rejecting tree copy\n"));
3934 END_PROFILE(SMBcopy);
3935 return ERROR_DOS(ERRSRV,ERRerror);
3938 p = strrchr_m(name,'/');
3939 if (!p) {
3940 pstrcpy(directory,"./");
3941 pstrcpy(mask,name);
3942 } else {
3943 *p = 0;
3944 pstrcpy(directory,name);
3945 pstrcpy(mask,p+1);
3949 * We should only check the mangled cache
3950 * here if unix_convert failed. This means
3951 * that the path in 'mask' doesn't exist
3952 * on the file system and so we need to look
3953 * for a possible mangle. This patch from
3954 * Tine Smukavec <valentin.smukavec@hermes.si>.
3957 if (!rc && mangle_is_mangled(mask))
3958 mangle_check_cache( mask );
3960 has_wild = ms_has_wild(mask);
3962 if (!has_wild) {
3963 pstrcat(directory,"/");
3964 pstrcat(directory,mask);
3965 if (resolve_wildcards(directory,newname) &&
3966 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3967 count++;
3968 if(!count && err) {
3969 errno = err;
3970 END_PROFILE(SMBcopy);
3971 return(UNIXERROR(ERRHRD,ERRgeneral));
3973 if (!count) {
3974 exists = vfs_file_exist(conn,directory,NULL);
3976 } else {
3977 void *dirptr = NULL;
3978 const char *dname;
3979 pstring destname;
3981 if (check_name(directory,conn))
3982 dirptr = OpenDir(conn, directory, True);
3984 if (dirptr) {
3985 error = ERRbadfile;
3987 if (strequal(mask,"????????.???"))
3988 pstrcpy(mask,"*");
3990 while ((dname = ReadDirName(dirptr))) {
3991 pstring fname;
3992 pstrcpy(fname,dname);
3994 if(!mask_match(fname, mask, case_sensitive))
3995 continue;
3997 error = ERRnoaccess;
3998 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3999 pstrcpy(destname,newname);
4000 if (resolve_wildcards(fname,destname) &&
4001 copy_file(fname,destname,conn,ofun,
4002 count,target_is_directory,&err))
4003 count++;
4004 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4006 CloseDir(dirptr);
4010 if (count == 0) {
4011 if(err) {
4012 /* Error on close... */
4013 errno = err;
4014 END_PROFILE(SMBcopy);
4015 return(UNIXERROR(ERRHRD,ERRgeneral));
4018 if (exists) {
4019 END_PROFILE(SMBcopy);
4020 return ERROR_DOS(ERRDOS,error);
4021 } else {
4022 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4023 unix_ERR_class = ERRDOS;
4024 unix_ERR_code = ERRbadpath;
4026 END_PROFILE(SMBcopy);
4027 return(UNIXERROR(ERRDOS,error));
4031 outsize = set_message(outbuf,1,0,True);
4032 SSVAL(outbuf,smb_vwv0,count);
4034 END_PROFILE(SMBcopy);
4035 return(outsize);
4038 /****************************************************************************
4039 Reply to a setdir.
4040 ****************************************************************************/
4042 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4044 int snum;
4045 int outsize = 0;
4046 BOOL ok = False;
4047 pstring newdir;
4048 NTSTATUS status;
4050 START_PROFILE(pathworks_setdir);
4052 snum = SNUM(conn);
4053 if (!CAN_SETDIR(snum)) {
4054 END_PROFILE(pathworks_setdir);
4055 return ERROR_DOS(ERRDOS,ERRnoaccess);
4058 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 END_PROFILE(pathworks_setdir);
4061 return ERROR_NT(status);
4064 if (strlen(newdir) == 0) {
4065 ok = True;
4066 } else {
4067 ok = vfs_directory_exist(conn,newdir,NULL);
4068 if (ok)
4069 string_set(&conn->connectpath,newdir);
4072 if (!ok) {
4073 END_PROFILE(pathworks_setdir);
4074 return ERROR_DOS(ERRDOS,ERRbadpath);
4077 outsize = set_message(outbuf,0,0,True);
4078 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4080 DEBUG(3,("setdir %s\n", newdir));
4082 END_PROFILE(pathworks_setdir);
4083 return(outsize);
4086 /****************************************************************************
4087 Get a lock pid, dealing with large count requests.
4088 ****************************************************************************/
4090 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4092 if(!large_file_format)
4093 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4094 else
4095 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4098 /****************************************************************************
4099 Get a lock count, dealing with large count requests.
4100 ****************************************************************************/
4102 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4104 SMB_BIG_UINT count = 0;
4106 if(!large_file_format) {
4107 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4108 } else {
4110 #if defined(HAVE_LONGLONG)
4111 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4112 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4113 #else /* HAVE_LONGLONG */
4116 * NT4.x seems to be broken in that it sends large file (64 bit)
4117 * lockingX calls even if the CAP_LARGE_FILES was *not*
4118 * negotiated. For boxes without large unsigned ints truncate the
4119 * lock count by dropping the top 32 bits.
4122 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4123 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4124 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4125 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4126 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4129 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4130 #endif /* HAVE_LONGLONG */
4133 return count;
4136 #if !defined(HAVE_LONGLONG)
4137 /****************************************************************************
4138 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4139 ****************************************************************************/
4141 static uint32 map_lock_offset(uint32 high, uint32 low)
4143 unsigned int i;
4144 uint32 mask = 0;
4145 uint32 highcopy = high;
4148 * Try and find out how many significant bits there are in high.
4151 for(i = 0; highcopy; i++)
4152 highcopy >>= 1;
4155 * We use 31 bits not 32 here as POSIX
4156 * lock offsets may not be negative.
4159 mask = (~0) << (31 - i);
4161 if(low & mask)
4162 return 0; /* Fail. */
4164 high <<= (31 - i);
4166 return (high|low);
4168 #endif /* !defined(HAVE_LONGLONG) */
4170 /****************************************************************************
4171 Get a lock offset, dealing with large offset requests.
4172 ****************************************************************************/
4174 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4176 SMB_BIG_UINT offset = 0;
4178 *err = False;
4180 if(!large_file_format) {
4181 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4182 } else {
4184 #if defined(HAVE_LONGLONG)
4185 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4186 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4187 #else /* HAVE_LONGLONG */
4190 * NT4.x seems to be broken in that it sends large file (64 bit)
4191 * lockingX calls even if the CAP_LARGE_FILES was *not*
4192 * negotiated. For boxes without large unsigned ints mangle the
4193 * lock offset by mapping the top 32 bits onto the lower 32.
4196 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4197 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4198 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4199 uint32 new_low = 0;
4201 if((new_low = map_lock_offset(high, low)) == 0) {
4202 *err = True;
4203 return (SMB_BIG_UINT)-1;
4206 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4207 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4208 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4209 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4212 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4213 #endif /* HAVE_LONGLONG */
4216 return offset;
4219 /****************************************************************************
4220 Reply to a lockingX request.
4221 ****************************************************************************/
4223 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4225 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4226 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4227 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4228 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4229 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4230 SMB_BIG_UINT count = 0, offset = 0;
4231 uint16 lock_pid;
4232 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4233 int i;
4234 char *data;
4235 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4236 BOOL err;
4237 BOOL my_lock_ctx = False;
4238 NTSTATUS status;
4240 START_PROFILE(SMBlockingX);
4242 CHECK_FSP(fsp,conn);
4244 data = smb_buf(inbuf);
4246 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4247 /* we don't support these - and CANCEL_LOCK makes w2k
4248 and XP reboot so I don't really want to be
4249 compatible! (tridge) */
4250 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4253 /* Check if this is an oplock break on a file
4254 we have granted an oplock on.
4256 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4257 /* Client can insist on breaking to none. */
4258 BOOL break_to_none = (oplocklevel == 0);
4260 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4261 (unsigned int)oplocklevel, fsp->fnum ));
4264 * Make sure we have granted an exclusive or batch oplock on this file.
4267 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4268 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4269 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4271 /* if this is a pure oplock break request then don't send a reply */
4272 if (num_locks == 0 && num_ulocks == 0) {
4273 END_PROFILE(SMBlockingX);
4274 return -1;
4275 } else {
4276 END_PROFILE(SMBlockingX);
4277 return ERROR_DOS(ERRDOS,ERRlock);
4281 if (remove_oplock(fsp, break_to_none) == False) {
4282 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4283 fsp->fsp_name ));
4286 /* if this is a pure oplock break request then don't send a reply */
4287 if (num_locks == 0 && num_ulocks == 0) {
4288 /* Sanity check - ensure a pure oplock break is not a
4289 chained request. */
4290 if(CVAL(inbuf,smb_vwv0) != 0xff)
4291 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4292 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4293 END_PROFILE(SMBlockingX);
4294 return -1;
4299 * We do this check *after* we have checked this is not a oplock break
4300 * response message. JRA.
4303 release_level_2_oplocks_on_change(fsp);
4305 /* Data now points at the beginning of the list
4306 of smb_unlkrng structs */
4307 for(i = 0; i < (int)num_ulocks; i++) {
4308 lock_pid = get_lock_pid( data, i, large_file_format);
4309 count = get_lock_count( data, i, large_file_format);
4310 offset = get_lock_offset( data, i, large_file_format, &err);
4313 * There is no error code marked "stupid client bug".... :-).
4315 if(err) {
4316 END_PROFILE(SMBlockingX);
4317 return ERROR_DOS(ERRDOS,ERRnoaccess);
4320 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4321 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4323 status = do_unlock(fsp,conn,lock_pid,count,offset);
4324 if (NT_STATUS_V(status)) {
4325 END_PROFILE(SMBlockingX);
4326 return ERROR_NT(status);
4330 /* Setup the timeout in seconds. */
4332 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4334 /* Now do any requested locks */
4335 data += ((large_file_format ? 20 : 10)*num_ulocks);
4337 /* Data now points at the beginning of the list
4338 of smb_lkrng structs */
4340 for(i = 0; i < (int)num_locks; i++) {
4341 lock_pid = get_lock_pid( data, i, large_file_format);
4342 count = get_lock_count( data, i, large_file_format);
4343 offset = get_lock_offset( data, i, large_file_format, &err);
4346 * There is no error code marked "stupid client bug".... :-).
4348 if(err) {
4349 END_PROFILE(SMBlockingX);
4350 return ERROR_DOS(ERRDOS,ERRnoaccess);
4353 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4354 (double)offset, (double)count, (unsigned int)lock_pid,
4355 fsp->fsp_name, (int)lock_timeout ));
4357 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4358 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4359 if (NT_STATUS_V(status)) {
4361 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4362 * Even if it's our own lock context, we need to wait here as
4363 * there may be an unlock on the way.
4364 * So I removed a "&& !my_lock_ctx" from the following
4365 * if statement. JRA.
4367 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4369 * A blocking lock was requested. Package up
4370 * this smb into a queued request and push it
4371 * onto the blocking lock queue.
4373 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4374 END_PROFILE(SMBlockingX);
4375 return -1;
4378 break;
4382 /* If any of the above locks failed, then we must unlock
4383 all of the previous locks (X/Open spec). */
4384 if (i != num_locks && num_locks != 0) {
4386 * Ensure we don't do a remove on the lock that just failed,
4387 * as under POSIX rules, if we have a lock already there, we
4388 * will delete it (and we shouldn't) .....
4390 for(i--; i >= 0; i--) {
4391 lock_pid = get_lock_pid( data, i, large_file_format);
4392 count = get_lock_count( data, i, large_file_format);
4393 offset = get_lock_offset( data, i, large_file_format, &err);
4396 * There is no error code marked "stupid client bug".... :-).
4398 if(err) {
4399 END_PROFILE(SMBlockingX);
4400 return ERROR_DOS(ERRDOS,ERRnoaccess);
4403 do_unlock(fsp,conn,lock_pid,count,offset);
4405 END_PROFILE(SMBlockingX);
4406 return ERROR_NT(status);
4409 set_message(outbuf,2,0,True);
4411 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4412 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4414 END_PROFILE(SMBlockingX);
4415 return chain_reply(inbuf,outbuf,length,bufsize);
4418 /****************************************************************************
4419 Reply to a SMBreadbmpx (read block multiplex) request.
4420 ****************************************************************************/
4422 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4424 ssize_t nread = -1;
4425 ssize_t total_read;
4426 char *data;
4427 SMB_OFF_T startpos;
4428 int outsize;
4429 size_t maxcount;
4430 int max_per_packet;
4431 size_t tcount;
4432 int pad;
4433 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4434 START_PROFILE(SMBreadBmpx);
4436 /* this function doesn't seem to work - disable by default */
4437 if (!lp_readbmpx()) {
4438 END_PROFILE(SMBreadBmpx);
4439 return ERROR_DOS(ERRSRV,ERRuseSTD);
4442 outsize = set_message(outbuf,8,0,True);
4444 CHECK_FSP(fsp,conn);
4445 CHECK_READ(fsp);
4447 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4448 maxcount = SVAL(inbuf,smb_vwv3);
4450 data = smb_buf(outbuf);
4451 pad = ((long)data)%4;
4452 if (pad)
4453 pad = 4 - pad;
4454 data += pad;
4456 max_per_packet = bufsize-(outsize+pad);
4457 tcount = maxcount;
4458 total_read = 0;
4460 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4461 END_PROFILE(SMBreadBmpx);
4462 return ERROR_DOS(ERRDOS,ERRlock);
4465 do {
4466 size_t N = MIN(max_per_packet,tcount-total_read);
4468 nread = read_file(fsp,data,startpos,N);
4470 if (nread <= 0)
4471 nread = 0;
4473 if (nread < (ssize_t)N)
4474 tcount = total_read + nread;
4476 set_message(outbuf,8,nread,False);
4477 SIVAL(outbuf,smb_vwv0,startpos);
4478 SSVAL(outbuf,smb_vwv2,tcount);
4479 SSVAL(outbuf,smb_vwv6,nread);
4480 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4482 if (!send_smb(smbd_server_fd(),outbuf))
4483 exit_server("reply_readbmpx: send_smb failed.");
4485 total_read += nread;
4486 startpos += nread;
4487 } while (total_read < (ssize_t)tcount);
4489 END_PROFILE(SMBreadBmpx);
4490 return(-1);
4493 /****************************************************************************
4494 Reply to a SMBsetattrE.
4495 ****************************************************************************/
4497 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4499 struct utimbuf unix_times;
4500 int outsize = 0;
4501 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4502 START_PROFILE(SMBsetattrE);
4504 outsize = set_message(outbuf,0,0,True);
4506 if(!fsp || (fsp->conn != conn)) {
4507 END_PROFILE(SMBgetattrE);
4508 return ERROR_DOS(ERRDOS,ERRbadfid);
4512 * Convert the DOS times into unix times. Ignore create
4513 * time as UNIX can't set this.
4516 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4517 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4520 * Patch from Ray Frush <frush@engr.colostate.edu>
4521 * Sometimes times are sent as zero - ignore them.
4524 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4525 /* Ignore request */
4526 if( DEBUGLVL( 3 ) ) {
4527 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4528 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4530 END_PROFILE(SMBsetattrE);
4531 return(outsize);
4532 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4533 /* set modify time = to access time if modify time was 0 */
4534 unix_times.modtime = unix_times.actime;
4537 /* Set the date on this file */
4538 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4539 END_PROFILE(SMBsetattrE);
4540 return ERROR_DOS(ERRDOS,ERRnoaccess);
4543 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4544 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4546 END_PROFILE(SMBsetattrE);
4547 return(outsize);
4551 /* Back from the dead for OS/2..... JRA. */
4553 /****************************************************************************
4554 Reply to a SMBwritebmpx (write block multiplex primary) request.
4555 ****************************************************************************/
4557 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4559 size_t numtowrite;
4560 ssize_t nwritten = -1;
4561 int outsize = 0;
4562 SMB_OFF_T startpos;
4563 size_t tcount;
4564 BOOL write_through;
4565 int smb_doff;
4566 char *data;
4567 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4568 START_PROFILE(SMBwriteBmpx);
4570 CHECK_FSP(fsp,conn);
4571 CHECK_WRITE(fsp);
4572 CHECK_ERROR(fsp);
4574 tcount = SVAL(inbuf,smb_vwv1);
4575 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4576 write_through = BITSETW(inbuf+smb_vwv7,0);
4577 numtowrite = SVAL(inbuf,smb_vwv10);
4578 smb_doff = SVAL(inbuf,smb_vwv11);
4580 data = smb_base(inbuf) + smb_doff;
4582 /* If this fails we need to send an SMBwriteC response,
4583 not an SMBwritebmpx - set this up now so we don't forget */
4584 SCVAL(outbuf,smb_com,SMBwritec);
4586 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4587 END_PROFILE(SMBwriteBmpx);
4588 return(ERROR_DOS(ERRDOS,ERRlock));
4591 nwritten = write_file(fsp,data,startpos,numtowrite);
4593 if(lp_syncalways(SNUM(conn)) || write_through)
4594 sync_file(conn,fsp);
4596 if(nwritten < (ssize_t)numtowrite) {
4597 END_PROFILE(SMBwriteBmpx);
4598 return(UNIXERROR(ERRHRD,ERRdiskfull));
4601 /* If the maximum to be written to this file
4602 is greater than what we just wrote then set
4603 up a secondary struct to be attached to this
4604 fd, we will use this to cache error messages etc. */
4606 if((ssize_t)tcount > nwritten) {
4607 write_bmpx_struct *wbms;
4608 if(fsp->wbmpx_ptr != NULL)
4609 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4610 else
4611 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4612 if(!wbms) {
4613 DEBUG(0,("Out of memory in reply_readmpx\n"));
4614 END_PROFILE(SMBwriteBmpx);
4615 return(ERROR_DOS(ERRSRV,ERRnoresource));
4617 wbms->wr_mode = write_through;
4618 wbms->wr_discard = False; /* No errors yet */
4619 wbms->wr_total_written = nwritten;
4620 wbms->wr_errclass = 0;
4621 wbms->wr_error = 0;
4622 fsp->wbmpx_ptr = wbms;
4625 /* We are returning successfully, set the message type back to
4626 SMBwritebmpx */
4627 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4629 outsize = set_message(outbuf,1,0,True);
4631 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4633 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4634 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4636 if (write_through && tcount==nwritten) {
4637 /* We need to send both a primary and a secondary response */
4638 smb_setlen(outbuf,outsize - 4);
4639 if (!send_smb(smbd_server_fd(),outbuf))
4640 exit_server("reply_writebmpx: send_smb failed.");
4642 /* Now the secondary */
4643 outsize = set_message(outbuf,1,0,True);
4644 SCVAL(outbuf,smb_com,SMBwritec);
4645 SSVAL(outbuf,smb_vwv0,nwritten);
4648 END_PROFILE(SMBwriteBmpx);
4649 return(outsize);
4652 /****************************************************************************
4653 Reply to a SMBwritebs (write block multiplex secondary) request.
4654 ****************************************************************************/
4656 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4658 size_t numtowrite;
4659 ssize_t nwritten = -1;
4660 int outsize = 0;
4661 SMB_OFF_T startpos;
4662 size_t tcount;
4663 BOOL write_through;
4664 int smb_doff;
4665 char *data;
4666 write_bmpx_struct *wbms;
4667 BOOL send_response = False;
4668 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4669 START_PROFILE(SMBwriteBs);
4671 CHECK_FSP(fsp,conn);
4672 CHECK_WRITE(fsp);
4674 tcount = SVAL(inbuf,smb_vwv1);
4675 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4676 numtowrite = SVAL(inbuf,smb_vwv6);
4677 smb_doff = SVAL(inbuf,smb_vwv7);
4679 data = smb_base(inbuf) + smb_doff;
4681 /* We need to send an SMBwriteC response, not an SMBwritebs */
4682 SCVAL(outbuf,smb_com,SMBwritec);
4684 /* This fd should have an auxiliary struct attached,
4685 check that it does */
4686 wbms = fsp->wbmpx_ptr;
4687 if(!wbms) {
4688 END_PROFILE(SMBwriteBs);
4689 return(-1);
4692 /* If write through is set we can return errors, else we must cache them */
4693 write_through = wbms->wr_mode;
4695 /* Check for an earlier error */
4696 if(wbms->wr_discard) {
4697 END_PROFILE(SMBwriteBs);
4698 return -1; /* Just discard the packet */
4701 nwritten = write_file(fsp,data,startpos,numtowrite);
4703 if(lp_syncalways(SNUM(conn)) || write_through)
4704 sync_file(conn,fsp);
4706 if (nwritten < (ssize_t)numtowrite) {
4707 if(write_through) {
4708 /* We are returning an error - we can delete the aux struct */
4709 if (wbms)
4710 free((char *)wbms);
4711 fsp->wbmpx_ptr = NULL;
4712 END_PROFILE(SMBwriteBs);
4713 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4715 END_PROFILE(SMBwriteBs);
4716 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4719 /* Increment the total written, if this matches tcount
4720 we can discard the auxiliary struct (hurrah !) and return a writeC */
4721 wbms->wr_total_written += nwritten;
4722 if(wbms->wr_total_written >= tcount) {
4723 if (write_through) {
4724 outsize = set_message(outbuf,1,0,True);
4725 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4726 send_response = True;
4729 free((char *)wbms);
4730 fsp->wbmpx_ptr = NULL;
4733 if(send_response) {
4734 END_PROFILE(SMBwriteBs);
4735 return(outsize);
4738 END_PROFILE(SMBwriteBs);
4739 return(-1);
4742 /****************************************************************************
4743 Reply to a SMBgetattrE.
4744 ****************************************************************************/
4746 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4748 SMB_STRUCT_STAT sbuf;
4749 int outsize = 0;
4750 int mode;
4751 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4752 START_PROFILE(SMBgetattrE);
4754 outsize = set_message(outbuf,11,0,True);
4756 if(!fsp || (fsp->conn != conn)) {
4757 END_PROFILE(SMBgetattrE);
4758 return ERROR_DOS(ERRDOS,ERRbadfid);
4761 /* Do an fstat on this file */
4762 if(fsp_stat(fsp, &sbuf)) {
4763 END_PROFILE(SMBgetattrE);
4764 return(UNIXERROR(ERRDOS,ERRnoaccess));
4767 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4770 * Convert the times into dos times. Set create
4771 * date to be last modify date as UNIX doesn't save
4772 * this.
4775 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4776 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4777 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4779 if (mode & aDIR) {
4780 SIVAL(outbuf,smb_vwv6,0);
4781 SIVAL(outbuf,smb_vwv8,0);
4782 } else {
4783 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4784 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4785 SIVAL(outbuf,smb_vwv8,allocation_size);
4787 SSVAL(outbuf,smb_vwv10, mode);
4789 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4791 END_PROFILE(SMBgetattrE);
4792 return(outsize);