r4231: commiting changes to 3.0.10
[Samba/gbeck.git] / source / smbd / reply.c
blob6135c36580bbad427a3357b2ab29af462d940c9a
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2004.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern int Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43 set.
44 ****************************************************************************/
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
48 char *d = destname;
49 const char *s = srcname;
50 NTSTATUS ret = NT_STATUS_OK;
51 BOOL start_of_name_component = True;
52 unsigned int num_bad_components = 0;
54 while (*s) {
55 if (IS_DIRECTORY_SEP(*s)) {
57 * Safe to assume is not the second part of a mb char as this is handled below.
59 /* Eat multiple '/' or '\\' */
60 while (IS_DIRECTORY_SEP(*s)) {
61 s++;
63 if ((d != destname) && (*s != '\0')) {
64 /* We only care about non-leading or trailing '/' or '\\' */
65 *d++ = '/';
68 start_of_name_component = True;
69 continue;
72 if (start_of_name_component) {
73 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
74 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
77 * No mb char starts with '.' so we're safe checking the directory separator here.
80 /* If we just added a '/' - delete it */
81 if ((d > destname) && (*(d-1) == '/')) {
82 *(d-1) = '\0';
83 d--;
86 /* Are we at the start ? Can't go back further if so. */
87 if (d <= destname) {
88 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
89 break;
91 /* Go back one level... */
92 /* We know this is safe as '/' cannot be part of a mb sequence. */
93 /* NOTE - if this assumption is invalid we are not in good shape... */
94 /* Decrement d first as d points to the *next* char to write into. */
95 for (d--; d > destname; d--) {
96 if (*d == '/')
97 break;
99 s += 2; /* Else go past the .. */
100 /* We're still at the start of a name component, just the previous one. */
102 if (num_bad_components) {
103 /* Hmmm. Should we only decrement the bad_components if
104 we're removing a bad component ? Need to check this. JRA. */
105 num_bad_components--;
108 continue;
110 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
111 /* Component of pathname can't be "." only. */
112 ret = NT_STATUS_OBJECT_NAME_INVALID;
113 num_bad_components++;
114 *d++ = *s++;
115 continue;
119 if (!(*s & 0x80)) {
120 if (allow_wcard_names) {
121 *d++ = *s++;
122 } else {
123 switch (*s) {
124 case '*':
125 case '?':
126 case '<':
127 case '>':
128 case '"':
129 return NT_STATUS_OBJECT_NAME_INVALID;
130 default:
131 *d++ = *s++;
132 break;
135 } else {
136 switch(next_mb_char_size(s)) {
137 case 4:
138 *d++ = *s++;
139 case 3:
140 *d++ = *s++;
141 case 2:
142 *d++ = *s++;
143 case 1:
144 *d++ = *s++;
145 break;
146 default:
147 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
148 *d = '\0';
149 return NT_STATUS_INVALID_PARAMETER;
152 if (start_of_name_component && num_bad_components) {
153 num_bad_components++;
155 start_of_name_component = False;
158 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
159 /* For some strange reason being called from findfirst changes
160 the num_components number to cause the error return to change. JRA. */
161 if (allow_wcard_names) {
162 if (num_bad_components > 2) {
163 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
165 } else {
166 if (num_bad_components > 1) {
167 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
172 *d = '\0';
173 return ret;
176 /****************************************************************************
177 Pull a string and check the path - provide for error return.
178 ****************************************************************************/
180 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
182 pstring tmppath;
183 char *tmppath_ptr = tmppath;
184 size_t ret;
185 #ifdef DEVELOPER
186 SMB_ASSERT(dest_len == sizeof(pstring));
187 #endif
189 if (src_len == 0) {
190 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
191 } else {
192 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
194 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
195 return ret;
198 /****************************************************************************
199 Reply to a special message.
200 ****************************************************************************/
202 int reply_special(char *inbuf,char *outbuf)
204 int outsize = 4;
205 int msg_type = CVAL(inbuf,0);
206 int msg_flags = CVAL(inbuf,1);
207 fstring name1,name2;
208 char name_type = 0;
210 static BOOL already_got_session = False;
212 *name1 = *name2 = 0;
214 memset(outbuf,'\0',smb_size);
216 smb_setlen(outbuf,0);
218 switch (msg_type) {
219 case 0x81: /* session request */
221 if (already_got_session) {
222 exit_server("multiple session request not permitted");
225 SCVAL(outbuf,0,0x82);
226 SCVAL(outbuf,3,0);
227 if (name_len(inbuf+4) > 50 ||
228 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
229 DEBUG(0,("Invalid name length in session request\n"));
230 return(0);
232 name_extract(inbuf,4,name1);
233 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
234 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
235 name1,name2));
237 set_local_machine_name(name1, True);
238 set_remote_machine_name(name2, True);
240 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
241 get_local_machine_name(), get_remote_machine_name(),
242 name_type));
244 if (name_type == 'R') {
245 /* We are being asked for a pathworks session ---
246 no thanks! */
247 SCVAL(outbuf, 0,0x83);
248 break;
251 /* only add the client's machine name to the list
252 of possibly valid usernames if we are operating
253 in share mode security */
254 if (lp_security() == SEC_SHARE) {
255 add_session_user(get_remote_machine_name());
258 reload_services(True);
259 reopen_logs();
261 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
263 already_got_session = True;
264 break;
266 case 0x89: /* session keepalive request
267 (some old clients produce this?) */
268 SCVAL(outbuf,0,SMBkeepalive);
269 SCVAL(outbuf,3,0);
270 break;
272 case 0x82: /* positive session response */
273 case 0x83: /* negative session response */
274 case 0x84: /* retarget session response */
275 DEBUG(0,("Unexpected session response\n"));
276 break;
278 case SMBkeepalive: /* session keepalive */
279 default:
280 return(0);
283 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
284 msg_type, msg_flags));
286 return(outsize);
289 /****************************************************************************
290 Reply to a tcon.
291 ****************************************************************************/
293 int reply_tcon(connection_struct *conn,
294 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
296 const char *service;
297 pstring service_buf;
298 pstring password;
299 pstring dev;
300 int outsize = 0;
301 uint16 vuid = SVAL(inbuf,smb_uid);
302 int pwlen=0;
303 NTSTATUS nt_status;
304 char *p;
305 DATA_BLOB password_blob;
307 START_PROFILE(SMBtcon);
309 *service_buf = *password = *dev = 0;
311 p = smb_buf(inbuf)+1;
312 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
313 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
314 p += pwlen;
315 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
317 p = strrchr_m(service_buf,'\\');
318 if (p) {
319 service = p+1;
320 } else {
321 service = service_buf;
324 password_blob = data_blob(password, pwlen+1);
326 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
328 data_blob_clear_free(&password_blob);
330 if (!conn) {
331 END_PROFILE(SMBtcon);
332 return ERROR_NT(nt_status);
335 outsize = set_message(outbuf,2,0,True);
336 SSVAL(outbuf,smb_vwv0,max_recv);
337 SSVAL(outbuf,smb_vwv1,conn->cnum);
338 SSVAL(outbuf,smb_tid,conn->cnum);
340 DEBUG(3,("tcon service=%s cnum=%d\n",
341 service, conn->cnum));
343 END_PROFILE(SMBtcon);
344 return(outsize);
347 /****************************************************************************
348 Reply to a tcon and X.
349 ****************************************************************************/
351 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
353 fstring service;
354 DATA_BLOB password;
356 /* what the cleint thinks the device is */
357 fstring client_devicetype;
358 /* what the server tells the client the share represents */
359 const char *server_devicetype;
360 NTSTATUS nt_status;
361 uint16 vuid = SVAL(inbuf,smb_uid);
362 int passlen = SVAL(inbuf,smb_vwv3);
363 pstring path;
364 char *p, *q;
365 extern BOOL global_encrypted_passwords_negotiated;
367 START_PROFILE(SMBtconX);
369 *service = *client_devicetype = 0;
371 /* we might have to close an old one */
372 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
373 close_cnum(conn,vuid);
376 if (passlen > MAX_PASS_LEN) {
377 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
380 if (global_encrypted_passwords_negotiated) {
381 password = data_blob(smb_buf(inbuf),passlen);
382 } else {
383 password = data_blob(smb_buf(inbuf),passlen+1);
384 /* Ensure correct termination */
385 password.data[passlen]=0;
388 p = smb_buf(inbuf) + passlen;
389 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
392 * the service name can be either: \\server\share
393 * or share directly like on the DELL PowerVault 705
395 if (*path=='\\') {
396 q = strchr_m(path+2,'\\');
397 if (!q) {
398 END_PROFILE(SMBtconX);
399 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
401 fstrcpy(service,q+1);
403 else
404 fstrcpy(service,path);
406 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
408 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
410 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
412 data_blob_clear_free(&password);
414 if (!conn) {
415 END_PROFILE(SMBtconX);
416 return ERROR_NT(nt_status);
419 if ( IS_IPC(conn) )
420 server_devicetype = "IPC";
421 else if ( IS_PRINT(conn) )
422 server_devicetype = "LPT1:";
423 else
424 server_devicetype = "A:";
426 if (Protocol < PROTOCOL_NT1) {
427 set_message(outbuf,2,0,True);
428 p = smb_buf(outbuf);
429 p += srvstr_push(outbuf, p, server_devicetype, -1,
430 STR_TERMINATE|STR_ASCII);
431 set_message_end(outbuf,p);
432 } else {
433 /* NT sets the fstype of IPC$ to the null string */
434 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
436 set_message(outbuf,3,0,True);
438 p = smb_buf(outbuf);
439 p += srvstr_push(outbuf, p, server_devicetype, -1,
440 STR_TERMINATE|STR_ASCII);
441 p += srvstr_push(outbuf, p, fstype, -1,
442 STR_TERMINATE);
444 set_message_end(outbuf,p);
446 /* what does setting this bit do? It is set by NT4 and
447 may affect the ability to autorun mounted cdroms */
448 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
449 (lp_csc_policy(SNUM(conn)) << 2));
451 init_dfsroot(conn, inbuf, outbuf);
455 DEBUG(3,("tconX service=%s \n",
456 service));
458 /* set the incoming and outgoing tid to the just created one */
459 SSVAL(inbuf,smb_tid,conn->cnum);
460 SSVAL(outbuf,smb_tid,conn->cnum);
462 END_PROFILE(SMBtconX);
463 return chain_reply(inbuf,outbuf,length,bufsize);
466 /****************************************************************************
467 Reply to an unknown type.
468 ****************************************************************************/
470 int reply_unknown(char *inbuf,char *outbuf)
472 int type;
473 type = CVAL(inbuf,smb_com);
475 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
476 smb_fn_name(type), type, type));
478 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
481 /****************************************************************************
482 Reply to an ioctl.
483 ****************************************************************************/
485 int reply_ioctl(connection_struct *conn,
486 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
488 uint16 device = SVAL(inbuf,smb_vwv1);
489 uint16 function = SVAL(inbuf,smb_vwv2);
490 uint32 ioctl_code = (device << 16) + function;
491 int replysize, outsize;
492 char *p;
493 START_PROFILE(SMBioctl);
495 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
497 switch (ioctl_code) {
498 case IOCTL_QUERY_JOB_INFO:
499 replysize = 32;
500 break;
501 default:
502 END_PROFILE(SMBioctl);
503 return(ERROR_DOS(ERRSRV,ERRnosupport));
506 outsize = set_message(outbuf,8,replysize+1,True);
507 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
508 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
509 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
510 p = smb_buf(outbuf) + 1; /* Allow for alignment */
512 switch (ioctl_code) {
513 case IOCTL_QUERY_JOB_INFO:
515 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
516 if (!fsp) {
517 END_PROFILE(SMBioctl);
518 return(UNIXERROR(ERRDOS,ERRbadfid));
520 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
521 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
522 if (conn) {
523 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
525 break;
529 END_PROFILE(SMBioctl);
530 return outsize;
533 /****************************************************************************
534 Reply to a chkpth.
535 ****************************************************************************/
537 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
539 int outsize = 0;
540 pstring name;
541 BOOL ok = False;
542 BOOL bad_path = False;
543 SMB_STRUCT_STAT sbuf;
544 NTSTATUS status;
546 START_PROFILE(SMBchkpth);
548 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
549 if (!NT_STATUS_IS_OK(status)) {
550 END_PROFILE(SMBchkpth);
551 return ERROR_NT(status);
554 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
556 unix_convert(name,conn,0,&bad_path,&sbuf);
557 if (bad_path) {
558 END_PROFILE(SMBchkpth);
559 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
562 if (check_name(name,conn)) {
563 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
564 if (!(ok = S_ISDIR(sbuf.st_mode))) {
565 END_PROFILE(SMBchkpth);
566 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
570 if (!ok) {
571 /* We special case this - as when a Windows machine
572 is parsing a path is steps through the components
573 one at a time - if a component fails it expects
574 ERRbadpath, not ERRbadfile.
576 if(errno == ENOENT) {
578 * Windows returns different error codes if
579 * the parent directory is valid but not the
580 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
581 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
582 * if the path is invalid. This is different from set_bad_path_error()
583 * in the non-NT error case.
585 END_PROFILE(SMBchkpth);
586 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
589 END_PROFILE(SMBchkpth);
590 return(UNIXERROR(ERRDOS,ERRbadpath));
593 outsize = set_message(outbuf,0,0,True);
594 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
596 END_PROFILE(SMBchkpth);
597 return(outsize);
600 /****************************************************************************
601 Reply to a getatr.
602 ****************************************************************************/
604 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
606 pstring fname;
607 int outsize = 0;
608 SMB_STRUCT_STAT sbuf;
609 BOOL ok = False;
610 int mode=0;
611 SMB_OFF_T size=0;
612 time_t mtime=0;
613 BOOL bad_path = False;
614 char *p;
615 NTSTATUS status;
617 START_PROFILE(SMBgetatr);
619 p = smb_buf(inbuf) + 1;
620 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
621 if (!NT_STATUS_IS_OK(status)) {
622 END_PROFILE(SMBgetatr);
623 return ERROR_NT(status);
626 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
628 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
629 under WfWg - weird! */
630 if (! (*fname)) {
631 mode = aHIDDEN | aDIR;
632 if (!CAN_WRITE(conn))
633 mode |= aRONLY;
634 size = 0;
635 mtime = 0;
636 ok = True;
637 } else {
638 unix_convert(fname,conn,0,&bad_path,&sbuf);
639 if (bad_path) {
640 END_PROFILE(SMBgetatr);
641 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
643 if (check_name(fname,conn)) {
644 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
645 mode = dos_mode(conn,fname,&sbuf);
646 size = sbuf.st_size;
647 mtime = sbuf.st_mtime;
648 if (mode & aDIR)
649 size = 0;
650 ok = True;
651 } else {
652 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
657 if (!ok) {
658 END_PROFILE(SMBgetatr);
659 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
662 outsize = set_message(outbuf,10,0,True);
664 SSVAL(outbuf,smb_vwv0,mode);
665 if(lp_dos_filetime_resolution(SNUM(conn)) )
666 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
667 else
668 put_dos_date3(outbuf,smb_vwv1,mtime);
669 SIVAL(outbuf,smb_vwv3,(uint32)size);
671 if (Protocol >= PROTOCOL_NT1)
672 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
674 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
676 END_PROFILE(SMBgetatr);
677 return(outsize);
680 /****************************************************************************
681 Reply to a setatr.
682 ****************************************************************************/
684 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
686 pstring fname;
687 int outsize = 0;
688 BOOL ok=False;
689 int mode;
690 time_t mtime;
691 SMB_STRUCT_STAT sbuf;
692 BOOL bad_path = False;
693 char *p;
694 NTSTATUS status;
696 START_PROFILE(SMBsetatr);
698 p = smb_buf(inbuf) + 1;
699 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
700 if (!NT_STATUS_IS_OK(status)) {
701 END_PROFILE(SMBsetatr);
702 return ERROR_NT(status);
705 unix_convert(fname,conn,0,&bad_path,&sbuf);
706 if (bad_path) {
707 END_PROFILE(SMBsetatr);
708 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
711 mode = SVAL(inbuf,smb_vwv0);
712 mtime = make_unix_date3(inbuf+smb_vwv1);
714 if (mode != FILE_ATTRIBUTE_NORMAL) {
715 if (VALID_STAT_OF_DIR(sbuf))
716 mode |= aDIR;
717 else
718 mode &= ~aDIR;
720 if (check_name(fname,conn)) {
721 ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
723 } else {
724 ok = True;
727 if (ok)
728 ok = set_filetime(conn,fname,mtime);
730 if (!ok) {
731 END_PROFILE(SMBsetatr);
732 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
735 outsize = set_message(outbuf,0,0,True);
737 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
739 END_PROFILE(SMBsetatr);
740 return(outsize);
743 /****************************************************************************
744 Reply to a dskattr.
745 ****************************************************************************/
747 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
749 int outsize = 0;
750 SMB_BIG_UINT dfree,dsize,bsize;
751 START_PROFILE(SMBdskattr);
753 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
755 outsize = set_message(outbuf,5,0,True);
757 if (Protocol <= PROTOCOL_LANMAN2) {
758 double total_space, free_space;
759 /* we need to scale this to a number that DOS6 can handle. We
760 use floating point so we can handle large drives on systems
761 that don't have 64 bit integers
763 we end up displaying a maximum of 2G to DOS systems
765 total_space = dsize * (double)bsize;
766 free_space = dfree * (double)bsize;
768 dsize = (total_space+63*512) / (64*512);
769 dfree = (free_space+63*512) / (64*512);
771 if (dsize > 0xFFFF) dsize = 0xFFFF;
772 if (dfree > 0xFFFF) dfree = 0xFFFF;
774 SSVAL(outbuf,smb_vwv0,dsize);
775 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
776 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
777 SSVAL(outbuf,smb_vwv3,dfree);
778 } else {
779 SSVAL(outbuf,smb_vwv0,dsize);
780 SSVAL(outbuf,smb_vwv1,bsize/512);
781 SSVAL(outbuf,smb_vwv2,512);
782 SSVAL(outbuf,smb_vwv3,dfree);
785 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
787 END_PROFILE(SMBdskattr);
788 return(outsize);
791 /****************************************************************************
792 Reply to a search.
793 Can be called from SMBsearch, SMBffirst or SMBfunique.
794 ****************************************************************************/
796 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
798 pstring mask;
799 pstring directory;
800 pstring fname;
801 SMB_OFF_T size;
802 int mode;
803 time_t date;
804 int dirtype;
805 int outsize = 0;
806 unsigned int numentries = 0;
807 unsigned int maxentries = 0;
808 BOOL finished = False;
809 char *p;
810 BOOL ok = False;
811 int status_len;
812 pstring path;
813 char status[21];
814 int dptr_num= -1;
815 BOOL check_descend = False;
816 BOOL expect_close = False;
817 BOOL can_open = True;
818 BOOL bad_path = False;
819 NTSTATUS nt_status;
820 START_PROFILE(SMBsearch);
822 *mask = *directory = *fname = 0;
824 /* If we were called as SMBffirst then we must expect close. */
825 if(CVAL(inbuf,smb_com) == SMBffirst)
826 expect_close = True;
828 outsize = set_message(outbuf,1,3,True);
829 maxentries = SVAL(inbuf,smb_vwv0);
830 dirtype = SVAL(inbuf,smb_vwv1);
831 p = smb_buf(inbuf) + 1;
832 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
833 if (!NT_STATUS_IS_OK(nt_status)) {
834 END_PROFILE(SMBsearch);
835 return ERROR_NT(nt_status);
837 p++;
838 status_len = SVAL(p, 0);
839 p += 2;
841 /* dirtype &= ~aDIR; */
843 if (status_len == 0) {
844 SMB_STRUCT_STAT sbuf;
845 pstring dir2;
847 pstrcpy(directory,path);
848 pstrcpy(dir2,path);
849 unix_convert(directory,conn,0,&bad_path,&sbuf);
850 unix_format(dir2);
852 if (!check_name(directory,conn))
853 can_open = False;
855 p = strrchr_m(dir2,'/');
856 if (p == NULL) {
857 pstrcpy(mask,dir2);
858 *dir2 = 0;
859 } else {
860 *p = 0;
861 pstrcpy(mask,p+1);
864 p = strrchr_m(directory,'/');
865 if (!p)
866 *directory = 0;
867 else
868 *p = 0;
870 if (strlen(directory) == 0)
871 pstrcpy(directory,".");
872 memset((char *)status,'\0',21);
873 SCVAL(status,0,(dirtype & 0x1F));
874 } else {
875 int status_dirtype;
877 memcpy(status,p,21);
878 status_dirtype = CVAL(status,0) & 0x1F;
879 if (status_dirtype != (dirtype & 0x1F))
880 dirtype = status_dirtype;
882 conn->dirptr = dptr_fetch(status+12,&dptr_num);
883 if (!conn->dirptr)
884 goto SearchEmpty;
885 string_set(&conn->dirpath,dptr_path(dptr_num));
886 pstrcpy(mask, dptr_wcard(dptr_num));
889 if (can_open) {
890 p = smb_buf(outbuf) + 3;
891 ok = True;
893 if (status_len == 0) {
894 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
895 if (dptr_num < 0) {
896 if(dptr_num == -2) {
897 END_PROFILE(SMBsearch);
898 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
900 END_PROFILE(SMBsearch);
901 return ERROR_DOS(ERRDOS,ERRnofids);
903 dptr_set_wcard(dptr_num, SMB_STRDUP(mask));
904 dptr_set_attr(dptr_num, dirtype);
905 } else {
906 dirtype = dptr_attr(dptr_num);
909 DEBUG(4,("dptr_num is %d\n",dptr_num));
911 if (ok) {
912 if ((dirtype&0x1F) == aVOLID) {
913 memcpy(p,status,21);
914 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
915 dptr_fill(p+12,dptr_num);
916 if (dptr_zero(p+12) && (status_len==0))
917 numentries = 1;
918 else
919 numentries = 0;
920 p += DIR_STRUCT_SIZE;
921 } else {
922 unsigned int i;
923 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
925 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
926 conn->dirpath,lp_dontdescend(SNUM(conn))));
927 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
928 check_descend = True;
930 for (i=numentries;(i<maxentries) && !finished;i++) {
931 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
932 if (!finished) {
933 memcpy(p,status,21);
934 make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
935 dptr_fill(p+12,dptr_num);
936 numentries++;
937 p += DIR_STRUCT_SIZE;
941 } /* if (ok ) */
945 SearchEmpty:
947 /* If we were called as SMBffirst with smb_search_id == NULL
948 and no entries were found then return error and close dirptr
949 (X/Open spec) */
951 if(ok && expect_close && numentries == 0 && status_len == 0) {
952 /* Close the dptr - we know it's gone */
953 dptr_close(&dptr_num);
954 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
955 } else if (numentries == 0 || !ok) {
956 dptr_close(&dptr_num);
957 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
960 /* If we were called as SMBfunique, then we can close the dirptr now ! */
961 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
962 dptr_close(&dptr_num);
964 SSVAL(outbuf,smb_vwv0,numentries);
965 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
966 SCVAL(smb_buf(outbuf),0,5);
967 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
969 if (Protocol >= PROTOCOL_NT1)
970 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
972 outsize += DIR_STRUCT_SIZE*numentries;
973 smb_setlen(outbuf,outsize - 4);
975 if ((! *directory) && dptr_path(dptr_num))
976 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
978 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
979 smb_fn_name(CVAL(inbuf,smb_com)),
980 mask, directory, dirtype, numentries, maxentries ) );
982 END_PROFILE(SMBsearch);
983 return(outsize);
986 /****************************************************************************
987 Reply to a fclose (stop directory search).
988 ****************************************************************************/
990 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
992 int outsize = 0;
993 int status_len;
994 pstring path;
995 char status[21];
996 int dptr_num= -2;
997 char *p;
998 NTSTATUS err;
1000 START_PROFILE(SMBfclose);
1002 outsize = set_message(outbuf,1,0,True);
1003 p = smb_buf(inbuf) + 1;
1004 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1005 if (!NT_STATUS_IS_OK(err)) {
1006 END_PROFILE(SMBfclose);
1007 return ERROR_NT(err);
1009 p++;
1010 status_len = SVAL(p,0);
1011 p += 2;
1013 if (status_len == 0) {
1014 END_PROFILE(SMBfclose);
1015 return ERROR_DOS(ERRSRV,ERRsrverror);
1018 memcpy(status,p,21);
1020 if(dptr_fetch(status+12,&dptr_num)) {
1021 /* Close the dptr - we know it's gone */
1022 dptr_close(&dptr_num);
1025 SSVAL(outbuf,smb_vwv0,0);
1027 DEBUG(3,("search close\n"));
1029 END_PROFILE(SMBfclose);
1030 return(outsize);
1033 /****************************************************************************
1034 Reply to an open.
1035 ****************************************************************************/
1037 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1039 pstring fname;
1040 int outsize = 0;
1041 int fmode=0;
1042 int share_mode;
1043 SMB_OFF_T size = 0;
1044 time_t mtime=0;
1045 int rmode=0;
1046 SMB_STRUCT_STAT sbuf;
1047 BOOL bad_path = False;
1048 files_struct *fsp;
1049 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1050 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1051 NTSTATUS status;
1052 START_PROFILE(SMBopen);
1054 share_mode = SVAL(inbuf,smb_vwv0);
1056 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 END_PROFILE(SMBopen);
1059 return ERROR_NT(status);
1062 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1064 unix_convert(fname,conn,0,&bad_path,&sbuf);
1065 if (bad_path) {
1066 END_PROFILE(SMBopen);
1067 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1070 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1071 (uint32)dos_attr, oplock_request,&rmode,NULL);
1073 if (!fsp) {
1074 END_PROFILE(SMBopen);
1075 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1076 /* We have re-scheduled this call. */
1077 clear_cached_errors();
1078 return -1;
1080 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1083 size = sbuf.st_size;
1084 fmode = dos_mode(conn,fname,&sbuf);
1085 mtime = sbuf.st_mtime;
1087 if (fmode & aDIR) {
1088 DEBUG(3,("attempt to open a directory %s\n",fname));
1089 close_file(fsp,False);
1090 END_PROFILE(SMBopen);
1091 return ERROR_DOS(ERRDOS,ERRnoaccess);
1094 outsize = set_message(outbuf,7,0,True);
1095 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1096 SSVAL(outbuf,smb_vwv1,fmode);
1097 if(lp_dos_filetime_resolution(SNUM(conn)) )
1098 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1099 else
1100 put_dos_date3(outbuf,smb_vwv2,mtime);
1101 SIVAL(outbuf,smb_vwv4,(uint32)size);
1102 SSVAL(outbuf,smb_vwv6,rmode);
1104 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1105 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1107 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1108 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1109 END_PROFILE(SMBopen);
1110 return(outsize);
1113 /****************************************************************************
1114 Reply to an open and X.
1115 ****************************************************************************/
1117 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1119 pstring fname;
1120 int smb_mode = SVAL(inbuf,smb_vwv3);
1121 int smb_attr = SVAL(inbuf,smb_vwv5);
1122 /* Breakout the oplock request bits so we can set the
1123 reply bits separately. */
1124 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1125 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1126 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1127 #if 0
1128 int open_flags = SVAL(inbuf,smb_vwv2);
1129 int smb_sattr = SVAL(inbuf,smb_vwv4);
1130 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1131 #endif
1132 int smb_ofun = SVAL(inbuf,smb_vwv8);
1133 SMB_OFF_T size=0;
1134 int fmode=0,mtime=0,rmode=0;
1135 SMB_STRUCT_STAT sbuf;
1136 int smb_action = 0;
1137 BOOL bad_path = False;
1138 files_struct *fsp;
1139 NTSTATUS status;
1140 START_PROFILE(SMBopenX);
1142 /* If it's an IPC, pass off the pipe handler. */
1143 if (IS_IPC(conn)) {
1144 if (lp_nt_pipe_support()) {
1145 END_PROFILE(SMBopenX);
1146 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1147 } else {
1148 END_PROFILE(SMBopenX);
1149 return ERROR_DOS(ERRSRV,ERRaccess);
1153 /* XXXX we need to handle passed times, sattr and flags */
1154 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1155 if (!NT_STATUS_IS_OK(status)) {
1156 END_PROFILE(SMBopenX);
1157 return ERROR_NT(status);
1160 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1162 unix_convert(fname,conn,0,&bad_path,&sbuf);
1163 if (bad_path) {
1164 END_PROFILE(SMBopenX);
1165 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1168 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1169 oplock_request, &rmode,&smb_action);
1171 if (!fsp) {
1172 END_PROFILE(SMBopenX);
1173 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1174 /* We have re-scheduled this call. */
1175 clear_cached_errors();
1176 return -1;
1178 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1181 size = sbuf.st_size;
1182 fmode = dos_mode(conn,fname,&sbuf);
1183 mtime = sbuf.st_mtime;
1184 if (fmode & aDIR) {
1185 close_file(fsp,False);
1186 END_PROFILE(SMBopenX);
1187 return ERROR_DOS(ERRDOS,ERRnoaccess);
1190 /* If the caller set the extended oplock request bit
1191 and we granted one (by whatever means) - set the
1192 correct bit for extended oplock reply.
1195 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1196 smb_action |= EXTENDED_OPLOCK_GRANTED;
1198 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1199 smb_action |= EXTENDED_OPLOCK_GRANTED;
1201 /* If the caller set the core oplock request bit
1202 and we granted one (by whatever means) - set the
1203 correct bit for core oplock reply.
1206 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1207 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1209 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1210 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1212 set_message(outbuf,15,0,True);
1213 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1214 SSVAL(outbuf,smb_vwv3,fmode);
1215 if(lp_dos_filetime_resolution(SNUM(conn)) )
1216 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1217 else
1218 put_dos_date3(outbuf,smb_vwv4,mtime);
1219 SIVAL(outbuf,smb_vwv6,(uint32)size);
1220 SSVAL(outbuf,smb_vwv8,rmode);
1221 SSVAL(outbuf,smb_vwv11,smb_action);
1223 END_PROFILE(SMBopenX);
1224 return chain_reply(inbuf,outbuf,length,bufsize);
1227 /****************************************************************************
1228 Reply to a SMBulogoffX.
1229 ****************************************************************************/
1231 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1233 uint16 vuid = SVAL(inbuf,smb_uid);
1234 user_struct *vuser = get_valid_user_struct(vuid);
1235 START_PROFILE(SMBulogoffX);
1237 if(vuser == 0)
1238 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1240 /* in user level security we are supposed to close any files
1241 open by this user */
1242 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1243 file_close_user(vuid);
1245 invalidate_vuid(vuid);
1247 set_message(outbuf,2,0,True);
1249 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1251 END_PROFILE(SMBulogoffX);
1252 return chain_reply(inbuf,outbuf,length,bufsize);
1255 /****************************************************************************
1256 Reply to a mknew or a create.
1257 ****************************************************************************/
1259 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1261 pstring fname;
1262 int com;
1263 int outsize = 0;
1264 int createmode;
1265 int ofun = 0;
1266 BOOL bad_path = False;
1267 files_struct *fsp;
1268 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1269 SMB_STRUCT_STAT sbuf;
1270 NTSTATUS status;
1271 START_PROFILE(SMBcreate);
1273 com = SVAL(inbuf,smb_com);
1275 createmode = SVAL(inbuf,smb_vwv0);
1276 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 END_PROFILE(SMBcreate);
1279 return ERROR_NT(status);
1282 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1284 unix_convert(fname,conn,0,&bad_path,&sbuf);
1285 if (bad_path) {
1286 END_PROFILE(SMBcreate);
1287 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1290 if (createmode & aVOLID)
1291 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1293 if(com == SMBmknew) {
1294 /* We should fail if file exists. */
1295 ofun = FILE_CREATE_IF_NOT_EXIST;
1296 } else {
1297 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1298 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1301 /* Open file in dos compatibility share mode. */
1302 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1303 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1305 if (!fsp) {
1306 END_PROFILE(SMBcreate);
1307 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1308 /* We have re-scheduled this call. */
1309 clear_cached_errors();
1310 return -1;
1312 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1315 outsize = set_message(outbuf,1,0,True);
1316 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1318 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1319 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1321 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1322 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1324 DEBUG( 2, ( "new file %s\n", fname ) );
1325 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1327 END_PROFILE(SMBcreate);
1328 return(outsize);
1331 /****************************************************************************
1332 Reply to a create temporary file.
1333 ****************************************************************************/
1335 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1337 pstring fname;
1338 int outsize = 0;
1339 int createattr;
1340 BOOL bad_path = False;
1341 files_struct *fsp;
1342 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1343 int tmpfd;
1344 SMB_STRUCT_STAT sbuf;
1345 char *p, *s;
1346 NTSTATUS status;
1347 unsigned int namelen;
1349 START_PROFILE(SMBctemp);
1351 createattr = SVAL(inbuf,smb_vwv0);
1352 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1353 if (!NT_STATUS_IS_OK(status)) {
1354 END_PROFILE(SMBctemp);
1355 return ERROR_NT(status);
1357 if (*fname) {
1358 pstrcat(fname,"/TMXXXXXX");
1359 } else {
1360 pstrcat(fname,"TMXXXXXX");
1363 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1365 unix_convert(fname,conn,0,&bad_path,&sbuf);
1366 if (bad_path) {
1367 END_PROFILE(SMBctemp);
1368 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1371 tmpfd = smb_mkstemp(fname);
1372 if (tmpfd == -1) {
1373 END_PROFILE(SMBctemp);
1374 return(UNIXERROR(ERRDOS,ERRnoaccess));
1377 SMB_VFS_STAT(conn,fname,&sbuf);
1379 /* Open file in dos compatibility share mode. */
1380 /* We should fail if file does not exist. */
1381 fsp = open_file_shared(conn,fname,&sbuf,
1382 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1383 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1384 (uint32)createattr, oplock_request, NULL, NULL);
1386 /* close fd from smb_mkstemp() */
1387 close(tmpfd);
1389 if (!fsp) {
1390 END_PROFILE(SMBctemp);
1391 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1392 /* We have re-scheduled this call. */
1393 clear_cached_errors();
1394 return -1;
1396 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1399 outsize = set_message(outbuf,1,0,True);
1400 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1402 /* the returned filename is relative to the directory */
1403 s = strrchr_m(fname, '/');
1404 if (!s)
1405 s = fname;
1406 else
1407 s++;
1409 p = smb_buf(outbuf);
1410 #if 0
1411 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1412 thing in the byte section. JRA */
1413 SSVALS(p, 0, -1); /* what is this? not in spec */
1414 #endif
1415 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1416 p += namelen;
1417 outsize = set_message_end(outbuf, p);
1419 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1420 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1422 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1423 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1425 DEBUG( 2, ( "created temp file %s\n", fname ) );
1426 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1427 fname, fsp->fd, sbuf.st_mode ) );
1429 END_PROFILE(SMBctemp);
1430 return(outsize);
1433 /*******************************************************************
1434 Check if a user is allowed to rename a file.
1435 ********************************************************************/
1437 static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
1439 int smb_action;
1440 int access_mode;
1441 files_struct *fsp;
1442 uint16 fmode;
1444 if (!CAN_WRITE(conn))
1445 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1447 fmode = dos_mode(conn,fname,pst);
1448 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1449 return NT_STATUS_NO_SUCH_FILE;
1451 if (S_ISDIR(pst->st_mode))
1452 return NT_STATUS_OK;
1454 /* We need a better way to return NT status codes from open... */
1455 unix_ERR_class = 0;
1456 unix_ERR_code = 0;
1458 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1459 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1461 if (!fsp) {
1462 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1463 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1464 ret = NT_STATUS_SHARING_VIOLATION;
1465 unix_ERR_class = 0;
1466 unix_ERR_code = 0;
1467 unix_ERR_ntstatus = NT_STATUS_OK;
1468 return ret;
1470 close_file(fsp,False);
1471 return NT_STATUS_OK;
1474 /*******************************************************************
1475 Check if a user is allowed to delete a file.
1476 ********************************************************************/
1478 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
1480 SMB_STRUCT_STAT sbuf;
1481 int fmode;
1482 int smb_action;
1483 int access_mode;
1484 files_struct *fsp;
1486 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1487 fname, dirtype ));
1489 if (!CAN_WRITE(conn))
1490 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1492 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1493 if(errno == ENOENT) {
1494 if (bad_path)
1495 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1496 else
1497 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1499 return map_nt_error_from_unix(errno);
1502 fmode = dos_mode(conn,fname,&sbuf);
1504 /* Can't delete a directory. */
1505 if (fmode & aDIR)
1506 return NT_STATUS_FILE_IS_A_DIRECTORY;
1507 #if 0 /* JRATEST */
1508 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1509 return NT_STATUS_OBJECT_NAME_INVALID;
1510 #endif /* JRATEST */
1512 if (!lp_delete_readonly(SNUM(conn))) {
1513 if (fmode & aRONLY)
1514 return NT_STATUS_CANNOT_DELETE;
1516 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1517 return NT_STATUS_NO_SUCH_FILE;
1519 /* We need a better way to return NT status codes from open... */
1520 unix_ERR_class = 0;
1521 unix_ERR_code = 0;
1523 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1524 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1526 if (!fsp) {
1527 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1528 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1529 ret = unix_ERR_ntstatus;
1530 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1531 ret = NT_STATUS_SHARING_VIOLATION;
1532 unix_ERR_class = 0;
1533 unix_ERR_code = 0;
1534 unix_ERR_ntstatus = NT_STATUS_OK;
1535 return ret;
1537 close_file(fsp,False);
1538 return NT_STATUS_OK;
1541 /****************************************************************************
1542 The guts of the unlink command, split out so it may be called by the NT SMB
1543 code.
1544 ****************************************************************************/
1546 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1548 pstring directory;
1549 pstring mask;
1550 char *p;
1551 int count=0;
1552 NTSTATUS error = NT_STATUS_OK;
1553 BOOL has_wild;
1554 BOOL bad_path = False;
1555 BOOL rc = True;
1556 SMB_STRUCT_STAT sbuf;
1558 *directory = *mask = 0;
1560 /* We must check for wildcards in the name given
1561 * directly by the client - before any unmangling.
1562 * This prevents an unmangling of a UNIX name containing
1563 * a DOS wildcard like '*' or '?' from unmangling into
1564 * a wildcard delete which was not intended.
1565 * FIX for #226. JRA.
1568 has_wild = ms_has_wild(name);
1570 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1572 p = strrchr_m(name,'/');
1573 if (!p) {
1574 pstrcpy(directory,".");
1575 pstrcpy(mask,name);
1576 } else {
1577 *p = 0;
1578 pstrcpy(directory,name);
1579 pstrcpy(mask,p+1);
1583 * We should only check the mangled cache
1584 * here if unix_convert failed. This means
1585 * that the path in 'mask' doesn't exist
1586 * on the file system and so we need to look
1587 * for a possible mangle. This patch from
1588 * Tine Smukavec <valentin.smukavec@hermes.si>.
1591 if (!rc && mangle_is_mangled(mask))
1592 mangle_check_cache( mask, sizeof(pstring)-1 );
1594 if (!has_wild) {
1595 pstrcat(directory,"/");
1596 pstrcat(directory,mask);
1597 error = can_delete(directory,conn,dirtype,bad_path);
1598 if (!NT_STATUS_IS_OK(error))
1599 return error;
1601 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1602 count++;
1604 } else {
1605 void *dirptr = NULL;
1606 const char *dname;
1608 if (check_name(directory,conn))
1609 dirptr = OpenDir(conn, directory, True);
1611 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1612 the pattern matches against the long name, otherwise the short name
1613 We don't implement this yet XXXX
1616 if (dirptr) {
1617 error = NT_STATUS_NO_SUCH_FILE;
1619 if (strequal(mask,"????????.???"))
1620 pstrcpy(mask,"*");
1622 while ((dname = ReadDirName(dirptr))) {
1623 pstring fname;
1624 BOOL sys_direntry = False;
1625 pstrcpy(fname,dname);
1627 /* Quick check for "." and ".." */
1628 if (fname[0] == '.') {
1629 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1630 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1631 sys_direntry = True;
1632 } else {
1633 continue;
1638 if(!mask_match(fname, mask, conn->case_sensitive))
1639 continue;
1641 if (sys_direntry) {
1642 error = NT_STATUS_OBJECT_NAME_INVALID;
1643 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1644 fname, mask));
1645 break;
1648 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1649 error = can_delete(fname,conn,dirtype,bad_path);
1650 if (!NT_STATUS_IS_OK(error)) {
1651 continue;
1653 if (SMB_VFS_UNLINK(conn,fname) == 0)
1654 count++;
1655 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1657 CloseDir(dirptr);
1661 if (count == 0 && NT_STATUS_IS_OK(error)) {
1662 error = map_nt_error_from_unix(errno);
1665 return error;
1668 /****************************************************************************
1669 Reply to a unlink
1670 ****************************************************************************/
1672 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1673 int dum_buffsize)
1675 int outsize = 0;
1676 pstring name;
1677 int dirtype;
1678 NTSTATUS status;
1679 START_PROFILE(SMBunlink);
1681 dirtype = SVAL(inbuf,smb_vwv0);
1683 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 END_PROFILE(SMBunlink);
1686 return ERROR_NT(status);
1689 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1691 DEBUG(3,("reply_unlink : %s\n",name));
1693 status = unlink_internals(conn, dirtype, name);
1694 if (!NT_STATUS_IS_OK(status)) {
1695 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1696 /* We have re-scheduled this call. */
1697 clear_cached_errors();
1698 return -1;
1700 return ERROR_NT(status);
1704 * Win2k needs a changenotify request response before it will
1705 * update after a rename..
1707 process_pending_change_notify_queue((time_t)0);
1709 outsize = set_message(outbuf,0,0,True);
1711 END_PROFILE(SMBunlink);
1712 return outsize;
1715 /****************************************************************************
1716 Fail for readbraw.
1717 ****************************************************************************/
1719 void fail_readraw(void)
1721 pstring errstr;
1722 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1723 strerror(errno) );
1724 exit_server(errstr);
1727 /****************************************************************************
1728 Use sendfile in readbraw.
1729 ****************************************************************************/
1731 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1732 ssize_t mincount, char *outbuf)
1734 ssize_t ret=0;
1736 #if defined(WITH_SENDFILE)
1738 * We can only use sendfile on a non-chained packet
1739 * but we can use on a non-oplocked file. tridge proved this
1740 * on a train in Germany :-). JRA.
1741 * reply_readbraw has already checked the length.
1744 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1745 DATA_BLOB header;
1747 _smb_setlen(outbuf,nread);
1748 header.data = outbuf;
1749 header.length = 4;
1750 header.free = NULL;
1752 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1754 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1755 * return ENOSYS then pretend we just got a normal read.
1757 if (errno == ENOSYS) {
1758 set_use_sendfile(SNUM(conn), False);
1759 goto normal_read;
1762 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1763 fsp->fsp_name, strerror(errno) ));
1764 exit_server("send_file_readbraw sendfile failed");
1769 normal_read:
1770 #endif
1772 if (nread > 0) {
1773 ret = read_file(fsp,outbuf+4,startpos,nread);
1774 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1775 if (ret < mincount)
1776 ret = 0;
1777 #else
1778 if (ret < nread)
1779 ret = 0;
1780 #endif
1783 _smb_setlen(outbuf,ret);
1784 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1785 fail_readraw();
1788 /****************************************************************************
1789 Reply to a readbraw (core+ protocol).
1790 ****************************************************************************/
1792 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1794 extern struct current_user current_user;
1795 ssize_t maxcount,mincount;
1796 size_t nread = 0;
1797 SMB_OFF_T startpos;
1798 char *header = outbuf;
1799 files_struct *fsp;
1800 START_PROFILE(SMBreadbraw);
1802 if (srv_is_signing_active()) {
1803 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1807 * Special check if an oplock break has been issued
1808 * and the readraw request croses on the wire, we must
1809 * return a zero length response here.
1812 if(global_oplock_break) {
1813 _smb_setlen(header,0);
1814 if (write_data(smbd_server_fd(),header,4) != 4)
1815 fail_readraw();
1816 DEBUG(5,("readbraw - oplock break finished\n"));
1817 END_PROFILE(SMBreadbraw);
1818 return -1;
1821 fsp = file_fsp(inbuf,smb_vwv0);
1823 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1825 * fsp could be NULL here so use the value from the packet. JRA.
1827 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1828 _smb_setlen(header,0);
1829 if (write_data(smbd_server_fd(),header,4) != 4)
1830 fail_readraw();
1831 END_PROFILE(SMBreadbraw);
1832 return(-1);
1835 CHECK_FSP(fsp,conn);
1837 flush_write_cache(fsp, READRAW_FLUSH);
1839 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1840 if(CVAL(inbuf,smb_wct) == 10) {
1842 * This is a large offset (64 bit) read.
1844 #ifdef LARGE_SMB_OFF_T
1846 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1848 #else /* !LARGE_SMB_OFF_T */
1851 * Ensure we haven't been sent a >32 bit offset.
1854 if(IVAL(inbuf,smb_vwv8) != 0) {
1855 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1856 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1857 _smb_setlen(header,0);
1858 if (write_data(smbd_server_fd(),header,4) != 4)
1859 fail_readraw();
1860 END_PROFILE(SMBreadbraw);
1861 return(-1);
1864 #endif /* LARGE_SMB_OFF_T */
1866 if(startpos < 0) {
1867 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1868 _smb_setlen(header,0);
1869 if (write_data(smbd_server_fd(),header,4) != 4)
1870 fail_readraw();
1871 END_PROFILE(SMBreadbraw);
1872 return(-1);
1875 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1876 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1878 /* ensure we don't overrun the packet size */
1879 maxcount = MIN(65535,maxcount);
1881 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1882 SMB_OFF_T size = fsp->size;
1883 SMB_OFF_T sizeneeded = startpos + maxcount;
1885 if (size < sizeneeded) {
1886 SMB_STRUCT_STAT st;
1887 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1888 size = st.st_size;
1889 if (!fsp->can_write)
1890 fsp->size = size;
1893 if (startpos >= size)
1894 nread = 0;
1895 else
1896 nread = MIN(maxcount,(size - startpos));
1899 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1900 if (nread < mincount)
1901 nread = 0;
1902 #endif
1904 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1905 (int)maxcount, (int)mincount, (int)nread ) );
1907 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1909 DEBUG(5,("readbraw finished\n"));
1910 END_PROFILE(SMBreadbraw);
1911 return -1;
1914 /****************************************************************************
1915 Reply to a lockread (core+ protocol).
1916 ****************************************************************************/
1918 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1920 ssize_t nread = -1;
1921 char *data;
1922 int outsize = 0;
1923 SMB_OFF_T startpos;
1924 size_t numtoread;
1925 NTSTATUS status;
1926 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1927 BOOL my_lock_ctx = False;
1928 START_PROFILE(SMBlockread);
1930 CHECK_FSP(fsp,conn);
1931 CHECK_READ(fsp);
1933 release_level_2_oplocks_on_change(fsp);
1935 numtoread = SVAL(inbuf,smb_vwv1);
1936 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1938 outsize = set_message(outbuf,5,3,True);
1939 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1940 data = smb_buf(outbuf) + 3;
1943 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1944 * protocol request that predates the read/write lock concept.
1945 * Thus instead of asking for a read lock here we need to ask
1946 * for a write lock. JRA.
1947 * Note that the requested lock size is unaffected by max_recv.
1950 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1951 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1953 if (NT_STATUS_V(status)) {
1954 #if 0
1956 * We used to make lockread a blocking lock. It turns out
1957 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1958 * tester. JRA.
1961 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1963 * A blocking lock was requested. Package up
1964 * this smb into a queued request and push it
1965 * onto the blocking lock queue.
1967 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1968 (SMB_BIG_UINT)numtoread)) {
1969 END_PROFILE(SMBlockread);
1970 return -1;
1973 #endif
1974 END_PROFILE(SMBlockread);
1975 return ERROR_NT(status);
1979 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1982 if (numtoread > max_recv) {
1983 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1984 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1985 (unsigned int)numtoread, (unsigned int)max_recv ));
1986 numtoread = MIN(numtoread,max_recv);
1988 nread = read_file(fsp,data,startpos,numtoread);
1990 if (nread < 0) {
1991 END_PROFILE(SMBlockread);
1992 return(UNIXERROR(ERRDOS,ERRnoaccess));
1995 outsize += nread;
1996 SSVAL(outbuf,smb_vwv0,nread);
1997 SSVAL(outbuf,smb_vwv5,nread+3);
1998 SSVAL(smb_buf(outbuf),1,nread);
2000 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2001 fsp->fnum, (int)numtoread, (int)nread));
2003 END_PROFILE(SMBlockread);
2004 return(outsize);
2007 /****************************************************************************
2008 Reply to a read.
2009 ****************************************************************************/
2011 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2013 size_t numtoread;
2014 ssize_t nread = 0;
2015 char *data;
2016 SMB_OFF_T startpos;
2017 int outsize = 0;
2018 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2019 START_PROFILE(SMBread);
2021 CHECK_FSP(fsp,conn);
2022 CHECK_READ(fsp);
2024 numtoread = SVAL(inbuf,smb_vwv1);
2025 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2027 outsize = set_message(outbuf,5,3,True);
2028 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2030 * The requested read size cannot be greater than max_recv. JRA.
2032 if (numtoread > max_recv) {
2033 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2034 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2035 (unsigned int)numtoread, (unsigned int)max_recv ));
2036 numtoread = MIN(numtoread,max_recv);
2039 data = smb_buf(outbuf) + 3;
2041 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2042 END_PROFILE(SMBread);
2043 return ERROR_DOS(ERRDOS,ERRlock);
2046 if (numtoread > 0)
2047 nread = read_file(fsp,data,startpos,numtoread);
2049 if (nread < 0) {
2050 END_PROFILE(SMBread);
2051 return(UNIXERROR(ERRDOS,ERRnoaccess));
2054 outsize += nread;
2055 SSVAL(outbuf,smb_vwv0,nread);
2056 SSVAL(outbuf,smb_vwv5,nread+3);
2057 SCVAL(smb_buf(outbuf),0,1);
2058 SSVAL(smb_buf(outbuf),1,nread);
2060 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2061 fsp->fnum, (int)numtoread, (int)nread ) );
2063 END_PROFILE(SMBread);
2064 return(outsize);
2067 /****************************************************************************
2068 Reply to a read and X - possibly using sendfile.
2069 ****************************************************************************/
2071 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
2072 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2074 ssize_t nread = -1;
2075 char *data = smb_buf(outbuf);
2077 #if defined(WITH_SENDFILE)
2079 * We can only use sendfile on a non-chained packet
2080 * but we can use on a non-oplocked file. tridge proved this
2081 * on a train in Germany :-). JRA.
2084 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2085 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2086 SMB_STRUCT_STAT sbuf;
2087 DATA_BLOB header;
2089 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2090 return(UNIXERROR(ERRDOS,ERRnoaccess));
2092 if (startpos > sbuf.st_size)
2093 goto normal_read;
2095 if (smb_maxcnt > (sbuf.st_size - startpos))
2096 smb_maxcnt = (sbuf.st_size - startpos);
2098 if (smb_maxcnt == 0)
2099 goto normal_read;
2102 * Set up the packet header before send. We
2103 * assume here the sendfile will work (get the
2104 * correct amount of data).
2107 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2108 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2109 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2110 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2111 SCVAL(outbuf,smb_vwv0,0xFF);
2112 set_message(outbuf,12,smb_maxcnt,False);
2113 header.data = outbuf;
2114 header.length = data - outbuf;
2115 header.free = NULL;
2117 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2119 * Special hack for broken Linux with no 64 bit clean sendfile. If we
2120 * return ENOSYS then pretend we just got a normal read.
2122 if (errno == ENOSYS) {
2123 set_use_sendfile(SNUM(conn), False);
2124 goto normal_read;
2127 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2128 fsp->fsp_name, strerror(errno) ));
2129 exit_server("send_file_readX sendfile failed");
2132 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2133 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2134 return -1;
2137 normal_read:
2139 #endif
2141 nread = read_file(fsp,data,startpos,smb_maxcnt);
2143 if (nread < 0) {
2144 END_PROFILE(SMBreadX);
2145 return(UNIXERROR(ERRDOS,ERRnoaccess));
2148 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2149 SSVAL(outbuf,smb_vwv5,nread);
2150 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2151 SSVAL(smb_buf(outbuf),-2,nread);
2153 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2154 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2156 return nread;
2159 /****************************************************************************
2160 Reply to a read and X.
2161 ****************************************************************************/
2163 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2165 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2166 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2167 ssize_t nread = -1;
2168 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2169 #if 0
2170 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2171 #endif
2173 START_PROFILE(SMBreadX);
2175 /* If it's an IPC, pass off the pipe handler. */
2176 if (IS_IPC(conn)) {
2177 END_PROFILE(SMBreadX);
2178 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2181 CHECK_FSP(fsp,conn);
2182 CHECK_READ(fsp);
2184 set_message(outbuf,12,0,True);
2186 if(CVAL(inbuf,smb_wct) == 12) {
2187 #ifdef LARGE_SMB_OFF_T
2189 * This is a large offset (64 bit) read.
2191 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2193 #else /* !LARGE_SMB_OFF_T */
2196 * Ensure we haven't been sent a >32 bit offset.
2199 if(IVAL(inbuf,smb_vwv10) != 0) {
2200 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2201 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2202 END_PROFILE(SMBreadX);
2203 return ERROR_DOS(ERRDOS,ERRbadaccess);
2206 #endif /* LARGE_SMB_OFF_T */
2210 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2211 END_PROFILE(SMBreadX);
2212 return ERROR_DOS(ERRDOS,ERRlock);
2215 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2216 if (nread != -1)
2217 nread = chain_reply(inbuf,outbuf,length,bufsize);
2219 END_PROFILE(SMBreadX);
2220 return nread;
2223 /****************************************************************************
2224 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2225 ****************************************************************************/
2227 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2229 ssize_t nwritten=0;
2230 ssize_t total_written=0;
2231 size_t numtowrite=0;
2232 size_t tcount;
2233 SMB_OFF_T startpos;
2234 char *data=NULL;
2235 BOOL write_through;
2236 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2237 int outsize = 0;
2238 START_PROFILE(SMBwritebraw);
2240 if (srv_is_signing_active()) {
2241 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2244 CHECK_FSP(fsp,conn);
2245 CHECK_WRITE(fsp);
2247 tcount = IVAL(inbuf,smb_vwv1);
2248 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2249 write_through = BITSETW(inbuf+smb_vwv7,0);
2251 /* We have to deal with slightly different formats depending
2252 on whether we are using the core+ or lanman1.0 protocol */
2254 if(Protocol <= PROTOCOL_COREPLUS) {
2255 numtowrite = SVAL(smb_buf(inbuf),-2);
2256 data = smb_buf(inbuf);
2257 } else {
2258 numtowrite = SVAL(inbuf,smb_vwv10);
2259 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2262 /* force the error type */
2263 SCVAL(inbuf,smb_com,SMBwritec);
2264 SCVAL(outbuf,smb_com,SMBwritec);
2266 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2267 END_PROFILE(SMBwritebraw);
2268 return(ERROR_DOS(ERRDOS,ERRlock));
2271 if (numtowrite>0)
2272 nwritten = write_file(fsp,data,startpos,numtowrite);
2274 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2275 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2277 if (nwritten < (ssize_t)numtowrite) {
2278 END_PROFILE(SMBwritebraw);
2279 return(UNIXERROR(ERRHRD,ERRdiskfull));
2282 total_written = nwritten;
2284 /* Return a message to the redirector to tell it to send more bytes */
2285 SCVAL(outbuf,smb_com,SMBwritebraw);
2286 SSVALS(outbuf,smb_vwv0,-1);
2287 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2288 if (!send_smb(smbd_server_fd(),outbuf))
2289 exit_server("reply_writebraw: send_smb failed.");
2291 /* Now read the raw data into the buffer and write it */
2292 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2293 exit_server("secondary writebraw failed");
2296 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2297 numtowrite = smb_len(inbuf);
2299 /* Set up outbuf to return the correct return */
2300 outsize = set_message(outbuf,1,0,True);
2301 SCVAL(outbuf,smb_com,SMBwritec);
2302 SSVAL(outbuf,smb_vwv0,total_written);
2304 if (numtowrite != 0) {
2306 if (numtowrite > BUFFER_SIZE) {
2307 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2308 (unsigned int)numtowrite ));
2309 exit_server("secondary writebraw failed");
2312 if (tcount > nwritten+numtowrite) {
2313 DEBUG(3,("Client overestimated the write %d %d %d\n",
2314 (int)tcount,(int)nwritten,(int)numtowrite));
2317 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2318 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2319 strerror(errno) ));
2320 exit_server("secondary writebraw failed");
2323 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2325 if (nwritten < (ssize_t)numtowrite) {
2326 SCVAL(outbuf,smb_rcls,ERRHRD);
2327 SSVAL(outbuf,smb_err,ERRdiskfull);
2330 if (nwritten > 0)
2331 total_written += nwritten;
2334 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2335 sync_file(conn,fsp);
2337 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2338 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2340 /* we won't return a status if write through is not selected - this follows what WfWg does */
2341 END_PROFILE(SMBwritebraw);
2342 if (!write_through && total_written==tcount) {
2344 #if RABBIT_PELLET_FIX
2346 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2347 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2349 if (!send_keepalive(smbd_server_fd()))
2350 exit_server("reply_writebraw: send of keepalive failed");
2351 #endif
2352 return(-1);
2355 return(outsize);
2358 /****************************************************************************
2359 Reply to a writeunlock (core+).
2360 ****************************************************************************/
2362 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2363 int size, int dum_buffsize)
2365 ssize_t nwritten = -1;
2366 size_t numtowrite;
2367 SMB_OFF_T startpos;
2368 char *data;
2369 NTSTATUS status = NT_STATUS_OK;
2370 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2371 int outsize = 0;
2372 START_PROFILE(SMBwriteunlock);
2374 CHECK_FSP(fsp,conn);
2375 CHECK_WRITE(fsp);
2377 numtowrite = SVAL(inbuf,smb_vwv1);
2378 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2379 data = smb_buf(inbuf) + 3;
2381 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2382 WRITE_LOCK,False)) {
2383 END_PROFILE(SMBwriteunlock);
2384 return ERROR_DOS(ERRDOS,ERRlock);
2387 /* The special X/Open SMB protocol handling of
2388 zero length writes is *NOT* done for
2389 this call */
2390 if(numtowrite == 0)
2391 nwritten = 0;
2392 else
2393 nwritten = write_file(fsp,data,startpos,numtowrite);
2395 if (lp_syncalways(SNUM(conn)))
2396 sync_file(conn,fsp);
2398 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2399 END_PROFILE(SMBwriteunlock);
2400 return(UNIXERROR(ERRHRD,ERRdiskfull));
2403 if (numtowrite) {
2404 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2405 (SMB_BIG_UINT)startpos);
2406 if (NT_STATUS_V(status)) {
2407 END_PROFILE(SMBwriteunlock);
2408 return ERROR_NT(status);
2412 outsize = set_message(outbuf,1,0,True);
2414 SSVAL(outbuf,smb_vwv0,nwritten);
2416 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2417 fsp->fnum, (int)numtowrite, (int)nwritten));
2419 END_PROFILE(SMBwriteunlock);
2420 return outsize;
2423 /****************************************************************************
2424 Reply to a write.
2425 ****************************************************************************/
2427 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2429 size_t numtowrite;
2430 ssize_t nwritten = -1;
2431 SMB_OFF_T startpos;
2432 char *data;
2433 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2434 int outsize = 0;
2435 START_PROFILE(SMBwrite);
2437 /* If it's an IPC, pass off the pipe handler. */
2438 if (IS_IPC(conn)) {
2439 END_PROFILE(SMBwrite);
2440 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2443 CHECK_FSP(fsp,conn);
2444 CHECK_WRITE(fsp);
2446 numtowrite = SVAL(inbuf,smb_vwv1);
2447 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2448 data = smb_buf(inbuf) + 3;
2450 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2451 END_PROFILE(SMBwrite);
2452 return ERROR_DOS(ERRDOS,ERRlock);
2456 * X/Open SMB protocol says that if smb_vwv1 is
2457 * zero then the file size should be extended or
2458 * truncated to the size given in smb_vwv[2-3].
2461 if(numtowrite == 0) {
2463 * This is actually an allocate call, and set EOF. JRA.
2465 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2466 if (nwritten < 0) {
2467 END_PROFILE(SMBwrite);
2468 return ERROR_NT(NT_STATUS_DISK_FULL);
2470 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2471 if (nwritten < 0) {
2472 END_PROFILE(SMBwrite);
2473 return ERROR_NT(NT_STATUS_DISK_FULL);
2475 } else
2476 nwritten = write_file(fsp,data,startpos,numtowrite);
2478 if (lp_syncalways(SNUM(conn)))
2479 sync_file(conn,fsp);
2481 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2482 END_PROFILE(SMBwrite);
2483 return(UNIXERROR(ERRHRD,ERRdiskfull));
2486 outsize = set_message(outbuf,1,0,True);
2488 SSVAL(outbuf,smb_vwv0,nwritten);
2490 if (nwritten < (ssize_t)numtowrite) {
2491 SCVAL(outbuf,smb_rcls,ERRHRD);
2492 SSVAL(outbuf,smb_err,ERRdiskfull);
2495 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2497 END_PROFILE(SMBwrite);
2498 return(outsize);
2501 /****************************************************************************
2502 Reply to a write and X.
2503 ****************************************************************************/
2505 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2507 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2508 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2509 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2510 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2511 ssize_t nwritten = -1;
2512 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2513 unsigned int smblen = smb_len(inbuf);
2514 char *data;
2515 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2516 START_PROFILE(SMBwriteX);
2518 /* If it's an IPC, pass off the pipe handler. */
2519 if (IS_IPC(conn)) {
2520 END_PROFILE(SMBwriteX);
2521 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2524 CHECK_FSP(fsp,conn);
2525 CHECK_WRITE(fsp);
2527 /* Deal with possible LARGE_WRITEX */
2528 if (large_writeX)
2529 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2531 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2532 END_PROFILE(SMBwriteX);
2533 return ERROR_DOS(ERRDOS,ERRbadmem);
2536 data = smb_base(inbuf) + smb_doff;
2538 if(CVAL(inbuf,smb_wct) == 14) {
2539 #ifdef LARGE_SMB_OFF_T
2541 * This is a large offset (64 bit) write.
2543 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2545 #else /* !LARGE_SMB_OFF_T */
2548 * Ensure we haven't been sent a >32 bit offset.
2551 if(IVAL(inbuf,smb_vwv12) != 0) {
2552 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2553 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2554 END_PROFILE(SMBwriteX);
2555 return ERROR_DOS(ERRDOS,ERRbadaccess);
2558 #endif /* LARGE_SMB_OFF_T */
2561 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2562 END_PROFILE(SMBwriteX);
2563 return ERROR_DOS(ERRDOS,ERRlock);
2566 /* X/Open SMB protocol says that, unlike SMBwrite
2567 if the length is zero then NO truncation is
2568 done, just a write of zero. To truncate a file,
2569 use SMBwrite. */
2571 if(numtowrite == 0)
2572 nwritten = 0;
2573 else
2574 nwritten = write_file(fsp,data,startpos,numtowrite);
2576 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2577 END_PROFILE(SMBwriteX);
2578 return(UNIXERROR(ERRHRD,ERRdiskfull));
2581 set_message(outbuf,6,0,True);
2583 SSVAL(outbuf,smb_vwv2,nwritten);
2584 if (large_writeX)
2585 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2587 if (nwritten < (ssize_t)numtowrite) {
2588 SCVAL(outbuf,smb_rcls,ERRHRD);
2589 SSVAL(outbuf,smb_err,ERRdiskfull);
2592 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2593 fsp->fnum, (int)numtowrite, (int)nwritten));
2595 if (lp_syncalways(SNUM(conn)) || write_through)
2596 sync_file(conn,fsp);
2598 END_PROFILE(SMBwriteX);
2599 return chain_reply(inbuf,outbuf,length,bufsize);
2602 /****************************************************************************
2603 Reply to a lseek.
2604 ****************************************************************************/
2606 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2608 SMB_OFF_T startpos;
2609 SMB_OFF_T res= -1;
2610 int mode,umode;
2611 int outsize = 0;
2612 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2613 START_PROFILE(SMBlseek);
2615 CHECK_FSP(fsp,conn);
2617 flush_write_cache(fsp, SEEK_FLUSH);
2619 mode = SVAL(inbuf,smb_vwv1) & 3;
2620 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2621 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2623 switch (mode) {
2624 case 0:
2625 umode = SEEK_SET;
2626 res = startpos;
2627 break;
2628 case 1:
2629 umode = SEEK_CUR;
2630 res = fsp->pos + startpos;
2631 break;
2632 case 2:
2633 umode = SEEK_END;
2634 break;
2635 default:
2636 umode = SEEK_SET;
2637 res = startpos;
2638 break;
2641 if (umode == SEEK_END) {
2642 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2643 if(errno == EINVAL) {
2644 SMB_OFF_T current_pos = startpos;
2645 SMB_STRUCT_STAT sbuf;
2647 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2648 END_PROFILE(SMBlseek);
2649 return(UNIXERROR(ERRDOS,ERRnoaccess));
2652 current_pos += sbuf.st_size;
2653 if(current_pos < 0)
2654 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2658 if(res == -1) {
2659 END_PROFILE(SMBlseek);
2660 return(UNIXERROR(ERRDOS,ERRnoaccess));
2664 fsp->pos = res;
2666 outsize = set_message(outbuf,2,0,True);
2667 SIVAL(outbuf,smb_vwv0,res);
2669 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2670 fsp->fnum, (double)startpos, (double)res, mode));
2672 END_PROFILE(SMBlseek);
2673 return(outsize);
2676 /****************************************************************************
2677 Reply to a flush.
2678 ****************************************************************************/
2680 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2682 int outsize = set_message(outbuf,0,0,True);
2683 uint16 fnum = SVAL(inbuf,smb_vwv0);
2684 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2685 START_PROFILE(SMBflush);
2687 if (fnum != 0xFFFF)
2688 CHECK_FSP(fsp,conn);
2690 if (!fsp) {
2691 file_sync_all(conn);
2692 } else {
2693 sync_file(conn,fsp);
2696 DEBUG(3,("flush\n"));
2697 END_PROFILE(SMBflush);
2698 return(outsize);
2701 /****************************************************************************
2702 Reply to a exit.
2703 ****************************************************************************/
2705 int reply_exit(connection_struct *conn,
2706 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2708 int outsize;
2709 START_PROFILE(SMBexit);
2711 file_close_pid(SVAL(inbuf,smb_pid));
2713 outsize = set_message(outbuf,0,0,True);
2715 DEBUG(3,("exit\n"));
2717 END_PROFILE(SMBexit);
2718 return(outsize);
2721 /****************************************************************************
2722 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2723 ****************************************************************************/
2725 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2726 int dum_buffsize)
2728 extern struct current_user current_user;
2729 int outsize = 0;
2730 time_t mtime;
2731 int32 eclass = 0, err = 0;
2732 files_struct *fsp = NULL;
2733 START_PROFILE(SMBclose);
2735 outsize = set_message(outbuf,0,0,True);
2737 /* If it's an IPC, pass off to the pipe handler. */
2738 if (IS_IPC(conn)) {
2739 END_PROFILE(SMBclose);
2740 return reply_pipe_close(conn, inbuf,outbuf);
2743 fsp = file_fsp(inbuf,smb_vwv0);
2746 * We can only use CHECK_FSP if we know it's not a directory.
2749 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2750 END_PROFILE(SMBclose);
2751 return ERROR_DOS(ERRDOS,ERRbadfid);
2754 if(fsp->is_directory) {
2756 * Special case - close NT SMB directory handle.
2758 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2759 close_file(fsp,True);
2760 } else {
2762 * Close ordinary file.
2764 int close_err;
2765 pstring file_name;
2767 /* Save the name for time set in close. */
2768 pstrcpy( file_name, fsp->fsp_name);
2770 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2771 fsp->fd, fsp->fnum,
2772 conn->num_files_open));
2775 * close_file() returns the unix errno if an error
2776 * was detected on close - normally this is due to
2777 * a disk full error. If not then it was probably an I/O error.
2780 if((close_err = close_file(fsp,True)) != 0) {
2781 errno = close_err;
2782 END_PROFILE(SMBclose);
2783 return (UNIXERROR(ERRHRD,ERRgeneral));
2787 * Now take care of any time sent in the close.
2790 mtime = make_unix_date3(inbuf+smb_vwv1);
2792 /* try and set the date */
2793 set_filetime(conn, file_name, mtime);
2797 /* We have a cached error */
2798 if(eclass || err) {
2799 END_PROFILE(SMBclose);
2800 return ERROR_DOS(eclass,err);
2803 END_PROFILE(SMBclose);
2804 return(outsize);
2807 /****************************************************************************
2808 Reply to a writeclose (Core+ protocol).
2809 ****************************************************************************/
2811 int reply_writeclose(connection_struct *conn,
2812 char *inbuf,char *outbuf, int size, int dum_buffsize)
2814 size_t numtowrite;
2815 ssize_t nwritten = -1;
2816 int outsize = 0;
2817 int close_err = 0;
2818 SMB_OFF_T startpos;
2819 char *data;
2820 time_t mtime;
2821 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2822 START_PROFILE(SMBwriteclose);
2824 CHECK_FSP(fsp,conn);
2825 CHECK_WRITE(fsp);
2827 numtowrite = SVAL(inbuf,smb_vwv1);
2828 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2829 mtime = make_unix_date3(inbuf+smb_vwv4);
2830 data = smb_buf(inbuf) + 1;
2832 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2833 END_PROFILE(SMBwriteclose);
2834 return ERROR_DOS(ERRDOS,ERRlock);
2837 nwritten = write_file(fsp,data,startpos,numtowrite);
2839 set_filetime(conn, fsp->fsp_name,mtime);
2842 * More insanity. W2K only closes the file if writelen > 0.
2843 * JRA.
2846 if (numtowrite) {
2847 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2848 fsp->fsp_name ));
2849 close_err = close_file(fsp,True);
2852 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2853 fsp->fnum, (int)numtowrite, (int)nwritten,
2854 conn->num_files_open));
2856 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2857 END_PROFILE(SMBwriteclose);
2858 return(UNIXERROR(ERRHRD,ERRdiskfull));
2861 if(close_err != 0) {
2862 errno = close_err;
2863 END_PROFILE(SMBwriteclose);
2864 return(UNIXERROR(ERRHRD,ERRgeneral));
2867 outsize = set_message(outbuf,1,0,True);
2869 SSVAL(outbuf,smb_vwv0,nwritten);
2870 END_PROFILE(SMBwriteclose);
2871 return(outsize);
2874 /****************************************************************************
2875 Reply to a lock.
2876 ****************************************************************************/
2878 int reply_lock(connection_struct *conn,
2879 char *inbuf,char *outbuf, int length, int dum_buffsize)
2881 int outsize = set_message(outbuf,0,0,True);
2882 SMB_BIG_UINT count,offset;
2883 NTSTATUS status;
2884 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2885 BOOL my_lock_ctx = False;
2887 START_PROFILE(SMBlock);
2889 CHECK_FSP(fsp,conn);
2891 release_level_2_oplocks_on_change(fsp);
2893 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2894 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2896 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2897 fsp->fd, fsp->fnum, (double)offset, (double)count));
2899 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2900 if (NT_STATUS_V(status)) {
2901 #if 0
2902 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2903 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2905 * A blocking lock was requested. Package up
2906 * this smb into a queued request and push it
2907 * onto the blocking lock queue.
2909 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2910 END_PROFILE(SMBlock);
2911 return -1;
2914 #endif
2915 END_PROFILE(SMBlock);
2916 return ERROR_NT(status);
2919 END_PROFILE(SMBlock);
2920 return(outsize);
2923 /****************************************************************************
2924 Reply to a unlock.
2925 ****************************************************************************/
2927 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2928 int dum_buffsize)
2930 int outsize = set_message(outbuf,0,0,True);
2931 SMB_BIG_UINT count,offset;
2932 NTSTATUS status;
2933 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2934 START_PROFILE(SMBunlock);
2936 CHECK_FSP(fsp,conn);
2938 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2939 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2941 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2942 if (NT_STATUS_V(status)) {
2943 END_PROFILE(SMBunlock);
2944 return ERROR_NT(status);
2947 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2948 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2950 END_PROFILE(SMBunlock);
2951 return(outsize);
2954 /****************************************************************************
2955 Reply to a tdis.
2956 ****************************************************************************/
2958 int reply_tdis(connection_struct *conn,
2959 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2961 int outsize = set_message(outbuf,0,0,True);
2962 uint16 vuid;
2963 START_PROFILE(SMBtdis);
2965 vuid = SVAL(inbuf,smb_uid);
2967 if (!conn) {
2968 DEBUG(4,("Invalid connection in tdis\n"));
2969 END_PROFILE(SMBtdis);
2970 return ERROR_DOS(ERRSRV,ERRinvnid);
2973 conn->used = False;
2975 close_cnum(conn,vuid);
2977 END_PROFILE(SMBtdis);
2978 return outsize;
2981 /****************************************************************************
2982 Reply to a echo.
2983 ****************************************************************************/
2985 int reply_echo(connection_struct *conn,
2986 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2988 int smb_reverb = SVAL(inbuf,smb_vwv0);
2989 int seq_num;
2990 unsigned int data_len = smb_buflen(inbuf);
2991 int outsize = set_message(outbuf,1,data_len,True);
2992 START_PROFILE(SMBecho);
2994 if (data_len > BUFFER_SIZE) {
2995 DEBUG(0,("reply_echo: data_len too large.\n"));
2996 END_PROFILE(SMBecho);
2997 return -1;
3000 /* copy any incoming data back out */
3001 if (data_len > 0)
3002 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3004 if (smb_reverb > 100) {
3005 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3006 smb_reverb = 100;
3009 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3010 SSVAL(outbuf,smb_vwv0,seq_num);
3012 smb_setlen(outbuf,outsize - 4);
3014 if (!send_smb(smbd_server_fd(),outbuf))
3015 exit_server("reply_echo: send_smb failed.");
3018 DEBUG(3,("echo %d times\n", smb_reverb));
3020 smb_echo_count++;
3022 END_PROFILE(SMBecho);
3023 return -1;
3026 /****************************************************************************
3027 Reply to a printopen.
3028 ****************************************************************************/
3030 int reply_printopen(connection_struct *conn,
3031 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3033 int outsize = 0;
3034 files_struct *fsp;
3035 START_PROFILE(SMBsplopen);
3037 if (!CAN_PRINT(conn)) {
3038 END_PROFILE(SMBsplopen);
3039 return ERROR_DOS(ERRDOS,ERRnoaccess);
3042 /* Open for exclusive use, write only. */
3043 fsp = print_fsp_open(conn, NULL);
3045 if (!fsp) {
3046 END_PROFILE(SMBsplopen);
3047 return(UNIXERROR(ERRDOS,ERRnoaccess));
3050 outsize = set_message(outbuf,1,0,True);
3051 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3053 DEBUG(3,("openprint fd=%d fnum=%d\n",
3054 fsp->fd, fsp->fnum));
3056 END_PROFILE(SMBsplopen);
3057 return(outsize);
3060 /****************************************************************************
3061 Reply to a printclose.
3062 ****************************************************************************/
3064 int reply_printclose(connection_struct *conn,
3065 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3067 int outsize = set_message(outbuf,0,0,True);
3068 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3069 int close_err = 0;
3070 START_PROFILE(SMBsplclose);
3072 CHECK_FSP(fsp,conn);
3074 if (!CAN_PRINT(conn)) {
3075 END_PROFILE(SMBsplclose);
3076 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3079 DEBUG(3,("printclose fd=%d fnum=%d\n",
3080 fsp->fd,fsp->fnum));
3082 close_err = close_file(fsp,True);
3084 if(close_err != 0) {
3085 errno = close_err;
3086 END_PROFILE(SMBsplclose);
3087 return(UNIXERROR(ERRHRD,ERRgeneral));
3090 END_PROFILE(SMBsplclose);
3091 return(outsize);
3094 /****************************************************************************
3095 Reply to a printqueue.
3096 ****************************************************************************/
3098 int reply_printqueue(connection_struct *conn,
3099 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3101 int outsize = set_message(outbuf,2,3,True);
3102 int max_count = SVAL(inbuf,smb_vwv0);
3103 int start_index = SVAL(inbuf,smb_vwv1);
3104 START_PROFILE(SMBsplretq);
3106 /* we used to allow the client to get the cnum wrong, but that
3107 is really quite gross and only worked when there was only
3108 one printer - I think we should now only accept it if they
3109 get it right (tridge) */
3110 if (!CAN_PRINT(conn)) {
3111 END_PROFILE(SMBsplretq);
3112 return ERROR_DOS(ERRDOS,ERRnoaccess);
3115 SSVAL(outbuf,smb_vwv0,0);
3116 SSVAL(outbuf,smb_vwv1,0);
3117 SCVAL(smb_buf(outbuf),0,1);
3118 SSVAL(smb_buf(outbuf),1,0);
3120 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3121 start_index, max_count));
3124 print_queue_struct *queue = NULL;
3125 print_status_struct status;
3126 char *p = smb_buf(outbuf) + 3;
3127 int count = print_queue_status(SNUM(conn), &queue, &status);
3128 int num_to_get = ABS(max_count);
3129 int first = (max_count>0?start_index:start_index+max_count+1);
3130 int i;
3132 if (first >= count)
3133 num_to_get = 0;
3134 else
3135 num_to_get = MIN(num_to_get,count-first);
3138 for (i=first;i<first+num_to_get;i++) {
3139 put_dos_date2(p,0,queue[i].time);
3140 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3141 SSVAL(p,5, queue[i].job);
3142 SIVAL(p,7,queue[i].size);
3143 SCVAL(p,11,0);
3144 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3145 p += 28;
3148 if (count > 0) {
3149 outsize = set_message(outbuf,2,28*count+3,False);
3150 SSVAL(outbuf,smb_vwv0,count);
3151 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3152 SCVAL(smb_buf(outbuf),0,1);
3153 SSVAL(smb_buf(outbuf),1,28*count);
3156 SAFE_FREE(queue);
3158 DEBUG(3,("%d entries returned in queue\n",count));
3161 END_PROFILE(SMBsplretq);
3162 return(outsize);
3165 /****************************************************************************
3166 Reply to a printwrite.
3167 ****************************************************************************/
3169 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3171 int numtowrite;
3172 int outsize = set_message(outbuf,0,0,True);
3173 char *data;
3174 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3176 START_PROFILE(SMBsplwr);
3178 if (!CAN_PRINT(conn)) {
3179 END_PROFILE(SMBsplwr);
3180 return ERROR_DOS(ERRDOS,ERRnoaccess);
3183 CHECK_FSP(fsp,conn);
3184 CHECK_WRITE(fsp);
3186 numtowrite = SVAL(smb_buf(inbuf),1);
3187 data = smb_buf(inbuf) + 3;
3189 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3190 END_PROFILE(SMBsplwr);
3191 return(UNIXERROR(ERRHRD,ERRdiskfull));
3194 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3196 END_PROFILE(SMBsplwr);
3197 return(outsize);
3200 /****************************************************************************
3201 The guts of the mkdir command, split out so it may be called by the NT SMB
3202 code.
3203 ****************************************************************************/
3205 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3207 BOOL bad_path = False;
3208 SMB_STRUCT_STAT sbuf;
3209 int ret= -1;
3211 unix_convert(directory,conn,0,&bad_path,&sbuf);
3213 if( strchr_m(directory, ':')) {
3214 return NT_STATUS_NOT_A_DIRECTORY;
3217 if (ms_has_wild(directory)) {
3218 return NT_STATUS_OBJECT_NAME_INVALID;
3221 if (bad_path) {
3222 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3225 if (check_name(directory, conn))
3226 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3228 if (ret == -1) {
3229 if(errno == ENOENT) {
3230 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3232 return map_nt_error_from_unix(errno);
3235 return NT_STATUS_OK;
3238 /****************************************************************************
3239 Reply to a mkdir.
3240 ****************************************************************************/
3242 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3244 pstring directory;
3245 int outsize;
3246 NTSTATUS status;
3247 START_PROFILE(SMBmkdir);
3249 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3250 if (!NT_STATUS_IS_OK(status)) {
3251 END_PROFILE(SMBmkdir);
3252 return ERROR_NT(status);
3255 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3257 status = mkdir_internal(conn, directory);
3258 if (!NT_STATUS_IS_OK(status)) {
3259 END_PROFILE(SMBmkdir);
3260 return ERROR_NT(status);
3263 outsize = set_message(outbuf,0,0,True);
3265 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3267 END_PROFILE(SMBmkdir);
3268 return(outsize);
3271 /****************************************************************************
3272 Static function used by reply_rmdir to delete an entire directory
3273 tree recursively. Return False on ok, True on fail.
3274 ****************************************************************************/
3276 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3278 const char *dname = NULL;
3279 BOOL ret = False;
3280 void *dirptr = OpenDir(conn, directory, False);
3282 if(dirptr == NULL)
3283 return True;
3285 while((dname = ReadDirName(dirptr))) {
3286 pstring fullname;
3287 SMB_STRUCT_STAT st;
3289 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3290 continue;
3292 /* Construct the full name. */
3293 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3294 errno = ENOMEM;
3295 ret = True;
3296 break;
3299 pstrcpy(fullname, directory);
3300 pstrcat(fullname, "/");
3301 pstrcat(fullname, dname);
3303 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3304 ret = True;
3305 break;
3308 if(st.st_mode & S_IFDIR) {
3309 if(recursive_rmdir(conn, fullname)!=0) {
3310 ret = True;
3311 break;
3313 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3314 ret = True;
3315 break;
3317 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3318 ret = True;
3319 break;
3322 CloseDir(dirptr);
3323 return ret;
3326 /****************************************************************************
3327 The internals of the rmdir code - called elsewhere.
3328 ****************************************************************************/
3330 BOOL rmdir_internals(connection_struct *conn, char *directory)
3332 BOOL ok;
3334 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3335 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3337 * Check to see if the only thing in this directory are
3338 * vetoed files/directories. If so then delete them and
3339 * retry. If we fail to delete any of them (and we *don't*
3340 * do a recursive delete) then fail the rmdir.
3342 BOOL all_veto_files = True;
3343 const char *dname;
3344 void *dirptr = OpenDir(conn, directory, False);
3346 if(dirptr != NULL) {
3347 int dirpos = TellDir(dirptr);
3348 while ((dname = ReadDirName(dirptr))) {
3349 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3350 continue;
3351 if(!IS_VETO_PATH(conn, dname)) {
3352 all_veto_files = False;
3353 break;
3357 if(all_veto_files) {
3358 SeekDir(dirptr,dirpos);
3359 while ((dname = ReadDirName(dirptr))) {
3360 pstring fullname;
3361 SMB_STRUCT_STAT st;
3363 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3364 continue;
3366 /* Construct the full name. */
3367 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3368 errno = ENOMEM;
3369 break;
3372 pstrcpy(fullname, directory);
3373 pstrcat(fullname, "/");
3374 pstrcat(fullname, dname);
3376 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3377 break;
3378 if(st.st_mode & S_IFDIR) {
3379 if(lp_recursive_veto_delete(SNUM(conn))) {
3380 if(recursive_rmdir(conn, fullname) != 0)
3381 break;
3383 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3384 break;
3385 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3386 break;
3388 CloseDir(dirptr);
3389 /* Retry the rmdir */
3390 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3391 } else {
3392 CloseDir(dirptr);
3394 } else {
3395 errno = ENOTEMPTY;
3399 if (!ok)
3400 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3402 return ok;
3405 /****************************************************************************
3406 Reply to a rmdir.
3407 ****************************************************************************/
3409 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3411 pstring directory;
3412 int outsize = 0;
3413 BOOL ok = False;
3414 BOOL bad_path = False;
3415 SMB_STRUCT_STAT sbuf;
3416 NTSTATUS status;
3417 START_PROFILE(SMBrmdir);
3419 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3420 if (!NT_STATUS_IS_OK(status)) {
3421 END_PROFILE(SMBrmdir);
3422 return ERROR_NT(status);
3425 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3427 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3428 if (bad_path) {
3429 END_PROFILE(SMBrmdir);
3430 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3433 if (check_name(directory,conn)) {
3434 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3435 ok = rmdir_internals(conn, directory);
3438 if (!ok) {
3439 END_PROFILE(SMBrmdir);
3440 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3443 outsize = set_message(outbuf,0,0,True);
3445 DEBUG( 3, ( "rmdir %s\n", directory ) );
3447 END_PROFILE(SMBrmdir);
3448 return(outsize);
3451 /*******************************************************************
3452 Resolve wildcards in a filename rename.
3453 Note that name is in UNIX charset and thus potentially can be more
3454 than fstring buffer (255 bytes) especially in default UTF-8 case.
3455 Therefore, we use pstring inside and all calls should ensure that
3456 name2 is at least pstring-long (they do already)
3457 ********************************************************************/
3459 static BOOL resolve_wildcards(const char *name1, char *name2)
3461 pstring root1,root2;
3462 pstring ext1,ext2;
3463 char *p,*p2, *pname1, *pname2;
3464 int available_space, actual_space;
3467 pname1 = strrchr_m(name1,'/');
3468 pname2 = strrchr_m(name2,'/');
3470 if (!pname1 || !pname2)
3471 return(False);
3473 pstrcpy(root1,pname1);
3474 pstrcpy(root2,pname2);
3475 p = strrchr_m(root1,'.');
3476 if (p) {
3477 *p = 0;
3478 pstrcpy(ext1,p+1);
3479 } else {
3480 pstrcpy(ext1,"");
3482 p = strrchr_m(root2,'.');
3483 if (p) {
3484 *p = 0;
3485 pstrcpy(ext2,p+1);
3486 } else {
3487 pstrcpy(ext2,"");
3490 p = root1;
3491 p2 = root2;
3492 while (*p2) {
3493 if (*p2 == '?') {
3494 *p2 = *p;
3495 p2++;
3496 } else if (*p2 == '*') {
3497 pstrcpy(p2, p);
3498 break;
3499 } else {
3500 p2++;
3502 if (*p)
3503 p++;
3506 p = ext1;
3507 p2 = ext2;
3508 while (*p2) {
3509 if (*p2 == '?') {
3510 *p2 = *p;
3511 p2++;
3512 } else if (*p2 == '*') {
3513 pstrcpy(p2, p);
3514 break;
3515 } else {
3516 p2++;
3518 if (*p)
3519 p++;
3522 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3524 if (ext2[0]) {
3525 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3526 if (actual_space >= available_space - 1) {
3527 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3528 actual_space - available_space));
3530 } else {
3531 pstrcpy_base(pname2, root2, name2);
3534 return(True);
3537 /****************************************************************************
3538 Ensure open files have their names updates.
3539 ****************************************************************************/
3541 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3543 files_struct *fsp;
3544 BOOL did_rename = False;
3546 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3547 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3548 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3549 fsp->fsp_name, newname ));
3550 string_set(&fsp->fsp_name, newname);
3551 did_rename = True;
3554 if (!did_rename)
3555 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3556 (unsigned int)dev, (double)inode, newname ));
3559 /****************************************************************************
3560 Rename an open file - given an fsp.
3561 ****************************************************************************/
3563 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3565 SMB_STRUCT_STAT sbuf;
3566 BOOL bad_path = False;
3567 pstring newname_last_component;
3568 NTSTATUS error = NT_STATUS_OK;
3569 BOOL dest_exists;
3570 BOOL rcdest = True;
3572 ZERO_STRUCT(sbuf);
3573 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3575 /* Quick check for "." and ".." */
3576 if (!bad_path && newname_last_component[0] == '.') {
3577 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3578 return NT_STATUS_ACCESS_DENIED;
3581 if (!rcdest && bad_path) {
3582 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3585 /* Ensure newname contains a '/' */
3586 if(strrchr_m(newname,'/') == 0) {
3587 pstring tmpstr;
3589 pstrcpy(tmpstr, "./");
3590 pstrcat(tmpstr, newname);
3591 pstrcpy(newname, tmpstr);
3595 * Check for special case with case preserving and not
3596 * case sensitive. If the old last component differs from the original
3597 * last component only by case, then we should allow
3598 * the rename (user is trying to change the case of the
3599 * filename).
3602 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3603 strequal(newname, fsp->fsp_name)) {
3604 char *p;
3605 pstring newname_modified_last_component;
3608 * Get the last component of the modified name.
3609 * Note that we guarantee that newname contains a '/'
3610 * character above.
3612 p = strrchr_m(newname,'/');
3613 pstrcpy(newname_modified_last_component,p+1);
3615 if(strcsequal(newname_modified_last_component,
3616 newname_last_component) == False) {
3618 * Replace the modified last component with
3619 * the original.
3621 pstrcpy(p+1, newname_last_component);
3626 * If the src and dest names are identical - including case,
3627 * don't do the rename, just return success.
3630 if (strcsequal(fsp->fsp_name, newname)) {
3631 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3632 newname));
3633 return NT_STATUS_OK;
3636 dest_exists = vfs_object_exist(conn,newname,NULL);
3638 if(!replace_if_exists && dest_exists) {
3639 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3640 fsp->fsp_name,newname));
3641 return NT_STATUS_OBJECT_NAME_COLLISION;
3644 error = can_rename(newname,conn,attrs,&sbuf);
3646 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3647 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3648 nt_errstr(error), fsp->fsp_name,newname));
3649 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3650 error = NT_STATUS_ACCESS_DENIED;
3651 return error;
3654 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3655 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3656 fsp->fsp_name,newname));
3657 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3658 return NT_STATUS_OK;
3661 if (errno == ENOTDIR || errno == EISDIR)
3662 error = NT_STATUS_OBJECT_NAME_COLLISION;
3663 else
3664 error = map_nt_error_from_unix(errno);
3666 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3667 nt_errstr(error), fsp->fsp_name,newname));
3669 return error;
3672 /****************************************************************************
3673 The guts of the rename command, split out so it may be called by the NT SMB
3674 code.
3675 ****************************************************************************/
3677 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3679 pstring directory;
3680 pstring mask;
3681 pstring last_component_src;
3682 pstring last_component_dest;
3683 char *p;
3684 BOOL has_wild;
3685 BOOL bad_path_src = False;
3686 BOOL bad_path_dest = False;
3687 int count=0;
3688 NTSTATUS error = NT_STATUS_OK;
3689 BOOL rc = True;
3690 BOOL rcdest = True;
3691 SMB_STRUCT_STAT sbuf1, sbuf2;
3693 *directory = *mask = 0;
3695 ZERO_STRUCT(sbuf1);
3696 ZERO_STRUCT(sbuf2);
3698 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3699 if (!rc && bad_path_src) {
3700 if (ms_has_wild(last_component_src))
3701 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3702 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3705 /* Quick check for "." and ".." */
3706 if (last_component_src[0] == '.') {
3707 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3708 return NT_STATUS_OBJECT_NAME_INVALID;
3712 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3714 /* Quick check for "." and ".." */
3715 if (last_component_dest[0] == '.') {
3716 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3717 return NT_STATUS_OBJECT_NAME_INVALID;
3722 * Split the old name into directory and last component
3723 * strings. Note that unix_convert may have stripped off a
3724 * leading ./ from both name and newname if the rename is
3725 * at the root of the share. We need to make sure either both
3726 * name and newname contain a / character or neither of them do
3727 * as this is checked in resolve_wildcards().
3730 p = strrchr_m(name,'/');
3731 if (!p) {
3732 pstrcpy(directory,".");
3733 pstrcpy(mask,name);
3734 } else {
3735 *p = 0;
3736 pstrcpy(directory,name);
3737 pstrcpy(mask,p+1);
3738 *p = '/'; /* Replace needed for exceptional test below. */
3742 * We should only check the mangled cache
3743 * here if unix_convert failed. This means
3744 * that the path in 'mask' doesn't exist
3745 * on the file system and so we need to look
3746 * for a possible mangle. This patch from
3747 * Tine Smukavec <valentin.smukavec@hermes.si>.
3750 if (!rc && mangle_is_mangled(mask))
3751 mangle_check_cache( mask, sizeof(pstring)-1 );
3753 has_wild = ms_has_wild(mask);
3755 if (!has_wild) {
3757 * No wildcards - just process the one file.
3759 BOOL is_short_name = mangle_is_8_3(name, True);
3761 /* Add a terminating '/' to the directory name. */
3762 pstrcat(directory,"/");
3763 pstrcat(directory,mask);
3765 /* Ensure newname contains a '/' also */
3766 if(strrchr_m(newname,'/') == 0) {
3767 pstring tmpstr;
3769 pstrcpy(tmpstr, "./");
3770 pstrcat(tmpstr, newname);
3771 pstrcpy(newname, tmpstr);
3774 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3775 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3776 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3777 newname, last_component_dest, is_short_name));
3780 * Check for special case with case preserving and not
3781 * case sensitive, if directory and newname are identical,
3782 * and the old last component differs from the original
3783 * last component only by case, then we should allow
3784 * the rename (user is trying to change the case of the
3785 * filename).
3787 if((conn->case_sensitive == False) &&
3788 (((conn->case_preserve == True) &&
3789 (is_short_name == False)) ||
3790 ((conn->short_case_preserve == True) &&
3791 (is_short_name == True))) &&
3792 strcsequal(directory, newname)) {
3793 pstring modified_last_component;
3796 * Get the last component of the modified name.
3797 * Note that we guarantee that newname contains a '/'
3798 * character above.
3800 p = strrchr_m(newname,'/');
3801 pstrcpy(modified_last_component,p+1);
3803 if(strcsequal(modified_last_component,
3804 last_component_dest) == False) {
3806 * Replace the modified last component with
3807 * the original.
3809 pstrcpy(p+1, last_component_dest);
3813 resolve_wildcards(directory,newname);
3816 * The source object must exist.
3819 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3820 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3821 directory,newname));
3823 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3825 * Must return different errors depending on whether the parent
3826 * directory existed or not.
3829 p = strrchr_m(directory, '/');
3830 if (!p)
3831 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3832 *p = '\0';
3833 if (vfs_object_exist(conn, directory, NULL))
3834 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3835 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3837 error = map_nt_error_from_unix(errno);
3838 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3839 nt_errstr(error), directory,newname));
3841 return error;
3844 if (!rcdest && bad_path_dest) {
3845 if (ms_has_wild(last_component_dest))
3846 return NT_STATUS_OBJECT_NAME_INVALID;
3847 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3850 error = can_rename(directory,conn,attrs,&sbuf1);
3852 if (!NT_STATUS_IS_OK(error)) {
3853 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3854 nt_errstr(error), directory,newname));
3855 return error;
3859 * If the src and dest names are identical - including case,
3860 * don't do the rename, just return success.
3863 if (strcsequal(directory, newname)) {
3864 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3865 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3866 return NT_STATUS_OK;
3869 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3870 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3871 directory,newname));
3872 return NT_STATUS_OBJECT_NAME_COLLISION;
3875 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3876 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3877 directory,newname));
3878 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3879 return NT_STATUS_OK;
3882 if (errno == ENOTDIR || errno == EISDIR)
3883 error = NT_STATUS_OBJECT_NAME_COLLISION;
3884 else
3885 error = map_nt_error_from_unix(errno);
3887 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3888 nt_errstr(error), directory,newname));
3890 return error;
3891 } else {
3893 * Wildcards - process each file that matches.
3895 void *dirptr = NULL;
3896 const char *dname;
3897 pstring destname;
3899 if (check_name(directory,conn))
3900 dirptr = OpenDir(conn, directory, True);
3902 if (dirptr) {
3903 error = NT_STATUS_NO_SUCH_FILE;
3904 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3906 if (strequal(mask,"????????.???"))
3907 pstrcpy(mask,"*");
3909 while ((dname = ReadDirName(dirptr))) {
3910 pstring fname;
3911 BOOL sysdir_entry = False;
3913 pstrcpy(fname,dname);
3915 /* Quick check for "." and ".." */
3916 if (fname[0] == '.') {
3917 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3918 if (attrs & aDIR) {
3919 sysdir_entry = True;
3920 } else {
3921 continue;
3926 if(!mask_match(fname, mask, conn->case_sensitive))
3927 continue;
3929 if (sysdir_entry) {
3930 error = NT_STATUS_OBJECT_NAME_INVALID;
3931 break;
3934 error = NT_STATUS_ACCESS_DENIED;
3935 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3936 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3937 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3938 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3939 continue;
3941 error = can_rename(fname,conn,attrs,&sbuf1);
3942 if (!NT_STATUS_IS_OK(error)) {
3943 DEBUG(6,("rename %s refused\n", fname));
3944 continue;
3946 pstrcpy(destname,newname);
3948 if (!resolve_wildcards(fname,destname)) {
3949 DEBUG(6,("resolve_wildcards %s %s failed\n",
3950 fname, destname));
3951 continue;
3954 if (strcsequal(fname,destname)) {
3955 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3956 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3957 count++;
3958 error = NT_STATUS_OK;
3959 continue;
3962 if (!replace_if_exists &&
3963 vfs_file_exist(conn,destname, NULL)) {
3964 DEBUG(6,("file_exist %s\n", destname));
3965 error = NT_STATUS_OBJECT_NAME_COLLISION;
3966 continue;
3969 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3970 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3971 count++;
3972 error = NT_STATUS_OK;
3974 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3976 CloseDir(dirptr);
3979 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3980 if (!rcdest && bad_path_dest) {
3981 if (ms_has_wild(last_component_dest))
3982 return NT_STATUS_OBJECT_NAME_INVALID;
3983 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3988 if (count == 0 && NT_STATUS_IS_OK(error)) {
3989 error = map_nt_error_from_unix(errno);
3992 return error;
3995 /****************************************************************************
3996 Reply to a mv.
3997 ****************************************************************************/
3999 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4000 int dum_buffsize)
4002 int outsize = 0;
4003 pstring name;
4004 pstring newname;
4005 char *p;
4006 uint16 attrs = SVAL(inbuf,smb_vwv0);
4007 NTSTATUS status;
4009 START_PROFILE(SMBmv);
4011 p = smb_buf(inbuf) + 1;
4012 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 END_PROFILE(SMBmv);
4015 return ERROR_NT(status);
4017 p++;
4018 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4019 if (!NT_STATUS_IS_OK(status)) {
4020 END_PROFILE(SMBmv);
4021 return ERROR_NT(status);
4024 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4025 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4027 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4029 status = rename_internals(conn, name, newname, attrs, False);
4030 if (!NT_STATUS_IS_OK(status)) {
4031 END_PROFILE(SMBmv);
4032 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4033 /* We have re-scheduled this call. */
4034 clear_cached_errors();
4035 return -1;
4037 return ERROR_NT(status);
4041 * Win2k needs a changenotify request response before it will
4042 * update after a rename..
4044 process_pending_change_notify_queue((time_t)0);
4045 outsize = set_message(outbuf,0,0,True);
4047 END_PROFILE(SMBmv);
4048 return(outsize);
4051 /*******************************************************************
4052 Copy a file as part of a reply_copy.
4053 ******************************************************************/
4055 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4056 int count,BOOL target_is_directory, int *err_ret)
4058 int Access,action;
4059 SMB_STRUCT_STAT src_sbuf, sbuf2;
4060 SMB_OFF_T ret=-1;
4061 files_struct *fsp1,*fsp2;
4062 pstring dest;
4063 uint32 dosattrs;
4065 *err_ret = 0;
4067 pstrcpy(dest,dest1);
4068 if (target_is_directory) {
4069 char *p = strrchr_m(src,'/');
4070 if (p)
4071 p++;
4072 else
4073 p = src;
4074 pstrcat(dest,"/");
4075 pstrcat(dest,p);
4078 if (!vfs_file_exist(conn,src,&src_sbuf))
4079 return(False);
4081 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4082 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4083 &Access,&action);
4085 if (!fsp1)
4086 return(False);
4088 if (!target_is_directory && count)
4089 ofun = FILE_EXISTS_OPEN;
4091 dosattrs = dos_mode(conn, src, &src_sbuf);
4092 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4093 ZERO_STRUCTP(&sbuf2);
4095 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4096 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4098 if (!fsp2) {
4099 close_file(fsp1,False);
4100 return(False);
4103 if ((ofun&3) == 1) {
4104 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4105 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4107 * Stop the copy from occurring.
4109 ret = -1;
4110 src_sbuf.st_size = 0;
4114 if (src_sbuf.st_size)
4115 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4117 close_file(fsp1,False);
4119 /* Ensure the modtime is set correctly on the destination file. */
4120 fsp2->pending_modtime = src_sbuf.st_mtime;
4123 * As we are opening fsp1 read-only we only expect
4124 * an error on close on fsp2 if we are out of space.
4125 * Thus we don't look at the error return from the
4126 * close of fsp1.
4128 *err_ret = close_file(fsp2,False);
4130 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4133 /****************************************************************************
4134 Reply to a file copy.
4135 ****************************************************************************/
4137 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4139 int outsize = 0;
4140 pstring name;
4141 pstring directory;
4142 pstring mask,newname;
4143 char *p;
4144 int count=0;
4145 int error = ERRnoaccess;
4146 int err = 0;
4147 BOOL has_wild;
4148 BOOL exists=False;
4149 int tid2 = SVAL(inbuf,smb_vwv0);
4150 int ofun = SVAL(inbuf,smb_vwv1);
4151 int flags = SVAL(inbuf,smb_vwv2);
4152 BOOL target_is_directory=False;
4153 BOOL bad_path1 = False;
4154 BOOL bad_path2 = False;
4155 BOOL rc = True;
4156 SMB_STRUCT_STAT sbuf1, sbuf2;
4157 NTSTATUS status;
4159 START_PROFILE(SMBcopy);
4161 *directory = *mask = 0;
4163 p = smb_buf(inbuf);
4164 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4165 if (!NT_STATUS_IS_OK(status)) {
4166 END_PROFILE(SMBcopy);
4167 return ERROR_NT(status);
4169 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 END_PROFILE(SMBcopy);
4172 return ERROR_NT(status);
4175 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4177 if (tid2 != conn->cnum) {
4178 /* can't currently handle inter share copies XXXX */
4179 DEBUG(3,("Rejecting inter-share copy\n"));
4180 END_PROFILE(SMBcopy);
4181 return ERROR_DOS(ERRSRV,ERRinvdevice);
4184 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4185 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4187 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4188 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4190 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4192 if ((flags&1) && target_is_directory) {
4193 END_PROFILE(SMBcopy);
4194 return ERROR_DOS(ERRDOS,ERRbadfile);
4197 if ((flags&2) && !target_is_directory) {
4198 END_PROFILE(SMBcopy);
4199 return ERROR_DOS(ERRDOS,ERRbadpath);
4202 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4203 /* wants a tree copy! XXXX */
4204 DEBUG(3,("Rejecting tree copy\n"));
4205 END_PROFILE(SMBcopy);
4206 return ERROR_DOS(ERRSRV,ERRerror);
4209 p = strrchr_m(name,'/');
4210 if (!p) {
4211 pstrcpy(directory,"./");
4212 pstrcpy(mask,name);
4213 } else {
4214 *p = 0;
4215 pstrcpy(directory,name);
4216 pstrcpy(mask,p+1);
4220 * We should only check the mangled cache
4221 * here if unix_convert failed. This means
4222 * that the path in 'mask' doesn't exist
4223 * on the file system and so we need to look
4224 * for a possible mangle. This patch from
4225 * Tine Smukavec <valentin.smukavec@hermes.si>.
4228 if (!rc && mangle_is_mangled(mask))
4229 mangle_check_cache( mask, sizeof(pstring)-1 );
4231 has_wild = ms_has_wild(mask);
4233 if (!has_wild) {
4234 pstrcat(directory,"/");
4235 pstrcat(directory,mask);
4236 if (resolve_wildcards(directory,newname) &&
4237 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4238 count++;
4239 if(!count && err) {
4240 errno = err;
4241 END_PROFILE(SMBcopy);
4242 return(UNIXERROR(ERRHRD,ERRgeneral));
4244 if (!count) {
4245 exists = vfs_file_exist(conn,directory,NULL);
4247 } else {
4248 void *dirptr = NULL;
4249 const char *dname;
4250 pstring destname;
4252 if (check_name(directory,conn))
4253 dirptr = OpenDir(conn, directory, True);
4255 if (dirptr) {
4256 error = ERRbadfile;
4258 if (strequal(mask,"????????.???"))
4259 pstrcpy(mask,"*");
4261 while ((dname = ReadDirName(dirptr))) {
4262 pstring fname;
4263 pstrcpy(fname,dname);
4265 if(!mask_match(fname, mask, conn->case_sensitive))
4266 continue;
4268 error = ERRnoaccess;
4269 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4270 pstrcpy(destname,newname);
4271 if (resolve_wildcards(fname,destname) &&
4272 copy_file(fname,destname,conn,ofun,
4273 count,target_is_directory,&err))
4274 count++;
4275 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4277 CloseDir(dirptr);
4281 if (count == 0) {
4282 if(err) {
4283 /* Error on close... */
4284 errno = err;
4285 END_PROFILE(SMBcopy);
4286 return(UNIXERROR(ERRHRD,ERRgeneral));
4289 if (exists) {
4290 END_PROFILE(SMBcopy);
4291 return ERROR_DOS(ERRDOS,error);
4292 } else {
4293 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4294 unix_ERR_class = ERRDOS;
4295 unix_ERR_code = ERRbadpath;
4297 END_PROFILE(SMBcopy);
4298 return(UNIXERROR(ERRDOS,error));
4302 outsize = set_message(outbuf,1,0,True);
4303 SSVAL(outbuf,smb_vwv0,count);
4305 END_PROFILE(SMBcopy);
4306 return(outsize);
4309 /****************************************************************************
4310 Reply to a setdir.
4311 ****************************************************************************/
4313 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4315 int snum;
4316 int outsize = 0;
4317 BOOL ok = False;
4318 pstring newdir;
4319 NTSTATUS status;
4321 START_PROFILE(pathworks_setdir);
4323 snum = SNUM(conn);
4324 if (!CAN_SETDIR(snum)) {
4325 END_PROFILE(pathworks_setdir);
4326 return ERROR_DOS(ERRDOS,ERRnoaccess);
4329 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4330 if (!NT_STATUS_IS_OK(status)) {
4331 END_PROFILE(pathworks_setdir);
4332 return ERROR_NT(status);
4335 if (strlen(newdir) == 0) {
4336 ok = True;
4337 } else {
4338 ok = vfs_directory_exist(conn,newdir,NULL);
4339 if (ok)
4340 string_set(&conn->connectpath,newdir);
4343 if (!ok) {
4344 END_PROFILE(pathworks_setdir);
4345 return ERROR_DOS(ERRDOS,ERRbadpath);
4348 outsize = set_message(outbuf,0,0,True);
4349 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4351 DEBUG(3,("setdir %s\n", newdir));
4353 END_PROFILE(pathworks_setdir);
4354 return(outsize);
4357 /****************************************************************************
4358 Get a lock pid, dealing with large count requests.
4359 ****************************************************************************/
4361 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4363 if(!large_file_format)
4364 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4365 else
4366 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4369 /****************************************************************************
4370 Get a lock count, dealing with large count requests.
4371 ****************************************************************************/
4373 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4375 SMB_BIG_UINT count = 0;
4377 if(!large_file_format) {
4378 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4379 } else {
4381 #if defined(HAVE_LONGLONG)
4382 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4383 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4384 #else /* HAVE_LONGLONG */
4387 * NT4.x seems to be broken in that it sends large file (64 bit)
4388 * lockingX calls even if the CAP_LARGE_FILES was *not*
4389 * negotiated. For boxes without large unsigned ints truncate the
4390 * lock count by dropping the top 32 bits.
4393 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4394 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4395 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4396 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4397 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4400 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4401 #endif /* HAVE_LONGLONG */
4404 return count;
4407 #if !defined(HAVE_LONGLONG)
4408 /****************************************************************************
4409 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4410 ****************************************************************************/
4412 static uint32 map_lock_offset(uint32 high, uint32 low)
4414 unsigned int i;
4415 uint32 mask = 0;
4416 uint32 highcopy = high;
4419 * Try and find out how many significant bits there are in high.
4422 for(i = 0; highcopy; i++)
4423 highcopy >>= 1;
4426 * We use 31 bits not 32 here as POSIX
4427 * lock offsets may not be negative.
4430 mask = (~0) << (31 - i);
4432 if(low & mask)
4433 return 0; /* Fail. */
4435 high <<= (31 - i);
4437 return (high|low);
4439 #endif /* !defined(HAVE_LONGLONG) */
4441 /****************************************************************************
4442 Get a lock offset, dealing with large offset requests.
4443 ****************************************************************************/
4445 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4447 SMB_BIG_UINT offset = 0;
4449 *err = False;
4451 if(!large_file_format) {
4452 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4453 } else {
4455 #if defined(HAVE_LONGLONG)
4456 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4457 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4458 #else /* HAVE_LONGLONG */
4461 * NT4.x seems to be broken in that it sends large file (64 bit)
4462 * lockingX calls even if the CAP_LARGE_FILES was *not*
4463 * negotiated. For boxes without large unsigned ints mangle the
4464 * lock offset by mapping the top 32 bits onto the lower 32.
4467 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4468 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4469 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4470 uint32 new_low = 0;
4472 if((new_low = map_lock_offset(high, low)) == 0) {
4473 *err = True;
4474 return (SMB_BIG_UINT)-1;
4477 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4478 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4479 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4480 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4483 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4484 #endif /* HAVE_LONGLONG */
4487 return offset;
4490 /****************************************************************************
4491 Reply to a lockingX request.
4492 ****************************************************************************/
4494 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4496 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4497 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4498 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4499 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4500 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4501 SMB_BIG_UINT count = 0, offset = 0;
4502 uint16 lock_pid;
4503 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4504 int i;
4505 char *data;
4506 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4507 BOOL err;
4508 BOOL my_lock_ctx = False;
4509 NTSTATUS status;
4511 START_PROFILE(SMBlockingX);
4513 CHECK_FSP(fsp,conn);
4515 data = smb_buf(inbuf);
4517 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4518 /* we don't support these - and CANCEL_LOCK makes w2k
4519 and XP reboot so I don't really want to be
4520 compatible! (tridge) */
4521 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4524 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4525 /* Need to make this like a cancel.... JRA. */
4526 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4529 /* Check if this is an oplock break on a file
4530 we have granted an oplock on.
4532 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4533 /* Client can insist on breaking to none. */
4534 BOOL break_to_none = (oplocklevel == 0);
4536 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4537 (unsigned int)oplocklevel, fsp->fnum ));
4540 * Make sure we have granted an exclusive or batch oplock on this file.
4543 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4544 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4545 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4547 /* if this is a pure oplock break request then don't send a reply */
4548 if (num_locks == 0 && num_ulocks == 0) {
4549 END_PROFILE(SMBlockingX);
4550 return -1;
4551 } else {
4552 END_PROFILE(SMBlockingX);
4553 return ERROR_DOS(ERRDOS,ERRlock);
4557 if (remove_oplock(fsp, break_to_none) == False) {
4558 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4559 fsp->fsp_name ));
4562 /* if this is a pure oplock break request then don't send a reply */
4563 if (num_locks == 0 && num_ulocks == 0) {
4564 /* Sanity check - ensure a pure oplock break is not a
4565 chained request. */
4566 if(CVAL(inbuf,smb_vwv0) != 0xff)
4567 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4568 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4569 END_PROFILE(SMBlockingX);
4570 return -1;
4575 * We do this check *after* we have checked this is not a oplock break
4576 * response message. JRA.
4579 release_level_2_oplocks_on_change(fsp);
4581 /* Data now points at the beginning of the list
4582 of smb_unlkrng structs */
4583 for(i = 0; i < (int)num_ulocks; i++) {
4584 lock_pid = get_lock_pid( data, i, large_file_format);
4585 count = get_lock_count( data, i, large_file_format);
4586 offset = get_lock_offset( data, i, large_file_format, &err);
4589 * There is no error code marked "stupid client bug".... :-).
4591 if(err) {
4592 END_PROFILE(SMBlockingX);
4593 return ERROR_DOS(ERRDOS,ERRnoaccess);
4596 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4597 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4599 status = do_unlock(fsp,conn,lock_pid,count,offset);
4600 if (NT_STATUS_V(status)) {
4601 END_PROFILE(SMBlockingX);
4602 return ERROR_NT(status);
4606 /* Setup the timeout in seconds. */
4608 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4610 /* Now do any requested locks */
4611 data += ((large_file_format ? 20 : 10)*num_ulocks);
4613 /* Data now points at the beginning of the list
4614 of smb_lkrng structs */
4616 for(i = 0; i < (int)num_locks; i++) {
4617 lock_pid = get_lock_pid( data, i, large_file_format);
4618 count = get_lock_count( data, i, large_file_format);
4619 offset = get_lock_offset( data, i, large_file_format, &err);
4622 * There is no error code marked "stupid client bug".... :-).
4624 if(err) {
4625 END_PROFILE(SMBlockingX);
4626 return ERROR_DOS(ERRDOS,ERRnoaccess);
4629 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4630 (double)offset, (double)count, (unsigned int)lock_pid,
4631 fsp->fsp_name, (int)lock_timeout ));
4633 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4634 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4635 if (NT_STATUS_V(status)) {
4637 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4638 * Even if it's our own lock context, we need to wait here as
4639 * there may be an unlock on the way.
4640 * So I removed a "&& !my_lock_ctx" from the following
4641 * if statement. JRA.
4643 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4645 * A blocking lock was requested. Package up
4646 * this smb into a queued request and push it
4647 * onto the blocking lock queue.
4649 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4650 END_PROFILE(SMBlockingX);
4651 return -1;
4654 break;
4658 /* If any of the above locks failed, then we must unlock
4659 all of the previous locks (X/Open spec). */
4660 if (i != num_locks && num_locks != 0) {
4662 * Ensure we don't do a remove on the lock that just failed,
4663 * as under POSIX rules, if we have a lock already there, we
4664 * will delete it (and we shouldn't) .....
4666 for(i--; i >= 0; i--) {
4667 lock_pid = get_lock_pid( data, i, large_file_format);
4668 count = get_lock_count( data, i, large_file_format);
4669 offset = get_lock_offset( data, i, large_file_format, &err);
4672 * There is no error code marked "stupid client bug".... :-).
4674 if(err) {
4675 END_PROFILE(SMBlockingX);
4676 return ERROR_DOS(ERRDOS,ERRnoaccess);
4679 do_unlock(fsp,conn,lock_pid,count,offset);
4681 END_PROFILE(SMBlockingX);
4682 return ERROR_NT(status);
4685 set_message(outbuf,2,0,True);
4687 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4688 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4690 END_PROFILE(SMBlockingX);
4691 return chain_reply(inbuf,outbuf,length,bufsize);
4694 /****************************************************************************
4695 Reply to a SMBreadbmpx (read block multiplex) request.
4696 ****************************************************************************/
4698 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4700 ssize_t nread = -1;
4701 ssize_t total_read;
4702 char *data;
4703 SMB_OFF_T startpos;
4704 int outsize;
4705 size_t maxcount;
4706 int max_per_packet;
4707 size_t tcount;
4708 int pad;
4709 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4710 START_PROFILE(SMBreadBmpx);
4712 /* this function doesn't seem to work - disable by default */
4713 if (!lp_readbmpx()) {
4714 END_PROFILE(SMBreadBmpx);
4715 return ERROR_DOS(ERRSRV,ERRuseSTD);
4718 outsize = set_message(outbuf,8,0,True);
4720 CHECK_FSP(fsp,conn);
4721 CHECK_READ(fsp);
4723 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4724 maxcount = SVAL(inbuf,smb_vwv3);
4726 data = smb_buf(outbuf);
4727 pad = ((long)data)%4;
4728 if (pad)
4729 pad = 4 - pad;
4730 data += pad;
4732 max_per_packet = bufsize-(outsize+pad);
4733 tcount = maxcount;
4734 total_read = 0;
4736 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4737 END_PROFILE(SMBreadBmpx);
4738 return ERROR_DOS(ERRDOS,ERRlock);
4741 do {
4742 size_t N = MIN(max_per_packet,tcount-total_read);
4744 nread = read_file(fsp,data,startpos,N);
4746 if (nread <= 0)
4747 nread = 0;
4749 if (nread < (ssize_t)N)
4750 tcount = total_read + nread;
4752 set_message(outbuf,8,nread,False);
4753 SIVAL(outbuf,smb_vwv0,startpos);
4754 SSVAL(outbuf,smb_vwv2,tcount);
4755 SSVAL(outbuf,smb_vwv6,nread);
4756 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4758 if (!send_smb(smbd_server_fd(),outbuf))
4759 exit_server("reply_readbmpx: send_smb failed.");
4761 total_read += nread;
4762 startpos += nread;
4763 } while (total_read < (ssize_t)tcount);
4765 END_PROFILE(SMBreadBmpx);
4766 return(-1);
4769 /****************************************************************************
4770 Reply to a SMBsetattrE.
4771 ****************************************************************************/
4773 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4775 struct utimbuf unix_times;
4776 int outsize = 0;
4777 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4778 START_PROFILE(SMBsetattrE);
4780 outsize = set_message(outbuf,0,0,True);
4782 if(!fsp || (fsp->conn != conn)) {
4783 END_PROFILE(SMBgetattrE);
4784 return ERROR_DOS(ERRDOS,ERRbadfid);
4788 * Convert the DOS times into unix times. Ignore create
4789 * time as UNIX can't set this.
4792 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4793 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4796 * Patch from Ray Frush <frush@engr.colostate.edu>
4797 * Sometimes times are sent as zero - ignore them.
4800 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4801 /* Ignore request */
4802 if( DEBUGLVL( 3 ) ) {
4803 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4804 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4806 END_PROFILE(SMBsetattrE);
4807 return(outsize);
4808 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4809 /* set modify time = to access time if modify time was 0 */
4810 unix_times.modtime = unix_times.actime;
4813 /* Set the date on this file */
4814 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4815 END_PROFILE(SMBsetattrE);
4816 return ERROR_DOS(ERRDOS,ERRnoaccess);
4819 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4820 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4822 END_PROFILE(SMBsetattrE);
4823 return(outsize);
4827 /* Back from the dead for OS/2..... JRA. */
4829 /****************************************************************************
4830 Reply to a SMBwritebmpx (write block multiplex primary) request.
4831 ****************************************************************************/
4833 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4835 size_t numtowrite;
4836 ssize_t nwritten = -1;
4837 int outsize = 0;
4838 SMB_OFF_T startpos;
4839 size_t tcount;
4840 BOOL write_through;
4841 int smb_doff;
4842 char *data;
4843 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4844 START_PROFILE(SMBwriteBmpx);
4846 CHECK_FSP(fsp,conn);
4847 CHECK_WRITE(fsp);
4848 CHECK_ERROR(fsp);
4850 tcount = SVAL(inbuf,smb_vwv1);
4851 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4852 write_through = BITSETW(inbuf+smb_vwv7,0);
4853 numtowrite = SVAL(inbuf,smb_vwv10);
4854 smb_doff = SVAL(inbuf,smb_vwv11);
4856 data = smb_base(inbuf) + smb_doff;
4858 /* If this fails we need to send an SMBwriteC response,
4859 not an SMBwritebmpx - set this up now so we don't forget */
4860 SCVAL(outbuf,smb_com,SMBwritec);
4862 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4863 END_PROFILE(SMBwriteBmpx);
4864 return(ERROR_DOS(ERRDOS,ERRlock));
4867 nwritten = write_file(fsp,data,startpos,numtowrite);
4869 if(lp_syncalways(SNUM(conn)) || write_through)
4870 sync_file(conn,fsp);
4872 if(nwritten < (ssize_t)numtowrite) {
4873 END_PROFILE(SMBwriteBmpx);
4874 return(UNIXERROR(ERRHRD,ERRdiskfull));
4877 /* If the maximum to be written to this file
4878 is greater than what we just wrote then set
4879 up a secondary struct to be attached to this
4880 fd, we will use this to cache error messages etc. */
4882 if((ssize_t)tcount > nwritten) {
4883 write_bmpx_struct *wbms;
4884 if(fsp->wbmpx_ptr != NULL)
4885 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4886 else
4887 wbms = SMB_MALLOC_P(write_bmpx_struct);
4888 if(!wbms) {
4889 DEBUG(0,("Out of memory in reply_readmpx\n"));
4890 END_PROFILE(SMBwriteBmpx);
4891 return(ERROR_DOS(ERRSRV,ERRnoresource));
4893 wbms->wr_mode = write_through;
4894 wbms->wr_discard = False; /* No errors yet */
4895 wbms->wr_total_written = nwritten;
4896 wbms->wr_errclass = 0;
4897 wbms->wr_error = 0;
4898 fsp->wbmpx_ptr = wbms;
4901 /* We are returning successfully, set the message type back to
4902 SMBwritebmpx */
4903 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4905 outsize = set_message(outbuf,1,0,True);
4907 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4909 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4910 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4912 if (write_through && tcount==nwritten) {
4913 /* We need to send both a primary and a secondary response */
4914 smb_setlen(outbuf,outsize - 4);
4915 if (!send_smb(smbd_server_fd(),outbuf))
4916 exit_server("reply_writebmpx: send_smb failed.");
4918 /* Now the secondary */
4919 outsize = set_message(outbuf,1,0,True);
4920 SCVAL(outbuf,smb_com,SMBwritec);
4921 SSVAL(outbuf,smb_vwv0,nwritten);
4924 END_PROFILE(SMBwriteBmpx);
4925 return(outsize);
4928 /****************************************************************************
4929 Reply to a SMBwritebs (write block multiplex secondary) request.
4930 ****************************************************************************/
4932 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4934 size_t numtowrite;
4935 ssize_t nwritten = -1;
4936 int outsize = 0;
4937 SMB_OFF_T startpos;
4938 size_t tcount;
4939 BOOL write_through;
4940 int smb_doff;
4941 char *data;
4942 write_bmpx_struct *wbms;
4943 BOOL send_response = False;
4944 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4945 START_PROFILE(SMBwriteBs);
4947 CHECK_FSP(fsp,conn);
4948 CHECK_WRITE(fsp);
4950 tcount = SVAL(inbuf,smb_vwv1);
4951 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4952 numtowrite = SVAL(inbuf,smb_vwv6);
4953 smb_doff = SVAL(inbuf,smb_vwv7);
4955 data = smb_base(inbuf) + smb_doff;
4957 /* We need to send an SMBwriteC response, not an SMBwritebs */
4958 SCVAL(outbuf,smb_com,SMBwritec);
4960 /* This fd should have an auxiliary struct attached,
4961 check that it does */
4962 wbms = fsp->wbmpx_ptr;
4963 if(!wbms) {
4964 END_PROFILE(SMBwriteBs);
4965 return(-1);
4968 /* If write through is set we can return errors, else we must cache them */
4969 write_through = wbms->wr_mode;
4971 /* Check for an earlier error */
4972 if(wbms->wr_discard) {
4973 END_PROFILE(SMBwriteBs);
4974 return -1; /* Just discard the packet */
4977 nwritten = write_file(fsp,data,startpos,numtowrite);
4979 if(lp_syncalways(SNUM(conn)) || write_through)
4980 sync_file(conn,fsp);
4982 if (nwritten < (ssize_t)numtowrite) {
4983 if(write_through) {
4984 /* We are returning an error - we can delete the aux struct */
4985 if (wbms)
4986 free((char *)wbms);
4987 fsp->wbmpx_ptr = NULL;
4988 END_PROFILE(SMBwriteBs);
4989 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4991 END_PROFILE(SMBwriteBs);
4992 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4995 /* Increment the total written, if this matches tcount
4996 we can discard the auxiliary struct (hurrah !) and return a writeC */
4997 wbms->wr_total_written += nwritten;
4998 if(wbms->wr_total_written >= tcount) {
4999 if (write_through) {
5000 outsize = set_message(outbuf,1,0,True);
5001 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5002 send_response = True;
5005 free((char *)wbms);
5006 fsp->wbmpx_ptr = NULL;
5009 if(send_response) {
5010 END_PROFILE(SMBwriteBs);
5011 return(outsize);
5014 END_PROFILE(SMBwriteBs);
5015 return(-1);
5018 /****************************************************************************
5019 Reply to a SMBgetattrE.
5020 ****************************************************************************/
5022 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5024 SMB_STRUCT_STAT sbuf;
5025 int outsize = 0;
5026 int mode;
5027 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5028 START_PROFILE(SMBgetattrE);
5030 outsize = set_message(outbuf,11,0,True);
5032 if(!fsp || (fsp->conn != conn)) {
5033 END_PROFILE(SMBgetattrE);
5034 return ERROR_DOS(ERRDOS,ERRbadfid);
5037 /* Do an fstat on this file */
5038 if(fsp_stat(fsp, &sbuf)) {
5039 END_PROFILE(SMBgetattrE);
5040 return(UNIXERROR(ERRDOS,ERRnoaccess));
5043 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5046 * Convert the times into dos times. Set create
5047 * date to be last modify date as UNIX doesn't save
5048 * this.
5051 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5052 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5053 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5055 if (mode & aDIR) {
5056 SIVAL(outbuf,smb_vwv6,0);
5057 SIVAL(outbuf,smb_vwv8,0);
5058 } else {
5059 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5060 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5061 SIVAL(outbuf,smb_vwv8,allocation_size);
5063 SSVAL(outbuf,smb_vwv10, mode);
5065 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5067 END_PROFILE(SMBgetattrE);
5068 return(outsize);