Volker's fix for bug #668. Change the \n after the password prompt to go
[Samba/gbeck.git] / source / smbd / reply.c
blob011186ba89caf0b1309650a5da8fe858ae5ed404
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 int numentries = 0;
673 BOOL finished = False;
674 int maxentries;
675 int i;
676 char *p;
677 BOOL ok = False;
678 int status_len;
679 pstring path;
680 char status[21];
681 int dptr_num= -1;
682 BOOL check_descend = False;
683 BOOL expect_close = False;
684 BOOL can_open = True;
685 BOOL bad_path = False;
686 NTSTATUS nt_status;
687 START_PROFILE(SMBsearch);
689 *mask = *directory = *fname = 0;
691 /* If we were called as SMBffirst then we must expect close. */
692 if(CVAL(inbuf,smb_com) == SMBffirst)
693 expect_close = True;
695 outsize = set_message(outbuf,1,3,True);
696 maxentries = SVAL(inbuf,smb_vwv0);
697 dirtype = SVAL(inbuf,smb_vwv1);
698 p = smb_buf(inbuf) + 1;
699 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status);
700 if (!NT_STATUS_IS_OK(nt_status)) {
701 END_PROFILE(SMBsearch);
702 return ERROR_NT(nt_status);
704 p++;
705 status_len = SVAL(p, 0);
706 p += 2;
708 /* dirtype &= ~aDIR; */
710 if (status_len == 0) {
711 SMB_STRUCT_STAT sbuf;
712 pstring dir2;
714 pstrcpy(directory,path);
715 pstrcpy(dir2,path);
716 unix_convert(directory,conn,0,&bad_path,&sbuf);
717 unix_format(dir2);
719 if (!check_name(directory,conn))
720 can_open = False;
722 p = strrchr_m(dir2,'/');
723 if (p == NULL) {
724 pstrcpy(mask,dir2);
725 *dir2 = 0;
726 } else {
727 *p = 0;
728 pstrcpy(mask,p+1);
731 p = strrchr_m(directory,'/');
732 if (!p)
733 *directory = 0;
734 else
735 *p = 0;
737 if (strlen(directory) == 0)
738 pstrcpy(directory,".");
739 memset((char *)status,'\0',21);
740 SCVAL(status,0,(dirtype & 0x1F));
741 } else {
742 int status_dirtype;
744 memcpy(status,p,21);
745 status_dirtype = CVAL(status,0) & 0x1F;
746 if (status_dirtype != (dirtype & 0x1F))
747 dirtype = status_dirtype;
749 conn->dirptr = dptr_fetch(status+12,&dptr_num);
750 if (!conn->dirptr)
751 goto SearchEmpty;
752 string_set(&conn->dirpath,dptr_path(dptr_num));
753 pstrcpy(mask, dptr_wcard(dptr_num));
756 if (can_open) {
757 p = smb_buf(outbuf) + 3;
758 ok = True;
760 if (status_len == 0) {
761 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
762 if (dptr_num < 0) {
763 if(dptr_num == -2) {
764 END_PROFILE(SMBsearch);
765 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
767 END_PROFILE(SMBsearch);
768 return ERROR_DOS(ERRDOS,ERRnofids);
770 dptr_set_wcard(dptr_num, strdup(mask));
771 dptr_set_attr(dptr_num, dirtype);
772 } else {
773 dirtype = dptr_attr(dptr_num);
776 DEBUG(4,("dptr_num is %d\n",dptr_num));
778 if (ok) {
779 if ((dirtype&0x1F) == aVOLID) {
780 memcpy(p,status,21);
781 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
782 dptr_fill(p+12,dptr_num);
783 if (dptr_zero(p+12) && (status_len==0))
784 numentries = 1;
785 else
786 numentries = 0;
787 p += DIR_STRUCT_SIZE;
788 } else {
789 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
790 conn->dirpath,lp_dontdescend(SNUM(conn))));
791 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
792 check_descend = True;
794 for (i=numentries;(i<maxentries) && !finished;i++) {
795 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
796 if (!finished) {
797 memcpy(p,status,21);
798 make_dir_struct(p,mask,fname,size,mode,date);
799 dptr_fill(p+12,dptr_num);
800 numentries++;
802 p += DIR_STRUCT_SIZE;
805 } /* if (ok ) */
809 SearchEmpty:
811 /* If we were called as SMBffirst with smb_search_id == NULL
812 and no entries were found then return error and close dirptr
813 (X/Open spec) */
815 if(ok && expect_close && numentries == 0 && status_len == 0) {
816 if (Protocol < PROTOCOL_NT1) {
817 SCVAL(outbuf,smb_rcls,ERRDOS);
818 SSVAL(outbuf,smb_err,ERRnofiles);
820 /* Also close the dptr - we know it's gone */
821 dptr_close(&dptr_num);
822 } else if (numentries == 0 || !ok) {
823 if (Protocol < PROTOCOL_NT1) {
824 SCVAL(outbuf,smb_rcls,ERRDOS);
825 SSVAL(outbuf,smb_err,ERRnofiles);
827 dptr_close(&dptr_num);
830 /* If we were called as SMBfunique, then we can close the dirptr now ! */
831 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
832 dptr_close(&dptr_num);
834 SSVAL(outbuf,smb_vwv0,numentries);
835 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
836 SCVAL(smb_buf(outbuf),0,5);
837 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
839 if (Protocol >= PROTOCOL_NT1)
840 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
842 outsize += DIR_STRUCT_SIZE*numentries;
843 smb_setlen(outbuf,outsize - 4);
845 if ((! *directory) && dptr_path(dptr_num))
846 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
848 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
849 smb_fn_name(CVAL(inbuf,smb_com)),
850 mask, directory, dirtype, numentries, maxentries ) );
852 END_PROFILE(SMBsearch);
853 return(outsize);
856 /****************************************************************************
857 Reply to a fclose (stop directory search).
858 ****************************************************************************/
860 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
862 int outsize = 0;
863 int status_len;
864 pstring path;
865 char status[21];
866 int dptr_num= -2;
867 char *p;
868 NTSTATUS err;
870 START_PROFILE(SMBfclose);
872 outsize = set_message(outbuf,1,0,True);
873 p = smb_buf(inbuf) + 1;
874 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err);
875 if (!NT_STATUS_IS_OK(err)) {
876 END_PROFILE(SMBfclose);
877 return ERROR_NT(err);
879 p++;
880 status_len = SVAL(p,0);
881 p += 2;
883 if (status_len == 0) {
884 END_PROFILE(SMBfclose);
885 return ERROR_DOS(ERRSRV,ERRsrverror);
888 memcpy(status,p,21);
890 if(dptr_fetch(status+12,&dptr_num)) {
891 /* Close the dptr - we know it's gone */
892 dptr_close(&dptr_num);
895 SSVAL(outbuf,smb_vwv0,0);
897 DEBUG(3,("search close\n"));
899 END_PROFILE(SMBfclose);
900 return(outsize);
903 /****************************************************************************
904 Reply to an open.
905 ****************************************************************************/
907 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
909 pstring fname;
910 int outsize = 0;
911 int fmode=0;
912 int share_mode;
913 SMB_OFF_T size = 0;
914 time_t mtime=0;
915 mode_t unixmode;
916 int rmode=0;
917 SMB_STRUCT_STAT sbuf;
918 BOOL bad_path = False;
919 files_struct *fsp;
920 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
921 NTSTATUS status;
922 START_PROFILE(SMBopen);
924 share_mode = SVAL(inbuf,smb_vwv0);
926 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
927 if (!NT_STATUS_IS_OK(status)) {
928 END_PROFILE(SMBopen);
929 return ERROR_NT(status);
932 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
934 unix_convert(fname,conn,0,&bad_path,&sbuf);
936 unixmode = unix_mode(conn,aARCH,fname);
938 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
939 unixmode, oplock_request,&rmode,NULL);
941 if (!fsp) {
942 END_PROFILE(SMBopen);
943 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
946 size = sbuf.st_size;
947 fmode = dos_mode(conn,fname,&sbuf);
948 mtime = sbuf.st_mtime;
950 if (fmode & aDIR) {
951 DEBUG(3,("attempt to open a directory %s\n",fname));
952 close_file(fsp,False);
953 END_PROFILE(SMBopen);
954 return ERROR_DOS(ERRDOS,ERRnoaccess);
957 outsize = set_message(outbuf,7,0,True);
958 SSVAL(outbuf,smb_vwv0,fsp->fnum);
959 SSVAL(outbuf,smb_vwv1,fmode);
960 if(lp_dos_filetime_resolution(SNUM(conn)) )
961 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
962 else
963 put_dos_date3(outbuf,smb_vwv2,mtime);
964 SIVAL(outbuf,smb_vwv4,(uint32)size);
965 SSVAL(outbuf,smb_vwv6,rmode);
967 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
968 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
970 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
971 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
972 END_PROFILE(SMBopen);
973 return(outsize);
976 /****************************************************************************
977 Reply to an open and X.
978 ****************************************************************************/
980 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
982 pstring fname;
983 int smb_mode = SVAL(inbuf,smb_vwv3);
984 int smb_attr = SVAL(inbuf,smb_vwv5);
985 /* Breakout the oplock request bits so we can set the
986 reply bits separately. */
987 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
988 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
989 BOOL oplock_request = ex_oplock_request | core_oplock_request;
990 #if 0
991 int open_flags = SVAL(inbuf,smb_vwv2);
992 int smb_sattr = SVAL(inbuf,smb_vwv4);
993 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
994 #endif
995 int smb_ofun = SVAL(inbuf,smb_vwv8);
996 mode_t unixmode;
997 SMB_OFF_T size=0;
998 int fmode=0,mtime=0,rmode=0;
999 SMB_STRUCT_STAT sbuf;
1000 int smb_action = 0;
1001 BOOL bad_path = False;
1002 files_struct *fsp;
1003 NTSTATUS status;
1004 START_PROFILE(SMBopenX);
1006 /* If it's an IPC, pass off the pipe handler. */
1007 if (IS_IPC(conn)) {
1008 if (lp_nt_pipe_support()) {
1009 END_PROFILE(SMBopenX);
1010 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1011 } else {
1012 END_PROFILE(SMBopenX);
1013 return ERROR_DOS(ERRSRV,ERRaccess);
1017 /* XXXX we need to handle passed times, sattr and flags */
1018 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 END_PROFILE(SMBopenX);
1021 return ERROR_NT(status);
1024 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1026 unix_convert(fname,conn,0,&bad_path,&sbuf);
1028 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1030 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1031 oplock_request, &rmode,&smb_action);
1033 if (!fsp) {
1034 END_PROFILE(SMBopenX);
1035 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1038 size = sbuf.st_size;
1039 fmode = dos_mode(conn,fname,&sbuf);
1040 mtime = sbuf.st_mtime;
1041 if (fmode & aDIR) {
1042 close_file(fsp,False);
1043 END_PROFILE(SMBopenX);
1044 return ERROR_DOS(ERRDOS,ERRnoaccess);
1047 /* If the caller set the extended oplock request bit
1048 and we granted one (by whatever means) - set the
1049 correct bit for extended oplock reply.
1052 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1053 smb_action |= EXTENDED_OPLOCK_GRANTED;
1055 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1058 /* If the caller set the core oplock request bit
1059 and we granted one (by whatever means) - set the
1060 correct bit for core oplock reply.
1063 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1064 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1066 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1067 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1069 set_message(outbuf,15,0,True);
1070 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1071 SSVAL(outbuf,smb_vwv3,fmode);
1072 if(lp_dos_filetime_resolution(SNUM(conn)) )
1073 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1074 else
1075 put_dos_date3(outbuf,smb_vwv4,mtime);
1076 SIVAL(outbuf,smb_vwv6,(uint32)size);
1077 SSVAL(outbuf,smb_vwv8,rmode);
1078 SSVAL(outbuf,smb_vwv11,smb_action);
1080 END_PROFILE(SMBopenX);
1081 return chain_reply(inbuf,outbuf,length,bufsize);
1084 /****************************************************************************
1085 Reply to a SMBulogoffX.
1086 ****************************************************************************/
1088 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1090 uint16 vuid = SVAL(inbuf,smb_uid);
1091 user_struct *vuser = get_valid_user_struct(vuid);
1092 START_PROFILE(SMBulogoffX);
1094 if(vuser == 0)
1095 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1097 /* in user level security we are supposed to close any files
1098 open by this user */
1099 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1100 file_close_user(vuid);
1102 invalidate_vuid(vuid);
1104 set_message(outbuf,2,0,True);
1106 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1108 END_PROFILE(SMBulogoffX);
1109 return chain_reply(inbuf,outbuf,length,bufsize);
1112 /****************************************************************************
1113 Reply to a mknew or a create.
1114 ****************************************************************************/
1116 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1118 pstring fname;
1119 int com;
1120 int outsize = 0;
1121 int createmode;
1122 mode_t unixmode;
1123 int ofun = 0;
1124 BOOL bad_path = False;
1125 files_struct *fsp;
1126 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1127 SMB_STRUCT_STAT sbuf;
1128 NTSTATUS status;
1129 START_PROFILE(SMBcreate);
1131 com = SVAL(inbuf,smb_com);
1133 createmode = SVAL(inbuf,smb_vwv0);
1134 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 END_PROFILE(SMBcreate);
1137 return ERROR_NT(status);
1140 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1142 unix_convert(fname,conn,0,&bad_path,&sbuf);
1144 if (createmode & aVOLID)
1145 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1147 unixmode = unix_mode(conn,createmode,fname);
1149 if(com == SMBmknew) {
1150 /* We should fail if file exists. */
1151 ofun = FILE_CREATE_IF_NOT_EXIST;
1152 } else {
1153 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1154 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1157 /* Open file in dos compatibility share mode. */
1158 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1159 ofun, unixmode, oplock_request, NULL, NULL);
1161 if (!fsp) {
1162 END_PROFILE(SMBcreate);
1163 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1166 outsize = set_message(outbuf,1,0,True);
1167 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1169 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1170 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1172 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1173 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1175 DEBUG( 2, ( "new file %s\n", fname ) );
1176 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1178 END_PROFILE(SMBcreate);
1179 return(outsize);
1182 /****************************************************************************
1183 Reply to a create temporary file.
1184 ****************************************************************************/
1186 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1188 pstring fname;
1189 int outsize = 0;
1190 int createmode;
1191 mode_t unixmode;
1192 BOOL bad_path = False;
1193 files_struct *fsp;
1194 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1195 int tmpfd;
1196 SMB_STRUCT_STAT sbuf;
1197 char *p, *s;
1198 NTSTATUS status;
1200 START_PROFILE(SMBctemp);
1202 createmode = SVAL(inbuf,smb_vwv0);
1203 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 END_PROFILE(SMBctemp);
1206 return ERROR_NT(status);
1208 pstrcat(fname,"\\TMXXXXXX");
1210 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1212 unix_convert(fname,conn,0,&bad_path,&sbuf);
1214 unixmode = unix_mode(conn,createmode,fname);
1216 tmpfd = smb_mkstemp(fname);
1217 if (tmpfd == -1) {
1218 END_PROFILE(SMBctemp);
1219 return(UNIXERROR(ERRDOS,ERRnoaccess));
1222 SMB_VFS_STAT(conn,fname,&sbuf);
1224 /* Open file in dos compatibility share mode. */
1225 /* We should fail if file does not exist. */
1226 fsp = open_file_shared(conn,fname,&sbuf,
1227 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1228 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1229 unixmode, oplock_request, NULL, NULL);
1231 /* close fd from smb_mkstemp() */
1232 close(tmpfd);
1234 if (!fsp) {
1235 END_PROFILE(SMBctemp);
1236 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1239 outsize = set_message(outbuf,1,0,True);
1240 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1242 /* the returned filename is relative to the directory */
1243 s = strrchr_m(fname, '/');
1244 if (!s)
1245 s = fname;
1246 else
1247 s++;
1249 p = smb_buf(outbuf);
1250 SSVALS(p, 0, -1); /* what is this? not in spec */
1251 SSVAL(p, 2, strlen(s));
1252 p += 4;
1253 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1254 outsize = set_message_end(outbuf, p);
1256 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1257 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1259 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1260 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1262 DEBUG( 2, ( "created temp file %s\n", fname ) );
1263 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1264 fname, fsp->fd, createmode, (int)unixmode ) );
1266 END_PROFILE(SMBctemp);
1267 return(outsize);
1270 /*******************************************************************
1271 Check if a user is allowed to rename a file.
1272 ********************************************************************/
1274 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1276 int smb_action;
1277 int access_mode;
1278 files_struct *fsp;
1280 if (!CAN_WRITE(conn))
1281 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1283 if (S_ISDIR(pst->st_mode))
1284 return NT_STATUS_OK;
1286 /* We need a better way to return NT status codes from open... */
1287 unix_ERR_class = 0;
1288 unix_ERR_code = 0;
1290 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1291 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1293 if (!fsp) {
1294 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1295 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1296 ret = NT_STATUS_SHARING_VIOLATION;
1297 unix_ERR_class = 0;
1298 unix_ERR_code = 0;
1299 unix_ERR_ntstatus = NT_STATUS_OK;
1300 return ret;
1302 close_file(fsp,False);
1303 return NT_STATUS_OK;
1306 /*******************************************************************
1307 Check if a user is allowed to delete a file.
1308 ********************************************************************/
1310 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1312 SMB_STRUCT_STAT sbuf;
1313 int fmode;
1314 int smb_action;
1315 int access_mode;
1316 files_struct *fsp;
1318 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1319 fname, dirtype ));
1321 if (!CAN_WRITE(conn))
1322 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1324 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1325 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1327 fmode = dos_mode(conn,fname,&sbuf);
1329 /* Can't delete a directory. */
1330 if (fmode & aDIR)
1331 return NT_STATUS_FILE_IS_A_DIRECTORY;
1332 #if 0 /* JRATEST */
1333 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1334 return NT_STATUS_OBJECT_NAME_INVALID;
1335 #endif /* JRATEST */
1337 if (!lp_delete_readonly(SNUM(conn))) {
1338 if (fmode & aRONLY)
1339 return NT_STATUS_CANNOT_DELETE;
1341 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1342 return NT_STATUS_NO_SUCH_FILE;
1344 /* We need a better way to return NT status codes from open... */
1345 unix_ERR_class = 0;
1346 unix_ERR_code = 0;
1348 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1349 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1351 if (!fsp) {
1352 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1353 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1354 ret = unix_ERR_ntstatus;
1355 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1356 ret = NT_STATUS_SHARING_VIOLATION;
1357 unix_ERR_class = 0;
1358 unix_ERR_code = 0;
1359 unix_ERR_ntstatus = NT_STATUS_OK;
1360 return ret;
1362 close_file(fsp,False);
1363 return NT_STATUS_OK;
1366 /****************************************************************************
1367 The guts of the unlink command, split out so it may be called by the NT SMB
1368 code.
1369 ****************************************************************************/
1371 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1373 pstring directory;
1374 pstring mask;
1375 char *p;
1376 int count=0;
1377 NTSTATUS error = NT_STATUS_OK;
1378 BOOL has_wild;
1379 BOOL bad_path = False;
1380 BOOL rc = True;
1381 SMB_STRUCT_STAT sbuf;
1383 *directory = *mask = 0;
1385 /* We must check for wildcards in the name given
1386 * directly by the client - before any unmangling.
1387 * This prevents an unmangling of a UNIX name containing
1388 * a DOS wildcard like '*' or '?' from unmangling into
1389 * a wildcard delete which was not intended.
1390 * FIX for #226. JRA.
1393 has_wild = ms_has_wild(name);
1395 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1397 p = strrchr_m(name,'/');
1398 if (!p) {
1399 pstrcpy(directory,".");
1400 pstrcpy(mask,name);
1401 } else {
1402 *p = 0;
1403 pstrcpy(directory,name);
1404 pstrcpy(mask,p+1);
1408 * We should only check the mangled cache
1409 * here if unix_convert failed. This means
1410 * that the path in 'mask' doesn't exist
1411 * on the file system and so we need to look
1412 * for a possible mangle. This patch from
1413 * Tine Smukavec <valentin.smukavec@hermes.si>.
1416 if (!rc && mangle_is_mangled(mask))
1417 mangle_check_cache( mask );
1419 if (!has_wild) {
1420 pstrcat(directory,"/");
1421 pstrcat(directory,mask);
1422 error = can_delete(directory,conn,dirtype);
1423 if (!NT_STATUS_IS_OK(error))
1424 return error;
1426 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1427 count++;
1429 } else {
1430 void *dirptr = NULL;
1431 const char *dname;
1433 if (check_name(directory,conn))
1434 dirptr = OpenDir(conn, directory, True);
1436 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1437 the pattern matches against the long name, otherwise the short name
1438 We don't implement this yet XXXX
1441 if (dirptr) {
1442 error = NT_STATUS_NO_SUCH_FILE;
1444 if (strequal(mask,"????????.???"))
1445 pstrcpy(mask,"*");
1447 while ((dname = ReadDirName(dirptr))) {
1448 pstring fname;
1449 pstrcpy(fname,dname);
1451 if(!mask_match(fname, mask, case_sensitive))
1452 continue;
1454 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1455 error = can_delete(fname,conn,dirtype);
1456 if (!NT_STATUS_IS_OK(error))
1457 continue;
1458 if (SMB_VFS_UNLINK(conn,fname) == 0)
1459 count++;
1460 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1462 CloseDir(dirptr);
1466 if (count == 0 && NT_STATUS_IS_OK(error)) {
1467 error = map_nt_error_from_unix(errno);
1470 return error;
1473 /****************************************************************************
1474 Reply to a unlink
1475 ****************************************************************************/
1477 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1478 int dum_buffsize)
1480 int outsize = 0;
1481 pstring name;
1482 int dirtype;
1483 NTSTATUS status;
1484 START_PROFILE(SMBunlink);
1486 dirtype = SVAL(inbuf,smb_vwv0);
1488 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 END_PROFILE(SMBunlink);
1491 return ERROR_NT(status);
1494 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1496 DEBUG(3,("reply_unlink : %s\n",name));
1498 status = unlink_internals(conn, dirtype, name);
1499 if (!NT_STATUS_IS_OK(status))
1500 return ERROR_NT(status);
1503 * Win2k needs a changenotify request response before it will
1504 * update after a rename..
1506 process_pending_change_notify_queue((time_t)0);
1508 outsize = set_message(outbuf,0,0,True);
1510 END_PROFILE(SMBunlink);
1511 return outsize;
1514 /****************************************************************************
1515 Fail for readbraw.
1516 ****************************************************************************/
1518 void fail_readraw(void)
1520 pstring errstr;
1521 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1522 strerror(errno) );
1523 exit_server(errstr);
1526 /****************************************************************************
1527 Use sendfile in readbraw.
1528 ****************************************************************************/
1530 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1531 ssize_t mincount, char *outbuf)
1533 ssize_t ret=0;
1535 #if defined(WITH_SENDFILE)
1537 * We can only use sendfile on a non-chained packet and on a file
1538 * that is exclusively oplocked. reply_readbraw has already checked the length.
1541 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1542 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1543 DATA_BLOB header;
1545 _smb_setlen(outbuf,nread);
1546 header.data = outbuf;
1547 header.length = 4;
1548 header.free = NULL;
1550 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1552 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1553 * return ENOSYS then pretend we just got a normal read.
1555 if (errno == ENOSYS)
1556 goto normal_read;
1558 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1559 fsp->fsp_name, strerror(errno) ));
1560 exit_server("send_file_readbraw sendfile failed");
1565 normal_read:
1566 #endif
1568 if (nread > 0) {
1569 ret = read_file(fsp,outbuf+4,startpos,nread);
1570 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1571 if (ret < mincount)
1572 ret = 0;
1573 #else
1574 if (ret < nread)
1575 ret = 0;
1576 #endif
1579 _smb_setlen(outbuf,ret);
1580 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1581 fail_readraw();
1584 /****************************************************************************
1585 Reply to a readbraw (core+ protocol).
1586 ****************************************************************************/
1588 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1590 extern struct current_user current_user;
1591 ssize_t maxcount,mincount;
1592 size_t nread = 0;
1593 SMB_OFF_T startpos;
1594 char *header = outbuf;
1595 files_struct *fsp;
1596 START_PROFILE(SMBreadbraw);
1598 if (srv_is_signing_active()) {
1599 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1603 * Special check if an oplock break has been issued
1604 * and the readraw request croses on the wire, we must
1605 * return a zero length response here.
1608 if(global_oplock_break) {
1609 _smb_setlen(header,0);
1610 if (write_data(smbd_server_fd(),header,4) != 4)
1611 fail_readraw();
1612 DEBUG(5,("readbraw - oplock break finished\n"));
1613 END_PROFILE(SMBreadbraw);
1614 return -1;
1617 fsp = file_fsp(inbuf,smb_vwv0);
1619 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1621 * fsp could be NULL here so use the value from the packet. JRA.
1623 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1624 _smb_setlen(header,0);
1625 if (write_data(smbd_server_fd(),header,4) != 4)
1626 fail_readraw();
1627 END_PROFILE(SMBreadbraw);
1628 return(-1);
1631 CHECK_FSP(fsp,conn);
1633 flush_write_cache(fsp, READRAW_FLUSH);
1635 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1636 if(CVAL(inbuf,smb_wct) == 10) {
1638 * This is a large offset (64 bit) read.
1640 #ifdef LARGE_SMB_OFF_T
1642 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1644 #else /* !LARGE_SMB_OFF_T */
1647 * Ensure we haven't been sent a >32 bit offset.
1650 if(IVAL(inbuf,smb_vwv8) != 0) {
1651 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1652 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1653 _smb_setlen(header,0);
1654 if (write_data(smbd_server_fd(),header,4) != 4)
1655 fail_readraw();
1656 END_PROFILE(SMBreadbraw);
1657 return(-1);
1660 #endif /* LARGE_SMB_OFF_T */
1662 if(startpos < 0) {
1663 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1664 _smb_setlen(header,0);
1665 if (write_data(smbd_server_fd(),header,4) != 4)
1666 fail_readraw();
1667 END_PROFILE(SMBreadbraw);
1668 return(-1);
1671 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1672 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1674 /* ensure we don't overrun the packet size */
1675 maxcount = MIN(65535,maxcount);
1677 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1678 SMB_OFF_T size = fsp->size;
1679 SMB_OFF_T sizeneeded = startpos + maxcount;
1681 if (size < sizeneeded) {
1682 SMB_STRUCT_STAT st;
1683 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1684 size = st.st_size;
1685 if (!fsp->can_write)
1686 fsp->size = size;
1689 if (startpos >= size)
1690 nread = 0;
1691 else
1692 nread = MIN(maxcount,(size - startpos));
1695 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1696 if (nread < mincount)
1697 nread = 0;
1698 #endif
1700 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1701 (int)maxcount, (int)mincount, (int)nread ) );
1703 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1705 DEBUG(5,("readbraw finished\n"));
1706 END_PROFILE(SMBreadbraw);
1707 return -1;
1710 /****************************************************************************
1711 Reply to a lockread (core+ protocol).
1712 ****************************************************************************/
1714 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1716 ssize_t nread = -1;
1717 char *data;
1718 int outsize = 0;
1719 SMB_OFF_T startpos;
1720 size_t numtoread;
1721 NTSTATUS status;
1722 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1723 BOOL my_lock_ctx = False;
1724 START_PROFILE(SMBlockread);
1726 CHECK_FSP(fsp,conn);
1727 CHECK_READ(fsp);
1729 release_level_2_oplocks_on_change(fsp);
1731 numtoread = SVAL(inbuf,smb_vwv1);
1732 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1734 outsize = set_message(outbuf,5,3,True);
1735 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1736 data = smb_buf(outbuf) + 3;
1739 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1740 * protocol request that predates the read/write lock concept.
1741 * Thus instead of asking for a read lock here we need to ask
1742 * for a write lock. JRA.
1743 * Note that the requested lock size is unaffected by max_recv.
1746 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1747 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1749 if (NT_STATUS_V(status)) {
1750 #if 0
1752 * We used to make lockread a blocking lock. It turns out
1753 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1754 * tester. JRA.
1757 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1759 * A blocking lock was requested. Package up
1760 * this smb into a queued request and push it
1761 * onto the blocking lock queue.
1763 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1764 (SMB_BIG_UINT)numtoread)) {
1765 END_PROFILE(SMBlockread);
1766 return -1;
1769 #endif
1770 END_PROFILE(SMBlockread);
1771 return ERROR_NT(status);
1775 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1778 if (numtoread > max_recv) {
1779 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1780 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1781 (unsigned int)numtoread, (unsigned int)max_recv ));
1782 numtoread = MIN(numtoread,max_recv);
1784 nread = read_file(fsp,data,startpos,numtoread);
1786 if (nread < 0) {
1787 END_PROFILE(SMBlockread);
1788 return(UNIXERROR(ERRDOS,ERRnoaccess));
1791 outsize += nread;
1792 SSVAL(outbuf,smb_vwv0,nread);
1793 SSVAL(outbuf,smb_vwv5,nread+3);
1794 SSVAL(smb_buf(outbuf),1,nread);
1796 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1797 fsp->fnum, (int)numtoread, (int)nread));
1799 END_PROFILE(SMBlockread);
1800 return(outsize);
1803 /****************************************************************************
1804 Reply to a read.
1805 ****************************************************************************/
1807 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1809 size_t numtoread;
1810 ssize_t nread = 0;
1811 char *data;
1812 SMB_OFF_T startpos;
1813 int outsize = 0;
1814 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1815 START_PROFILE(SMBread);
1817 CHECK_FSP(fsp,conn);
1818 CHECK_READ(fsp);
1820 numtoread = SVAL(inbuf,smb_vwv1);
1821 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1823 outsize = set_message(outbuf,5,3,True);
1824 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1826 * The requested read size cannot be greater than max_recv. JRA.
1828 if (numtoread > max_recv) {
1829 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1830 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1831 (unsigned int)numtoread, (unsigned int)max_recv ));
1832 numtoread = MIN(numtoread,max_recv);
1835 data = smb_buf(outbuf) + 3;
1837 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1838 END_PROFILE(SMBread);
1839 return ERROR_DOS(ERRDOS,ERRlock);
1842 if (numtoread > 0)
1843 nread = read_file(fsp,data,startpos,numtoread);
1845 if (nread < 0) {
1846 END_PROFILE(SMBread);
1847 return(UNIXERROR(ERRDOS,ERRnoaccess));
1850 outsize += nread;
1851 SSVAL(outbuf,smb_vwv0,nread);
1852 SSVAL(outbuf,smb_vwv5,nread+3);
1853 SCVAL(smb_buf(outbuf),0,1);
1854 SSVAL(smb_buf(outbuf),1,nread);
1856 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1857 fsp->fnum, (int)numtoread, (int)nread ) );
1859 END_PROFILE(SMBread);
1860 return(outsize);
1863 /****************************************************************************
1864 Reply to a read and X - possibly using sendfile.
1865 ****************************************************************************/
1867 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1868 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1870 ssize_t nread = -1;
1871 char *data = smb_buf(outbuf);
1873 #if defined(WITH_SENDFILE)
1875 * We can only use sendfile on a non-chained packet and on a file
1876 * that is exclusively oplocked.
1879 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1880 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1881 SMB_STRUCT_STAT sbuf;
1882 DATA_BLOB header;
1884 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1885 return(UNIXERROR(ERRDOS,ERRnoaccess));
1887 if (startpos > sbuf.st_size)
1888 goto normal_read;
1890 if (smb_maxcnt > (sbuf.st_size - startpos))
1891 smb_maxcnt = (sbuf.st_size - startpos);
1893 if (smb_maxcnt == 0)
1894 goto normal_read;
1897 * Set up the packet header before send. We
1898 * assume here the sendfile will work (get the
1899 * correct amount of data).
1902 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1903 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1904 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1905 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1906 SCVAL(outbuf,smb_vwv0,0xFF);
1907 set_message(outbuf,12,smb_maxcnt,False);
1908 header.data = outbuf;
1909 header.length = data - outbuf;
1910 header.free = NULL;
1912 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1914 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1915 * return ENOSYS then pretend we just got a normal read.
1917 if (errno == ENOSYS)
1918 goto normal_read;
1920 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1921 fsp->fsp_name, strerror(errno) ));
1922 exit_server("send_file_readX sendfile failed");
1925 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1926 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1927 return -1;
1930 normal_read:
1932 #endif
1934 nread = read_file(fsp,data,startpos,smb_maxcnt);
1936 if (nread < 0) {
1937 END_PROFILE(SMBreadX);
1938 return(UNIXERROR(ERRDOS,ERRnoaccess));
1941 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1942 SSVAL(outbuf,smb_vwv5,nread);
1943 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1944 SSVAL(smb_buf(outbuf),-2,nread);
1946 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1947 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1949 return nread;
1952 /****************************************************************************
1953 Reply to a read and X.
1954 ****************************************************************************/
1956 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1958 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1959 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1960 ssize_t nread = -1;
1961 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1962 #if 0
1963 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1964 #endif
1966 START_PROFILE(SMBreadX);
1968 /* If it's an IPC, pass off the pipe handler. */
1969 if (IS_IPC(conn)) {
1970 END_PROFILE(SMBreadX);
1971 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1974 CHECK_FSP(fsp,conn);
1975 CHECK_READ(fsp);
1977 set_message(outbuf,12,0,True);
1979 if(CVAL(inbuf,smb_wct) == 12) {
1980 #ifdef LARGE_SMB_OFF_T
1982 * This is a large offset (64 bit) read.
1984 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1986 #else /* !LARGE_SMB_OFF_T */
1989 * Ensure we haven't been sent a >32 bit offset.
1992 if(IVAL(inbuf,smb_vwv10) != 0) {
1993 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1994 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1995 END_PROFILE(SMBreadX);
1996 return ERROR_DOS(ERRDOS,ERRbadaccess);
1999 #endif /* LARGE_SMB_OFF_T */
2003 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2004 END_PROFILE(SMBreadX);
2005 return ERROR_DOS(ERRDOS,ERRlock);
2008 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2009 if (nread != -1)
2010 nread = chain_reply(inbuf,outbuf,length,bufsize);
2012 END_PROFILE(SMBreadX);
2013 return nread;
2016 /****************************************************************************
2017 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2018 ****************************************************************************/
2020 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2022 ssize_t nwritten=0;
2023 ssize_t total_written=0;
2024 size_t numtowrite=0;
2025 size_t tcount;
2026 SMB_OFF_T startpos;
2027 char *data=NULL;
2028 BOOL write_through;
2029 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2030 int outsize = 0;
2031 START_PROFILE(SMBwritebraw);
2033 if (srv_is_signing_active()) {
2034 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2037 CHECK_FSP(fsp,conn);
2038 CHECK_WRITE(fsp);
2040 tcount = IVAL(inbuf,smb_vwv1);
2041 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2042 write_through = BITSETW(inbuf+smb_vwv7,0);
2044 /* We have to deal with slightly different formats depending
2045 on whether we are using the core+ or lanman1.0 protocol */
2047 if(Protocol <= PROTOCOL_COREPLUS) {
2048 numtowrite = SVAL(smb_buf(inbuf),-2);
2049 data = smb_buf(inbuf);
2050 } else {
2051 numtowrite = SVAL(inbuf,smb_vwv10);
2052 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2055 /* force the error type */
2056 SCVAL(inbuf,smb_com,SMBwritec);
2057 SCVAL(outbuf,smb_com,SMBwritec);
2059 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2060 END_PROFILE(SMBwritebraw);
2061 return(ERROR_DOS(ERRDOS,ERRlock));
2064 if (numtowrite>0)
2065 nwritten = write_file(fsp,data,startpos,numtowrite);
2067 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2068 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2070 if (nwritten < (ssize_t)numtowrite) {
2071 END_PROFILE(SMBwritebraw);
2072 return(UNIXERROR(ERRHRD,ERRdiskfull));
2075 total_written = nwritten;
2077 /* Return a message to the redirector to tell it to send more bytes */
2078 SCVAL(outbuf,smb_com,SMBwritebraw);
2079 SSVALS(outbuf,smb_vwv0,-1);
2080 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2081 if (!send_smb(smbd_server_fd(),outbuf))
2082 exit_server("reply_writebraw: send_smb failed.");
2084 /* Now read the raw data into the buffer and write it */
2085 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2086 exit_server("secondary writebraw failed");
2089 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2090 numtowrite = smb_len(inbuf);
2092 /* Set up outbuf to return the correct return */
2093 outsize = set_message(outbuf,1,0,True);
2094 SCVAL(outbuf,smb_com,SMBwritec);
2095 SSVAL(outbuf,smb_vwv0,total_written);
2097 if (numtowrite != 0) {
2099 if (numtowrite > BUFFER_SIZE) {
2100 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2101 (unsigned int)numtowrite ));
2102 exit_server("secondary writebraw failed");
2105 if (tcount > nwritten+numtowrite) {
2106 DEBUG(3,("Client overestimated the write %d %d %d\n",
2107 (int)tcount,(int)nwritten,(int)numtowrite));
2110 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2111 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2112 strerror(errno) ));
2113 exit_server("secondary writebraw failed");
2116 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2118 if (nwritten < (ssize_t)numtowrite) {
2119 SCVAL(outbuf,smb_rcls,ERRHRD);
2120 SSVAL(outbuf,smb_err,ERRdiskfull);
2123 if (nwritten > 0)
2124 total_written += nwritten;
2127 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2128 sync_file(conn,fsp);
2130 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2131 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2133 /* we won't return a status if write through is not selected - this follows what WfWg does */
2134 END_PROFILE(SMBwritebraw);
2135 if (!write_through && total_written==tcount) {
2137 #if RABBIT_PELLET_FIX
2139 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2140 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2142 if (!send_keepalive(smbd_server_fd()))
2143 exit_server("reply_writebraw: send of keepalive failed");
2144 #endif
2145 return(-1);
2148 return(outsize);
2151 /****************************************************************************
2152 Reply to a writeunlock (core+).
2153 ****************************************************************************/
2155 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2156 int size, int dum_buffsize)
2158 ssize_t nwritten = -1;
2159 size_t numtowrite;
2160 SMB_OFF_T startpos;
2161 char *data;
2162 NTSTATUS status = NT_STATUS_OK;
2163 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2164 int outsize = 0;
2165 START_PROFILE(SMBwriteunlock);
2167 CHECK_FSP(fsp,conn);
2168 CHECK_WRITE(fsp);
2170 numtowrite = SVAL(inbuf,smb_vwv1);
2171 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2172 data = smb_buf(inbuf) + 3;
2174 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2175 WRITE_LOCK,False)) {
2176 END_PROFILE(SMBwriteunlock);
2177 return ERROR_DOS(ERRDOS,ERRlock);
2180 /* The special X/Open SMB protocol handling of
2181 zero length writes is *NOT* done for
2182 this call */
2183 if(numtowrite == 0)
2184 nwritten = 0;
2185 else
2186 nwritten = write_file(fsp,data,startpos,numtowrite);
2188 if (lp_syncalways(SNUM(conn)))
2189 sync_file(conn,fsp);
2191 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2192 END_PROFILE(SMBwriteunlock);
2193 return(UNIXERROR(ERRHRD,ERRdiskfull));
2196 if (numtowrite) {
2197 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2198 (SMB_BIG_UINT)startpos);
2199 if (NT_STATUS_V(status)) {
2200 END_PROFILE(SMBwriteunlock);
2201 return ERROR_NT(status);
2205 outsize = set_message(outbuf,1,0,True);
2207 SSVAL(outbuf,smb_vwv0,nwritten);
2209 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2210 fsp->fnum, (int)numtowrite, (int)nwritten));
2212 END_PROFILE(SMBwriteunlock);
2213 return outsize;
2216 /****************************************************************************
2217 Reply to a write.
2218 ****************************************************************************/
2220 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2222 size_t numtowrite;
2223 ssize_t nwritten = -1;
2224 SMB_OFF_T startpos;
2225 char *data;
2226 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2227 int outsize = 0;
2228 START_PROFILE(SMBwrite);
2230 /* If it's an IPC, pass off the pipe handler. */
2231 if (IS_IPC(conn)) {
2232 END_PROFILE(SMBwrite);
2233 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2236 CHECK_FSP(fsp,conn);
2237 CHECK_WRITE(fsp);
2239 numtowrite = SVAL(inbuf,smb_vwv1);
2240 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2241 data = smb_buf(inbuf) + 3;
2243 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2244 END_PROFILE(SMBwrite);
2245 return ERROR_DOS(ERRDOS,ERRlock);
2249 * X/Open SMB protocol says that if smb_vwv1 is
2250 * zero then the file size should be extended or
2251 * truncated to the size given in smb_vwv[2-3].
2254 if(numtowrite == 0) {
2256 * This is actually an allocate call, and set EOF. JRA.
2258 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2259 if (nwritten < 0) {
2260 END_PROFILE(SMBwrite);
2261 return ERROR_NT(NT_STATUS_DISK_FULL);
2263 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2264 if (nwritten < 0) {
2265 END_PROFILE(SMBwrite);
2266 return ERROR_NT(NT_STATUS_DISK_FULL);
2268 } else
2269 nwritten = write_file(fsp,data,startpos,numtowrite);
2271 if (lp_syncalways(SNUM(conn)))
2272 sync_file(conn,fsp);
2274 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2275 END_PROFILE(SMBwrite);
2276 return(UNIXERROR(ERRHRD,ERRdiskfull));
2279 outsize = set_message(outbuf,1,0,True);
2281 SSVAL(outbuf,smb_vwv0,nwritten);
2283 if (nwritten < (ssize_t)numtowrite) {
2284 SCVAL(outbuf,smb_rcls,ERRHRD);
2285 SSVAL(outbuf,smb_err,ERRdiskfull);
2288 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2290 END_PROFILE(SMBwrite);
2291 return(outsize);
2294 /****************************************************************************
2295 Reply to a write and X.
2296 ****************************************************************************/
2298 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2300 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2301 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2302 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2303 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2304 ssize_t nwritten = -1;
2305 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2306 unsigned int smblen = smb_len(inbuf);
2307 char *data;
2308 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2309 START_PROFILE(SMBwriteX);
2311 /* If it's an IPC, pass off the pipe handler. */
2312 if (IS_IPC(conn)) {
2313 END_PROFILE(SMBwriteX);
2314 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2317 CHECK_FSP(fsp,conn);
2318 CHECK_WRITE(fsp);
2320 /* Deal with possible LARGE_WRITEX */
2321 if (large_writeX)
2322 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2324 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2325 END_PROFILE(SMBwriteX);
2326 return ERROR_DOS(ERRDOS,ERRbadmem);
2329 data = smb_base(inbuf) + smb_doff;
2331 if(CVAL(inbuf,smb_wct) == 14) {
2332 #ifdef LARGE_SMB_OFF_T
2334 * This is a large offset (64 bit) write.
2336 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2338 #else /* !LARGE_SMB_OFF_T */
2341 * Ensure we haven't been sent a >32 bit offset.
2344 if(IVAL(inbuf,smb_vwv12) != 0) {
2345 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2346 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2347 END_PROFILE(SMBwriteX);
2348 return ERROR_DOS(ERRDOS,ERRbadaccess);
2351 #endif /* LARGE_SMB_OFF_T */
2354 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2355 END_PROFILE(SMBwriteX);
2356 return ERROR_DOS(ERRDOS,ERRlock);
2359 /* X/Open SMB protocol says that, unlike SMBwrite
2360 if the length is zero then NO truncation is
2361 done, just a write of zero. To truncate a file,
2362 use SMBwrite. */
2364 if(numtowrite == 0)
2365 nwritten = 0;
2366 else
2367 nwritten = write_file(fsp,data,startpos,numtowrite);
2369 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2370 END_PROFILE(SMBwriteX);
2371 return(UNIXERROR(ERRHRD,ERRdiskfull));
2374 set_message(outbuf,6,0,True);
2376 SSVAL(outbuf,smb_vwv2,nwritten);
2377 if (large_writeX)
2378 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2380 if (nwritten < (ssize_t)numtowrite) {
2381 SCVAL(outbuf,smb_rcls,ERRHRD);
2382 SSVAL(outbuf,smb_err,ERRdiskfull);
2385 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2386 fsp->fnum, (int)numtowrite, (int)nwritten));
2388 if (lp_syncalways(SNUM(conn)) || write_through)
2389 sync_file(conn,fsp);
2391 END_PROFILE(SMBwriteX);
2392 return chain_reply(inbuf,outbuf,length,bufsize);
2395 /****************************************************************************
2396 Reply to a lseek.
2397 ****************************************************************************/
2399 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2401 SMB_OFF_T startpos;
2402 SMB_OFF_T res= -1;
2403 int mode,umode;
2404 int outsize = 0;
2405 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2406 START_PROFILE(SMBlseek);
2408 CHECK_FSP(fsp,conn);
2410 flush_write_cache(fsp, SEEK_FLUSH);
2412 mode = SVAL(inbuf,smb_vwv1) & 3;
2413 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2414 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2416 switch (mode) {
2417 case 0:
2418 umode = SEEK_SET;
2419 res = startpos;
2420 break;
2421 case 1:
2422 umode = SEEK_CUR;
2423 res = fsp->pos + startpos;
2424 break;
2425 case 2:
2426 umode = SEEK_END;
2427 break;
2428 default:
2429 umode = SEEK_SET;
2430 res = startpos;
2431 break;
2434 if (umode == SEEK_END) {
2435 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2436 if(errno == EINVAL) {
2437 SMB_OFF_T current_pos = startpos;
2438 SMB_STRUCT_STAT sbuf;
2440 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2441 END_PROFILE(SMBlseek);
2442 return(UNIXERROR(ERRDOS,ERRnoaccess));
2445 current_pos += sbuf.st_size;
2446 if(current_pos < 0)
2447 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2451 if(res == -1) {
2452 END_PROFILE(SMBlseek);
2453 return(UNIXERROR(ERRDOS,ERRnoaccess));
2457 fsp->pos = res;
2459 outsize = set_message(outbuf,2,0,True);
2460 SIVAL(outbuf,smb_vwv0,res);
2462 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2463 fsp->fnum, (double)startpos, (double)res, mode));
2465 END_PROFILE(SMBlseek);
2466 return(outsize);
2469 /****************************************************************************
2470 Reply to a flush.
2471 ****************************************************************************/
2473 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2475 int outsize = set_message(outbuf,0,0,True);
2476 uint16 fnum = SVAL(inbuf,smb_vwv0);
2477 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2478 START_PROFILE(SMBflush);
2480 if (fnum != 0xFFFF)
2481 CHECK_FSP(fsp,conn);
2483 if (!fsp) {
2484 file_sync_all(conn);
2485 } else {
2486 sync_file(conn,fsp);
2489 DEBUG(3,("flush\n"));
2490 END_PROFILE(SMBflush);
2491 return(outsize);
2494 /****************************************************************************
2495 Reply to a exit.
2496 ****************************************************************************/
2498 int reply_exit(connection_struct *conn,
2499 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2501 int outsize;
2502 START_PROFILE(SMBexit);
2504 file_close_pid(SVAL(inbuf,smb_pid));
2506 outsize = set_message(outbuf,0,0,True);
2508 DEBUG(3,("exit\n"));
2510 END_PROFILE(SMBexit);
2511 return(outsize);
2514 /****************************************************************************
2515 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2516 ****************************************************************************/
2518 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2519 int dum_buffsize)
2521 extern struct current_user current_user;
2522 int outsize = 0;
2523 time_t mtime;
2524 int32 eclass = 0, err = 0;
2525 files_struct *fsp = NULL;
2526 START_PROFILE(SMBclose);
2528 outsize = set_message(outbuf,0,0,True);
2530 /* If it's an IPC, pass off to the pipe handler. */
2531 if (IS_IPC(conn)) {
2532 END_PROFILE(SMBclose);
2533 return reply_pipe_close(conn, inbuf,outbuf);
2536 fsp = file_fsp(inbuf,smb_vwv0);
2539 * We can only use CHECK_FSP if we know it's not a directory.
2542 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2543 END_PROFILE(SMBclose);
2544 return ERROR_DOS(ERRDOS,ERRbadfid);
2547 if(fsp->is_directory) {
2549 * Special case - close NT SMB directory handle.
2551 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2552 close_file(fsp,True);
2553 } else {
2555 * Close ordinary file.
2557 int close_err;
2558 pstring file_name;
2560 /* Save the name for time set in close. */
2561 pstrcpy( file_name, fsp->fsp_name);
2563 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2564 fsp->fd, fsp->fnum,
2565 conn->num_files_open));
2568 * close_file() returns the unix errno if an error
2569 * was detected on close - normally this is due to
2570 * a disk full error. If not then it was probably an I/O error.
2573 if((close_err = close_file(fsp,True)) != 0) {
2574 errno = close_err;
2575 END_PROFILE(SMBclose);
2576 return (UNIXERROR(ERRHRD,ERRgeneral));
2580 * Now take care of any time sent in the close.
2583 mtime = make_unix_date3(inbuf+smb_vwv1);
2585 /* try and set the date */
2586 set_filetime(conn, file_name, mtime);
2590 /* We have a cached error */
2591 if(eclass || err) {
2592 END_PROFILE(SMBclose);
2593 return ERROR_DOS(eclass,err);
2596 END_PROFILE(SMBclose);
2597 return(outsize);
2600 /****************************************************************************
2601 Reply to a writeclose (Core+ protocol).
2602 ****************************************************************************/
2604 int reply_writeclose(connection_struct *conn,
2605 char *inbuf,char *outbuf, int size, int dum_buffsize)
2607 size_t numtowrite;
2608 ssize_t nwritten = -1;
2609 int outsize = 0;
2610 int close_err = 0;
2611 SMB_OFF_T startpos;
2612 char *data;
2613 time_t mtime;
2614 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2615 START_PROFILE(SMBwriteclose);
2617 CHECK_FSP(fsp,conn);
2618 CHECK_WRITE(fsp);
2620 numtowrite = SVAL(inbuf,smb_vwv1);
2621 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2622 mtime = make_unix_date3(inbuf+smb_vwv4);
2623 data = smb_buf(inbuf) + 1;
2625 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2626 END_PROFILE(SMBwriteclose);
2627 return ERROR_DOS(ERRDOS,ERRlock);
2630 nwritten = write_file(fsp,data,startpos,numtowrite);
2632 set_filetime(conn, fsp->fsp_name,mtime);
2635 * More insanity. W2K only closes the file if writelen > 0.
2636 * JRA.
2639 if (numtowrite) {
2640 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2641 fsp->fsp_name ));
2642 close_err = close_file(fsp,True);
2645 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2646 fsp->fnum, (int)numtowrite, (int)nwritten,
2647 conn->num_files_open));
2649 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2650 END_PROFILE(SMBwriteclose);
2651 return(UNIXERROR(ERRHRD,ERRdiskfull));
2654 if(close_err != 0) {
2655 errno = close_err;
2656 END_PROFILE(SMBwriteclose);
2657 return(UNIXERROR(ERRHRD,ERRgeneral));
2660 outsize = set_message(outbuf,1,0,True);
2662 SSVAL(outbuf,smb_vwv0,nwritten);
2663 END_PROFILE(SMBwriteclose);
2664 return(outsize);
2667 /****************************************************************************
2668 Reply to a lock.
2669 ****************************************************************************/
2671 int reply_lock(connection_struct *conn,
2672 char *inbuf,char *outbuf, int length, int dum_buffsize)
2674 int outsize = set_message(outbuf,0,0,True);
2675 SMB_BIG_UINT count,offset;
2676 NTSTATUS status;
2677 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2678 BOOL my_lock_ctx = False;
2680 START_PROFILE(SMBlock);
2682 CHECK_FSP(fsp,conn);
2684 release_level_2_oplocks_on_change(fsp);
2686 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2687 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2689 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2690 fsp->fd, fsp->fnum, (double)offset, (double)count));
2692 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2693 if (NT_STATUS_V(status)) {
2694 #if 0
2695 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2696 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2698 * A blocking lock was requested. Package up
2699 * this smb into a queued request and push it
2700 * onto the blocking lock queue.
2702 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2703 END_PROFILE(SMBlock);
2704 return -1;
2707 #endif
2708 END_PROFILE(SMBlock);
2709 return ERROR_NT(status);
2712 END_PROFILE(SMBlock);
2713 return(outsize);
2716 /****************************************************************************
2717 Reply to a unlock.
2718 ****************************************************************************/
2720 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2721 int dum_buffsize)
2723 int outsize = set_message(outbuf,0,0,True);
2724 SMB_BIG_UINT count,offset;
2725 NTSTATUS status;
2726 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2727 START_PROFILE(SMBunlock);
2729 CHECK_FSP(fsp,conn);
2731 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2732 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2734 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2735 if (NT_STATUS_V(status)) {
2736 END_PROFILE(SMBunlock);
2737 return ERROR_NT(status);
2740 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2741 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2743 END_PROFILE(SMBunlock);
2744 return(outsize);
2747 /****************************************************************************
2748 Reply to a tdis.
2749 ****************************************************************************/
2751 int reply_tdis(connection_struct *conn,
2752 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2754 int outsize = set_message(outbuf,0,0,True);
2755 uint16 vuid;
2756 START_PROFILE(SMBtdis);
2758 vuid = SVAL(inbuf,smb_uid);
2760 if (!conn) {
2761 DEBUG(4,("Invalid connection in tdis\n"));
2762 END_PROFILE(SMBtdis);
2763 return ERROR_DOS(ERRSRV,ERRinvnid);
2766 conn->used = False;
2768 close_cnum(conn,vuid);
2770 END_PROFILE(SMBtdis);
2771 return outsize;
2774 /****************************************************************************
2775 Reply to a echo.
2776 ****************************************************************************/
2778 int reply_echo(connection_struct *conn,
2779 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2781 int smb_reverb = SVAL(inbuf,smb_vwv0);
2782 int seq_num;
2783 unsigned int data_len = smb_buflen(inbuf);
2784 int outsize = set_message(outbuf,1,data_len,True);
2785 START_PROFILE(SMBecho);
2787 if (data_len > BUFFER_SIZE) {
2788 DEBUG(0,("reply_echo: data_len too large.\n"));
2789 END_PROFILE(SMBecho);
2790 return -1;
2793 /* copy any incoming data back out */
2794 if (data_len > 0)
2795 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2797 if (smb_reverb > 100) {
2798 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2799 smb_reverb = 100;
2802 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2803 SSVAL(outbuf,smb_vwv0,seq_num);
2805 smb_setlen(outbuf,outsize - 4);
2807 if (!send_smb(smbd_server_fd(),outbuf))
2808 exit_server("reply_echo: send_smb failed.");
2811 DEBUG(3,("echo %d times\n", smb_reverb));
2813 smb_echo_count++;
2815 END_PROFILE(SMBecho);
2816 return -1;
2819 /****************************************************************************
2820 Reply to a printopen.
2821 ****************************************************************************/
2823 int reply_printopen(connection_struct *conn,
2824 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2826 int outsize = 0;
2827 files_struct *fsp;
2828 START_PROFILE(SMBsplopen);
2830 if (!CAN_PRINT(conn)) {
2831 END_PROFILE(SMBsplopen);
2832 return ERROR_DOS(ERRDOS,ERRnoaccess);
2835 /* Open for exclusive use, write only. */
2836 fsp = print_fsp_open(conn, NULL);
2838 if (!fsp) {
2839 END_PROFILE(SMBsplopen);
2840 return(UNIXERROR(ERRDOS,ERRnoaccess));
2843 outsize = set_message(outbuf,1,0,True);
2844 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2846 DEBUG(3,("openprint fd=%d fnum=%d\n",
2847 fsp->fd, fsp->fnum));
2849 END_PROFILE(SMBsplopen);
2850 return(outsize);
2853 /****************************************************************************
2854 Reply to a printclose.
2855 ****************************************************************************/
2857 int reply_printclose(connection_struct *conn,
2858 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2860 int outsize = set_message(outbuf,0,0,True);
2861 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2862 int close_err = 0;
2863 START_PROFILE(SMBsplclose);
2865 CHECK_FSP(fsp,conn);
2867 if (!CAN_PRINT(conn)) {
2868 END_PROFILE(SMBsplclose);
2869 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2872 DEBUG(3,("printclose fd=%d fnum=%d\n",
2873 fsp->fd,fsp->fnum));
2875 close_err = close_file(fsp,True);
2877 if(close_err != 0) {
2878 errno = close_err;
2879 END_PROFILE(SMBsplclose);
2880 return(UNIXERROR(ERRHRD,ERRgeneral));
2883 END_PROFILE(SMBsplclose);
2884 return(outsize);
2887 /****************************************************************************
2888 Reply to a printqueue.
2889 ****************************************************************************/
2891 int reply_printqueue(connection_struct *conn,
2892 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2894 int outsize = set_message(outbuf,2,3,True);
2895 int max_count = SVAL(inbuf,smb_vwv0);
2896 int start_index = SVAL(inbuf,smb_vwv1);
2897 START_PROFILE(SMBsplretq);
2899 /* we used to allow the client to get the cnum wrong, but that
2900 is really quite gross and only worked when there was only
2901 one printer - I think we should now only accept it if they
2902 get it right (tridge) */
2903 if (!CAN_PRINT(conn)) {
2904 END_PROFILE(SMBsplretq);
2905 return ERROR_DOS(ERRDOS,ERRnoaccess);
2908 SSVAL(outbuf,smb_vwv0,0);
2909 SSVAL(outbuf,smb_vwv1,0);
2910 SCVAL(smb_buf(outbuf),0,1);
2911 SSVAL(smb_buf(outbuf),1,0);
2913 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2914 start_index, max_count));
2917 print_queue_struct *queue = NULL;
2918 print_status_struct status;
2919 char *p = smb_buf(outbuf) + 3;
2920 int count = print_queue_status(SNUM(conn), &queue, &status);
2921 int num_to_get = ABS(max_count);
2922 int first = (max_count>0?start_index:start_index+max_count+1);
2923 int i;
2925 if (first >= count)
2926 num_to_get = 0;
2927 else
2928 num_to_get = MIN(num_to_get,count-first);
2931 for (i=first;i<first+num_to_get;i++) {
2932 put_dos_date2(p,0,queue[i].time);
2933 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2934 SSVAL(p,5, queue[i].job);
2935 SIVAL(p,7,queue[i].size);
2936 SCVAL(p,11,0);
2937 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2938 p += 28;
2941 if (count > 0) {
2942 outsize = set_message(outbuf,2,28*count+3,False);
2943 SSVAL(outbuf,smb_vwv0,count);
2944 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2945 SCVAL(smb_buf(outbuf),0,1);
2946 SSVAL(smb_buf(outbuf),1,28*count);
2949 SAFE_FREE(queue);
2951 DEBUG(3,("%d entries returned in queue\n",count));
2954 END_PROFILE(SMBsplretq);
2955 return(outsize);
2958 /****************************************************************************
2959 Reply to a printwrite.
2960 ****************************************************************************/
2962 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2964 int numtowrite;
2965 int outsize = set_message(outbuf,0,0,True);
2966 char *data;
2967 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2969 START_PROFILE(SMBsplwr);
2971 if (!CAN_PRINT(conn)) {
2972 END_PROFILE(SMBsplwr);
2973 return ERROR_DOS(ERRDOS,ERRnoaccess);
2976 CHECK_FSP(fsp,conn);
2977 CHECK_WRITE(fsp);
2979 numtowrite = SVAL(smb_buf(inbuf),1);
2980 data = smb_buf(inbuf) + 3;
2982 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2983 END_PROFILE(SMBsplwr);
2984 return(UNIXERROR(ERRHRD,ERRdiskfull));
2987 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2989 END_PROFILE(SMBsplwr);
2990 return(outsize);
2993 /****************************************************************************
2994 The guts of the mkdir command, split out so it may be called by the NT SMB
2995 code.
2996 ****************************************************************************/
2998 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3000 BOOL bad_path = False;
3001 SMB_STRUCT_STAT sbuf;
3002 int ret= -1;
3004 unix_convert(directory,conn,0,&bad_path,&sbuf);
3006 if (ms_has_wild(directory)) {
3007 return NT_STATUS_OBJECT_NAME_INVALID;
3010 if (check_name(directory, conn))
3011 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3013 if (ret == -1) {
3014 NTSTATUS nterr = NT_STATUS_OK;
3015 if(errno == ENOENT) {
3016 unix_ERR_class = ERRDOS;
3017 if (bad_path) {
3018 unix_ERR_code = ERRbadpath;
3019 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
3020 } else {
3021 unix_ERR_code = ERRbadfile;
3022 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3025 if (!NT_STATUS_IS_OK(nterr))
3026 return nterr;
3027 return map_nt_error_from_unix(errno);
3030 return NT_STATUS_OK;
3033 /****************************************************************************
3034 Reply to a mkdir.
3035 ****************************************************************************/
3037 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3039 pstring directory;
3040 int outsize;
3041 NTSTATUS status;
3042 START_PROFILE(SMBmkdir);
3044 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3045 if (!NT_STATUS_IS_OK(status)) {
3046 END_PROFILE(SMBmkdir);
3047 return ERROR_NT(status);
3050 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3052 status = mkdir_internal(conn, directory);
3053 if (!NT_STATUS_IS_OK(status)) {
3054 END_PROFILE(SMBmkdir);
3055 return ERROR_NT(status);
3058 outsize = set_message(outbuf,0,0,True);
3060 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3062 END_PROFILE(SMBmkdir);
3063 return(outsize);
3066 /****************************************************************************
3067 Static function used by reply_rmdir to delete an entire directory
3068 tree recursively. Return False on ok, True on fail.
3069 ****************************************************************************/
3071 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3073 const char *dname = NULL;
3074 BOOL ret = False;
3075 void *dirptr = OpenDir(conn, directory, False);
3077 if(dirptr == NULL)
3078 return True;
3080 while((dname = ReadDirName(dirptr))) {
3081 pstring fullname;
3082 SMB_STRUCT_STAT st;
3084 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3085 continue;
3087 /* Construct the full name. */
3088 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3089 errno = ENOMEM;
3090 ret = True;
3091 break;
3094 pstrcpy(fullname, directory);
3095 pstrcat(fullname, "/");
3096 pstrcat(fullname, dname);
3098 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3099 ret = True;
3100 break;
3103 if(st.st_mode & S_IFDIR) {
3104 if(recursive_rmdir(conn, fullname)!=0) {
3105 ret = True;
3106 break;
3108 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3109 ret = True;
3110 break;
3112 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3113 ret = True;
3114 break;
3117 CloseDir(dirptr);
3118 return ret;
3121 /****************************************************************************
3122 The internals of the rmdir code - called elsewhere.
3123 ****************************************************************************/
3125 BOOL rmdir_internals(connection_struct *conn, char *directory)
3127 BOOL ok;
3129 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3130 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3132 * Check to see if the only thing in this directory are
3133 * vetoed files/directories. If so then delete them and
3134 * retry. If we fail to delete any of them (and we *don't*
3135 * do a recursive delete) then fail the rmdir.
3137 BOOL all_veto_files = True;
3138 const char *dname;
3139 void *dirptr = OpenDir(conn, directory, False);
3141 if(dirptr != NULL) {
3142 int dirpos = TellDir(dirptr);
3143 while ((dname = ReadDirName(dirptr))) {
3144 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3145 continue;
3146 if(!IS_VETO_PATH(conn, dname)) {
3147 all_veto_files = False;
3148 break;
3152 if(all_veto_files) {
3153 SeekDir(dirptr,dirpos);
3154 while ((dname = ReadDirName(dirptr))) {
3155 pstring fullname;
3156 SMB_STRUCT_STAT st;
3158 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3159 continue;
3161 /* Construct the full name. */
3162 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3163 errno = ENOMEM;
3164 break;
3167 pstrcpy(fullname, directory);
3168 pstrcat(fullname, "/");
3169 pstrcat(fullname, dname);
3171 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3172 break;
3173 if(st.st_mode & S_IFDIR) {
3174 if(lp_recursive_veto_delete(SNUM(conn))) {
3175 if(recursive_rmdir(conn, fullname) != 0)
3176 break;
3178 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3179 break;
3180 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3181 break;
3183 CloseDir(dirptr);
3184 /* Retry the rmdir */
3185 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3186 } else {
3187 CloseDir(dirptr);
3189 } else {
3190 errno = ENOTEMPTY;
3194 if (!ok)
3195 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3197 return ok;
3200 /****************************************************************************
3201 Reply to a rmdir.
3202 ****************************************************************************/
3204 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3206 pstring directory;
3207 int outsize = 0;
3208 BOOL ok = False;
3209 BOOL bad_path = False;
3210 SMB_STRUCT_STAT sbuf;
3211 NTSTATUS status;
3212 START_PROFILE(SMBrmdir);
3214 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3215 if (!NT_STATUS_IS_OK(status)) {
3216 END_PROFILE(SMBrmdir);
3217 return ERROR_NT(status);
3220 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3222 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3224 if (check_name(directory,conn)) {
3225 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3226 ok = rmdir_internals(conn, directory);
3229 if (!ok) {
3230 END_PROFILE(SMBrmdir);
3231 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3234 outsize = set_message(outbuf,0,0,True);
3236 DEBUG( 3, ( "rmdir %s\n", directory ) );
3238 END_PROFILE(SMBrmdir);
3239 return(outsize);
3242 /*******************************************************************
3243 Resolve wildcards in a filename rename.
3244 ********************************************************************/
3246 static BOOL resolve_wildcards(const char *name1, char *name2)
3248 fstring root1,root2;
3249 fstring ext1,ext2;
3250 char *p,*p2, *pname1, *pname2;
3251 int available_space;
3254 pname1 = strrchr_m(name1,'/');
3255 pname2 = strrchr_m(name2,'/');
3257 if (!pname1 || !pname2)
3258 return(False);
3260 fstrcpy(root1,pname1);
3261 fstrcpy(root2,pname2);
3262 p = strrchr_m(root1,'.');
3263 if (p) {
3264 *p = 0;
3265 fstrcpy(ext1,p+1);
3266 } else {
3267 fstrcpy(ext1,"");
3269 p = strrchr_m(root2,'.');
3270 if (p) {
3271 *p = 0;
3272 fstrcpy(ext2,p+1);
3273 } else {
3274 fstrcpy(ext2,"");
3277 p = root1;
3278 p2 = root2;
3279 while (*p2) {
3280 if (*p2 == '?') {
3281 *p2 = *p;
3282 p2++;
3283 } else {
3284 p2++;
3286 if (*p)
3287 p++;
3290 p = ext1;
3291 p2 = ext2;
3292 while (*p2) {
3293 if (*p2 == '?') {
3294 *p2 = *p;
3295 p2++;
3296 } else {
3297 p2++;
3299 if (*p)
3300 p++;
3303 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3305 if (ext2[0]) {
3306 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3307 } else {
3308 pstrcpy_base(pname2, root2, name2);
3311 return(True);
3314 /****************************************************************************
3315 Ensure open files have their names updates.
3316 ****************************************************************************/
3318 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3320 files_struct *fsp;
3321 BOOL did_rename = False;
3323 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3324 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3325 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3326 fsp->fsp_name, newname ));
3327 string_set(&fsp->fsp_name, newname);
3328 did_rename = True;
3331 if (!did_rename)
3332 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3333 (unsigned int)dev, (double)inode, newname ));
3336 /****************************************************************************
3337 Rename an open file - given an fsp.
3338 ****************************************************************************/
3340 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3342 SMB_STRUCT_STAT sbuf;
3343 BOOL bad_path = False;
3344 pstring newname_last_component;
3345 NTSTATUS error = NT_STATUS_OK;
3346 BOOL dest_exists;
3348 ZERO_STRUCT(sbuf);
3349 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3351 /* Ensure newname contains a '/' */
3352 if(strrchr_m(newname,'/') == 0) {
3353 pstring tmpstr;
3355 pstrcpy(tmpstr, "./");
3356 pstrcat(tmpstr, newname);
3357 pstrcpy(newname, tmpstr);
3361 * Check for special case with case preserving and not
3362 * case sensitive. If the old last component differs from the original
3363 * last component only by case, then we should allow
3364 * the rename (user is trying to change the case of the
3365 * filename).
3368 if((case_sensitive == False) && (case_preserve == True) &&
3369 strequal(newname, fsp->fsp_name)) {
3370 char *p;
3371 pstring newname_modified_last_component;
3374 * Get the last component of the modified name.
3375 * Note that we guarantee that newname contains a '/'
3376 * character above.
3378 p = strrchr_m(newname,'/');
3379 pstrcpy(newname_modified_last_component,p+1);
3381 if(strcsequal(newname_modified_last_component,
3382 newname_last_component) == False) {
3384 * Replace the modified last component with
3385 * the original.
3387 pstrcpy(p+1, newname_last_component);
3392 * If the src and dest names are identical - including case,
3393 * don't do the rename, just return success.
3396 if (strcsequal(fsp->fsp_name, newname)) {
3397 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3398 newname));
3399 return NT_STATUS_OK;
3402 dest_exists = vfs_object_exist(conn,newname,NULL);
3404 if(!replace_if_exists && dest_exists) {
3405 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3406 fsp->fsp_name,newname));
3407 return NT_STATUS_OBJECT_NAME_COLLISION;
3410 error = can_rename(newname,conn,&sbuf);
3412 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3413 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3414 nt_errstr(error), fsp->fsp_name,newname));
3415 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3416 error = NT_STATUS_ACCESS_DENIED;
3417 return error;
3420 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3421 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3422 fsp->fsp_name,newname));
3423 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3424 return NT_STATUS_OK;
3427 if (errno == ENOTDIR || errno == EISDIR)
3428 error = NT_STATUS_OBJECT_NAME_COLLISION;
3429 else
3430 error = map_nt_error_from_unix(errno);
3432 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3433 nt_errstr(error), fsp->fsp_name,newname));
3435 return error;
3438 /****************************************************************************
3439 The guts of the rename command, split out so it may be called by the NT SMB
3440 code.
3441 ****************************************************************************/
3443 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3445 pstring directory;
3446 pstring mask;
3447 pstring newname_last_component;
3448 char *p;
3449 BOOL has_wild;
3450 BOOL bad_path1 = False;
3451 BOOL bad_path2 = False;
3452 int count=0;
3453 NTSTATUS error = NT_STATUS_OK;
3454 BOOL rc = True;
3455 SMB_STRUCT_STAT sbuf1, sbuf2;
3457 *directory = *mask = 0;
3459 ZERO_STRUCT(sbuf1);
3460 ZERO_STRUCT(sbuf2);
3461 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3462 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3465 * Split the old name into directory and last component
3466 * strings. Note that unix_convert may have stripped off a
3467 * leading ./ from both name and newname if the rename is
3468 * at the root of the share. We need to make sure either both
3469 * name and newname contain a / character or neither of them do
3470 * as this is checked in resolve_wildcards().
3473 p = strrchr_m(name,'/');
3474 if (!p) {
3475 pstrcpy(directory,".");
3476 pstrcpy(mask,name);
3477 } else {
3478 *p = 0;
3479 pstrcpy(directory,name);
3480 pstrcpy(mask,p+1);
3481 *p = '/'; /* Replace needed for exceptional test below. */
3485 * We should only check the mangled cache
3486 * here if unix_convert failed. This means
3487 * that the path in 'mask' doesn't exist
3488 * on the file system and so we need to look
3489 * for a possible mangle. This patch from
3490 * Tine Smukavec <valentin.smukavec@hermes.si>.
3493 if (!rc && mangle_is_mangled(mask))
3494 mangle_check_cache( mask );
3496 has_wild = ms_has_wild(mask);
3498 if (!has_wild) {
3500 * No wildcards - just process the one file.
3502 BOOL is_short_name = mangle_is_8_3(name, True);
3504 /* Add a terminating '/' to the directory name. */
3505 pstrcat(directory,"/");
3506 pstrcat(directory,mask);
3508 /* Ensure newname contains a '/' also */
3509 if(strrchr_m(newname,'/') == 0) {
3510 pstring tmpstr;
3512 pstrcpy(tmpstr, "./");
3513 pstrcat(tmpstr, newname);
3514 pstrcpy(newname, tmpstr);
3517 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3518 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3519 case_sensitive, case_preserve, short_case_preserve, directory,
3520 newname, newname_last_component, is_short_name));
3523 * Check for special case with case preserving and not
3524 * case sensitive, if directory and newname are identical,
3525 * and the old last component differs from the original
3526 * last component only by case, then we should allow
3527 * the rename (user is trying to change the case of the
3528 * filename).
3530 if((case_sensitive == False) &&
3531 (((case_preserve == True) &&
3532 (is_short_name == False)) ||
3533 ((short_case_preserve == True) &&
3534 (is_short_name == True))) &&
3535 strcsequal(directory, newname)) {
3536 pstring newname_modified_last_component;
3539 * Get the last component of the modified name.
3540 * Note that we guarantee that newname contains a '/'
3541 * character above.
3543 p = strrchr_m(newname,'/');
3544 pstrcpy(newname_modified_last_component,p+1);
3546 if(strcsequal(newname_modified_last_component,
3547 newname_last_component) == False) {
3549 * Replace the modified last component with
3550 * the original.
3552 pstrcpy(p+1, newname_last_component);
3556 resolve_wildcards(directory,newname);
3559 * The source object must exist.
3562 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3563 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3564 directory,newname));
3566 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3568 * Must return different errors depending on whether the parent
3569 * directory existed or not.
3572 p = strrchr_m(directory, '/');
3573 if (!p)
3574 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3575 *p = '\0';
3576 if (vfs_object_exist(conn, directory, NULL))
3577 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3578 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3580 error = map_nt_error_from_unix(errno);
3581 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3582 nt_errstr(error), directory,newname));
3584 return error;
3587 error = can_rename(directory,conn,&sbuf1);
3589 if (!NT_STATUS_IS_OK(error)) {
3590 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3591 nt_errstr(error), directory,newname));
3592 return error;
3596 * If the src and dest names are identical - including case,
3597 * don't do the rename, just return success.
3600 if (strcsequal(directory, newname)) {
3601 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3602 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3603 return NT_STATUS_OK;
3606 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3607 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3608 directory,newname));
3609 return NT_STATUS_OBJECT_NAME_COLLISION;
3612 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3613 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3614 directory,newname));
3615 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3616 return NT_STATUS_OK;
3619 if (errno == ENOTDIR || errno == EISDIR)
3620 error = NT_STATUS_OBJECT_NAME_COLLISION;
3621 else
3622 error = map_nt_error_from_unix(errno);
3624 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3625 nt_errstr(error), directory,newname));
3627 return error;
3628 } else {
3630 * Wildcards - process each file that matches.
3632 void *dirptr = NULL;
3633 const char *dname;
3634 pstring destname;
3636 if (check_name(directory,conn))
3637 dirptr = OpenDir(conn, directory, True);
3639 if (dirptr) {
3640 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3642 if (strequal(mask,"????????.???"))
3643 pstrcpy(mask,"*");
3645 while ((dname = ReadDirName(dirptr))) {
3646 pstring fname;
3648 pstrcpy(fname,dname);
3650 if(!mask_match(fname, mask, case_sensitive))
3651 continue;
3653 error = NT_STATUS_ACCESS_DENIED;
3654 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3655 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3656 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3657 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3658 continue;
3660 error = can_rename(fname,conn,&sbuf1);
3661 if (!NT_STATUS_IS_OK(error)) {
3662 DEBUG(6,("rename %s refused\n", fname));
3663 continue;
3665 pstrcpy(destname,newname);
3667 if (!resolve_wildcards(fname,destname)) {
3668 DEBUG(6,("resolve_wildcards %s %s failed\n",
3669 fname, destname));
3670 continue;
3673 if (!replace_if_exists &&
3674 vfs_file_exist(conn,destname, NULL)) {
3675 DEBUG(6,("file_exist %s\n", destname));
3676 error = NT_STATUS_OBJECT_NAME_COLLISION;
3677 continue;
3680 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3681 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3682 count++;
3684 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3686 CloseDir(dirptr);
3690 if (count == 0 && NT_STATUS_IS_OK(error)) {
3691 error = map_nt_error_from_unix(errno);
3694 return error;
3697 /****************************************************************************
3698 Reply to a mv.
3699 ****************************************************************************/
3701 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3702 int dum_buffsize)
3704 int outsize = 0;
3705 pstring name;
3706 pstring newname;
3707 char *p;
3708 NTSTATUS status;
3710 START_PROFILE(SMBmv);
3712 p = smb_buf(inbuf) + 1;
3713 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 END_PROFILE(SMBmv);
3716 return ERROR_NT(status);
3718 p++;
3719 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3720 if (!NT_STATUS_IS_OK(status)) {
3721 END_PROFILE(SMBmv);
3722 return ERROR_NT(status);
3725 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3726 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3728 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3730 status = rename_internals(conn, name, newname, False);
3731 if (!NT_STATUS_IS_OK(status)) {
3732 END_PROFILE(SMBmv);
3733 return ERROR_NT(status);
3737 * Win2k needs a changenotify request response before it will
3738 * update after a rename..
3740 process_pending_change_notify_queue((time_t)0);
3741 outsize = set_message(outbuf,0,0,True);
3743 END_PROFILE(SMBmv);
3744 return(outsize);
3747 /*******************************************************************
3748 Copy a file as part of a reply_copy.
3749 ******************************************************************/
3751 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3752 int count,BOOL target_is_directory, int *err_ret)
3754 int Access,action;
3755 SMB_STRUCT_STAT src_sbuf, sbuf2;
3756 SMB_OFF_T ret=-1;
3757 files_struct *fsp1,*fsp2;
3758 pstring dest;
3760 *err_ret = 0;
3762 pstrcpy(dest,dest1);
3763 if (target_is_directory) {
3764 char *p = strrchr_m(src,'/');
3765 if (p)
3766 p++;
3767 else
3768 p = src;
3769 pstrcat(dest,"/");
3770 pstrcat(dest,p);
3773 if (!vfs_file_exist(conn,src,&src_sbuf))
3774 return(False);
3776 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3777 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3779 if (!fsp1)
3780 return(False);
3782 if (!target_is_directory && count)
3783 ofun = FILE_EXISTS_OPEN;
3785 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3786 ZERO_STRUCTP(&sbuf2);
3788 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3789 ofun,src_sbuf.st_mode,0,&Access,&action);
3791 if (!fsp2) {
3792 close_file(fsp1,False);
3793 return(False);
3796 if ((ofun&3) == 1) {
3797 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3798 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3800 * Stop the copy from occurring.
3802 ret = -1;
3803 src_sbuf.st_size = 0;
3807 if (src_sbuf.st_size)
3808 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3810 close_file(fsp1,False);
3812 /* Ensure the modtime is set correctly on the destination file. */
3813 fsp2->pending_modtime = src_sbuf.st_mtime;
3816 * As we are opening fsp1 read-only we only expect
3817 * an error on close on fsp2 if we are out of space.
3818 * Thus we don't look at the error return from the
3819 * close of fsp1.
3821 *err_ret = close_file(fsp2,False);
3823 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3826 /****************************************************************************
3827 Reply to a file copy.
3828 ****************************************************************************/
3830 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3832 int outsize = 0;
3833 pstring name;
3834 pstring directory;
3835 pstring mask,newname;
3836 char *p;
3837 int count=0;
3838 int error = ERRnoaccess;
3839 int err = 0;
3840 BOOL has_wild;
3841 BOOL exists=False;
3842 int tid2 = SVAL(inbuf,smb_vwv0);
3843 int ofun = SVAL(inbuf,smb_vwv1);
3844 int flags = SVAL(inbuf,smb_vwv2);
3845 BOOL target_is_directory=False;
3846 BOOL bad_path1 = False;
3847 BOOL bad_path2 = False;
3848 BOOL rc = True;
3849 SMB_STRUCT_STAT sbuf1, sbuf2;
3850 NTSTATUS status;
3852 START_PROFILE(SMBcopy);
3854 *directory = *mask = 0;
3856 p = smb_buf(inbuf);
3857 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3858 if (!NT_STATUS_IS_OK(status)) {
3859 END_PROFILE(SMBcopy);
3860 return ERROR_NT(status);
3862 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3863 if (!NT_STATUS_IS_OK(status)) {
3864 END_PROFILE(SMBcopy);
3865 return ERROR_NT(status);
3868 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3870 if (tid2 != conn->cnum) {
3871 /* can't currently handle inter share copies XXXX */
3872 DEBUG(3,("Rejecting inter-share copy\n"));
3873 END_PROFILE(SMBcopy);
3874 return ERROR_DOS(ERRSRV,ERRinvdevice);
3877 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3878 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3880 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3881 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3883 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3885 if ((flags&1) && target_is_directory) {
3886 END_PROFILE(SMBcopy);
3887 return ERROR_DOS(ERRDOS,ERRbadfile);
3890 if ((flags&2) && !target_is_directory) {
3891 END_PROFILE(SMBcopy);
3892 return ERROR_DOS(ERRDOS,ERRbadpath);
3895 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3896 /* wants a tree copy! XXXX */
3897 DEBUG(3,("Rejecting tree copy\n"));
3898 END_PROFILE(SMBcopy);
3899 return ERROR_DOS(ERRSRV,ERRerror);
3902 p = strrchr_m(name,'/');
3903 if (!p) {
3904 pstrcpy(directory,"./");
3905 pstrcpy(mask,name);
3906 } else {
3907 *p = 0;
3908 pstrcpy(directory,name);
3909 pstrcpy(mask,p+1);
3913 * We should only check the mangled cache
3914 * here if unix_convert failed. This means
3915 * that the path in 'mask' doesn't exist
3916 * on the file system and so we need to look
3917 * for a possible mangle. This patch from
3918 * Tine Smukavec <valentin.smukavec@hermes.si>.
3921 if (!rc && mangle_is_mangled(mask))
3922 mangle_check_cache( mask );
3924 has_wild = ms_has_wild(mask);
3926 if (!has_wild) {
3927 pstrcat(directory,"/");
3928 pstrcat(directory,mask);
3929 if (resolve_wildcards(directory,newname) &&
3930 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3931 count++;
3932 if(!count && err) {
3933 errno = err;
3934 END_PROFILE(SMBcopy);
3935 return(UNIXERROR(ERRHRD,ERRgeneral));
3937 if (!count) {
3938 exists = vfs_file_exist(conn,directory,NULL);
3940 } else {
3941 void *dirptr = NULL;
3942 const char *dname;
3943 pstring destname;
3945 if (check_name(directory,conn))
3946 dirptr = OpenDir(conn, directory, True);
3948 if (dirptr) {
3949 error = ERRbadfile;
3951 if (strequal(mask,"????????.???"))
3952 pstrcpy(mask,"*");
3954 while ((dname = ReadDirName(dirptr))) {
3955 pstring fname;
3956 pstrcpy(fname,dname);
3958 if(!mask_match(fname, mask, case_sensitive))
3959 continue;
3961 error = ERRnoaccess;
3962 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3963 pstrcpy(destname,newname);
3964 if (resolve_wildcards(fname,destname) &&
3965 copy_file(fname,destname,conn,ofun,
3966 count,target_is_directory,&err))
3967 count++;
3968 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3970 CloseDir(dirptr);
3974 if (count == 0) {
3975 if(err) {
3976 /* Error on close... */
3977 errno = err;
3978 END_PROFILE(SMBcopy);
3979 return(UNIXERROR(ERRHRD,ERRgeneral));
3982 if (exists) {
3983 END_PROFILE(SMBcopy);
3984 return ERROR_DOS(ERRDOS,error);
3985 } else {
3986 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3987 unix_ERR_class = ERRDOS;
3988 unix_ERR_code = ERRbadpath;
3990 END_PROFILE(SMBcopy);
3991 return(UNIXERROR(ERRDOS,error));
3995 outsize = set_message(outbuf,1,0,True);
3996 SSVAL(outbuf,smb_vwv0,count);
3998 END_PROFILE(SMBcopy);
3999 return(outsize);
4002 /****************************************************************************
4003 Reply to a setdir.
4004 ****************************************************************************/
4006 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4008 int snum;
4009 int outsize = 0;
4010 BOOL ok = False;
4011 pstring newdir;
4012 NTSTATUS status;
4014 START_PROFILE(pathworks_setdir);
4016 snum = SNUM(conn);
4017 if (!CAN_SETDIR(snum)) {
4018 END_PROFILE(pathworks_setdir);
4019 return ERROR_DOS(ERRDOS,ERRnoaccess);
4022 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4023 if (!NT_STATUS_IS_OK(status)) {
4024 END_PROFILE(pathworks_setdir);
4025 return ERROR_NT(status);
4028 if (strlen(newdir) == 0) {
4029 ok = True;
4030 } else {
4031 ok = vfs_directory_exist(conn,newdir,NULL);
4032 if (ok)
4033 string_set(&conn->connectpath,newdir);
4036 if (!ok) {
4037 END_PROFILE(pathworks_setdir);
4038 return ERROR_DOS(ERRDOS,ERRbadpath);
4041 outsize = set_message(outbuf,0,0,True);
4042 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4044 DEBUG(3,("setdir %s\n", newdir));
4046 END_PROFILE(pathworks_setdir);
4047 return(outsize);
4050 /****************************************************************************
4051 Get a lock pid, dealing with large count requests.
4052 ****************************************************************************/
4054 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4056 if(!large_file_format)
4057 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4058 else
4059 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4062 /****************************************************************************
4063 Get a lock count, dealing with large count requests.
4064 ****************************************************************************/
4066 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4068 SMB_BIG_UINT count = 0;
4070 if(!large_file_format) {
4071 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4072 } else {
4074 #if defined(HAVE_LONGLONG)
4075 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4076 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4077 #else /* HAVE_LONGLONG */
4080 * NT4.x seems to be broken in that it sends large file (64 bit)
4081 * lockingX calls even if the CAP_LARGE_FILES was *not*
4082 * negotiated. For boxes without large unsigned ints truncate the
4083 * lock count by dropping the top 32 bits.
4086 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4087 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4088 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4089 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4090 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4093 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4094 #endif /* HAVE_LONGLONG */
4097 return count;
4100 #if !defined(HAVE_LONGLONG)
4101 /****************************************************************************
4102 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4103 ****************************************************************************/
4105 static uint32 map_lock_offset(uint32 high, uint32 low)
4107 unsigned int i;
4108 uint32 mask = 0;
4109 uint32 highcopy = high;
4112 * Try and find out how many significant bits there are in high.
4115 for(i = 0; highcopy; i++)
4116 highcopy >>= 1;
4119 * We use 31 bits not 32 here as POSIX
4120 * lock offsets may not be negative.
4123 mask = (~0) << (31 - i);
4125 if(low & mask)
4126 return 0; /* Fail. */
4128 high <<= (31 - i);
4130 return (high|low);
4132 #endif /* !defined(HAVE_LONGLONG) */
4134 /****************************************************************************
4135 Get a lock offset, dealing with large offset requests.
4136 ****************************************************************************/
4138 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4140 SMB_BIG_UINT offset = 0;
4142 *err = False;
4144 if(!large_file_format) {
4145 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4146 } else {
4148 #if defined(HAVE_LONGLONG)
4149 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4150 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4151 #else /* HAVE_LONGLONG */
4154 * NT4.x seems to be broken in that it sends large file (64 bit)
4155 * lockingX calls even if the CAP_LARGE_FILES was *not*
4156 * negotiated. For boxes without large unsigned ints mangle the
4157 * lock offset by mapping the top 32 bits onto the lower 32.
4160 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4161 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4162 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4163 uint32 new_low = 0;
4165 if((new_low = map_lock_offset(high, low)) == 0) {
4166 *err = True;
4167 return (SMB_BIG_UINT)-1;
4170 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4171 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4172 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4173 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4176 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4177 #endif /* HAVE_LONGLONG */
4180 return offset;
4183 /****************************************************************************
4184 Reply to a lockingX request.
4185 ****************************************************************************/
4187 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4189 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4190 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4191 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4192 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4193 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4194 SMB_BIG_UINT count = 0, offset = 0;
4195 uint16 lock_pid;
4196 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4197 int i;
4198 char *data;
4199 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4200 BOOL err;
4201 BOOL my_lock_ctx = False;
4202 NTSTATUS status;
4204 START_PROFILE(SMBlockingX);
4206 CHECK_FSP(fsp,conn);
4208 data = smb_buf(inbuf);
4210 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4211 /* we don't support these - and CANCEL_LOCK makes w2k
4212 and XP reboot so I don't really want to be
4213 compatible! (tridge) */
4214 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4217 /* Check if this is an oplock break on a file
4218 we have granted an oplock on.
4220 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4221 /* Client can insist on breaking to none. */
4222 BOOL break_to_none = (oplocklevel == 0);
4224 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4225 (unsigned int)oplocklevel, fsp->fnum ));
4228 * Make sure we have granted an exclusive or batch oplock on this file.
4231 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4232 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4233 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4235 /* if this is a pure oplock break request then don't send a reply */
4236 if (num_locks == 0 && num_ulocks == 0) {
4237 END_PROFILE(SMBlockingX);
4238 return -1;
4239 } else {
4240 END_PROFILE(SMBlockingX);
4241 return ERROR_DOS(ERRDOS,ERRlock);
4245 if (remove_oplock(fsp, break_to_none) == False) {
4246 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4247 fsp->fsp_name ));
4250 /* if this is a pure oplock break request then don't send a reply */
4251 if (num_locks == 0 && num_ulocks == 0) {
4252 /* Sanity check - ensure a pure oplock break is not a
4253 chained request. */
4254 if(CVAL(inbuf,smb_vwv0) != 0xff)
4255 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4256 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4257 END_PROFILE(SMBlockingX);
4258 return -1;
4263 * We do this check *after* we have checked this is not a oplock break
4264 * response message. JRA.
4267 release_level_2_oplocks_on_change(fsp);
4269 /* Data now points at the beginning of the list
4270 of smb_unlkrng structs */
4271 for(i = 0; i < (int)num_ulocks; i++) {
4272 lock_pid = get_lock_pid( data, i, large_file_format);
4273 count = get_lock_count( data, i, large_file_format);
4274 offset = get_lock_offset( data, i, large_file_format, &err);
4277 * There is no error code marked "stupid client bug".... :-).
4279 if(err) {
4280 END_PROFILE(SMBlockingX);
4281 return ERROR_DOS(ERRDOS,ERRnoaccess);
4284 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4285 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4287 status = do_unlock(fsp,conn,lock_pid,count,offset);
4288 if (NT_STATUS_V(status)) {
4289 END_PROFILE(SMBlockingX);
4290 return ERROR_NT(status);
4294 /* Setup the timeout in seconds. */
4296 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4298 /* Now do any requested locks */
4299 data += ((large_file_format ? 20 : 10)*num_ulocks);
4301 /* Data now points at the beginning of the list
4302 of smb_lkrng structs */
4304 for(i = 0; i < (int)num_locks; i++) {
4305 lock_pid = get_lock_pid( data, i, large_file_format);
4306 count = get_lock_count( data, i, large_file_format);
4307 offset = get_lock_offset( data, i, large_file_format, &err);
4310 * There is no error code marked "stupid client bug".... :-).
4312 if(err) {
4313 END_PROFILE(SMBlockingX);
4314 return ERROR_DOS(ERRDOS,ERRnoaccess);
4317 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4318 (double)offset, (double)count, (unsigned int)lock_pid,
4319 fsp->fsp_name, (int)lock_timeout ));
4321 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4322 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4323 if (NT_STATUS_V(status)) {
4324 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4326 * A blocking lock was requested. Package up
4327 * this smb into a queued request and push it
4328 * onto the blocking lock queue.
4330 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4331 END_PROFILE(SMBlockingX);
4332 return -1;
4335 break;
4339 /* If any of the above locks failed, then we must unlock
4340 all of the previous locks (X/Open spec). */
4341 if (i != num_locks && num_locks != 0) {
4343 * Ensure we don't do a remove on the lock that just failed,
4344 * as under POSIX rules, if we have a lock already there, we
4345 * will delete it (and we shouldn't) .....
4347 for(i--; i >= 0; i--) {
4348 lock_pid = get_lock_pid( data, i, large_file_format);
4349 count = get_lock_count( data, i, large_file_format);
4350 offset = get_lock_offset( data, i, large_file_format, &err);
4353 * There is no error code marked "stupid client bug".... :-).
4355 if(err) {
4356 END_PROFILE(SMBlockingX);
4357 return ERROR_DOS(ERRDOS,ERRnoaccess);
4360 do_unlock(fsp,conn,lock_pid,count,offset);
4362 END_PROFILE(SMBlockingX);
4363 return ERROR_NT(status);
4366 set_message(outbuf,2,0,True);
4368 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4369 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4371 END_PROFILE(SMBlockingX);
4372 return chain_reply(inbuf,outbuf,length,bufsize);
4375 /****************************************************************************
4376 Reply to a SMBreadbmpx (read block multiplex) request.
4377 ****************************************************************************/
4379 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4381 ssize_t nread = -1;
4382 ssize_t total_read;
4383 char *data;
4384 SMB_OFF_T startpos;
4385 int outsize;
4386 size_t maxcount;
4387 int max_per_packet;
4388 size_t tcount;
4389 int pad;
4390 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4391 START_PROFILE(SMBreadBmpx);
4393 /* this function doesn't seem to work - disable by default */
4394 if (!lp_readbmpx()) {
4395 END_PROFILE(SMBreadBmpx);
4396 return ERROR_DOS(ERRSRV,ERRuseSTD);
4399 outsize = set_message(outbuf,8,0,True);
4401 CHECK_FSP(fsp,conn);
4402 CHECK_READ(fsp);
4404 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4405 maxcount = SVAL(inbuf,smb_vwv3);
4407 data = smb_buf(outbuf);
4408 pad = ((long)data)%4;
4409 if (pad)
4410 pad = 4 - pad;
4411 data += pad;
4413 max_per_packet = bufsize-(outsize+pad);
4414 tcount = maxcount;
4415 total_read = 0;
4417 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4418 END_PROFILE(SMBreadBmpx);
4419 return ERROR_DOS(ERRDOS,ERRlock);
4422 do {
4423 size_t N = MIN(max_per_packet,tcount-total_read);
4425 nread = read_file(fsp,data,startpos,N);
4427 if (nread <= 0)
4428 nread = 0;
4430 if (nread < (ssize_t)N)
4431 tcount = total_read + nread;
4433 set_message(outbuf,8,nread,False);
4434 SIVAL(outbuf,smb_vwv0,startpos);
4435 SSVAL(outbuf,smb_vwv2,tcount);
4436 SSVAL(outbuf,smb_vwv6,nread);
4437 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4439 if (!send_smb(smbd_server_fd(),outbuf))
4440 exit_server("reply_readbmpx: send_smb failed.");
4442 total_read += nread;
4443 startpos += nread;
4444 } while (total_read < (ssize_t)tcount);
4446 END_PROFILE(SMBreadBmpx);
4447 return(-1);
4450 /****************************************************************************
4451 Reply to a SMBsetattrE.
4452 ****************************************************************************/
4454 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4456 struct utimbuf unix_times;
4457 int outsize = 0;
4458 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4459 START_PROFILE(SMBsetattrE);
4461 outsize = set_message(outbuf,0,0,True);
4463 if(!fsp || (fsp->conn != conn)) {
4464 END_PROFILE(SMBgetattrE);
4465 return ERROR_DOS(ERRDOS,ERRbadfid);
4469 * Convert the DOS times into unix times. Ignore create
4470 * time as UNIX can't set this.
4473 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4474 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4477 * Patch from Ray Frush <frush@engr.colostate.edu>
4478 * Sometimes times are sent as zero - ignore them.
4481 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4482 /* Ignore request */
4483 if( DEBUGLVL( 3 ) ) {
4484 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4485 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4487 END_PROFILE(SMBsetattrE);
4488 return(outsize);
4489 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4490 /* set modify time = to access time if modify time was 0 */
4491 unix_times.modtime = unix_times.actime;
4494 /* Set the date on this file */
4495 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4496 END_PROFILE(SMBsetattrE);
4497 return ERROR_DOS(ERRDOS,ERRnoaccess);
4500 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4501 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4503 END_PROFILE(SMBsetattrE);
4504 return(outsize);
4508 /* Back from the dead for OS/2..... JRA. */
4510 /****************************************************************************
4511 Reply to a SMBwritebmpx (write block multiplex primary) request.
4512 ****************************************************************************/
4514 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4516 size_t numtowrite;
4517 ssize_t nwritten = -1;
4518 int outsize = 0;
4519 SMB_OFF_T startpos;
4520 size_t tcount;
4521 BOOL write_through;
4522 int smb_doff;
4523 char *data;
4524 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4525 START_PROFILE(SMBwriteBmpx);
4527 CHECK_FSP(fsp,conn);
4528 CHECK_WRITE(fsp);
4529 CHECK_ERROR(fsp);
4531 tcount = SVAL(inbuf,smb_vwv1);
4532 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4533 write_through = BITSETW(inbuf+smb_vwv7,0);
4534 numtowrite = SVAL(inbuf,smb_vwv10);
4535 smb_doff = SVAL(inbuf,smb_vwv11);
4537 data = smb_base(inbuf) + smb_doff;
4539 /* If this fails we need to send an SMBwriteC response,
4540 not an SMBwritebmpx - set this up now so we don't forget */
4541 SCVAL(outbuf,smb_com,SMBwritec);
4543 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4544 END_PROFILE(SMBwriteBmpx);
4545 return(ERROR_DOS(ERRDOS,ERRlock));
4548 nwritten = write_file(fsp,data,startpos,numtowrite);
4550 if(lp_syncalways(SNUM(conn)) || write_through)
4551 sync_file(conn,fsp);
4553 if(nwritten < (ssize_t)numtowrite) {
4554 END_PROFILE(SMBwriteBmpx);
4555 return(UNIXERROR(ERRHRD,ERRdiskfull));
4558 /* If the maximum to be written to this file
4559 is greater than what we just wrote then set
4560 up a secondary struct to be attached to this
4561 fd, we will use this to cache error messages etc. */
4563 if((ssize_t)tcount > nwritten) {
4564 write_bmpx_struct *wbms;
4565 if(fsp->wbmpx_ptr != NULL)
4566 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4567 else
4568 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4569 if(!wbms) {
4570 DEBUG(0,("Out of memory in reply_readmpx\n"));
4571 END_PROFILE(SMBwriteBmpx);
4572 return(ERROR_DOS(ERRSRV,ERRnoresource));
4574 wbms->wr_mode = write_through;
4575 wbms->wr_discard = False; /* No errors yet */
4576 wbms->wr_total_written = nwritten;
4577 wbms->wr_errclass = 0;
4578 wbms->wr_error = 0;
4579 fsp->wbmpx_ptr = wbms;
4582 /* We are returning successfully, set the message type back to
4583 SMBwritebmpx */
4584 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4586 outsize = set_message(outbuf,1,0,True);
4588 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4590 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4591 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4593 if (write_through && tcount==nwritten) {
4594 /* We need to send both a primary and a secondary response */
4595 smb_setlen(outbuf,outsize - 4);
4596 if (!send_smb(smbd_server_fd(),outbuf))
4597 exit_server("reply_writebmpx: send_smb failed.");
4599 /* Now the secondary */
4600 outsize = set_message(outbuf,1,0,True);
4601 SCVAL(outbuf,smb_com,SMBwritec);
4602 SSVAL(outbuf,smb_vwv0,nwritten);
4605 END_PROFILE(SMBwriteBmpx);
4606 return(outsize);
4609 /****************************************************************************
4610 Reply to a SMBwritebs (write block multiplex secondary) request.
4611 ****************************************************************************/
4613 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4615 size_t numtowrite;
4616 ssize_t nwritten = -1;
4617 int outsize = 0;
4618 SMB_OFF_T startpos;
4619 size_t tcount;
4620 BOOL write_through;
4621 int smb_doff;
4622 char *data;
4623 write_bmpx_struct *wbms;
4624 BOOL send_response = False;
4625 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4626 START_PROFILE(SMBwriteBs);
4628 CHECK_FSP(fsp,conn);
4629 CHECK_WRITE(fsp);
4631 tcount = SVAL(inbuf,smb_vwv1);
4632 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4633 numtowrite = SVAL(inbuf,smb_vwv6);
4634 smb_doff = SVAL(inbuf,smb_vwv7);
4636 data = smb_base(inbuf) + smb_doff;
4638 /* We need to send an SMBwriteC response, not an SMBwritebs */
4639 SCVAL(outbuf,smb_com,SMBwritec);
4641 /* This fd should have an auxiliary struct attached,
4642 check that it does */
4643 wbms = fsp->wbmpx_ptr;
4644 if(!wbms) {
4645 END_PROFILE(SMBwriteBs);
4646 return(-1);
4649 /* If write through is set we can return errors, else we must cache them */
4650 write_through = wbms->wr_mode;
4652 /* Check for an earlier error */
4653 if(wbms->wr_discard) {
4654 END_PROFILE(SMBwriteBs);
4655 return -1; /* Just discard the packet */
4658 nwritten = write_file(fsp,data,startpos,numtowrite);
4660 if(lp_syncalways(SNUM(conn)) || write_through)
4661 sync_file(conn,fsp);
4663 if (nwritten < (ssize_t)numtowrite) {
4664 if(write_through) {
4665 /* We are returning an error - we can delete the aux struct */
4666 if (wbms)
4667 free((char *)wbms);
4668 fsp->wbmpx_ptr = NULL;
4669 END_PROFILE(SMBwriteBs);
4670 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4672 END_PROFILE(SMBwriteBs);
4673 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4676 /* Increment the total written, if this matches tcount
4677 we can discard the auxiliary struct (hurrah !) and return a writeC */
4678 wbms->wr_total_written += nwritten;
4679 if(wbms->wr_total_written >= tcount) {
4680 if (write_through) {
4681 outsize = set_message(outbuf,1,0,True);
4682 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4683 send_response = True;
4686 free((char *)wbms);
4687 fsp->wbmpx_ptr = NULL;
4690 if(send_response) {
4691 END_PROFILE(SMBwriteBs);
4692 return(outsize);
4695 END_PROFILE(SMBwriteBs);
4696 return(-1);
4699 /****************************************************************************
4700 Reply to a SMBgetattrE.
4701 ****************************************************************************/
4703 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4705 SMB_STRUCT_STAT sbuf;
4706 int outsize = 0;
4707 int mode;
4708 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4709 START_PROFILE(SMBgetattrE);
4711 outsize = set_message(outbuf,11,0,True);
4713 if(!fsp || (fsp->conn != conn)) {
4714 END_PROFILE(SMBgetattrE);
4715 return ERROR_DOS(ERRDOS,ERRbadfid);
4718 /* Do an fstat on this file */
4719 if(fsp_stat(fsp, &sbuf)) {
4720 END_PROFILE(SMBgetattrE);
4721 return(UNIXERROR(ERRDOS,ERRnoaccess));
4724 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4727 * Convert the times into dos times. Set create
4728 * date to be last modify date as UNIX doesn't save
4729 * this.
4732 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4733 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4734 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4736 if (mode & aDIR) {
4737 SIVAL(outbuf,smb_vwv6,0);
4738 SIVAL(outbuf,smb_vwv8,0);
4739 } else {
4740 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4741 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4742 SIVAL(outbuf,smb_vwv8,allocation_size);
4744 SSVAL(outbuf,smb_vwv10, mode);
4746 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4748 END_PROFILE(SMBgetattrE);
4749 return(outsize);