source: trunk/samba-3.0.25pre1/source/smbd/reply.c@ 1

Last change on this file since 1 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 155.9 KB
Line 
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-2007.
7
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.
12
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.
17
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.
21*/
22/*
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
25*/
26
27#include "includes.h"
28
29/* look in server.c for some explanation of these variables */
30extern enum protocol_types Protocol;
31extern int max_send;
32extern int max_recv;
33unsigned int smb_echo_count = 0;
34extern uint32 global_client_caps;
35
36extern struct current_user current_user;
37extern BOOL global_encrypted_passwords_negotiated;
38
39/****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 set.
45****************************************************************************/
46
47NTSTATUS check_path_syntax_internal(pstring destname,
48 const pstring srcname,
49 BOOL windows_path,
50 BOOL *p_last_component_contains_wcard)
51{
52 char *d = destname;
53 const char *s = srcname;
54 NTSTATUS ret = NT_STATUS_OK;
55 BOOL start_of_name_component = True;
56
57 *p_last_component_contains_wcard = False;
58
59 while (*s) {
60 if (IS_DIRECTORY_SEP(*s)) {
61 /*
62 * Safe to assume is not the second part of a mb char as this is handled below.
63 */
64 /* Eat multiple '/' or '\\' */
65 while (IS_DIRECTORY_SEP(*s)) {
66 s++;
67 }
68 if ((d != destname) && (*s != '\0')) {
69 /* We only care about non-leading or trailing '/' or '\\' */
70 *d++ = '/';
71 }
72
73 start_of_name_component = True;
74 /* New component. */
75 *p_last_component_contains_wcard = False;
76 continue;
77 }
78
79 if (start_of_name_component) {
80 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
81 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
82
83 /*
84 * No mb char starts with '.' so we're safe checking the directory separator here.
85 */
86
87 /* If we just added a '/' - delete it */
88 if ((d > destname) && (*(d-1) == '/')) {
89 *(d-1) = '\0';
90 d--;
91 }
92
93 /* Are we at the start ? Can't go back further if so. */
94 if (d <= destname) {
95 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
96 break;
97 }
98 /* Go back one level... */
99 /* We know this is safe as '/' cannot be part of a mb sequence. */
100 /* NOTE - if this assumption is invalid we are not in good shape... */
101 /* Decrement d first as d points to the *next* char to write into. */
102 for (d--; d > destname; d--) {
103 if (*d == '/')
104 break;
105 }
106 s += 2; /* Else go past the .. */
107 /* We're still at the start of a name component, just the previous one. */
108 continue;
109
110 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
111 if (!windows_path) {
112 /* Eat the '.' */
113 s++;
114 continue;
115 }
116 }
117
118 }
119
120 if (!(*s & 0x80)) {
121 if (windows_path) {
122 if (*s <= 0x1f) {
123 return NT_STATUS_OBJECT_NAME_INVALID;
124 }
125 switch (*s) {
126 case '*':
127 case '?':
128 case '<':
129 case '>':
130 case '"':
131 *p_last_component_contains_wcard = True;
132 break;
133 default:
134 break;
135 }
136 }
137 *d++ = *s++;
138 } else {
139 size_t siz;
140 /* Get the size of the next MB character. */
141 next_codepoint(s,&siz);
142 switch(siz) {
143 case 5:
144 *d++ = *s++;
145 /*fall through*/
146 case 4:
147 *d++ = *s++;
148 /*fall through*/
149 case 3:
150 *d++ = *s++;
151 /*fall through*/
152 case 2:
153 *d++ = *s++;
154 /*fall through*/
155 case 1:
156 *d++ = *s++;
157 break;
158 default:
159 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
160 *d = '\0';
161 return NT_STATUS_INVALID_PARAMETER;
162 }
163 }
164 start_of_name_component = False;
165 }
166
167 *d = '\0';
168
169 return ret;
170}
171
172/****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175****************************************************************************/
176
177NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
178{
179 BOOL ignore;
180 return check_path_syntax_internal(destname, srcname, True, &ignore);
181}
182
183/****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
186 a wildcard.
187****************************************************************************/
188
189NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
190{
191 return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
192}
193
194/****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198****************************************************************************/
199
200static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
201{
202 BOOL ignore;
203 return check_path_syntax_internal(destname, srcname, False, &ignore);
204}
205
206/****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208****************************************************************************/
209
210size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
211 NTSTATUS *err, BOOL *contains_wcard)
212{
213 pstring tmppath;
214 char *tmppath_ptr = tmppath;
215 size_t ret;
216#ifdef DEVELOPER
217 SMB_ASSERT(dest_len == sizeof(pstring));
218#endif
219
220 if (src_len == 0) {
221 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
222 } else {
223 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
224 }
225
226 *contains_wcard = False;
227
228 if (lp_posix_pathnames()) {
229 *err = check_path_syntax_posix(dest, tmppath);
230 } else {
231 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
232 }
233
234 return ret;
235}
236
237/****************************************************************************
238 Pull a string and check the path - provide for error return.
239****************************************************************************/
240
241size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
242{
243 pstring tmppath;
244 char *tmppath_ptr = tmppath;
245 size_t ret;
246#ifdef DEVELOPER
247 SMB_ASSERT(dest_len == sizeof(pstring));
248#endif
249
250 if (src_len == 0) {
251 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
252 } else {
253 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
254 }
255 if (lp_posix_pathnames()) {
256 *err = check_path_syntax_posix(dest, tmppath);
257 } else {
258 *err = check_path_syntax(dest, tmppath);
259 }
260
261 return ret;
262}
263
264/****************************************************************************
265 Reply to a special message.
266****************************************************************************/
267
268int reply_special(char *inbuf,char *outbuf)
269{
270 int outsize = 4;
271 int msg_type = CVAL(inbuf,0);
272 int msg_flags = CVAL(inbuf,1);
273 fstring name1,name2;
274 char name_type = 0;
275
276 static BOOL already_got_session = False;
277
278 *name1 = *name2 = 0;
279
280 memset(outbuf,'\0',smb_size);
281
282 smb_setlen(outbuf,0);
283
284 switch (msg_type) {
285 case 0x81: /* session request */
286
287 if (already_got_session) {
288 exit_server_cleanly("multiple session request not permitted");
289 }
290
291 SCVAL(outbuf,0,0x82);
292 SCVAL(outbuf,3,0);
293 if (name_len(inbuf+4) > 50 ||
294 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
295 DEBUG(0,("Invalid name length in session request\n"));
296 return(0);
297 }
298 name_extract(inbuf,4,name1);
299 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
300 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
301 name1,name2));
302
303 set_local_machine_name(name1, True);
304 set_remote_machine_name(name2, True);
305
306 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
307 get_local_machine_name(), get_remote_machine_name(),
308 name_type));
309
310 if (name_type == 'R') {
311 /* We are being asked for a pathworks session ---
312 no thanks! */
313 SCVAL(outbuf, 0,0x83);
314 break;
315 }
316
317 /* only add the client's machine name to the list
318 of possibly valid usernames if we are operating
319 in share mode security */
320 if (lp_security() == SEC_SHARE) {
321 add_session_user(get_remote_machine_name());
322 }
323
324 reload_services(True);
325 reopen_logs();
326
327 already_got_session = True;
328 break;
329
330 case 0x89: /* session keepalive request
331 (some old clients produce this?) */
332 SCVAL(outbuf,0,SMBkeepalive);
333 SCVAL(outbuf,3,0);
334 break;
335
336 case 0x82: /* positive session response */
337 case 0x83: /* negative session response */
338 case 0x84: /* retarget session response */
339 DEBUG(0,("Unexpected session response\n"));
340 break;
341
342 case SMBkeepalive: /* session keepalive */
343 default:
344 return(0);
345 }
346
347 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
348 msg_type, msg_flags));
349
350 return(outsize);
351}
352
353/****************************************************************************
354 Reply to a tcon.
355 conn POINTER CAN BE NULL HERE !
356****************************************************************************/
357
358int reply_tcon(connection_struct *conn,
359 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
360{
361 const char *service;
362 pstring service_buf;
363 pstring password;
364 pstring dev;
365 int outsize = 0;
366 uint16 vuid = SVAL(inbuf,smb_uid);
367 int pwlen=0;
368 NTSTATUS nt_status;
369 char *p;
370 DATA_BLOB password_blob;
371
372 START_PROFILE(SMBtcon);
373
374 *service_buf = *password = *dev = 0;
375
376 p = smb_buf(inbuf)+1;
377 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
378 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
379 p += pwlen;
380 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
381
382 p = strrchr_m(service_buf,'\\');
383 if (p) {
384 service = p+1;
385 } else {
386 service = service_buf;
387 }
388
389 password_blob = data_blob(password, pwlen+1);
390
391 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
392
393 data_blob_clear_free(&password_blob);
394
395 if (!conn) {
396 END_PROFILE(SMBtcon);
397 return ERROR_NT(nt_status);
398 }
399
400 outsize = set_message(outbuf,2,0,True);
401 SSVAL(outbuf,smb_vwv0,max_recv);
402 SSVAL(outbuf,smb_vwv1,conn->cnum);
403 SSVAL(outbuf,smb_tid,conn->cnum);
404
405 DEBUG(3,("tcon service=%s cnum=%d\n",
406 service, conn->cnum));
407
408 END_PROFILE(SMBtcon);
409 return(outsize);
410}
411
412/****************************************************************************
413 Reply to a tcon and X.
414 conn POINTER CAN BE NULL HERE !
415****************************************************************************/
416
417int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
418{
419 fstring service;
420 DATA_BLOB password;
421
422 /* what the cleint thinks the device is */
423 fstring client_devicetype;
424 /* what the server tells the client the share represents */
425 const char *server_devicetype;
426 NTSTATUS nt_status;
427 uint16 vuid = SVAL(inbuf,smb_uid);
428 int passlen = SVAL(inbuf,smb_vwv3);
429 pstring path;
430 char *p, *q;
431
432 START_PROFILE(SMBtconX);
433
434 *service = *client_devicetype = 0;
435
436 /* we might have to close an old one */
437 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
438 close_cnum(conn,vuid);
439 }
440
441 if (passlen > MAX_PASS_LEN) {
442 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
443 }
444
445 if (global_encrypted_passwords_negotiated) {
446 password = data_blob(smb_buf(inbuf),passlen);
447 } else {
448 password = data_blob(smb_buf(inbuf),passlen+1);
449 /* Ensure correct termination */
450 password.data[passlen]=0;
451 }
452
453 p = smb_buf(inbuf) + passlen;
454 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
455
456 /*
457 * the service name can be either: \\server\share
458 * or share directly like on the DELL PowerVault 705
459 */
460 if (*path=='\\') {
461 q = strchr_m(path+2,'\\');
462 if (!q) {
463 END_PROFILE(SMBtconX);
464 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
465 }
466 fstrcpy(service,q+1);
467 }
468 else
469 fstrcpy(service,path);
470
471 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
472
473 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
474
475 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
476
477 data_blob_clear_free(&password);
478
479 if (!conn) {
480 END_PROFILE(SMBtconX);
481 return ERROR_NT(nt_status);
482 }
483
484 if ( IS_IPC(conn) )
485 server_devicetype = "IPC";
486 else if ( IS_PRINT(conn) )
487 server_devicetype = "LPT1:";
488 else
489 server_devicetype = "A:";
490
491 if (Protocol < PROTOCOL_NT1) {
492 set_message(outbuf,2,0,True);
493 p = smb_buf(outbuf);
494 p += srvstr_push(outbuf, p, server_devicetype, -1,
495 STR_TERMINATE|STR_ASCII);
496 set_message_end(outbuf,p);
497 } else {
498 /* NT sets the fstype of IPC$ to the null string */
499 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
500
501 set_message(outbuf,3,0,True);
502
503 p = smb_buf(outbuf);
504 p += srvstr_push(outbuf, p, server_devicetype, -1,
505 STR_TERMINATE|STR_ASCII);
506 p += srvstr_push(outbuf, p, fstype, -1,
507 STR_TERMINATE);
508
509 set_message_end(outbuf,p);
510
511 /* what does setting this bit do? It is set by NT4 and
512 may affect the ability to autorun mounted cdroms */
513 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
514 (lp_csc_policy(SNUM(conn)) << 2));
515
516 init_dfsroot(conn, inbuf, outbuf);
517 }
518
519
520 DEBUG(3,("tconX service=%s \n",
521 service));
522
523 /* set the incoming and outgoing tid to the just created one */
524 SSVAL(inbuf,smb_tid,conn->cnum);
525 SSVAL(outbuf,smb_tid,conn->cnum);
526
527 END_PROFILE(SMBtconX);
528 return chain_reply(inbuf,outbuf,length,bufsize);
529}
530
531/****************************************************************************
532 Reply to an unknown type.
533****************************************************************************/
534
535int reply_unknown(char *inbuf,char *outbuf)
536{
537 int type;
538 type = CVAL(inbuf,smb_com);
539
540 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
541 smb_fn_name(type), type, type));
542
543 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
544}
545
546/****************************************************************************
547 Reply to an ioctl.
548 conn POINTER CAN BE NULL HERE !
549****************************************************************************/
550
551int reply_ioctl(connection_struct *conn,
552 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
553{
554 uint16 device = SVAL(inbuf,smb_vwv1);
555 uint16 function = SVAL(inbuf,smb_vwv2);
556 uint32 ioctl_code = (device << 16) + function;
557 int replysize, outsize;
558 char *p;
559 START_PROFILE(SMBioctl);
560
561 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
562
563 switch (ioctl_code) {
564 case IOCTL_QUERY_JOB_INFO:
565 replysize = 32;
566 break;
567 default:
568 END_PROFILE(SMBioctl);
569 return(ERROR_DOS(ERRSRV,ERRnosupport));
570 }
571
572 outsize = set_message(outbuf,8,replysize+1,True);
573 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
574 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
575 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
576 p = smb_buf(outbuf) + 1; /* Allow for alignment */
577
578 switch (ioctl_code) {
579 case IOCTL_QUERY_JOB_INFO:
580 {
581 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
582 if (!fsp) {
583 END_PROFILE(SMBioctl);
584 return(UNIXERROR(ERRDOS,ERRbadfid));
585 }
586 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
587 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
588 if (conn) {
589 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
590 }
591 break;
592 }
593 }
594
595 END_PROFILE(SMBioctl);
596 return outsize;
597}
598
599/****************************************************************************
600 Strange checkpath NTSTATUS mapping.
601****************************************************************************/
602
603static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
604{
605 /* Strange DOS error code semantics only for checkpath... */
606 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
607 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
608 /* We need to map to ERRbadpath */
609 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
610 }
611 }
612 return status;
613}
614
615/****************************************************************************
616 Reply to a checkpath.
617****************************************************************************/
618
619int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
620{
621 int outsize = 0;
622 pstring name;
623 SMB_STRUCT_STAT sbuf;
624 NTSTATUS status;
625
626 START_PROFILE(SMBcheckpath);
627
628 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
629 if (!NT_STATUS_IS_OK(status)) {
630 END_PROFILE(SMBcheckpath);
631 status = map_checkpath_error(inbuf, status);
632 return ERROR_NT(status);
633 }
634
635 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
636
637 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
638
639 status = unix_convert(conn, name, False, NULL, &sbuf);
640 if (!NT_STATUS_IS_OK(status)) {
641 goto path_err;
642 }
643
644 status = check_name(conn, name);
645 if (!NT_STATUS_IS_OK(status)) {
646 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
647 goto path_err;
648 }
649
650 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
651 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
652 status = map_nt_error_from_unix(errno);
653 goto path_err;
654 }
655
656 if (!S_ISDIR(sbuf.st_mode)) {
657 END_PROFILE(SMBcheckpath);
658 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
659 }
660
661 outsize = set_message(outbuf,0,0,False);
662
663 END_PROFILE(SMBcheckpath);
664 return outsize;
665
666 path_err:
667
668 END_PROFILE(SMBcheckpath);
669
670 /* We special case this - as when a Windows machine
671 is parsing a path is steps through the components
672 one at a time - if a component fails it expects
673 ERRbadpath, not ERRbadfile.
674 */
675 status = map_checkpath_error(inbuf, status);
676 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
677 /*
678 * Windows returns different error codes if
679 * the parent directory is valid but not the
680 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
681 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
682 * if the path is invalid.
683 */
684 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
685 }
686
687 return ERROR_NT(status);
688}
689
690/****************************************************************************
691 Reply to a getatr.
692****************************************************************************/
693
694int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
695{
696 pstring fname;
697 int outsize = 0;
698 SMB_STRUCT_STAT sbuf;
699 int mode=0;
700 SMB_OFF_T size=0;
701 time_t mtime=0;
702 char *p;
703 NTSTATUS status;
704
705 START_PROFILE(SMBgetatr);
706
707 p = smb_buf(inbuf) + 1;
708 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
709 if (!NT_STATUS_IS_OK(status)) {
710 END_PROFILE(SMBgetatr);
711 return ERROR_NT(status);
712 }
713
714 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
715
716 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
717 under WfWg - weird! */
718 if (*fname == '\0') {
719 mode = aHIDDEN | aDIR;
720 if (!CAN_WRITE(conn)) {
721 mode |= aRONLY;
722 }
723 size = 0;
724 mtime = 0;
725 } else {
726 status = unix_convert(conn, fname, False, NULL,&sbuf);
727 if (!NT_STATUS_IS_OK(status)) {
728 END_PROFILE(SMBgetatr);
729 return ERROR_NT(status);
730 }
731 status = check_name(conn, fname);
732 if (!NT_STATUS_IS_OK(status)) {
733 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
734 END_PROFILE(SMBgetatr);
735 return ERROR_NT(status);
736 }
737 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
738 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
739 return UNIXERROR(ERRDOS,ERRbadfile);
740 }
741
742 mode = dos_mode(conn,fname,&sbuf);
743 size = sbuf.st_size;
744 mtime = sbuf.st_mtime;
745 if (mode & aDIR) {
746 size = 0;
747 }
748 }
749
750 outsize = set_message(outbuf,10,0,True);
751
752 SSVAL(outbuf,smb_vwv0,mode);
753 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
754 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
755 } else {
756 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
757 }
758 SIVAL(outbuf,smb_vwv3,(uint32)size);
759
760 if (Protocol >= PROTOCOL_NT1) {
761 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
762 }
763
764 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
765
766 END_PROFILE(SMBgetatr);
767 return(outsize);
768}
769
770/****************************************************************************
771 Reply to a setatr.
772****************************************************************************/
773
774int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
775{
776 pstring fname;
777 int outsize = 0;
778 int mode;
779 time_t mtime;
780 SMB_STRUCT_STAT sbuf;
781 char *p;
782 NTSTATUS status;
783
784 START_PROFILE(SMBsetatr);
785
786 p = smb_buf(inbuf) + 1;
787 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
788 if (!NT_STATUS_IS_OK(status)) {
789 END_PROFILE(SMBsetatr);
790 return ERROR_NT(status);
791 }
792
793 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
794
795 status = unix_convert(conn, fname, False, NULL, &sbuf);
796 if (!NT_STATUS_IS_OK(status)) {
797 END_PROFILE(SMBsetatr);
798 return ERROR_NT(status);
799 }
800
801 if (fname[0] == '.' && fname[1] == '\0') {
802 /*
803 * Not sure here is the right place to catch this
804 * condition. Might be moved to somewhere else later -- vl
805 */
806 END_PROFILE(SMBsetatr);
807 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
808 }
809
810 status = check_name(conn, fname);
811 if (!NT_STATUS_IS_OK(status)) {
812 END_PROFILE(SMBsetatr);
813 return ERROR_NT(status);
814 }
815
816 mode = SVAL(inbuf,smb_vwv0);
817 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
818
819 if (mode != FILE_ATTRIBUTE_NORMAL) {
820 if (VALID_STAT_OF_DIR(sbuf))
821 mode |= aDIR;
822 else
823 mode &= ~aDIR;
824
825 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
826 END_PROFILE(SMBsetatr);
827 return UNIXERROR(ERRDOS, ERRnoaccess);
828 }
829 }
830
831 if (!set_filetime(conn,fname,mtime)) {
832 END_PROFILE(SMBsetatr);
833 return UNIXERROR(ERRDOS, ERRnoaccess);
834 }
835
836 outsize = set_message(outbuf,0,0,False);
837
838 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
839
840 END_PROFILE(SMBsetatr);
841 return(outsize);
842}
843
844/****************************************************************************
845 Reply to a dskattr.
846****************************************************************************/
847
848int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
849{
850 int outsize = 0;
851 SMB_BIG_UINT dfree,dsize,bsize;
852 START_PROFILE(SMBdskattr);
853
854 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
855 END_PROFILE(SMBdskattr);
856 return(UNIXERROR(ERRHRD,ERRgeneral));
857 }
858
859 outsize = set_message(outbuf,5,0,True);
860
861 if (Protocol <= PROTOCOL_LANMAN2) {
862 double total_space, free_space;
863 /* we need to scale this to a number that DOS6 can handle. We
864 use floating point so we can handle large drives on systems
865 that don't have 64 bit integers
866
867 we end up displaying a maximum of 2G to DOS systems
868 */
869 total_space = dsize * (double)bsize;
870 free_space = dfree * (double)bsize;
871
872 dsize = (total_space+63*512) / (64*512);
873 dfree = (free_space+63*512) / (64*512);
874
875 if (dsize > 0xFFFF) dsize = 0xFFFF;
876 if (dfree > 0xFFFF) dfree = 0xFFFF;
877
878 SSVAL(outbuf,smb_vwv0,dsize);
879 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
880 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
881 SSVAL(outbuf,smb_vwv3,dfree);
882 } else {
883 SSVAL(outbuf,smb_vwv0,dsize);
884 SSVAL(outbuf,smb_vwv1,bsize/512);
885 SSVAL(outbuf,smb_vwv2,512);
886 SSVAL(outbuf,smb_vwv3,dfree);
887 }
888
889 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
890
891 END_PROFILE(SMBdskattr);
892 return(outsize);
893}
894
895/****************************************************************************
896 Reply to a search.
897 Can be called from SMBsearch, SMBffirst or SMBfunique.
898****************************************************************************/
899
900int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
901{
902 pstring mask;
903 pstring directory;
904 pstring fname;
905 SMB_OFF_T size;
906 uint32 mode;
907 time_t date;
908 uint32 dirtype;
909 int outsize = 0;
910 unsigned int numentries = 0;
911 unsigned int maxentries = 0;
912 BOOL finished = False;
913 char *p;
914 int status_len;
915 pstring path;
916 char status[21];
917 int dptr_num= -1;
918 BOOL check_descend = False;
919 BOOL expect_close = False;
920 NTSTATUS nt_status;
921 BOOL mask_contains_wcard = False;
922 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
923
924 START_PROFILE(SMBsearch);
925
926 if (lp_posix_pathnames()) {
927 END_PROFILE(SMBsearch);
928 return reply_unknown(inbuf, outbuf);
929 }
930
931 *mask = *directory = *fname = 0;
932
933 /* If we were called as SMBffirst then we must expect close. */
934 if(CVAL(inbuf,smb_com) == SMBffirst) {
935 expect_close = True;
936 }
937
938 outsize = set_message(outbuf,1,3,True);
939 maxentries = SVAL(inbuf,smb_vwv0);
940 dirtype = SVAL(inbuf,smb_vwv1);
941 p = smb_buf(inbuf) + 1;
942 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
943 if (!NT_STATUS_IS_OK(nt_status)) {
944 END_PROFILE(SMBsearch);
945 return ERROR_NT(nt_status);
946 }
947
948 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
949
950 p++;
951 status_len = SVAL(p, 0);
952 p += 2;
953
954 /* dirtype &= ~aDIR; */
955
956 if (status_len == 0) {
957 SMB_STRUCT_STAT sbuf;
958 pstring dir2;
959
960 pstrcpy(directory,path);
961 pstrcpy(dir2,path);
962 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
963 if (!NT_STATUS_IS_OK(nt_status)) {
964 END_PROFILE(SMBsearch);
965 return ERROR_NT(nt_status);
966 }
967 unix_format(dir2);
968
969 nt_status = check_name(conn, directory);
970 if (!NT_STATUS_IS_OK(nt_status)) {
971 END_PROFILE(SMBsearch);
972 return ERROR_NT(nt_status);
973 }
974
975 p = strrchr_m(dir2,'/');
976 if (p == NULL) {
977 pstrcpy(mask,dir2);
978 *dir2 = 0;
979 } else {
980 *p = 0;
981 pstrcpy(mask,p+1);
982 }
983
984 p = strrchr_m(directory,'/');
985 if (!p) {
986 *directory = 0;
987 } else {
988 *p = 0;
989 }
990
991 if (strlen(directory) == 0) {
992 pstrcpy(directory,".");
993 }
994 memset((char *)status,'\0',21);
995 SCVAL(status,0,(dirtype & 0x1F));
996 } else {
997 int status_dirtype;
998
999 memcpy(status,p,21);
1000 status_dirtype = CVAL(status,0) & 0x1F;
1001 if (status_dirtype != (dirtype & 0x1F)) {
1002 dirtype = status_dirtype;
1003 }
1004
1005 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1006 if (!conn->dirptr) {
1007 goto SearchEmpty;
1008 }
1009 string_set(&conn->dirpath,dptr_path(dptr_num));
1010 pstrcpy(mask, dptr_wcard(dptr_num));
1011 }
1012
1013 p = smb_buf(outbuf) + 3;
1014
1015 if (status_len == 0) {
1016 nt_status = dptr_create(conn,
1017 directory,
1018 True,
1019 expect_close,
1020 SVAL(inbuf,smb_pid),
1021 mask,
1022 mask_contains_wcard,
1023 dirtype,
1024 &conn->dirptr);
1025 if (!NT_STATUS_IS_OK(nt_status)) {
1026 return ERROR_NT(nt_status);
1027 }
1028 dptr_num = dptr_dnum(conn->dirptr);
1029 } else {
1030 dirtype = dptr_attr(dptr_num);
1031 }
1032
1033 DEBUG(4,("dptr_num is %d\n",dptr_num));
1034
1035 if ((dirtype&0x1F) == aVOLID) {
1036 memcpy(p,status,21);
1037 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1038 0,aVOLID,0,!allow_long_path_components);
1039 dptr_fill(p+12,dptr_num);
1040 if (dptr_zero(p+12) && (status_len==0)) {
1041 numentries = 1;
1042 } else {
1043 numentries = 0;
1044 }
1045 p += DIR_STRUCT_SIZE;
1046 } else {
1047 unsigned int i;
1048 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1049
1050 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1051 conn->dirpath,lp_dontdescend(SNUM(conn))));
1052 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1053 check_descend = True;
1054 }
1055
1056 for (i=numentries;(i<maxentries) && !finished;i++) {
1057 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1058 if (!finished) {
1059 memcpy(p,status,21);
1060 make_dir_struct(p,mask,fname,size, mode,date,
1061 !allow_long_path_components);
1062 if (!dptr_fill(p+12,dptr_num)) {
1063 break;
1064 }
1065 numentries++;
1066 p += DIR_STRUCT_SIZE;
1067 }
1068 }
1069 }
1070
1071 SearchEmpty:
1072
1073 /* If we were called as SMBffirst with smb_search_id == NULL
1074 and no entries were found then return error and close dirptr
1075 (X/Open spec) */
1076
1077 if (numentries == 0) {
1078 dptr_close(&dptr_num);
1079 } else if(expect_close && status_len == 0) {
1080 /* Close the dptr - we know it's gone */
1081 dptr_close(&dptr_num);
1082 }
1083
1084 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1085 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1086 dptr_close(&dptr_num);
1087 }
1088
1089 if ((numentries == 0) && !mask_contains_wcard) {
1090 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1091 }
1092
1093 SSVAL(outbuf,smb_vwv0,numentries);
1094 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1095 SCVAL(smb_buf(outbuf),0,5);
1096 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1097
1098 /* The replies here are never long name. */
1099 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1100 if (!allow_long_path_components) {
1101 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1102 }
1103
1104 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1105 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1106
1107 outsize += DIR_STRUCT_SIZE*numentries;
1108 smb_setlen(outbuf,outsize - 4);
1109
1110 if ((! *directory) && dptr_path(dptr_num))
1111 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1112
1113 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1114 smb_fn_name(CVAL(inbuf,smb_com)),
1115 mask, directory, dirtype, numentries, maxentries ) );
1116
1117 END_PROFILE(SMBsearch);
1118 return(outsize);
1119}
1120
1121/****************************************************************************
1122 Reply to a fclose (stop directory search).
1123****************************************************************************/
1124
1125int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1126{
1127 int outsize = 0;
1128 int status_len;
1129 pstring path;
1130 char status[21];
1131 int dptr_num= -2;
1132 char *p;
1133 NTSTATUS err;
1134 BOOL path_contains_wcard = False;
1135
1136 START_PROFILE(SMBfclose);
1137
1138 if (lp_posix_pathnames()) {
1139 END_PROFILE(SMBfclose);
1140 return reply_unknown(inbuf, outbuf);
1141 }
1142
1143 outsize = set_message(outbuf,1,0,True);
1144 p = smb_buf(inbuf) + 1;
1145 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1146 if (!NT_STATUS_IS_OK(err)) {
1147 END_PROFILE(SMBfclose);
1148 return ERROR_NT(err);
1149 }
1150 p++;
1151 status_len = SVAL(p,0);
1152 p += 2;
1153
1154 if (status_len == 0) {
1155 END_PROFILE(SMBfclose);
1156 return ERROR_DOS(ERRSRV,ERRsrverror);
1157 }
1158
1159 memcpy(status,p,21);
1160
1161 if(dptr_fetch(status+12,&dptr_num)) {
1162 /* Close the dptr - we know it's gone */
1163 dptr_close(&dptr_num);
1164 }
1165
1166 SSVAL(outbuf,smb_vwv0,0);
1167
1168 DEBUG(3,("search close\n"));
1169
1170 END_PROFILE(SMBfclose);
1171 return(outsize);
1172}
1173
1174/****************************************************************************
1175 Reply to an open.
1176****************************************************************************/
1177
1178int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1179{
1180 pstring fname;
1181 int outsize = 0;
1182 uint32 fattr=0;
1183 SMB_OFF_T size = 0;
1184 time_t mtime=0;
1185 int info;
1186 SMB_STRUCT_STAT sbuf;
1187 files_struct *fsp;
1188 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1189 int deny_mode;
1190 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1191 uint32 access_mask;
1192 uint32 share_mode;
1193 uint32 create_disposition;
1194 uint32 create_options = 0;
1195 NTSTATUS status;
1196 START_PROFILE(SMBopen);
1197
1198 deny_mode = SVAL(inbuf,smb_vwv0);
1199
1200 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 END_PROFILE(SMBopen);
1203 return ERROR_NT(status);
1204 }
1205
1206 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1207
1208 status = unix_convert(conn, fname, False, NULL, &sbuf);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 END_PROFILE(SMBopen);
1211 return ERROR_NT(status);
1212 }
1213
1214 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1215 &access_mask, &share_mode, &create_disposition, &create_options)) {
1216 END_PROFILE(SMBopen);
1217 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1218 }
1219
1220 status = open_file_ntcreate(conn,fname,&sbuf,
1221 access_mask,
1222 share_mode,
1223 create_disposition,
1224 create_options,
1225 dos_attr,
1226 oplock_request,
1227 &info, &fsp);
1228
1229 if (!NT_STATUS_IS_OK(status)) {
1230 END_PROFILE(SMBopen);
1231 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1232 /* We have re-scheduled this call. */
1233 return -1;
1234 }
1235 return ERROR_NT(status);
1236 }
1237
1238 size = sbuf.st_size;
1239 fattr = dos_mode(conn,fname,&sbuf);
1240 mtime = sbuf.st_mtime;
1241
1242 if (fattr & aDIR) {
1243 DEBUG(3,("attempt to open a directory %s\n",fname));
1244 close_file(fsp,ERROR_CLOSE);
1245 END_PROFILE(SMBopen);
1246 return ERROR_DOS(ERRDOS,ERRnoaccess);
1247 }
1248
1249 outsize = set_message(outbuf,7,0,True);
1250 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1251 SSVAL(outbuf,smb_vwv1,fattr);
1252 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1253 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1254 } else {
1255 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1256 }
1257 SIVAL(outbuf,smb_vwv4,(uint32)size);
1258 SSVAL(outbuf,smb_vwv6,deny_mode);
1259
1260 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1261 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1262 }
1263
1264 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1265 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1266 }
1267 END_PROFILE(SMBopen);
1268 return(outsize);
1269}
1270
1271/****************************************************************************
1272 Reply to an open and X.
1273****************************************************************************/
1274
1275int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1276{
1277 pstring fname;
1278 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1279 int deny_mode = SVAL(inbuf,smb_vwv3);
1280 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1281 /* Breakout the oplock request bits so we can set the
1282 reply bits separately. */
1283 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1284 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1285 int oplock_request = ex_oplock_request | core_oplock_request;
1286#if 0
1287 int smb_sattr = SVAL(inbuf,smb_vwv4);
1288 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1289#endif
1290 int smb_ofun = SVAL(inbuf,smb_vwv8);
1291 uint32 fattr=0;
1292 int mtime=0;
1293 SMB_STRUCT_STAT sbuf;
1294 int smb_action = 0;
1295 files_struct *fsp;
1296 NTSTATUS status;
1297 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1298 ssize_t retval = -1;
1299 uint32 access_mask;
1300 uint32 share_mode;
1301 uint32 create_disposition;
1302 uint32 create_options = 0;
1303
1304 START_PROFILE(SMBopenX);
1305
1306 /* If it's an IPC, pass off the pipe handler. */
1307 if (IS_IPC(conn)) {
1308 if (lp_nt_pipe_support()) {
1309 END_PROFILE(SMBopenX);
1310 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1311 } else {
1312 END_PROFILE(SMBopenX);
1313 return ERROR_DOS(ERRSRV,ERRaccess);
1314 }
1315 }
1316
1317 /* XXXX we need to handle passed times, sattr and flags */
1318 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1319 if (!NT_STATUS_IS_OK(status)) {
1320 END_PROFILE(SMBopenX);
1321 return ERROR_NT(status);
1322 }
1323
1324 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1325
1326 status = unix_convert(conn, fname, False, NULL, &sbuf);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 END_PROFILE(SMBopenX);
1329 return ERROR_NT(status);
1330 }
1331
1332 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1333 &access_mask,
1334 &share_mode,
1335 &create_disposition,
1336 &create_options)) {
1337 END_PROFILE(SMBopenX);
1338 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1339 }
1340
1341 status = open_file_ntcreate(conn,fname,&sbuf,
1342 access_mask,
1343 share_mode,
1344 create_disposition,
1345 create_options,
1346 smb_attr,
1347 oplock_request,
1348 &smb_action, &fsp);
1349
1350 if (!NT_STATUS_IS_OK(status)) {
1351 END_PROFILE(SMBopenX);
1352 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1353 /* We have re-scheduled this call. */
1354 return -1;
1355 }
1356 return ERROR_NT(status);
1357 }
1358
1359 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1360 if the file is truncated or created. */
1361 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1362 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1363 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1364 close_file(fsp,ERROR_CLOSE);
1365 END_PROFILE(SMBopenX);
1366 return ERROR_NT(NT_STATUS_DISK_FULL);
1367 }
1368 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1369 if (retval < 0) {
1370 close_file(fsp,ERROR_CLOSE);
1371 END_PROFILE(SMBopenX);
1372 return ERROR_NT(NT_STATUS_DISK_FULL);
1373 }
1374 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1375 }
1376
1377 fattr = dos_mode(conn,fname,&sbuf);
1378 mtime = sbuf.st_mtime;
1379 if (fattr & aDIR) {
1380 close_file(fsp,ERROR_CLOSE);
1381 END_PROFILE(SMBopenX);
1382 return ERROR_DOS(ERRDOS,ERRnoaccess);
1383 }
1384
1385 /* If the caller set the extended oplock request bit
1386 and we granted one (by whatever means) - set the
1387 correct bit for extended oplock reply.
1388 */
1389
1390 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1391 smb_action |= EXTENDED_OPLOCK_GRANTED;
1392 }
1393
1394 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1395 smb_action |= EXTENDED_OPLOCK_GRANTED;
1396 }
1397
1398 /* If the caller set the core oplock request bit
1399 and we granted one (by whatever means) - set the
1400 correct bit for core oplock reply.
1401 */
1402
1403 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1404 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1405 }
1406
1407 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1408 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1409 }
1410
1411 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1412 set_message(outbuf,19,0,True);
1413 } else {
1414 set_message(outbuf,15,0,True);
1415 }
1416 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1417 SSVAL(outbuf,smb_vwv3,fattr);
1418 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1419 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1420 } else {
1421 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1422 }
1423 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1424 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1425 SSVAL(outbuf,smb_vwv11,smb_action);
1426
1427 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1428 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1429 }
1430
1431 END_PROFILE(SMBopenX);
1432 return chain_reply(inbuf,outbuf,length,bufsize);
1433}
1434
1435/****************************************************************************
1436 Reply to a SMBulogoffX.
1437 conn POINTER CAN BE NULL HERE !
1438****************************************************************************/
1439
1440int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1441{
1442 uint16 vuid = SVAL(inbuf,smb_uid);
1443 user_struct *vuser = get_valid_user_struct(vuid);
1444 START_PROFILE(SMBulogoffX);
1445
1446 if(vuser == 0)
1447 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1448
1449 /* in user level security we are supposed to close any files
1450 open by this user */
1451 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1452 file_close_user(vuid);
1453
1454 invalidate_vuid(vuid);
1455
1456 set_message(outbuf,2,0,True);
1457
1458 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1459
1460 END_PROFILE(SMBulogoffX);
1461 return chain_reply(inbuf,outbuf,length,bufsize);
1462}
1463
1464/****************************************************************************
1465 Reply to a mknew or a create.
1466****************************************************************************/
1467
1468int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1469{
1470 pstring fname;
1471 int com;
1472 int outsize = 0;
1473 uint32 fattr = SVAL(inbuf,smb_vwv0);
1474 struct utimbuf times;
1475 files_struct *fsp;
1476 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1477 SMB_STRUCT_STAT sbuf;
1478 NTSTATUS status;
1479 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1480 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1481 uint32 create_disposition;
1482 uint32 create_options = 0;
1483
1484 START_PROFILE(SMBcreate);
1485
1486 com = SVAL(inbuf,smb_com);
1487
1488 times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
1489
1490 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 END_PROFILE(SMBcreate);
1493 return ERROR_NT(status);
1494 }
1495
1496 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1497
1498 status = unix_convert(conn, fname, False, NULL, &sbuf);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 END_PROFILE(SMBcreate);
1501 return ERROR_NT(status);
1502 }
1503
1504 if (fattr & aVOLID) {
1505 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1506 }
1507
1508 if(com == SMBmknew) {
1509 /* We should fail if file exists. */
1510 create_disposition = FILE_CREATE;
1511 } else {
1512 /* Create if file doesn't exist, truncate if it does. */
1513 create_disposition = FILE_OVERWRITE_IF;
1514 }
1515
1516 /* Open file using ntcreate. */
1517 status = open_file_ntcreate(conn,fname,&sbuf,
1518 access_mask,
1519 share_mode,
1520 create_disposition,
1521 create_options,
1522 fattr,
1523 oplock_request,
1524 NULL, &fsp);
1525
1526 if (!NT_STATUS_IS_OK(status)) {
1527 END_PROFILE(SMBcreate);
1528 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1529 /* We have re-scheduled this call. */
1530 return -1;
1531 }
1532 return ERROR_NT(status);
1533 }
1534
1535 times.actime = sbuf.st_atime;
1536 file_utime(conn, fname, &times);
1537
1538 outsize = set_message(outbuf,1,0,True);
1539 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1540
1541 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1542 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1543 }
1544
1545 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1546 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1547 }
1548
1549 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1550 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1551
1552 END_PROFILE(SMBcreate);
1553 return(outsize);
1554}
1555
1556/****************************************************************************
1557 Reply to a create temporary file.
1558****************************************************************************/
1559
1560int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1561{
1562 pstring fname;
1563 int outsize = 0;
1564 uint32 fattr = SVAL(inbuf,smb_vwv0);
1565 files_struct *fsp;
1566 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1567 int tmpfd;
1568 SMB_STRUCT_STAT sbuf;
1569 char *p, *s;
1570 NTSTATUS status;
1571 unsigned int namelen;
1572
1573 START_PROFILE(SMBctemp);
1574
1575 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 END_PROFILE(SMBctemp);
1578 return ERROR_NT(status);
1579 }
1580 if (*fname) {
1581 pstrcat(fname,"/TMXXXXXX");
1582 } else {
1583 pstrcat(fname,"TMXXXXXX");
1584 }
1585
1586 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1587
1588 status = unix_convert(conn, fname, False, NULL, &sbuf);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 END_PROFILE(SMBctemp);
1591 return ERROR_NT(status);
1592 }
1593
1594 tmpfd = smb_mkstemp(fname);
1595 if (tmpfd == -1) {
1596 END_PROFILE(SMBctemp);
1597 return(UNIXERROR(ERRDOS,ERRnoaccess));
1598 }
1599
1600 SMB_VFS_STAT(conn,fname,&sbuf);
1601
1602 /* We should fail if file does not exist. */
1603 status = open_file_ntcreate(conn,fname,&sbuf,
1604 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1605 FILE_SHARE_READ|FILE_SHARE_WRITE,
1606 FILE_OPEN,
1607 0,
1608 fattr,
1609 oplock_request,
1610 NULL, &fsp);
1611
1612 /* close fd from smb_mkstemp() */
1613 close(tmpfd);
1614
1615 if (!NT_STATUS_IS_OK(status)) {
1616 END_PROFILE(SMBctemp);
1617 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1618 /* We have re-scheduled this call. */
1619 return -1;
1620 }
1621 return ERROR_NT(status);
1622 }
1623
1624 outsize = set_message(outbuf,1,0,True);
1625 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1626
1627 /* the returned filename is relative to the directory */
1628 s = strrchr_m(fname, '/');
1629 if (!s) {
1630 s = fname;
1631 } else {
1632 s++;
1633 }
1634
1635 p = smb_buf(outbuf);
1636#if 0
1637 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1638 thing in the byte section. JRA */
1639 SSVALS(p, 0, -1); /* what is this? not in spec */
1640#endif
1641 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1642 p += namelen;
1643 outsize = set_message_end(outbuf, p);
1644
1645 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1646 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1647 }
1648
1649 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1650 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1651 }
1652
1653 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1654 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1655 (unsigned int)sbuf.st_mode ) );
1656
1657 END_PROFILE(SMBctemp);
1658 return(outsize);
1659}
1660
1661/*******************************************************************
1662 Check if a user is allowed to rename a file.
1663********************************************************************/
1664
1665static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1666{
1667 files_struct *fsp;
1668 uint32 fmode;
1669 NTSTATUS status;
1670
1671 if (!CAN_WRITE(conn)) {
1672 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1673 }
1674
1675 fmode = dos_mode(conn,fname,pst);
1676 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1677 return NT_STATUS_NO_SUCH_FILE;
1678 }
1679
1680 if (S_ISDIR(pst->st_mode)) {
1681 return NT_STATUS_OK;
1682 }
1683
1684 status = open_file_ntcreate(conn, fname, pst,
1685 DELETE_ACCESS,
1686 FILE_SHARE_READ|FILE_SHARE_WRITE,
1687 FILE_OPEN,
1688 0,
1689 FILE_ATTRIBUTE_NORMAL,
1690 0,
1691 NULL, &fsp);
1692
1693 if (!NT_STATUS_IS_OK(status)) {
1694 return status;
1695 }
1696 close_file(fsp,NORMAL_CLOSE);
1697 return NT_STATUS_OK;
1698}
1699
1700/*******************************************************************
1701 Check if a user is allowed to delete a file.
1702********************************************************************/
1703
1704static NTSTATUS can_delete(connection_struct *conn, char *fname,
1705 uint32 dirtype, BOOL can_defer)
1706{
1707 SMB_STRUCT_STAT sbuf;
1708 uint32 fattr;
1709 files_struct *fsp;
1710 uint32 dirtype_orig = dirtype;
1711 NTSTATUS status;
1712
1713 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1714
1715 if (!CAN_WRITE(conn)) {
1716 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1717 }
1718
1719 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1720 return map_nt_error_from_unix(errno);
1721 }
1722
1723 fattr = dos_mode(conn,fname,&sbuf);
1724
1725 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1726 dirtype = aDIR|aARCH|aRONLY;
1727 }
1728
1729 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1730 if (!dirtype) {
1731 return NT_STATUS_NO_SUCH_FILE;
1732 }
1733
1734 if (!dir_check_ftype(conn, fattr, dirtype)) {
1735 if (fattr & aDIR) {
1736 return NT_STATUS_FILE_IS_A_DIRECTORY;
1737 }
1738 return NT_STATUS_NO_SUCH_FILE;
1739 }
1740
1741 if (dirtype_orig & 0x8000) {
1742 /* These will never be set for POSIX. */
1743 return NT_STATUS_NO_SUCH_FILE;
1744 }
1745
1746#if 0
1747 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1748 return NT_STATUS_FILE_IS_A_DIRECTORY;
1749 }
1750
1751 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1752 return NT_STATUS_NO_SUCH_FILE;
1753 }
1754
1755 if (dirtype & 0xFF00) {
1756 /* These will never be set for POSIX. */
1757 return NT_STATUS_NO_SUCH_FILE;
1758 }
1759
1760 dirtype &= 0xFF;
1761 if (!dirtype) {
1762 return NT_STATUS_NO_SUCH_FILE;
1763 }
1764
1765 /* Can't delete a directory. */
1766 if (fattr & aDIR) {
1767 return NT_STATUS_FILE_IS_A_DIRECTORY;
1768 }
1769#endif
1770
1771#if 0 /* JRATEST */
1772 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1773 return NT_STATUS_OBJECT_NAME_INVALID;
1774#endif /* JRATEST */
1775
1776 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1777
1778 On a Windows share, a file with read-only dosmode can be opened with
1779 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1780 fails with NT_STATUS_CANNOT_DELETE error.
1781
1782 This semantic causes a problem that a user can not
1783 rename a file with read-only dosmode on a Samba share
1784 from a Windows command prompt (i.e. cmd.exe, but can rename
1785 from Windows Explorer).
1786 */
1787
1788 if (!lp_delete_readonly(SNUM(conn))) {
1789 if (fattr & aRONLY) {
1790 return NT_STATUS_CANNOT_DELETE;
1791 }
1792 }
1793
1794 /* On open checks the open itself will check the share mode, so
1795 don't do it here as we'll get it wrong. */
1796
1797 status = open_file_ntcreate(conn, fname, &sbuf,
1798 DELETE_ACCESS,
1799 FILE_SHARE_NONE,
1800 FILE_OPEN,
1801 0,
1802 FILE_ATTRIBUTE_NORMAL,
1803 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1804 NULL, &fsp);
1805
1806 if (NT_STATUS_IS_OK(status)) {
1807 close_file(fsp,NORMAL_CLOSE);
1808 }
1809 return status;
1810}
1811
1812/****************************************************************************
1813 The guts of the unlink command, split out so it may be called by the NT SMB
1814 code.
1815****************************************************************************/
1816
1817NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1818 char *name, BOOL has_wild, BOOL can_defer)
1819{
1820 pstring directory;
1821 pstring mask;
1822 char *p;
1823 int count=0;
1824 NTSTATUS status = NT_STATUS_OK;
1825 SMB_STRUCT_STAT sbuf;
1826
1827 *directory = *mask = 0;
1828
1829 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1830 if (!NT_STATUS_IS_OK(status)) {
1831 return status;
1832 }
1833
1834 p = strrchr_m(name,'/');
1835 if (!p) {
1836 pstrcpy(directory,".");
1837 pstrcpy(mask,name);
1838 } else {
1839 *p = 0;
1840 pstrcpy(directory,name);
1841 pstrcpy(mask,p+1);
1842 }
1843
1844 /*
1845 * We should only check the mangled cache
1846 * here if unix_convert failed. This means
1847 * that the path in 'mask' doesn't exist
1848 * on the file system and so we need to look
1849 * for a possible mangle. This patch from
1850 * Tine Smukavec <valentin.smukavec@hermes.si>.
1851 */
1852
1853 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1854 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1855
1856 if (!has_wild) {
1857 pstrcat(directory,"/");
1858 pstrcat(directory,mask);
1859 if (dirtype == 0) {
1860 dirtype = FILE_ATTRIBUTE_NORMAL;
1861 }
1862 status = can_delete(conn,directory,dirtype,can_defer);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 return status;
1865 }
1866
1867 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1868 count++;
1869 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1870 FILE_NOTIFY_CHANGE_FILE_NAME,
1871 directory);
1872 }
1873 } else {
1874 struct smb_Dir *dir_hnd = NULL;
1875 long offset = 0;
1876 const char *dname;
1877
1878 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1879 return NT_STATUS_OBJECT_NAME_INVALID;
1880 }
1881
1882 if (strequal(mask,"????????.???")) {
1883 pstrcpy(mask,"*");
1884 }
1885
1886 status = check_name(conn, directory);
1887 if (!NT_STATUS_IS_OK(status)) {
1888 return status;
1889 }
1890
1891 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1892 if (dir_hnd == NULL) {
1893 return map_nt_error_from_unix(errno);
1894 }
1895
1896 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1897 the pattern matches against the long name, otherwise the short name
1898 We don't implement this yet XXXX
1899 */
1900
1901 status = NT_STATUS_NO_SUCH_FILE;
1902
1903 while ((dname = ReadDirName(dir_hnd, &offset))) {
1904 SMB_STRUCT_STAT st;
1905 pstring fname;
1906 pstrcpy(fname,dname);
1907
1908 if (!is_visible_file(conn, directory, dname, &st, True)) {
1909 continue;
1910 }
1911
1912 /* Quick check for "." and ".." */
1913 if (fname[0] == '.') {
1914 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1915 continue;
1916 }
1917 }
1918
1919 if(!mask_match(fname, mask, conn->case_sensitive)) {
1920 continue;
1921 }
1922
1923 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1924 status = can_delete(conn, fname, dirtype, can_defer);
1925 if (!NT_STATUS_IS_OK(status)) {
1926 continue;
1927 }
1928 if (SMB_VFS_UNLINK(conn,fname) == 0) {
1929 count++;
1930 DEBUG(3,("unlink_internals: succesful unlink "
1931 "[%s]\n",fname));
1932 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1933 FILE_NOTIFY_CHANGE_FILE_NAME,
1934 fname);
1935 }
1936
1937 }
1938 CloseDir(dir_hnd);
1939 }
1940
1941 if (count == 0 && NT_STATUS_IS_OK(status)) {
1942 status = map_nt_error_from_unix(errno);
1943 }
1944
1945 return status;
1946}
1947
1948/****************************************************************************
1949 Reply to a unlink
1950****************************************************************************/
1951
1952int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1953 int dum_buffsize)
1954{
1955 int outsize = 0;
1956 pstring name;
1957 uint32 dirtype;
1958 NTSTATUS status;
1959 BOOL path_contains_wcard = False;
1960
1961 START_PROFILE(SMBunlink);
1962
1963 dirtype = SVAL(inbuf,smb_vwv0);
1964
1965 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
1966 if (!NT_STATUS_IS_OK(status)) {
1967 END_PROFILE(SMBunlink);
1968 return ERROR_NT(status);
1969 }
1970
1971 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1972
1973 DEBUG(3,("reply_unlink : %s\n",name));
1974
1975 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
1976 True);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1979 /* We have re-scheduled this call. */
1980 return -1;
1981 }
1982 return ERROR_NT(status);
1983 }
1984
1985 outsize = set_message(outbuf,0,0,False);
1986
1987 END_PROFILE(SMBunlink);
1988 return outsize;
1989}
1990
1991/****************************************************************************
1992 Fail for readbraw.
1993****************************************************************************/
1994
1995static void fail_readraw(void)
1996{
1997 pstring errstr;
1998 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1999 strerror(errno) );
2000 exit_server_cleanly(errstr);
2001}
2002
2003#if defined(WITH_SENDFILE)
2004/****************************************************************************
2005 Fake (read/write) sendfile. Returns -1 on read or write fail.
2006****************************************************************************/
2007
2008static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2009{
2010 ssize_t ret=0;
2011
2012 /* Paranioa check... */
2013 if (nread > bufsize) {
2014 fail_readraw();
2015 }
2016
2017 if (nread > 0) {
2018 ret = read_file(fsp,buf,startpos,nread);
2019 if (ret == -1) {
2020 return -1;
2021 }
2022 }
2023
2024 /* If we had a short read, fill with zeros. */
2025 if (ret < nread) {
2026 memset(buf, '\0', nread - ret);
2027 }
2028
2029 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2030 return -1;
2031 }
2032
2033 return (ssize_t)nread;
2034}
2035#endif
2036
2037/****************************************************************************
2038 Use sendfile in readbraw.
2039****************************************************************************/
2040
2041void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2042 ssize_t mincount, char *outbuf, int out_buffsize)
2043{
2044 ssize_t ret=0;
2045
2046#if defined(WITH_SENDFILE)
2047 /*
2048 * We can only use sendfile on a non-chained packet
2049 * but we can use on a non-oplocked file. tridge proved this
2050 * on a train in Germany :-). JRA.
2051 * reply_readbraw has already checked the length.
2052 */
2053
2054 if ( (chain_size == 0) && (nread > 0) &&
2055 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2056 DATA_BLOB header;
2057
2058 _smb_setlen(outbuf,nread);
2059 header.data = (uint8 *)outbuf;
2060 header.length = 4;
2061 header.free = NULL;
2062
2063 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2064 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2065 if (errno == ENOSYS) {
2066 goto normal_readbraw;
2067 }
2068
2069 /*
2070 * Special hack for broken Linux with no working sendfile. If we
2071 * return EINTR we sent the header but not the rest of the data.
2072 * Fake this up by doing read/write calls.
2073 */
2074 if (errno == EINTR) {
2075 /* Ensure we don't do this again. */
2076 set_use_sendfile(SNUM(conn), False);
2077 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2078
2079 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2080 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2081 fsp->fsp_name, strerror(errno) ));
2082 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2083 }
2084 return;
2085 }
2086
2087 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2088 fsp->fsp_name, strerror(errno) ));
2089 exit_server_cleanly("send_file_readbraw sendfile failed");
2090 }
2091
2092 }
2093
2094 normal_readbraw:
2095
2096#endif
2097
2098 if (nread > 0) {
2099 ret = read_file(fsp,outbuf+4,startpos,nread);
2100#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2101 if (ret < mincount)
2102 ret = 0;
2103#else
2104 if (ret < nread)
2105 ret = 0;
2106#endif
2107 }
2108
2109 _smb_setlen(outbuf,ret);
2110 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2111 fail_readraw();
2112}
2113
2114/****************************************************************************
2115 Reply to a readbraw (core+ protocol).
2116****************************************************************************/
2117
2118int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2119{
2120 ssize_t maxcount,mincount;
2121 size_t nread = 0;
2122 SMB_OFF_T startpos;
2123 char *header = outbuf;
2124 files_struct *fsp;
2125 START_PROFILE(SMBreadbraw);
2126
2127 if (srv_is_signing_active()) {
2128 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2129 }
2130
2131 /*
2132 * Special check if an oplock break has been issued
2133 * and the readraw request croses on the wire, we must
2134 * return a zero length response here.
2135 */
2136
2137 fsp = file_fsp(inbuf,smb_vwv0);
2138
2139 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2140 /*
2141 * fsp could be NULL here so use the value from the packet. JRA.
2142 */
2143 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2144 _smb_setlen(header,0);
2145 if (write_data(smbd_server_fd(),header,4) != 4)
2146 fail_readraw();
2147 END_PROFILE(SMBreadbraw);
2148 return(-1);
2149 }
2150
2151 CHECK_FSP(fsp,conn);
2152
2153 flush_write_cache(fsp, READRAW_FLUSH);
2154
2155 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2156 if(CVAL(inbuf,smb_wct) == 10) {
2157 /*
2158 * This is a large offset (64 bit) read.
2159 */
2160#ifdef LARGE_SMB_OFF_T
2161
2162 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2163
2164#else /* !LARGE_SMB_OFF_T */
2165
2166 /*
2167 * Ensure we haven't been sent a >32 bit offset.
2168 */
2169
2170 if(IVAL(inbuf,smb_vwv8) != 0) {
2171 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
217264 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2173 _smb_setlen(header,0);
2174 if (write_data(smbd_server_fd(),header,4) != 4)
2175 fail_readraw();
2176 END_PROFILE(SMBreadbraw);
2177 return(-1);
2178 }
2179
2180#endif /* LARGE_SMB_OFF_T */
2181
2182 if(startpos < 0) {
2183 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2184 _smb_setlen(header,0);
2185 if (write_data(smbd_server_fd(),header,4) != 4)
2186 fail_readraw();
2187 END_PROFILE(SMBreadbraw);
2188 return(-1);
2189 }
2190 }
2191 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2192 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2193
2194 /* ensure we don't overrun the packet size */
2195 maxcount = MIN(65535,maxcount);
2196
2197 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2198 SMB_STRUCT_STAT st;
2199 SMB_OFF_T size = 0;
2200
2201 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2202 size = st.st_size;
2203 }
2204
2205 if (startpos >= size) {
2206 nread = 0;
2207 } else {
2208 nread = MIN(maxcount,(size - startpos));
2209 }
2210 }
2211
2212#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2213 if (nread < mincount)
2214 nread = 0;
2215#endif
2216
2217 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2218 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2219
2220 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2221
2222 DEBUG(5,("readbraw finished\n"));
2223 END_PROFILE(SMBreadbraw);
2224 return -1;
2225}
2226
2227#undef DBGC_CLASS
2228#define DBGC_CLASS DBGC_LOCKING
2229
2230/****************************************************************************
2231 Reply to a lockread (core+ protocol).
2232****************************************************************************/
2233
2234int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2235{
2236 ssize_t nread = -1;
2237 char *data;
2238 int outsize = 0;
2239 SMB_OFF_T startpos;
2240 size_t numtoread;
2241 NTSTATUS status;
2242 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2243 struct byte_range_lock *br_lck = NULL;
2244 START_PROFILE(SMBlockread);
2245
2246 CHECK_FSP(fsp,conn);
2247 if (!CHECK_READ(fsp,inbuf)) {
2248 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2249 }
2250
2251 release_level_2_oplocks_on_change(fsp);
2252
2253 numtoread = SVAL(inbuf,smb_vwv1);
2254 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2255
2256 outsize = set_message(outbuf,5,3,True);
2257 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2258 data = smb_buf(outbuf) + 3;
2259
2260 /*
2261 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2262 * protocol request that predates the read/write lock concept.
2263 * Thus instead of asking for a read lock here we need to ask
2264 * for a write lock. JRA.
2265 * Note that the requested lock size is unaffected by max_recv.
2266 */
2267
2268 br_lck = do_lock(fsp,
2269 (uint32)SVAL(inbuf,smb_pid),
2270 (SMB_BIG_UINT)numtoread,
2271 (SMB_BIG_UINT)startpos,
2272 WRITE_LOCK,
2273 WINDOWS_LOCK,
2274 False, /* Non-blocking lock. */
2275 &status);
2276 TALLOC_FREE(br_lck);
2277
2278 if (NT_STATUS_V(status)) {
2279 END_PROFILE(SMBlockread);
2280 return ERROR_NT(status);
2281 }
2282
2283 /*
2284 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2285 */
2286
2287 if (numtoread > max_recv) {
2288 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2289Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2290 (unsigned int)numtoread, (unsigned int)max_recv ));
2291 numtoread = MIN(numtoread,max_recv);
2292 }
2293 nread = read_file(fsp,data,startpos,numtoread);
2294
2295 if (nread < 0) {
2296 END_PROFILE(SMBlockread);
2297 return(UNIXERROR(ERRDOS,ERRnoaccess));
2298 }
2299
2300 outsize += nread;
2301 SSVAL(outbuf,smb_vwv0,nread);
2302 SSVAL(outbuf,smb_vwv5,nread+3);
2303 SSVAL(smb_buf(outbuf),1,nread);
2304
2305 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2306 fsp->fnum, (int)numtoread, (int)nread));
2307
2308 END_PROFILE(SMBlockread);
2309 return(outsize);
2310}
2311
2312#undef DBGC_CLASS
2313#define DBGC_CLASS DBGC_ALL
2314
2315/****************************************************************************
2316 Reply to a read.
2317****************************************************************************/
2318
2319int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2320{
2321 size_t numtoread;
2322 ssize_t nread = 0;
2323 char *data;
2324 SMB_OFF_T startpos;
2325 int outsize = 0;
2326 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2327 START_PROFILE(SMBread);
2328
2329 CHECK_FSP(fsp,conn);
2330 if (!CHECK_READ(fsp,inbuf)) {
2331 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2332 }
2333
2334 numtoread = SVAL(inbuf,smb_vwv1);
2335 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2336
2337 outsize = set_message(outbuf,5,3,True);
2338 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2339 /*
2340 * The requested read size cannot be greater than max_recv. JRA.
2341 */
2342 if (numtoread > max_recv) {
2343 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2344Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2345 (unsigned int)numtoread, (unsigned int)max_recv ));
2346 numtoread = MIN(numtoread,max_recv);
2347 }
2348
2349 data = smb_buf(outbuf) + 3;
2350
2351 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2352 END_PROFILE(SMBread);
2353 return ERROR_DOS(ERRDOS,ERRlock);
2354 }
2355
2356 if (numtoread > 0)
2357 nread = read_file(fsp,data,startpos,numtoread);
2358
2359 if (nread < 0) {
2360 END_PROFILE(SMBread);
2361 return(UNIXERROR(ERRDOS,ERRnoaccess));
2362 }
2363
2364 outsize += nread;
2365 SSVAL(outbuf,smb_vwv0,nread);
2366 SSVAL(outbuf,smb_vwv5,nread+3);
2367 SCVAL(smb_buf(outbuf),0,1);
2368 SSVAL(smb_buf(outbuf),1,nread);
2369
2370 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2371 fsp->fnum, (int)numtoread, (int)nread ) );
2372
2373 END_PROFILE(SMBread);
2374 return(outsize);
2375}
2376
2377/****************************************************************************
2378 Reply to a read and X - possibly using sendfile.
2379****************************************************************************/
2380
2381int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2382 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2383{
2384 int outsize = 0;
2385 ssize_t nread = -1;
2386 char *data = smb_buf(outbuf);
2387
2388#if defined(WITH_SENDFILE)
2389 /*
2390 * We can only use sendfile on a non-chained packet
2391 * but we can use on a non-oplocked file. tridge proved this
2392 * on a train in Germany :-). JRA.
2393 */
2394
2395 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2396 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2397 SMB_STRUCT_STAT sbuf;
2398 DATA_BLOB header;
2399
2400 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2401 return(UNIXERROR(ERRDOS,ERRnoaccess));
2402
2403 if (startpos > sbuf.st_size)
2404 goto normal_read;
2405
2406 if (smb_maxcnt > (sbuf.st_size - startpos))
2407 smb_maxcnt = (sbuf.st_size - startpos);
2408
2409 if (smb_maxcnt == 0)
2410 goto normal_read;
2411
2412 /*
2413 * Set up the packet header before send. We
2414 * assume here the sendfile will work (get the
2415 * correct amount of data).
2416 */
2417
2418 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2419 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2420 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2421 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2422 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2423 SCVAL(outbuf,smb_vwv0,0xFF);
2424 set_message(outbuf,12,smb_maxcnt,False);
2425 header.data = (uint8 *)outbuf;
2426 header.length = data - outbuf;
2427 header.free = NULL;
2428
2429 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2430 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2431 if (errno == ENOSYS) {
2432 goto normal_read;
2433 }
2434
2435 /*
2436 * Special hack for broken Linux with no working sendfile. If we
2437 * return EINTR we sent the header but not the rest of the data.
2438 * Fake this up by doing read/write calls.
2439 */
2440
2441 if (errno == EINTR) {
2442 /* Ensure we don't do this again. */
2443 set_use_sendfile(SNUM(conn), False);
2444 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2445
2446 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2447 len_outbuf - (data-outbuf))) == -1) {
2448 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2449 fsp->fsp_name, strerror(errno) ));
2450 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2451 }
2452 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2453 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2454 /* Returning -1 here means successful sendfile. */
2455 return -1;
2456 }
2457
2458 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2459 fsp->fsp_name, strerror(errno) ));
2460 exit_server_cleanly("send_file_readX sendfile failed");
2461 }
2462
2463 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2464 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2465 /* Returning -1 here means successful sendfile. */
2466 return -1;
2467 }
2468
2469 normal_read:
2470
2471#endif
2472
2473 nread = read_file(fsp,data,startpos,smb_maxcnt);
2474
2475 if (nread < 0) {
2476 return(UNIXERROR(ERRDOS,ERRnoaccess));
2477 }
2478
2479 outsize = set_message(outbuf,12,nread,False);
2480 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2481 SSVAL(outbuf,smb_vwv5,nread);
2482 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2483 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2484 SSVAL(smb_buf(outbuf),-2,nread);
2485
2486 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2487 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2488
2489 /* Returning the number of bytes we want to send back - including header. */
2490 return outsize;
2491}
2492
2493/****************************************************************************
2494 Reply to a read and X.
2495****************************************************************************/
2496
2497int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2498{
2499 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2500 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2501 ssize_t nread = -1;
2502 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2503#if 0
2504 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2505#endif
2506
2507 START_PROFILE(SMBreadX);
2508
2509 /* If it's an IPC, pass off the pipe handler. */
2510 if (IS_IPC(conn)) {
2511 END_PROFILE(SMBreadX);
2512 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2513 }
2514
2515 CHECK_FSP(fsp,conn);
2516 if (!CHECK_READ(fsp,inbuf)) {
2517 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2518 }
2519
2520 set_message(outbuf,12,0,True);
2521
2522 if (global_client_caps & CAP_LARGE_READX) {
2523 if (SVAL(inbuf,smb_vwv7) == 1) {
2524 smb_maxcnt |= (1<<16);
2525 }
2526 if (smb_maxcnt > BUFFER_SIZE) {
2527 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2528 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2529 END_PROFILE(SMBreadX);
2530 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2531 }
2532 }
2533
2534 if(CVAL(inbuf,smb_wct) == 12) {
2535#ifdef LARGE_SMB_OFF_T
2536 /*
2537 * This is a large offset (64 bit) read.
2538 */
2539 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2540
2541#else /* !LARGE_SMB_OFF_T */
2542
2543 /*
2544 * Ensure we haven't been sent a >32 bit offset.
2545 */
2546
2547 if(IVAL(inbuf,smb_vwv10) != 0) {
2548 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
254964 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2550 END_PROFILE(SMBreadX);
2551 return ERROR_DOS(ERRDOS,ERRbadaccess);
2552 }
2553
2554#endif /* LARGE_SMB_OFF_T */
2555
2556 }
2557
2558 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2559 END_PROFILE(SMBreadX);
2560 return ERROR_DOS(ERRDOS,ERRlock);
2561 }
2562
2563 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2564 END_PROFILE(SMBreadX);
2565 return -1;
2566 }
2567
2568 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2569 if (nread != -1)
2570 nread = chain_reply(inbuf,outbuf,length,bufsize);
2571
2572 END_PROFILE(SMBreadX);
2573 return nread;
2574}
2575
2576/****************************************************************************
2577 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2578****************************************************************************/
2579
2580int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2581{
2582 ssize_t nwritten=0;
2583 ssize_t total_written=0;
2584 size_t numtowrite=0;
2585 size_t tcount;
2586 SMB_OFF_T startpos;
2587 char *data=NULL;
2588 BOOL write_through;
2589 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2590 int outsize = 0;
2591 START_PROFILE(SMBwritebraw);
2592
2593 if (srv_is_signing_active()) {
2594 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2595 }
2596
2597 CHECK_FSP(fsp,conn);
2598 if (!CHECK_WRITE(fsp)) {
2599 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2600 }
2601
2602 tcount = IVAL(inbuf,smb_vwv1);
2603 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2604 write_through = BITSETW(inbuf+smb_vwv7,0);
2605
2606 /* We have to deal with slightly different formats depending
2607 on whether we are using the core+ or lanman1.0 protocol */
2608
2609 if(Protocol <= PROTOCOL_COREPLUS) {
2610 numtowrite = SVAL(smb_buf(inbuf),-2);
2611 data = smb_buf(inbuf);
2612 } else {
2613 numtowrite = SVAL(inbuf,smb_vwv10);
2614 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2615 }
2616
2617 /* force the error type */
2618 SCVAL(inbuf,smb_com,SMBwritec);
2619 SCVAL(outbuf,smb_com,SMBwritec);
2620
2621 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2622 END_PROFILE(SMBwritebraw);
2623 return(ERROR_DOS(ERRDOS,ERRlock));
2624 }
2625
2626 if (numtowrite>0)
2627 nwritten = write_file(fsp,data,startpos,numtowrite);
2628
2629 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2630 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2631
2632 if (nwritten < (ssize_t)numtowrite) {
2633 END_PROFILE(SMBwritebraw);
2634 return(UNIXERROR(ERRHRD,ERRdiskfull));
2635 }
2636
2637 total_written = nwritten;
2638
2639 /* Return a message to the redirector to tell it to send more bytes */
2640 SCVAL(outbuf,smb_com,SMBwritebraw);
2641 SSVALS(outbuf,smb_vwv0,-1);
2642 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2643 show_msg(outbuf);
2644 if (!send_smb(smbd_server_fd(),outbuf))
2645 exit_server_cleanly("reply_writebraw: send_smb failed.");
2646
2647 /* Now read the raw data into the buffer and write it */
2648 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2649 exit_server_cleanly("secondary writebraw failed");
2650 }
2651
2652 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2653 numtowrite = smb_len(inbuf);
2654
2655 /* Set up outbuf to return the correct return */
2656 outsize = set_message(outbuf,1,0,True);
2657 SCVAL(outbuf,smb_com,SMBwritec);
2658
2659 if (numtowrite != 0) {
2660
2661 if (numtowrite > BUFFER_SIZE) {
2662 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2663 (unsigned int)numtowrite ));
2664 exit_server_cleanly("secondary writebraw failed");
2665 }
2666
2667 if (tcount > nwritten+numtowrite) {
2668 DEBUG(3,("Client overestimated the write %d %d %d\n",
2669 (int)tcount,(int)nwritten,(int)numtowrite));
2670 }
2671
2672 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2673 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2674 strerror(errno) ));
2675 exit_server_cleanly("secondary writebraw failed");
2676 }
2677
2678 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2679 if (nwritten == -1) {
2680 END_PROFILE(SMBwritebraw);
2681 return(UNIXERROR(ERRHRD,ERRdiskfull));
2682 }
2683
2684 if (nwritten < (ssize_t)numtowrite) {
2685 SCVAL(outbuf,smb_rcls,ERRHRD);
2686 SSVAL(outbuf,smb_err,ERRdiskfull);
2687 }
2688
2689 if (nwritten > 0)
2690 total_written += nwritten;
2691 }
2692
2693 SSVAL(outbuf,smb_vwv0,total_written);
2694
2695 sync_file(conn, fsp, write_through);
2696
2697 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2698 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2699
2700 /* we won't return a status if write through is not selected - this follows what WfWg does */
2701 END_PROFILE(SMBwritebraw);
2702 if (!write_through && total_written==tcount) {
2703
2704#if RABBIT_PELLET_FIX
2705 /*
2706 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2707 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2708 */
2709 if (!send_keepalive(smbd_server_fd()))
2710 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2711#endif
2712 return(-1);
2713 }
2714
2715 return(outsize);
2716}
2717
2718#undef DBGC_CLASS
2719#define DBGC_CLASS DBGC_LOCKING
2720
2721/****************************************************************************
2722 Reply to a writeunlock (core+).
2723****************************************************************************/
2724
2725int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2726 int size, int dum_buffsize)
2727{
2728 ssize_t nwritten = -1;
2729 size_t numtowrite;
2730 SMB_OFF_T startpos;
2731 char *data;
2732 NTSTATUS status = NT_STATUS_OK;
2733 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2734 int outsize = 0;
2735 START_PROFILE(SMBwriteunlock);
2736
2737 CHECK_FSP(fsp,conn);
2738 if (!CHECK_WRITE(fsp)) {
2739 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2740 }
2741
2742 numtowrite = SVAL(inbuf,smb_vwv1);
2743 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2744 data = smb_buf(inbuf) + 3;
2745
2746 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2747 END_PROFILE(SMBwriteunlock);
2748 return ERROR_DOS(ERRDOS,ERRlock);
2749 }
2750
2751 /* The special X/Open SMB protocol handling of
2752 zero length writes is *NOT* done for
2753 this call */
2754 if(numtowrite == 0) {
2755 nwritten = 0;
2756 } else {
2757 nwritten = write_file(fsp,data,startpos,numtowrite);
2758 }
2759
2760 sync_file(conn, fsp, False /* write through */);
2761
2762 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2763 END_PROFILE(SMBwriteunlock);
2764 return(UNIXERROR(ERRHRD,ERRdiskfull));
2765 }
2766
2767 if (numtowrite) {
2768 status = do_unlock(fsp,
2769 (uint32)SVAL(inbuf,smb_pid),
2770 (SMB_BIG_UINT)numtowrite,
2771 (SMB_BIG_UINT)startpos,
2772 WINDOWS_LOCK);
2773
2774 if (NT_STATUS_V(status)) {
2775 END_PROFILE(SMBwriteunlock);
2776 return ERROR_NT(status);
2777 }
2778 }
2779
2780 outsize = set_message(outbuf,1,0,True);
2781
2782 SSVAL(outbuf,smb_vwv0,nwritten);
2783
2784 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2785 fsp->fnum, (int)numtowrite, (int)nwritten));
2786
2787 END_PROFILE(SMBwriteunlock);
2788 return outsize;
2789}
2790
2791#undef DBGC_CLASS
2792#define DBGC_CLASS DBGC_ALL
2793
2794/****************************************************************************
2795 Reply to a write.
2796****************************************************************************/
2797
2798int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2799{
2800 size_t numtowrite;
2801 ssize_t nwritten = -1;
2802 SMB_OFF_T startpos;
2803 char *data;
2804 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2805 int outsize = 0;
2806 START_PROFILE(SMBwrite);
2807
2808 /* If it's an IPC, pass off the pipe handler. */
2809 if (IS_IPC(conn)) {
2810 END_PROFILE(SMBwrite);
2811 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2812 }
2813
2814 CHECK_FSP(fsp,conn);
2815 if (!CHECK_WRITE(fsp)) {
2816 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2817 }
2818
2819 numtowrite = SVAL(inbuf,smb_vwv1);
2820 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2821 data = smb_buf(inbuf) + 3;
2822
2823 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2824 END_PROFILE(SMBwrite);
2825 return ERROR_DOS(ERRDOS,ERRlock);
2826 }
2827
2828 /*
2829 * X/Open SMB protocol says that if smb_vwv1 is
2830 * zero then the file size should be extended or
2831 * truncated to the size given in smb_vwv[2-3].
2832 */
2833
2834 if(numtowrite == 0) {
2835 /*
2836 * This is actually an allocate call, and set EOF. JRA.
2837 */
2838 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2839 if (nwritten < 0) {
2840 END_PROFILE(SMBwrite);
2841 return ERROR_NT(NT_STATUS_DISK_FULL);
2842 }
2843 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2844 if (nwritten < 0) {
2845 END_PROFILE(SMBwrite);
2846 return ERROR_NT(NT_STATUS_DISK_FULL);
2847 }
2848 } else
2849 nwritten = write_file(fsp,data,startpos,numtowrite);
2850
2851 sync_file(conn, fsp, False);
2852
2853 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2854 END_PROFILE(SMBwrite);
2855 return(UNIXERROR(ERRHRD,ERRdiskfull));
2856 }
2857
2858 outsize = set_message(outbuf,1,0,True);
2859
2860 SSVAL(outbuf,smb_vwv0,nwritten);
2861
2862 if (nwritten < (ssize_t)numtowrite) {
2863 SCVAL(outbuf,smb_rcls,ERRHRD);
2864 SSVAL(outbuf,smb_err,ERRdiskfull);
2865 }
2866
2867 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2868
2869 END_PROFILE(SMBwrite);
2870 return(outsize);
2871}
2872
2873/****************************************************************************
2874 Reply to a write and X.
2875****************************************************************************/
2876
2877int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2878{
2879 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2880 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2881 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2882 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2883 ssize_t nwritten = -1;
2884 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2885 unsigned int smblen = smb_len(inbuf);
2886 char *data;
2887 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2888 START_PROFILE(SMBwriteX);
2889
2890 /* If it's an IPC, pass off the pipe handler. */
2891 if (IS_IPC(conn)) {
2892 END_PROFILE(SMBwriteX);
2893 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2894 }
2895
2896 CHECK_FSP(fsp,conn);
2897 if (!CHECK_WRITE(fsp)) {
2898 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2899 }
2900
2901 set_message(outbuf,6,0,True);
2902
2903 /* Deal with possible LARGE_WRITEX */
2904 if (large_writeX) {
2905 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2906 }
2907
2908 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2909 END_PROFILE(SMBwriteX);
2910 return ERROR_DOS(ERRDOS,ERRbadmem);
2911 }
2912
2913 data = smb_base(inbuf) + smb_doff;
2914
2915 if(CVAL(inbuf,smb_wct) == 14) {
2916#ifdef LARGE_SMB_OFF_T
2917 /*
2918 * This is a large offset (64 bit) write.
2919 */
2920 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2921
2922#else /* !LARGE_SMB_OFF_T */
2923
2924 /*
2925 * Ensure we haven't been sent a >32 bit offset.
2926 */
2927
2928 if(IVAL(inbuf,smb_vwv12) != 0) {
2929 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
293064 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2931 END_PROFILE(SMBwriteX);
2932 return ERROR_DOS(ERRDOS,ERRbadaccess);
2933 }
2934
2935#endif /* LARGE_SMB_OFF_T */
2936 }
2937
2938 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2939 END_PROFILE(SMBwriteX);
2940 return ERROR_DOS(ERRDOS,ERRlock);
2941 }
2942
2943 /* X/Open SMB protocol says that, unlike SMBwrite
2944 if the length is zero then NO truncation is
2945 done, just a write of zero. To truncate a file,
2946 use SMBwrite. */
2947
2948 if(numtowrite == 0) {
2949 nwritten = 0;
2950 } else {
2951
2952 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2953 fsp,data,startpos,numtowrite)) {
2954 END_PROFILE(SMBwriteX);
2955 return -1;
2956 }
2957
2958 nwritten = write_file(fsp,data,startpos,numtowrite);
2959 }
2960
2961 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2962 END_PROFILE(SMBwriteX);
2963 return(UNIXERROR(ERRHRD,ERRdiskfull));
2964 }
2965
2966 SSVAL(outbuf,smb_vwv2,nwritten);
2967 if (large_writeX)
2968 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2969
2970 if (nwritten < (ssize_t)numtowrite) {
2971 SCVAL(outbuf,smb_rcls,ERRHRD);
2972 SSVAL(outbuf,smb_err,ERRdiskfull);
2973 }
2974
2975 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2976 fsp->fnum, (int)numtowrite, (int)nwritten));
2977
2978 sync_file(conn, fsp, write_through);
2979
2980 END_PROFILE(SMBwriteX);
2981 return chain_reply(inbuf,outbuf,length,bufsize);
2982}
2983
2984/****************************************************************************
2985 Reply to a lseek.
2986****************************************************************************/
2987
2988int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2989{
2990 SMB_OFF_T startpos;
2991 SMB_OFF_T res= -1;
2992 int mode,umode;
2993 int outsize = 0;
2994 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2995 START_PROFILE(SMBlseek);
2996
2997 CHECK_FSP(fsp,conn);
2998
2999 flush_write_cache(fsp, SEEK_FLUSH);
3000
3001 mode = SVAL(inbuf,smb_vwv1) & 3;
3002 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3003 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3004
3005 switch (mode) {
3006 case 0:
3007 umode = SEEK_SET;
3008 res = startpos;
3009 break;
3010 case 1:
3011 umode = SEEK_CUR;
3012 res = fsp->fh->pos + startpos;
3013 break;
3014 case 2:
3015 umode = SEEK_END;
3016 break;
3017 default:
3018 umode = SEEK_SET;
3019 res = startpos;
3020 break;
3021 }
3022
3023 if (umode == SEEK_END) {
3024 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3025 if(errno == EINVAL) {
3026 SMB_OFF_T current_pos = startpos;
3027 SMB_STRUCT_STAT sbuf;
3028
3029 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3030 END_PROFILE(SMBlseek);
3031 return(UNIXERROR(ERRDOS,ERRnoaccess));
3032 }
3033
3034 current_pos += sbuf.st_size;
3035 if(current_pos < 0)
3036 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3037 }
3038 }
3039
3040 if(res == -1) {
3041 END_PROFILE(SMBlseek);
3042 return(UNIXERROR(ERRDOS,ERRnoaccess));
3043 }
3044 }
3045
3046 fsp->fh->pos = res;
3047
3048 outsize = set_message(outbuf,2,0,True);
3049 SIVAL(outbuf,smb_vwv0,res);
3050
3051 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3052 fsp->fnum, (double)startpos, (double)res, mode));
3053
3054 END_PROFILE(SMBlseek);
3055 return(outsize);
3056}
3057
3058/****************************************************************************
3059 Reply to a flush.
3060****************************************************************************/
3061
3062int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3063{
3064 int outsize = set_message(outbuf,0,0,False);
3065 uint16 fnum = SVAL(inbuf,smb_vwv0);
3066 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3067 START_PROFILE(SMBflush);
3068
3069 if (fnum != 0xFFFF)
3070 CHECK_FSP(fsp,conn);
3071
3072 if (!fsp) {
3073 file_sync_all(conn);
3074 } else {
3075 sync_file(conn,fsp, True);
3076 }
3077
3078 DEBUG(3,("flush\n"));
3079 END_PROFILE(SMBflush);
3080 return(outsize);
3081}
3082
3083/****************************************************************************
3084 Reply to a exit.
3085 conn POINTER CAN BE NULL HERE !
3086****************************************************************************/
3087
3088int reply_exit(connection_struct *conn,
3089 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3090{
3091 int outsize;
3092 START_PROFILE(SMBexit);
3093
3094 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3095
3096 outsize = set_message(outbuf,0,0,False);
3097
3098 DEBUG(3,("exit\n"));
3099
3100 END_PROFILE(SMBexit);
3101 return(outsize);
3102}
3103
3104/****************************************************************************
3105 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3106****************************************************************************/
3107
3108int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3109 int dum_buffsize)
3110{
3111 NTSTATUS status = NT_STATUS_OK;
3112 int outsize = 0;
3113 time_t mtime;
3114 files_struct *fsp = NULL;
3115 START_PROFILE(SMBclose);
3116
3117 outsize = set_message(outbuf,0,0,False);
3118
3119 /* If it's an IPC, pass off to the pipe handler. */
3120 if (IS_IPC(conn)) {
3121 END_PROFILE(SMBclose);
3122 return reply_pipe_close(conn, inbuf,outbuf);
3123 }
3124
3125 fsp = file_fsp(inbuf,smb_vwv0);
3126
3127 /*
3128 * We can only use CHECK_FSP if we know it's not a directory.
3129 */
3130
3131 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3132 END_PROFILE(SMBclose);
3133 return ERROR_DOS(ERRDOS,ERRbadfid);
3134 }
3135
3136 if(fsp->is_directory) {
3137 /*
3138 * Special case - close NT SMB directory handle.
3139 */
3140 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3141 status = close_file(fsp,NORMAL_CLOSE);
3142 } else {
3143 /*
3144 * Close ordinary file.
3145 */
3146
3147 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3148 fsp->fh->fd, fsp->fnum,
3149 conn->num_files_open));
3150
3151 /*
3152 * Take care of any time sent in the close.
3153 */
3154
3155 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3156 fsp_set_pending_modtime(fsp, mtime);
3157
3158 /*
3159 * close_file() returns the unix errno if an error
3160 * was detected on close - normally this is due to
3161 * a disk full error. If not then it was probably an I/O error.
3162 */
3163
3164 status = close_file(fsp,NORMAL_CLOSE);
3165 }
3166
3167 if(!NT_STATUS_IS_OK(status)) {
3168 END_PROFILE(SMBclose);
3169 return ERROR_NT(status);
3170 }
3171
3172 END_PROFILE(SMBclose);
3173 return(outsize);
3174}
3175
3176/****************************************************************************
3177 Reply to a writeclose (Core+ protocol).
3178****************************************************************************/
3179
3180int reply_writeclose(connection_struct *conn,
3181 char *inbuf,char *outbuf, int size, int dum_buffsize)
3182{
3183 size_t numtowrite;
3184 ssize_t nwritten = -1;
3185 int outsize = 0;
3186 NTSTATUS close_status = NT_STATUS_OK;
3187 SMB_OFF_T startpos;
3188 char *data;
3189 time_t mtime;
3190 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3191 START_PROFILE(SMBwriteclose);
3192
3193 CHECK_FSP(fsp,conn);
3194 if (!CHECK_WRITE(fsp)) {
3195 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3196 }
3197
3198 numtowrite = SVAL(inbuf,smb_vwv1);
3199 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3200 mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3201 data = smb_buf(inbuf) + 1;
3202
3203 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3204 END_PROFILE(SMBwriteclose);
3205 return ERROR_DOS(ERRDOS,ERRlock);
3206 }
3207
3208 nwritten = write_file(fsp,data,startpos,numtowrite);
3209
3210 set_filetime(conn, fsp->fsp_name,mtime);
3211
3212 /*
3213 * More insanity. W2K only closes the file if writelen > 0.
3214 * JRA.
3215 */
3216
3217 if (numtowrite) {
3218 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3219 fsp->fsp_name ));
3220 close_status = close_file(fsp,NORMAL_CLOSE);
3221 }
3222
3223 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3224 fsp->fnum, (int)numtowrite, (int)nwritten,
3225 conn->num_files_open));
3226
3227 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3228 END_PROFILE(SMBwriteclose);
3229 return(UNIXERROR(ERRHRD,ERRdiskfull));
3230 }
3231
3232 if(!NT_STATUS_IS_OK(close_status)) {
3233 END_PROFILE(SMBwriteclose);
3234 return ERROR_NT(close_status);
3235 }
3236
3237 outsize = set_message(outbuf,1,0,True);
3238
3239 SSVAL(outbuf,smb_vwv0,nwritten);
3240 END_PROFILE(SMBwriteclose);
3241 return(outsize);
3242}
3243
3244#undef DBGC_CLASS
3245#define DBGC_CLASS DBGC_LOCKING
3246
3247/****************************************************************************
3248 Reply to a lock.
3249****************************************************************************/
3250
3251int reply_lock(connection_struct *conn,
3252 char *inbuf,char *outbuf, int length, int dum_buffsize)
3253{
3254 int outsize = set_message(outbuf,0,0,False);
3255 SMB_BIG_UINT count,offset;
3256 NTSTATUS status;
3257 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3258 struct byte_range_lock *br_lck = NULL;
3259
3260 START_PROFILE(SMBlock);
3261
3262 CHECK_FSP(fsp,conn);
3263
3264 release_level_2_oplocks_on_change(fsp);
3265
3266 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3267 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3268
3269 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3270 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3271
3272 br_lck = do_lock(fsp,
3273 (uint32)SVAL(inbuf,smb_pid),
3274 count,
3275 offset,
3276 WRITE_LOCK,
3277 WINDOWS_LOCK,
3278 False, /* Non-blocking lock. */
3279 &status);
3280
3281 TALLOC_FREE(br_lck);
3282
3283 if (NT_STATUS_V(status)) {
3284 END_PROFILE(SMBlock);
3285 return ERROR_NT(status);
3286 }
3287
3288 END_PROFILE(SMBlock);
3289 return(outsize);
3290}
3291
3292/****************************************************************************
3293 Reply to a unlock.
3294****************************************************************************/
3295
3296int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3297 int dum_buffsize)
3298{
3299 int outsize = set_message(outbuf,0,0,False);
3300 SMB_BIG_UINT count,offset;
3301 NTSTATUS status;
3302 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3303 START_PROFILE(SMBunlock);
3304
3305 CHECK_FSP(fsp,conn);
3306
3307 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3308 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3309
3310 status = do_unlock(fsp,
3311 (uint32)SVAL(inbuf,smb_pid),
3312 count,
3313 offset,
3314 WINDOWS_LOCK);
3315
3316 if (NT_STATUS_V(status)) {
3317 END_PROFILE(SMBunlock);
3318 return ERROR_NT(status);
3319 }
3320
3321 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3322 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3323
3324 END_PROFILE(SMBunlock);
3325 return(outsize);
3326}
3327
3328#undef DBGC_CLASS
3329#define DBGC_CLASS DBGC_ALL
3330
3331/****************************************************************************
3332 Reply to a tdis.
3333 conn POINTER CAN BE NULL HERE !
3334****************************************************************************/
3335
3336int reply_tdis(connection_struct *conn,
3337 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3338{
3339 int outsize = set_message(outbuf,0,0,False);
3340 uint16 vuid;
3341 START_PROFILE(SMBtdis);
3342
3343 vuid = SVAL(inbuf,smb_uid);
3344
3345 if (!conn) {
3346 DEBUG(4,("Invalid connection in tdis\n"));
3347 END_PROFILE(SMBtdis);
3348 return ERROR_DOS(ERRSRV,ERRinvnid);
3349 }
3350
3351 conn->used = False;
3352
3353 close_cnum(conn,vuid);
3354
3355 END_PROFILE(SMBtdis);
3356 return outsize;
3357}
3358
3359/****************************************************************************
3360 Reply to a echo.
3361 conn POINTER CAN BE NULL HERE !
3362****************************************************************************/
3363
3364int reply_echo(connection_struct *conn,
3365 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3366{
3367 int smb_reverb = SVAL(inbuf,smb_vwv0);
3368 int seq_num;
3369 unsigned int data_len = smb_buflen(inbuf);
3370 int outsize = set_message(outbuf,1,data_len,True);
3371 START_PROFILE(SMBecho);
3372
3373 if (data_len > BUFFER_SIZE) {
3374 DEBUG(0,("reply_echo: data_len too large.\n"));
3375 END_PROFILE(SMBecho);
3376 return -1;
3377 }
3378
3379 /* copy any incoming data back out */
3380 if (data_len > 0)
3381 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3382
3383 if (smb_reverb > 100) {
3384 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3385 smb_reverb = 100;
3386 }
3387
3388 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3389 SSVAL(outbuf,smb_vwv0,seq_num);
3390
3391 smb_setlen(outbuf,outsize - 4);
3392
3393 show_msg(outbuf);
3394 if (!send_smb(smbd_server_fd(),outbuf))
3395 exit_server_cleanly("reply_echo: send_smb failed.");
3396 }
3397
3398 DEBUG(3,("echo %d times\n", smb_reverb));
3399
3400 smb_echo_count++;
3401
3402 END_PROFILE(SMBecho);
3403 return -1;
3404}
3405
3406/****************************************************************************
3407 Reply to a printopen.
3408****************************************************************************/
3409
3410int reply_printopen(connection_struct *conn,
3411 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3412{
3413 int outsize = 0;
3414 files_struct *fsp;
3415 NTSTATUS status;
3416
3417 START_PROFILE(SMBsplopen);
3418
3419 if (!CAN_PRINT(conn)) {
3420 END_PROFILE(SMBsplopen);
3421 return ERROR_DOS(ERRDOS,ERRnoaccess);
3422 }
3423
3424 /* Open for exclusive use, write only. */
3425 status = print_fsp_open(conn, NULL, &fsp);
3426
3427 if (!NT_STATUS_IS_OK(status)) {
3428 END_PROFILE(SMBsplopen);
3429 return(ERROR_NT(status));
3430 }
3431
3432 outsize = set_message(outbuf,1,0,True);
3433 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3434
3435 DEBUG(3,("openprint fd=%d fnum=%d\n",
3436 fsp->fh->fd, fsp->fnum));
3437
3438 END_PROFILE(SMBsplopen);
3439 return(outsize);
3440}
3441
3442/****************************************************************************
3443 Reply to a printclose.
3444****************************************************************************/
3445
3446int reply_printclose(connection_struct *conn,
3447 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3448{
3449 int outsize = set_message(outbuf,0,0,False);
3450 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3451 NTSTATUS status;
3452 START_PROFILE(SMBsplclose);
3453
3454 CHECK_FSP(fsp,conn);
3455
3456 if (!CAN_PRINT(conn)) {
3457 END_PROFILE(SMBsplclose);
3458 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3459 }
3460
3461 DEBUG(3,("printclose fd=%d fnum=%d\n",
3462 fsp->fh->fd,fsp->fnum));
3463
3464 status = close_file(fsp,NORMAL_CLOSE);
3465
3466 if(!NT_STATUS_IS_OK(status)) {
3467 END_PROFILE(SMBsplclose);
3468 return ERROR_NT(status);
3469 }
3470
3471 END_PROFILE(SMBsplclose);
3472 return(outsize);
3473}
3474
3475/****************************************************************************
3476 Reply to a printqueue.
3477****************************************************************************/
3478
3479int reply_printqueue(connection_struct *conn,
3480 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3481{
3482 int outsize = set_message(outbuf,2,3,True);
3483 int max_count = SVAL(inbuf,smb_vwv0);
3484 int start_index = SVAL(inbuf,smb_vwv1);
3485 START_PROFILE(SMBsplretq);
3486
3487 /* we used to allow the client to get the cnum wrong, but that
3488 is really quite gross and only worked when there was only
3489 one printer - I think we should now only accept it if they
3490 get it right (tridge) */
3491 if (!CAN_PRINT(conn)) {
3492 END_PROFILE(SMBsplretq);
3493 return ERROR_DOS(ERRDOS,ERRnoaccess);
3494 }
3495
3496 SSVAL(outbuf,smb_vwv0,0);
3497 SSVAL(outbuf,smb_vwv1,0);
3498 SCVAL(smb_buf(outbuf),0,1);
3499 SSVAL(smb_buf(outbuf),1,0);
3500
3501 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3502 start_index, max_count));
3503
3504 {
3505 print_queue_struct *queue = NULL;
3506 print_status_struct status;
3507 char *p = smb_buf(outbuf) + 3;
3508 int count = print_queue_status(SNUM(conn), &queue, &status);
3509 int num_to_get = ABS(max_count);
3510 int first = (max_count>0?start_index:start_index+max_count+1);
3511 int i;
3512
3513 if (first >= count)
3514 num_to_get = 0;
3515 else
3516 num_to_get = MIN(num_to_get,count-first);
3517
3518
3519 for (i=first;i<first+num_to_get;i++) {
3520 srv_put_dos_date2(p,0,queue[i].time);
3521 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3522 SSVAL(p,5, queue[i].job);
3523 SIVAL(p,7,queue[i].size);
3524 SCVAL(p,11,0);
3525 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3526 p += 28;
3527 }
3528
3529 if (count > 0) {
3530 outsize = set_message(outbuf,2,28*count+3,False);
3531 SSVAL(outbuf,smb_vwv0,count);
3532 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3533 SCVAL(smb_buf(outbuf),0,1);
3534 SSVAL(smb_buf(outbuf),1,28*count);
3535 }
3536
3537 SAFE_FREE(queue);
3538
3539 DEBUG(3,("%d entries returned in queue\n",count));
3540 }
3541
3542 END_PROFILE(SMBsplretq);
3543 return(outsize);
3544}
3545
3546/****************************************************************************
3547 Reply to a printwrite.
3548****************************************************************************/
3549
3550int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3551{
3552 int numtowrite;
3553 int outsize = set_message(outbuf,0,0,False);
3554 char *data;
3555 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3556
3557 START_PROFILE(SMBsplwr);
3558
3559 if (!CAN_PRINT(conn)) {
3560 END_PROFILE(SMBsplwr);
3561 return ERROR_DOS(ERRDOS,ERRnoaccess);
3562 }
3563
3564 CHECK_FSP(fsp,conn);
3565 if (!CHECK_WRITE(fsp)) {
3566 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3567 }
3568
3569 numtowrite = SVAL(smb_buf(inbuf),1);
3570 data = smb_buf(inbuf) + 3;
3571
3572 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3573 END_PROFILE(SMBsplwr);
3574 return(UNIXERROR(ERRHRD,ERRdiskfull));
3575 }
3576
3577 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3578
3579 END_PROFILE(SMBsplwr);
3580 return(outsize);
3581}
3582
3583/****************************************************************************
3584 Reply to a mkdir.
3585****************************************************************************/
3586
3587int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3588{
3589 pstring directory;
3590 int outsize;
3591 NTSTATUS status;
3592 SMB_STRUCT_STAT sbuf;
3593
3594 START_PROFILE(SMBmkdir);
3595
3596 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3597 if (!NT_STATUS_IS_OK(status)) {
3598 END_PROFILE(SMBmkdir);
3599 return ERROR_NT(status);
3600 }
3601
3602 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3603
3604 status = unix_convert(conn, directory, False, NULL, &sbuf);
3605 if (!NT_STATUS_IS_OK(status)) {
3606 END_PROFILE(SMBmkdir);
3607 return ERROR_NT(status);
3608 }
3609
3610 status = create_directory(conn, directory);
3611
3612 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3613
3614 if (!NT_STATUS_IS_OK(status)) {
3615
3616 if (!use_nt_status()
3617 && NT_STATUS_EQUAL(status,
3618 NT_STATUS_OBJECT_NAME_COLLISION)) {
3619 /*
3620 * Yes, in the DOS error code case we get a
3621 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3622 * samba4 torture test.
3623 */
3624 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3625 }
3626
3627 END_PROFILE(SMBmkdir);
3628 return ERROR_NT(status);
3629 }
3630
3631 outsize = set_message(outbuf,0,0,False);
3632
3633 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3634
3635 END_PROFILE(SMBmkdir);
3636 return(outsize);
3637}
3638
3639/****************************************************************************
3640 Static function used by reply_rmdir to delete an entire directory
3641 tree recursively. Return True on ok, False on fail.
3642****************************************************************************/
3643
3644static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3645{
3646 const char *dname = NULL;
3647 BOOL ret = True;
3648 long offset = 0;
3649 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3650
3651 if(dir_hnd == NULL)
3652 return False;
3653
3654 while((dname = ReadDirName(dir_hnd, &offset))) {
3655 pstring fullname;
3656 SMB_STRUCT_STAT st;
3657
3658 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3659 continue;
3660
3661 if (!is_visible_file(conn, directory, dname, &st, False))
3662 continue;
3663
3664 /* Construct the full name. */
3665 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3666 errno = ENOMEM;
3667 ret = False;
3668 break;
3669 }
3670
3671 pstrcpy(fullname, directory);
3672 pstrcat(fullname, "/");
3673 pstrcat(fullname, dname);
3674
3675 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3676 ret = False;
3677 break;
3678 }
3679
3680 if(st.st_mode & S_IFDIR) {
3681 if(!recursive_rmdir(conn, fullname)) {
3682 ret = False;
3683 break;
3684 }
3685 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3686 ret = False;
3687 break;
3688 }
3689 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3690 ret = False;
3691 break;
3692 }
3693 }
3694 CloseDir(dir_hnd);
3695 return ret;
3696}
3697
3698/****************************************************************************
3699 The internals of the rmdir code - called elsewhere.
3700****************************************************************************/
3701
3702NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3703{
3704 int ret;
3705 SMB_STRUCT_STAT st;
3706
3707 ret = SMB_VFS_RMDIR(conn,directory);
3708 if (ret == 0) {
3709 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3710 FILE_NOTIFY_CHANGE_DIR_NAME,
3711 directory);
3712 return NT_STATUS_OK;
3713 }
3714
3715 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3716 /*
3717 * Check to see if the only thing in this directory are
3718 * vetoed files/directories. If so then delete them and
3719 * retry. If we fail to delete any of them (and we *don't*
3720 * do a recursive delete) then fail the rmdir.
3721 */
3722 const char *dname;
3723 long dirpos = 0;
3724 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3725
3726 if(dir_hnd == NULL) {
3727 errno = ENOTEMPTY;
3728 goto err;
3729 }
3730
3731 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3732 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3733 continue;
3734 if (!is_visible_file(conn, directory, dname, &st, False))
3735 continue;
3736 if(!IS_VETO_PATH(conn, dname)) {
3737 CloseDir(dir_hnd);
3738 errno = ENOTEMPTY;
3739 goto err;
3740 }
3741 }
3742
3743 /* We only have veto files/directories. Recursive delete. */
3744
3745 RewindDir(dir_hnd,&dirpos);
3746 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3747 pstring fullname;
3748
3749 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3750 continue;
3751 if (!is_visible_file(conn, directory, dname, &st, False))
3752 continue;
3753
3754 /* Construct the full name. */
3755 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3756 errno = ENOMEM;
3757 break;
3758 }
3759
3760 pstrcpy(fullname, directory);
3761 pstrcat(fullname, "/");
3762 pstrcat(fullname, dname);
3763
3764 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3765 break;
3766 if(st.st_mode & S_IFDIR) {
3767 if(lp_recursive_veto_delete(SNUM(conn))) {
3768 if(!recursive_rmdir(conn, fullname))
3769 break;
3770 }
3771 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3772 break;
3773 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3774 break;
3775 }
3776 CloseDir(dir_hnd);
3777 /* Retry the rmdir */
3778 ret = SMB_VFS_RMDIR(conn,directory);
3779 }
3780
3781 err:
3782
3783 if (ret != 0) {
3784 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3785 "%s\n", directory,strerror(errno)));
3786 return map_nt_error_from_unix(errno);
3787 }
3788
3789 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3790 FILE_NOTIFY_CHANGE_DIR_NAME,
3791 directory);
3792
3793 return NT_STATUS_OK;
3794}
3795
3796/****************************************************************************
3797 Reply to a rmdir.
3798****************************************************************************/
3799
3800int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3801{
3802 pstring directory;
3803 int outsize = 0;
3804 SMB_STRUCT_STAT sbuf;
3805 NTSTATUS status;
3806 START_PROFILE(SMBrmdir);
3807
3808 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3809 if (!NT_STATUS_IS_OK(status)) {
3810 END_PROFILE(SMBrmdir);
3811 return ERROR_NT(status);
3812 }
3813
3814 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3815
3816 status = unix_convert(conn, directory, False, NULL, &sbuf);
3817 if (!NT_STATUS_IS_OK(status)) {
3818 END_PROFILE(SMBrmdir);
3819 return ERROR_NT(status);
3820 }
3821
3822 status = check_name(conn, directory);
3823 if (!NT_STATUS_IS_OK(status)) {
3824 END_PROFILE(SMBrmdir);
3825 return ERROR_NT(status);
3826 }
3827
3828 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3829 status = rmdir_internals(conn, directory);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 END_PROFILE(SMBrmdir);
3832 return ERROR_NT(status);
3833 }
3834
3835 outsize = set_message(outbuf,0,0,False);
3836
3837 DEBUG( 3, ( "rmdir %s\n", directory ) );
3838
3839 END_PROFILE(SMBrmdir);
3840 return(outsize);
3841}
3842
3843/*******************************************************************
3844 Resolve wildcards in a filename rename.
3845 Note that name is in UNIX charset and thus potentially can be more
3846 than fstring buffer (255 bytes) especially in default UTF-8 case.
3847 Therefore, we use pstring inside and all calls should ensure that
3848 name2 is at least pstring-long (they do already)
3849********************************************************************/
3850
3851static BOOL resolve_wildcards(const char *name1, char *name2)
3852{
3853 pstring root1,root2;
3854 pstring ext1,ext2;
3855 char *p,*p2, *pname1, *pname2;
3856 int available_space, actual_space;
3857
3858
3859 pname1 = strrchr_m(name1,'/');
3860 pname2 = strrchr_m(name2,'/');
3861
3862 if (!pname1 || !pname2)
3863 return(False);
3864
3865 pstrcpy(root1,pname1);
3866 pstrcpy(root2,pname2);
3867 p = strrchr_m(root1,'.');
3868 if (p) {
3869 *p = 0;
3870 pstrcpy(ext1,p+1);
3871 } else {
3872 pstrcpy(ext1,"");
3873 }
3874 p = strrchr_m(root2,'.');
3875 if (p) {
3876 *p = 0;
3877 pstrcpy(ext2,p+1);
3878 } else {
3879 pstrcpy(ext2,"");
3880 }
3881
3882 p = root1;
3883 p2 = root2;
3884 while (*p2) {
3885 if (*p2 == '?') {
3886 *p2 = *p;
3887 p2++;
3888 } else if (*p2 == '*') {
3889 pstrcpy(p2, p);
3890 break;
3891 } else {
3892 p2++;
3893 }
3894 if (*p)
3895 p++;
3896 }
3897
3898 p = ext1;
3899 p2 = ext2;
3900 while (*p2) {
3901 if (*p2 == '?') {
3902 *p2 = *p;
3903 p2++;
3904 } else if (*p2 == '*') {
3905 pstrcpy(p2, p);
3906 break;
3907 } else {
3908 p2++;
3909 }
3910 if (*p)
3911 p++;
3912 }
3913
3914 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3915
3916 if (ext2[0]) {
3917 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3918 if (actual_space >= available_space - 1) {
3919 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3920 actual_space - available_space));
3921 }
3922 } else {
3923 pstrcpy_base(pname2, root2, name2);
3924 }
3925
3926 return(True);
3927}
3928
3929/****************************************************************************
3930 Ensure open files have their names updated. Updated to notify other smbd's
3931 asynchronously.
3932****************************************************************************/
3933
3934static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
3935 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
3936{
3937 files_struct *fsp;
3938 BOOL did_rename = False;
3939
3940 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3941 /* fsp_name is a relative path under the fsp. To change this for other
3942 sharepaths we need to manipulate relative paths. */
3943 /* TODO - create the absolute path and manipulate the newname
3944 relative to the sharepath. */
3945 if (fsp->conn != conn) {
3946 continue;
3947 }
3948 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3949 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3950 fsp->fsp_name, newname ));
3951 string_set(&fsp->fsp_name, newname);
3952 did_rename = True;
3953 }
3954
3955 if (!did_rename) {
3956 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3957 (unsigned int)dev, (double)inode, newname ));
3958 }
3959
3960 /* Send messages to all smbd's (not ourself) that the name has changed. */
3961 rename_share_filename(lck, conn->connectpath, newname);
3962}
3963
3964/****************************************************************************
3965 We need to check if the source path is a parent directory of the destination
3966 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
3967 refuse the rename with a sharing violation. Under UNIX the above call can
3968 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
3969 probably need to check that the client is a Windows one before disallowing
3970 this as a UNIX client (one with UNIX extensions) can know the source is a
3971 symlink and make this decision intelligently. Found by an excellent bug
3972 report from <AndyLiebman@aol.com>.
3973****************************************************************************/
3974
3975static BOOL rename_path_prefix_equal(const char *src, const char *dest)
3976{
3977 const char *psrc = src;
3978 const char *pdst = dest;
3979 size_t slen;
3980
3981 if (psrc[0] == '.' && psrc[1] == '/') {
3982 psrc += 2;
3983 }
3984 if (pdst[0] == '.' && pdst[1] == '/') {
3985 pdst += 2;
3986 }
3987 if ((slen = strlen(psrc)) > strlen(pdst)) {
3988 return False;
3989 }
3990 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
3991}
3992
3993/****************************************************************************
3994 Rename an open file - given an fsp.
3995****************************************************************************/
3996
3997NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
3998{
3999 SMB_STRUCT_STAT sbuf;
4000 pstring newname_last_component;
4001 NTSTATUS status = NT_STATUS_OK;
4002 BOOL dest_exists;
4003 struct share_mode_lock *lck = NULL;
4004
4005 ZERO_STRUCT(sbuf);
4006
4007 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 return status;
4010 }
4011
4012 /* Ensure newname contains a '/' */
4013 if(strrchr_m(newname,'/') == 0) {
4014 pstring tmpstr;
4015
4016 pstrcpy(tmpstr, "./");
4017 pstrcat(tmpstr, newname);
4018 pstrcpy(newname, tmpstr);
4019 }
4020
4021 /*
4022 * Check for special case with case preserving and not
4023 * case sensitive. If the old last component differs from the original
4024 * last component only by case, then we should allow
4025 * the rename (user is trying to change the case of the
4026 * filename).
4027 */
4028
4029 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4030 strequal(newname, fsp->fsp_name)) {
4031 char *p;
4032 pstring newname_modified_last_component;
4033
4034 /*
4035 * Get the last component of the modified name.
4036 * Note that we guarantee that newname contains a '/'
4037 * character above.
4038 */
4039 p = strrchr_m(newname,'/');
4040 pstrcpy(newname_modified_last_component,p+1);
4041
4042 if(strcsequal(newname_modified_last_component,
4043 newname_last_component) == False) {
4044 /*
4045 * Replace the modified last component with
4046 * the original.
4047 */
4048 pstrcpy(p+1, newname_last_component);
4049 }
4050 }
4051
4052 /*
4053 * If the src and dest names are identical - including case,
4054 * don't do the rename, just return success.
4055 */
4056
4057 if (strcsequal(fsp->fsp_name, newname)) {
4058 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4059 newname));
4060 return NT_STATUS_OK;
4061 }
4062
4063 dest_exists = vfs_object_exist(conn,newname,NULL);
4064
4065 if(!replace_if_exists && dest_exists) {
4066 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4067 fsp->fsp_name,newname));
4068 return NT_STATUS_OBJECT_NAME_COLLISION;
4069 }
4070
4071 status = can_rename(conn,newname,attrs,&sbuf);
4072
4073 if (dest_exists && !NT_STATUS_IS_OK(status)) {
4074 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4075 nt_errstr(status), fsp->fsp_name,newname));
4076 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4077 status = NT_STATUS_ACCESS_DENIED;
4078 return status;
4079 }
4080
4081 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4082 return NT_STATUS_ACCESS_DENIED;
4083 }
4084
4085 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4086
4087 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4088 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4089 fsp->fsp_name,newname));
4090 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4091 TALLOC_FREE(lck);
4092 return NT_STATUS_OK;
4093 }
4094
4095 TALLOC_FREE(lck);
4096
4097 if (errno == ENOTDIR || errno == EISDIR) {
4098 status = NT_STATUS_OBJECT_NAME_COLLISION;
4099 } else {
4100 status = map_nt_error_from_unix(errno);
4101 }
4102
4103 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4104 nt_errstr(status), fsp->fsp_name,newname));
4105
4106 return status;
4107}
4108
4109/*
4110 * Do the notify calls from a rename
4111 */
4112
4113static void notify_rename(connection_struct *conn, BOOL is_dir,
4114 const char *oldpath, const char *newpath)
4115{
4116 char *olddir, *newdir;
4117 const char *oldname, *newname;
4118 uint32 mask;
4119
4120 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4121 : FILE_NOTIFY_CHANGE_FILE_NAME;
4122
4123 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4124 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4125 TALLOC_FREE(olddir);
4126 return;
4127 }
4128
4129 if (strcmp(olddir, newdir) == 0) {
4130 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4131 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4132 }
4133 else {
4134 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4135 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4136 }
4137 TALLOC_FREE(olddir);
4138 TALLOC_FREE(newdir);
4139
4140 /* this is a strange one. w2k3 gives an additional event for
4141 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4142 files, but not directories */
4143 if (!is_dir) {
4144 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4145 FILE_NOTIFY_CHANGE_ATTRIBUTES
4146 |FILE_NOTIFY_CHANGE_CREATION,
4147 newpath);
4148 }
4149}
4150
4151/****************************************************************************
4152 The guts of the rename command, split out so it may be called by the NT SMB
4153 code.
4154****************************************************************************/
4155
4156NTSTATUS rename_internals(connection_struct *conn, pstring name,
4157 pstring newname, uint32 attrs,
4158 BOOL replace_if_exists, BOOL has_wild)
4159{
4160 pstring directory;
4161 pstring mask;
4162 pstring last_component_src;
4163 pstring last_component_dest;
4164 char *p;
4165 int count=0;
4166 NTSTATUS status = NT_STATUS_OK;
4167 SMB_STRUCT_STAT sbuf1, sbuf2;
4168 struct share_mode_lock *lck = NULL;
4169
4170 *directory = *mask = 0;
4171
4172 ZERO_STRUCT(sbuf1);
4173 ZERO_STRUCT(sbuf2);
4174
4175 status = unix_convert(conn, name, has_wild, last_component_src,
4176 &sbuf1);
4177 if (!NT_STATUS_IS_OK(status)) {
4178 return status;
4179 }
4180
4181 status = unix_convert(conn, newname, True, last_component_dest,
4182 &sbuf2);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 return status;
4185 }
4186
4187 /*
4188 * Split the old name into directory and last component
4189 * strings. Note that unix_convert may have stripped off a
4190 * leading ./ from both name and newname if the rename is
4191 * at the root of the share. We need to make sure either both
4192 * name and newname contain a / character or neither of them do
4193 * as this is checked in resolve_wildcards().
4194 */
4195
4196 p = strrchr_m(name,'/');
4197 if (!p) {
4198 pstrcpy(directory,".");
4199 pstrcpy(mask,name);
4200 } else {
4201 *p = 0;
4202 pstrcpy(directory,name);
4203 pstrcpy(mask,p+1);
4204 *p = '/'; /* Replace needed for exceptional test below. */
4205 }
4206
4207 /*
4208 * We should only check the mangled cache
4209 * here if unix_convert failed. This means
4210 * that the path in 'mask' doesn't exist
4211 * on the file system and so we need to look
4212 * for a possible mangle. This patch from
4213 * Tine Smukavec <valentin.smukavec@hermes.si>.
4214 */
4215
4216 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4217 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4218
4219 if (!has_wild) {
4220 /*
4221 * No wildcards - just process the one file.
4222 */
4223 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4224
4225 /* Add a terminating '/' to the directory name. */
4226 pstrcat(directory,"/");
4227 pstrcat(directory,mask);
4228
4229 /* Ensure newname contains a '/' also */
4230 if(strrchr_m(newname,'/') == 0) {
4231 pstring tmpstr;
4232
4233 pstrcpy(tmpstr, "./");
4234 pstrcat(tmpstr, newname);
4235 pstrcpy(newname, tmpstr);
4236 }
4237
4238 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4239 "case_preserve = %d, short case preserve = %d, "
4240 "directory = %s, newname = %s, "
4241 "last_component_dest = %s, is_8_3 = %d\n",
4242 conn->case_sensitive, conn->case_preserve,
4243 conn->short_case_preserve, directory,
4244 newname, last_component_dest, is_short_name));
4245
4246 /*
4247 * Check for special case with case preserving and not
4248 * case sensitive, if directory and newname are identical,
4249 * and the old last component differs from the original
4250 * last component only by case, then we should allow
4251 * the rename (user is trying to change the case of the
4252 * filename).
4253 */
4254 if((conn->case_sensitive == False) &&
4255 (((conn->case_preserve == True) &&
4256 (is_short_name == False)) ||
4257 ((conn->short_case_preserve == True) &&
4258 (is_short_name == True))) &&
4259 strcsequal(directory, newname)) {
4260 pstring modified_last_component;
4261
4262 /*
4263 * Get the last component of the modified name.
4264 * Note that we guarantee that newname contains a '/'
4265 * character above.
4266 */
4267 p = strrchr_m(newname,'/');
4268 pstrcpy(modified_last_component,p+1);
4269
4270 if(strcsequal(modified_last_component,
4271 last_component_dest) == False) {
4272 /*
4273 * Replace the modified last component with
4274 * the original.
4275 */
4276 pstrcpy(p+1, last_component_dest);
4277 }
4278 }
4279
4280 resolve_wildcards(directory,newname);
4281
4282 /*
4283 * The source object must exist.
4284 */
4285
4286 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4287 DEBUG(3, ("rename_internals: source doesn't exist "
4288 "doing rename %s -> %s\n",
4289 directory,newname));
4290
4291 if (errno == ENOTDIR || errno == EISDIR
4292 || errno == ENOENT) {
4293 /*
4294 * Must return different errors depending on
4295 * whether the parent directory existed or
4296 * not.
4297 */
4298
4299 p = strrchr_m(directory, '/');
4300 if (!p)
4301 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4302 *p = '\0';
4303 if (vfs_object_exist(conn, directory, NULL))
4304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4305 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4306 }
4307 status = map_nt_error_from_unix(errno);
4308 DEBUG(3, ("rename_internals: Error %s rename %s -> "
4309 "%s\n", nt_errstr(status), directory,
4310 newname));
4311
4312 return status;
4313 }
4314
4315 status = can_rename(conn,directory,attrs,&sbuf1);
4316
4317 if (!NT_STATUS_IS_OK(status)) {
4318 DEBUG(3,("rename_internals: Error %s rename %s -> "
4319 "%s\n", nt_errstr(status), directory,
4320 newname));
4321 return status;
4322 }
4323
4324 /*
4325 * If the src and dest names are identical - including case,
4326 * don't do the rename, just return success.
4327 */
4328
4329 if (strcsequal(directory, newname)) {
4330 rename_open_files(conn, NULL, sbuf1.st_dev,
4331 sbuf1.st_ino, newname);
4332 DEBUG(3, ("rename_internals: identical names in "
4333 "rename %s - returning success\n",
4334 directory));
4335 return NT_STATUS_OK;
4336 }
4337
4338 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4339 DEBUG(3,("rename_internals: dest exists doing "
4340 "rename %s -> %s\n", directory, newname));
4341 return NT_STATUS_OBJECT_NAME_COLLISION;
4342 }
4343
4344 if (rename_path_prefix_equal(directory, newname)) {
4345 return NT_STATUS_SHARING_VIOLATION;
4346 }
4347
4348 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4349 NULL, NULL);
4350
4351 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4352 DEBUG(3,("rename_internals: succeeded doing rename "
4353 "on %s -> %s\n", directory, newname));
4354 rename_open_files(conn, lck, sbuf1.st_dev,
4355 sbuf1.st_ino, newname);
4356 TALLOC_FREE(lck);
4357 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4358 directory, newname);
4359 return NT_STATUS_OK;
4360 }
4361
4362 TALLOC_FREE(lck);
4363 if (errno == ENOTDIR || errno == EISDIR) {
4364 status = NT_STATUS_OBJECT_NAME_COLLISION;
4365 } else {
4366 status = map_nt_error_from_unix(errno);
4367 }
4368
4369 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4370 nt_errstr(status), directory,newname));
4371
4372 return status;
4373 } else {
4374 /*
4375 * Wildcards - process each file that matches.
4376 */
4377 struct smb_Dir *dir_hnd = NULL;
4378 const char *dname;
4379 long offset = 0;
4380 pstring destname;
4381
4382 if (strequal(mask,"????????.???"))
4383 pstrcpy(mask,"*");
4384
4385 status = check_name(conn, directory);
4386 if (!NT_STATUS_IS_OK(status)) {
4387 return status;
4388 }
4389
4390 dir_hnd = OpenDir(conn, directory, mask, attrs);
4391 if (dir_hnd == NULL) {
4392 return map_nt_error_from_unix(errno);
4393 }
4394
4395 status = NT_STATUS_NO_SUCH_FILE;
4396 /*
4397 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4398 * - gentest fix. JRA
4399 */
4400
4401 while ((dname = ReadDirName(dir_hnd, &offset))) {
4402 pstring fname;
4403 BOOL sysdir_entry = False;
4404
4405 pstrcpy(fname,dname);
4406
4407 /* Quick check for "." and ".." */
4408 if (fname[0] == '.') {
4409 if (!fname[1]
4410 || (fname[1] == '.' && !fname[2])) {
4411 if (attrs & aDIR) {
4412 sysdir_entry = True;
4413 } else {
4414 continue;
4415 }
4416 }
4417 }
4418
4419 if (!is_visible_file(conn, directory, dname, &sbuf1,
4420 False)) {
4421 continue;
4422 }
4423
4424 if(!mask_match(fname, mask, conn->case_sensitive)) {
4425 continue;
4426 }
4427
4428 if (sysdir_entry) {
4429 status = NT_STATUS_OBJECT_NAME_INVALID;
4430 break;
4431 }
4432
4433 status = NT_STATUS_ACCESS_DENIED;
4434 slprintf(fname, sizeof(fname)-1, "%s/%s", directory,
4435 dname);
4436 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4437 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4438 DEBUG(6, ("rename %s failed. Error %s\n",
4439 fname, nt_errstr(status)));
4440 continue;
4441 }
4442 status = can_rename(conn,fname,attrs,&sbuf1);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 DEBUG(6, ("rename %s refused\n", fname));
4445 continue;
4446 }
4447 pstrcpy(destname,newname);
4448
4449 if (!resolve_wildcards(fname,destname)) {
4450 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4451 fname, destname));
4452 continue;
4453 }
4454
4455 if (strcsequal(fname,destname)) {
4456 rename_open_files(conn, NULL, sbuf1.st_dev,
4457 sbuf1.st_ino, newname);
4458 DEBUG(3,("rename_internals: identical names "
4459 "in wildcard rename %s - success\n",
4460 fname));
4461 count++;
4462 status = NT_STATUS_OK;
4463 continue;
4464 }
4465
4466 if (!replace_if_exists
4467 && vfs_file_exist(conn,destname, NULL)) {
4468 DEBUG(6,("file_exist %s\n", destname));
4469 status = NT_STATUS_OBJECT_NAME_COLLISION;
4470 continue;
4471 }
4472
4473 if (rename_path_prefix_equal(fname, destname)) {
4474 return NT_STATUS_SHARING_VIOLATION;
4475 }
4476
4477 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4478 sbuf1.st_ino, NULL, NULL);
4479
4480 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4481 rename_open_files(conn, lck, sbuf1.st_dev,
4482 sbuf1.st_ino, newname);
4483 count++;
4484 status = NT_STATUS_OK;
4485 }
4486 TALLOC_FREE(lck);
4487 DEBUG(3,("rename_internals: doing rename on %s -> "
4488 "%s\n",fname,destname));
4489 }
4490 CloseDir(dir_hnd);
4491 }
4492
4493#if 0
4494 /* Don't think needed any more - JRA. */
4495 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4496 if (!rcdest && bad_path_dest) {
4497 if (ms_has_wild(last_component_dest))
4498 return NT_STATUS_OBJECT_NAME_INVALID;
4499 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4500 }
4501 }
4502#endif
4503
4504 if (count == 0 && NT_STATUS_IS_OK(status)) {
4505 status = map_nt_error_from_unix(errno);
4506 }
4507
4508 return status;
4509}
4510
4511/****************************************************************************
4512 Reply to a mv.
4513****************************************************************************/
4514
4515int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4516 int dum_buffsize)
4517{
4518 int outsize = 0;
4519 pstring name;
4520 pstring newname;
4521 char *p;
4522 uint32 attrs = SVAL(inbuf,smb_vwv0);
4523 NTSTATUS status;
4524 BOOL path1_contains_wcard = False;
4525 BOOL path2_contains_wcard = False;
4526
4527 START_PROFILE(SMBmv);
4528
4529 p = smb_buf(inbuf) + 1;
4530 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 END_PROFILE(SMBmv);
4533 return ERROR_NT(status);
4534 }
4535 p++;
4536 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
4537 if (!NT_STATUS_IS_OK(status)) {
4538 END_PROFILE(SMBmv);
4539 return ERROR_NT(status);
4540 }
4541
4542 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4543 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4544
4545 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4546
4547 status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 END_PROFILE(SMBmv);
4550 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4551 /* We have re-scheduled this call. */
4552 return -1;
4553 }
4554 return ERROR_NT(status);
4555 }
4556
4557 outsize = set_message(outbuf,0,0,False);
4558
4559 END_PROFILE(SMBmv);
4560 return(outsize);
4561}
4562
4563/*******************************************************************
4564 Copy a file as part of a reply_copy.
4565******************************************************************/
4566
4567/*
4568 * TODO: check error codes on all callers
4569 */
4570
4571NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
4572 int count, BOOL target_is_directory)
4573{
4574 SMB_STRUCT_STAT src_sbuf, sbuf2;
4575 SMB_OFF_T ret=-1;
4576 files_struct *fsp1,*fsp2;
4577 pstring dest;
4578 uint32 dosattrs;
4579 uint32 new_create_disposition;
4580 NTSTATUS status;
4581
4582 pstrcpy(dest,dest1);
4583 if (target_is_directory) {
4584 char *p = strrchr_m(src,'/');
4585 if (p) {
4586 p++;
4587 } else {
4588 p = src;
4589 }
4590 pstrcat(dest,"/");
4591 pstrcat(dest,p);
4592 }
4593
4594 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4595 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4596 }
4597
4598 if (!target_is_directory && count) {
4599 new_create_disposition = FILE_OPEN;
4600 } else {
4601 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4602 NULL, NULL, &new_create_disposition, NULL)) {
4603 return NT_STATUS_INVALID_PARAMETER;
4604 }
4605 }
4606
4607 status = open_file_ntcreate(conn,src,&src_sbuf,
4608 FILE_GENERIC_READ,
4609 FILE_SHARE_READ|FILE_SHARE_WRITE,
4610 FILE_OPEN,
4611 0,
4612 FILE_ATTRIBUTE_NORMAL,
4613 INTERNAL_OPEN_ONLY,
4614 NULL, &fsp1);
4615
4616 if (!NT_STATUS_IS_OK(status)) {
4617 return status;
4618 }
4619
4620 dosattrs = dos_mode(conn, src, &src_sbuf);
4621 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4622 ZERO_STRUCTP(&sbuf2);
4623 }
4624
4625 status = open_file_ntcreate(conn,dest,&sbuf2,
4626 FILE_GENERIC_WRITE,
4627 FILE_SHARE_READ|FILE_SHARE_WRITE,
4628 new_create_disposition,
4629 0,
4630 dosattrs,
4631 INTERNAL_OPEN_ONLY,
4632 NULL, &fsp2);
4633
4634 if (!NT_STATUS_IS_OK(status)) {
4635 close_file(fsp1,ERROR_CLOSE);
4636 return status;
4637 }
4638
4639 if ((ofun&3) == 1) {
4640 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4641 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4642 /*
4643 * Stop the copy from occurring.
4644 */
4645 ret = -1;
4646 src_sbuf.st_size = 0;
4647 }
4648 }
4649
4650 if (src_sbuf.st_size) {
4651 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4652 }
4653
4654 close_file(fsp1,NORMAL_CLOSE);
4655
4656 /* Ensure the modtime is set correctly on the destination file. */
4657 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4658
4659 /*
4660 * As we are opening fsp1 read-only we only expect
4661 * an error on close on fsp2 if we are out of space.
4662 * Thus we don't look at the error return from the
4663 * close of fsp1.
4664 */
4665 status = close_file(fsp2,NORMAL_CLOSE);
4666
4667 if (!NT_STATUS_IS_OK(status)) {
4668 return status;
4669 }
4670
4671 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4672 return NT_STATUS_DISK_FULL;
4673 }
4674
4675 return NT_STATUS_OK;
4676}
4677
4678/****************************************************************************
4679 Reply to a file copy.
4680****************************************************************************/
4681
4682int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4683{
4684 int outsize = 0;
4685 pstring name;
4686 pstring directory;
4687 pstring mask,newname;
4688 char *p;
4689 int count=0;
4690 int error = ERRnoaccess;
4691 int err = 0;
4692 BOOL has_wild;
4693 BOOL exists=False;
4694 int tid2 = SVAL(inbuf,smb_vwv0);
4695 int ofun = SVAL(inbuf,smb_vwv1);
4696 int flags = SVAL(inbuf,smb_vwv2);
4697 BOOL target_is_directory=False;
4698 BOOL path_contains_wcard1 = False;
4699 BOOL path_contains_wcard2 = False;
4700 SMB_STRUCT_STAT sbuf1, sbuf2;
4701 NTSTATUS status;
4702 START_PROFILE(SMBcopy);
4703
4704 *directory = *mask = 0;
4705
4706 p = smb_buf(inbuf);
4707 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4708 if (!NT_STATUS_IS_OK(status)) {
4709 END_PROFILE(SMBcopy);
4710 return ERROR_NT(status);
4711 }
4712 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 END_PROFILE(SMBcopy);
4715 return ERROR_NT(status);
4716 }
4717
4718 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4719
4720 if (tid2 != conn->cnum) {
4721 /* can't currently handle inter share copies XXXX */
4722 DEBUG(3,("Rejecting inter-share copy\n"));
4723 END_PROFILE(SMBcopy);
4724 return ERROR_DOS(ERRSRV,ERRinvdevice);
4725 }
4726
4727 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4728 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4729
4730 status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
4731 if (!NT_STATUS_IS_OK(status)) {
4732 END_PROFILE(SMBcopy);
4733 return ERROR_NT(status);
4734 }
4735
4736 status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
4737 if (!NT_STATUS_IS_OK(status)) {
4738 END_PROFILE(SMBcopy);
4739 return ERROR_NT(status);
4740 }
4741
4742 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4743
4744 if ((flags&1) && target_is_directory) {
4745 END_PROFILE(SMBcopy);
4746 return ERROR_DOS(ERRDOS,ERRbadfile);
4747 }
4748
4749 if ((flags&2) && !target_is_directory) {
4750 END_PROFILE(SMBcopy);
4751 return ERROR_DOS(ERRDOS,ERRbadpath);
4752 }
4753
4754 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4755 /* wants a tree copy! XXXX */
4756 DEBUG(3,("Rejecting tree copy\n"));
4757 END_PROFILE(SMBcopy);
4758 return ERROR_DOS(ERRSRV,ERRerror);
4759 }
4760
4761 p = strrchr_m(name,'/');
4762 if (!p) {
4763 pstrcpy(directory,"./");
4764 pstrcpy(mask,name);
4765 } else {
4766 *p = 0;
4767 pstrcpy(directory,name);
4768 pstrcpy(mask,p+1);
4769 }
4770
4771 /*
4772 * We should only check the mangled cache
4773 * here if unix_convert failed. This means
4774 * that the path in 'mask' doesn't exist
4775 * on the file system and so we need to look
4776 * for a possible mangle. This patch from
4777 * Tine Smukavec <valentin.smukavec@hermes.si>.
4778 */
4779
4780 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4781 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4782
4783 has_wild = path_contains_wcard1;
4784
4785 if (!has_wild) {
4786 pstrcat(directory,"/");
4787 pstrcat(directory,mask);
4788 if (resolve_wildcards(directory,newname)
4789 && NT_STATUS_IS_OK(status = copy_file(
4790 directory,newname,conn,ofun,
4791 count,target_is_directory)))
4792 count++;
4793 if(!count && !NT_STATUS_IS_OK(status)) {
4794 END_PROFILE(SMBcopy);
4795 return ERROR_NT(status);
4796 }
4797 if (!count) {
4798 exists = vfs_file_exist(conn,directory,NULL);
4799 }
4800 } else {
4801 struct smb_Dir *dir_hnd = NULL;
4802 const char *dname;
4803 long offset = 0;
4804 pstring destname;
4805
4806 if (strequal(mask,"????????.???"))
4807 pstrcpy(mask,"*");
4808
4809 status = check_name(conn, directory);
4810 if (!NT_STATUS_IS_OK(status)) {
4811 return ERROR_NT(status);
4812 }
4813
4814 dir_hnd = OpenDir(conn, directory, mask, 0);
4815 if (dir_hnd == NULL) {
4816 status = map_nt_error_from_unix(errno);
4817 return ERROR_NT(status);
4818 }
4819
4820 error = ERRbadfile;
4821
4822 while ((dname = ReadDirName(dir_hnd, &offset))) {
4823 pstring fname;
4824 pstrcpy(fname,dname);
4825
4826 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4827 continue;
4828 }
4829
4830 if(!mask_match(fname, mask, conn->case_sensitive)) {
4831 continue;
4832 }
4833
4834 error = ERRnoaccess;
4835 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4836 pstrcpy(destname,newname);
4837 if (resolve_wildcards(fname,destname) &&
4838 NT_STATUS_IS_OK(status = copy_file(
4839 fname,destname,conn,ofun,
4840 count,target_is_directory))) {
4841 count++;
4842 }
4843 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4844 }
4845 CloseDir(dir_hnd);
4846 }
4847
4848 if (count == 0) {
4849 if(err) {
4850 /* Error on close... */
4851 errno = err;
4852 END_PROFILE(SMBcopy);
4853 return(UNIXERROR(ERRHRD,ERRgeneral));
4854 }
4855
4856 END_PROFILE(SMBcopy);
4857 return ERROR_DOS(ERRDOS,error);
4858 }
4859
4860 outsize = set_message(outbuf,1,0,True);
4861 SSVAL(outbuf,smb_vwv0,count);
4862
4863 END_PROFILE(SMBcopy);
4864 return(outsize);
4865}
4866
4867/****************************************************************************
4868 Reply to a setdir.
4869****************************************************************************/
4870
4871int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4872{
4873 int snum;
4874 int outsize = 0;
4875 pstring newdir;
4876 NTSTATUS status;
4877
4878 START_PROFILE(pathworks_setdir);
4879
4880 snum = SNUM(conn);
4881 if (!CAN_SETDIR(snum)) {
4882 END_PROFILE(pathworks_setdir);
4883 return ERROR_DOS(ERRDOS,ERRnoaccess);
4884 }
4885
4886 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4887 if (!NT_STATUS_IS_OK(status)) {
4888 END_PROFILE(pathworks_setdir);
4889 return ERROR_NT(status);
4890 }
4891
4892 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4893
4894 if (strlen(newdir) != 0) {
4895 if (!vfs_directory_exist(conn,newdir,NULL)) {
4896 END_PROFILE(pathworks_setdir);
4897 return ERROR_DOS(ERRDOS,ERRbadpath);
4898 }
4899 set_conn_connectpath(conn,newdir);
4900 }
4901
4902 outsize = set_message(outbuf,0,0,False);
4903 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4904
4905 DEBUG(3,("setdir %s\n", newdir));
4906
4907 END_PROFILE(pathworks_setdir);
4908 return(outsize);
4909}
4910
4911#undef DBGC_CLASS
4912#define DBGC_CLASS DBGC_LOCKING
4913
4914/****************************************************************************
4915 Get a lock pid, dealing with large count requests.
4916****************************************************************************/
4917
4918uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4919{
4920 if(!large_file_format)
4921 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
4922 else
4923 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4924}
4925
4926/****************************************************************************
4927 Get a lock count, dealing with large count requests.
4928****************************************************************************/
4929
4930SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4931{
4932 SMB_BIG_UINT count = 0;
4933
4934 if(!large_file_format) {
4935 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4936 } else {
4937
4938#if defined(HAVE_LONGLONG)
4939 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4940 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4941#else /* HAVE_LONGLONG */
4942
4943 /*
4944 * NT4.x seems to be broken in that it sends large file (64 bit)
4945 * lockingX calls even if the CAP_LARGE_FILES was *not*
4946 * negotiated. For boxes without large unsigned ints truncate the
4947 * lock count by dropping the top 32 bits.
4948 */
4949
4950 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4951 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4952 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4953 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4954 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4955 }
4956
4957 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4958#endif /* HAVE_LONGLONG */
4959 }
4960
4961 return count;
4962}
4963
4964#if !defined(HAVE_LONGLONG)
4965/****************************************************************************
4966 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4967****************************************************************************/
4968
4969static uint32 map_lock_offset(uint32 high, uint32 low)
4970{
4971 unsigned int i;
4972 uint32 mask = 0;
4973 uint32 highcopy = high;
4974
4975 /*
4976 * Try and find out how many significant bits there are in high.
4977 */
4978
4979 for(i = 0; highcopy; i++)
4980 highcopy >>= 1;
4981
4982 /*
4983 * We use 31 bits not 32 here as POSIX
4984 * lock offsets may not be negative.
4985 */
4986
4987 mask = (~0) << (31 - i);
4988
4989 if(low & mask)
4990 return 0; /* Fail. */
4991
4992 high <<= (31 - i);
4993
4994 return (high|low);
4995}
4996#endif /* !defined(HAVE_LONGLONG) */
4997
4998/****************************************************************************
4999 Get a lock offset, dealing with large offset requests.
5000****************************************************************************/
5001
5002SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5003{
5004 SMB_BIG_UINT offset = 0;
5005
5006 *err = False;
5007
5008 if(!large_file_format) {
5009 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5010 } else {
5011
5012#if defined(HAVE_LONGLONG)
5013 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5014 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5015#else /* HAVE_LONGLONG */
5016
5017 /*
5018 * NT4.x seems to be broken in that it sends large file (64 bit)
5019 * lockingX calls even if the CAP_LARGE_FILES was *not*
5020 * negotiated. For boxes without large unsigned ints mangle the
5021 * lock offset by mapping the top 32 bits onto the lower 32.
5022 */
5023
5024 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5025 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5026 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5027 uint32 new_low = 0;
5028
5029 if((new_low = map_lock_offset(high, low)) == 0) {
5030 *err = True;
5031 return (SMB_BIG_UINT)-1;
5032 }
5033
5034 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5035 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5036 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5037 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5038 }
5039
5040 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5041#endif /* HAVE_LONGLONG */
5042 }
5043
5044 return offset;
5045}
5046
5047/****************************************************************************
5048 Reply to a lockingX request.
5049****************************************************************************/
5050
5051int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5052 int length, int bufsize)
5053{
5054 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5055 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5056 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5057 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5058 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5059 SMB_BIG_UINT count = 0, offset = 0;
5060 uint32 lock_pid;
5061 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5062 int i;
5063 char *data;
5064 BOOL large_file_format =
5065 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5066 BOOL err;
5067 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5068
5069 START_PROFILE(SMBlockingX);
5070
5071 CHECK_FSP(fsp,conn);
5072
5073 data = smb_buf(inbuf);
5074
5075 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5076 /* we don't support these - and CANCEL_LOCK makes w2k
5077 and XP reboot so I don't really want to be
5078 compatible! (tridge) */
5079 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5080 }
5081
5082 /* Check if this is an oplock break on a file
5083 we have granted an oplock on.
5084 */
5085 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5086 /* Client can insist on breaking to none. */
5087 BOOL break_to_none = (oplocklevel == 0);
5088 BOOL result;
5089
5090 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5091 "for fnum = %d\n", (unsigned int)oplocklevel,
5092 fsp->fnum ));
5093
5094 /*
5095 * Make sure we have granted an exclusive or batch oplock on
5096 * this file.
5097 */
5098
5099 if (fsp->oplock_type == 0) {
5100
5101 /* The Samba4 nbench simulator doesn't understand
5102 the difference between break to level2 and break
5103 to none from level2 - it sends oplock break
5104 replies in both cases. Don't keep logging an error
5105 message here - just ignore it. JRA. */
5106
5107 DEBUG(5,("reply_lockingX: Error : oplock break from "
5108 "client for fnum = %d (oplock=%d) and no "
5109 "oplock granted on this file (%s).\n",
5110 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5111
5112 /* if this is a pure oplock break request then don't
5113 * send a reply */
5114 if (num_locks == 0 && num_ulocks == 0) {
5115 END_PROFILE(SMBlockingX);
5116 return -1;
5117 } else {
5118 END_PROFILE(SMBlockingX);
5119 return ERROR_DOS(ERRDOS,ERRlock);
5120 }
5121 }
5122
5123 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5124 (break_to_none)) {
5125 result = remove_oplock(fsp);
5126 } else {
5127 result = downgrade_oplock(fsp);
5128 }
5129
5130 if (!result) {
5131 DEBUG(0, ("reply_lockingX: error in removing "
5132 "oplock on file %s\n", fsp->fsp_name));
5133 /* Hmmm. Is this panic justified? */
5134 smb_panic("internal tdb error");
5135 }
5136
5137 reply_to_oplock_break_requests(fsp);
5138
5139 /* if this is a pure oplock break request then don't send a
5140 * reply */
5141 if (num_locks == 0 && num_ulocks == 0) {
5142 /* Sanity check - ensure a pure oplock break is not a
5143 chained request. */
5144 if(CVAL(inbuf,smb_vwv0) != 0xff)
5145 DEBUG(0,("reply_lockingX: Error : pure oplock "
5146 "break is a chained %d request !\n",
5147 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5148 END_PROFILE(SMBlockingX);
5149 return -1;
5150 }
5151 }
5152
5153 /*
5154 * We do this check *after* we have checked this is not a oplock break
5155 * response message. JRA.
5156 */
5157
5158 release_level_2_oplocks_on_change(fsp);
5159
5160 /* Data now points at the beginning of the list
5161 of smb_unlkrng structs */
5162 for(i = 0; i < (int)num_ulocks; i++) {
5163 lock_pid = get_lock_pid( data, i, large_file_format);
5164 count = get_lock_count( data, i, large_file_format);
5165 offset = get_lock_offset( data, i, large_file_format, &err);
5166
5167 /*
5168 * There is no error code marked "stupid client bug".... :-).
5169 */
5170 if(err) {
5171 END_PROFILE(SMBlockingX);
5172 return ERROR_DOS(ERRDOS,ERRnoaccess);
5173 }
5174
5175 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5176 "pid %u, file %s\n", (double)offset, (double)count,
5177 (unsigned int)lock_pid, fsp->fsp_name ));
5178
5179 status = do_unlock(fsp,
5180 lock_pid,
5181 count,
5182 offset,
5183 WINDOWS_LOCK);
5184
5185 if (NT_STATUS_V(status)) {
5186 END_PROFILE(SMBlockingX);
5187 return ERROR_NT(status);
5188 }
5189 }
5190
5191 /* Setup the timeout in seconds. */
5192
5193 if (!lp_blocking_locks(SNUM(conn))) {
5194 lock_timeout = 0;
5195 }
5196
5197 /* Now do any requested locks */
5198 data += ((large_file_format ? 20 : 10)*num_ulocks);
5199
5200 /* Data now points at the beginning of the list
5201 of smb_lkrng structs */
5202
5203 for(i = 0; i < (int)num_locks; i++) {
5204 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5205 READ_LOCK:WRITE_LOCK);
5206 lock_pid = get_lock_pid( data, i, large_file_format);
5207 count = get_lock_count( data, i, large_file_format);
5208 offset = get_lock_offset( data, i, large_file_format, &err);
5209
5210 /*
5211 * There is no error code marked "stupid client bug".... :-).
5212 */
5213 if(err) {
5214 END_PROFILE(SMBlockingX);
5215 return ERROR_DOS(ERRDOS,ERRnoaccess);
5216 }
5217
5218 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5219 "%u, file %s timeout = %d\n", (double)offset,
5220 (double)count, (unsigned int)lock_pid,
5221 fsp->fsp_name, (int)lock_timeout ));
5222
5223 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5224 if (lp_blocking_locks(SNUM(conn))) {
5225
5226 /* Schedule a message to ourselves to
5227 remove the blocking lock record and
5228 return the right error. */
5229
5230 if (!blocking_lock_cancel(fsp,
5231 lock_pid,
5232 offset,
5233 count,
5234 WINDOWS_LOCK,
5235 locktype,
5236 NT_STATUS_FILE_LOCK_CONFLICT)) {
5237 END_PROFILE(SMBlockingX);
5238 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5239 }
5240 }
5241 /* Remove a matching pending lock. */
5242 status = do_lock_cancel(fsp,
5243 lock_pid,
5244 count,
5245 offset,
5246 WINDOWS_LOCK);
5247 } else {
5248 BOOL blocking_lock = lock_timeout ? True : False;
5249 BOOL defer_lock = False;
5250 struct byte_range_lock *br_lck;
5251
5252 br_lck = do_lock(fsp,
5253 lock_pid,
5254 count,
5255 offset,
5256 lock_type,
5257 WINDOWS_LOCK,
5258 blocking_lock,
5259 &status);
5260
5261 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5262 /* Windows internal resolution for blocking locks seems
5263 to be about 200ms... Don't wait for less than that. JRA. */
5264 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5265 lock_timeout = lp_lock_spin_time();
5266 }
5267 defer_lock = True;
5268 }
5269
5270 /* This heuristic seems to match W2K3 very well. If a
5271 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5272 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5273 far as I can tell. Replacement for do_lock_spin(). JRA. */
5274
5275 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5276 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5277 defer_lock = True;
5278 lock_timeout = lp_lock_spin_time();
5279 }
5280
5281 if (br_lck && defer_lock) {
5282 /*
5283 * A blocking lock was requested. Package up
5284 * this smb into a queued request and push it
5285 * onto the blocking lock queue.
5286 */
5287 if(push_blocking_lock_request(br_lck,
5288 inbuf, length,
5289 fsp,
5290 lock_timeout,
5291 i,
5292 lock_pid,
5293 lock_type,
5294 WINDOWS_LOCK,
5295 offset,
5296 count)) {
5297 TALLOC_FREE(br_lck);
5298 END_PROFILE(SMBlockingX);
5299 return -1;
5300 }
5301 }
5302
5303 TALLOC_FREE(br_lck);
5304 }
5305
5306 if (NT_STATUS_V(status)) {
5307 END_PROFILE(SMBlockingX);
5308 return ERROR_NT(status);
5309 }
5310 }
5311
5312 /* If any of the above locks failed, then we must unlock
5313 all of the previous locks (X/Open spec). */
5314
5315 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5316 (i != num_locks) &&
5317 (num_locks != 0)) {
5318 /*
5319 * Ensure we don't do a remove on the lock that just failed,
5320 * as under POSIX rules, if we have a lock already there, we
5321 * will delete it (and we shouldn't) .....
5322 */
5323 for(i--; i >= 0; i--) {
5324 lock_pid = get_lock_pid( data, i, large_file_format);
5325 count = get_lock_count( data, i, large_file_format);
5326 offset = get_lock_offset( data, i, large_file_format,
5327 &err);
5328
5329 /*
5330 * There is no error code marked "stupid client
5331 * bug".... :-).
5332 */
5333 if(err) {
5334 END_PROFILE(SMBlockingX);
5335 return ERROR_DOS(ERRDOS,ERRnoaccess);
5336 }
5337
5338 do_unlock(fsp,
5339 lock_pid,
5340 count,
5341 offset,
5342 WINDOWS_LOCK);
5343 }
5344 END_PROFILE(SMBlockingX);
5345 return ERROR_NT(status);
5346 }
5347
5348 set_message(outbuf,2,0,True);
5349
5350 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5351 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5352
5353 END_PROFILE(SMBlockingX);
5354 return chain_reply(inbuf,outbuf,length,bufsize);
5355}
5356
5357#undef DBGC_CLASS
5358#define DBGC_CLASS DBGC_ALL
5359
5360/****************************************************************************
5361 Reply to a SMBreadbmpx (read block multiplex) request.
5362****************************************************************************/
5363
5364int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5365{
5366 ssize_t nread = -1;
5367 ssize_t total_read;
5368 char *data;
5369 SMB_OFF_T startpos;
5370 int outsize;
5371 size_t maxcount;
5372 int max_per_packet;
5373 size_t tcount;
5374 int pad;
5375 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5376 START_PROFILE(SMBreadBmpx);
5377
5378 /* this function doesn't seem to work - disable by default */
5379 if (!lp_readbmpx()) {
5380 END_PROFILE(SMBreadBmpx);
5381 return ERROR_DOS(ERRSRV,ERRuseSTD);
5382 }
5383
5384 outsize = set_message(outbuf,8,0,True);
5385
5386 CHECK_FSP(fsp,conn);
5387 if (!CHECK_READ(fsp,inbuf)) {
5388 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5389 }
5390
5391 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5392 maxcount = SVAL(inbuf,smb_vwv3);
5393
5394 data = smb_buf(outbuf);
5395 pad = ((long)data)%4;
5396 if (pad)
5397 pad = 4 - pad;
5398 data += pad;
5399
5400 max_per_packet = bufsize-(outsize+pad);
5401 tcount = maxcount;
5402 total_read = 0;
5403
5404 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5405 END_PROFILE(SMBreadBmpx);
5406 return ERROR_DOS(ERRDOS,ERRlock);
5407 }
5408
5409 do {
5410 size_t N = MIN(max_per_packet,tcount-total_read);
5411
5412 nread = read_file(fsp,data,startpos,N);
5413
5414 if (nread <= 0)
5415 nread = 0;
5416
5417 if (nread < (ssize_t)N)
5418 tcount = total_read + nread;
5419
5420 set_message(outbuf,8,nread+pad,False);
5421 SIVAL(outbuf,smb_vwv0,startpos);
5422 SSVAL(outbuf,smb_vwv2,tcount);
5423 SSVAL(outbuf,smb_vwv6,nread);
5424 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5425
5426 show_msg(outbuf);
5427 if (!send_smb(smbd_server_fd(),outbuf))
5428 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5429
5430 total_read += nread;
5431 startpos += nread;
5432 } while (total_read < (ssize_t)tcount);
5433
5434 END_PROFILE(SMBreadBmpx);
5435 return(-1);
5436}
5437
5438/****************************************************************************
5439 Reply to a SMBsetattrE.
5440****************************************************************************/
5441
5442int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5443{
5444 struct utimbuf unix_times;
5445 int outsize = 0;
5446 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5447 START_PROFILE(SMBsetattrE);
5448
5449 outsize = set_message(outbuf,0,0,False);
5450
5451 if(!fsp || (fsp->conn != conn)) {
5452 END_PROFILE(SMBsetattrE);
5453 return ERROR_DOS(ERRDOS,ERRbadfid);
5454 }
5455
5456 /*
5457 * Convert the DOS times into unix times. Ignore create
5458 * time as UNIX can't set this.
5459 */
5460
5461 unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5462 unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5463
5464 /*
5465 * Patch from Ray Frush <frush@engr.colostate.edu>
5466 * Sometimes times are sent as zero - ignore them.
5467 */
5468
5469 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5470 /* Ignore request */
5471 if( DEBUGLVL( 3 ) ) {
5472 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5473 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5474 }
5475 END_PROFILE(SMBsetattrE);
5476 return(outsize);
5477 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5478 /* set modify time = to access time if modify time was unset */
5479 unix_times.modtime = unix_times.actime;
5480 }
5481
5482 /* Set the date on this file */
5483 /* Should we set pending modtime here ? JRA */
5484 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5485 END_PROFILE(SMBsetattrE);
5486 return ERROR_DOS(ERRDOS,ERRnoaccess);
5487 }
5488
5489 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5490 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5491
5492 END_PROFILE(SMBsetattrE);
5493 return(outsize);
5494}
5495
5496
5497/* Back from the dead for OS/2..... JRA. */
5498
5499/****************************************************************************
5500 Reply to a SMBwritebmpx (write block multiplex primary) request.
5501****************************************************************************/
5502
5503int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5504{
5505 size_t numtowrite;
5506 ssize_t nwritten = -1;
5507 int outsize = 0;
5508 SMB_OFF_T startpos;
5509 size_t tcount;
5510 BOOL write_through;
5511 int smb_doff;
5512 char *data;
5513 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5514 START_PROFILE(SMBwriteBmpx);
5515
5516 CHECK_FSP(fsp,conn);
5517 if (!CHECK_WRITE(fsp)) {
5518 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5519 }
5520 if (HAS_CACHED_ERROR(fsp)) {
5521 return(CACHED_ERROR(fsp));
5522 }
5523
5524 tcount = SVAL(inbuf,smb_vwv1);
5525 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5526 write_through = BITSETW(inbuf+smb_vwv7,0);
5527 numtowrite = SVAL(inbuf,smb_vwv10);
5528 smb_doff = SVAL(inbuf,smb_vwv11);
5529
5530 data = smb_base(inbuf) + smb_doff;
5531
5532 /* If this fails we need to send an SMBwriteC response,
5533 not an SMBwritebmpx - set this up now so we don't forget */
5534 SCVAL(outbuf,smb_com,SMBwritec);
5535
5536 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5537 END_PROFILE(SMBwriteBmpx);
5538 return(ERROR_DOS(ERRDOS,ERRlock));
5539 }
5540
5541 nwritten = write_file(fsp,data,startpos,numtowrite);
5542
5543 sync_file(conn, fsp, write_through);
5544
5545 if(nwritten < (ssize_t)numtowrite) {
5546 END_PROFILE(SMBwriteBmpx);
5547 return(UNIXERROR(ERRHRD,ERRdiskfull));
5548 }
5549
5550 /* If the maximum to be written to this file
5551 is greater than what we just wrote then set
5552 up a secondary struct to be attached to this
5553 fd, we will use this to cache error messages etc. */
5554
5555 if((ssize_t)tcount > nwritten) {
5556 write_bmpx_struct *wbms;
5557 if(fsp->wbmpx_ptr != NULL)
5558 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5559 else
5560 wbms = SMB_MALLOC_P(write_bmpx_struct);
5561 if(!wbms) {
5562 DEBUG(0,("Out of memory in reply_readmpx\n"));
5563 END_PROFILE(SMBwriteBmpx);
5564 return(ERROR_DOS(ERRSRV,ERRnoresource));
5565 }
5566 wbms->wr_mode = write_through;
5567 wbms->wr_discard = False; /* No errors yet */
5568 wbms->wr_total_written = nwritten;
5569 wbms->wr_errclass = 0;
5570 wbms->wr_error = 0;
5571 fsp->wbmpx_ptr = wbms;
5572 }
5573
5574 /* We are returning successfully, set the message type back to
5575 SMBwritebmpx */
5576 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5577
5578 outsize = set_message(outbuf,1,0,True);
5579
5580 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5581
5582 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5583 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5584
5585 if (write_through && tcount==nwritten) {
5586 /* We need to send both a primary and a secondary response */
5587 smb_setlen(outbuf,outsize - 4);
5588 show_msg(outbuf);
5589 if (!send_smb(smbd_server_fd(),outbuf))
5590 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5591
5592 /* Now the secondary */
5593 outsize = set_message(outbuf,1,0,True);
5594 SCVAL(outbuf,smb_com,SMBwritec);
5595 SSVAL(outbuf,smb_vwv0,nwritten);
5596 }
5597
5598 END_PROFILE(SMBwriteBmpx);
5599 return(outsize);
5600}
5601
5602/****************************************************************************
5603 Reply to a SMBwritebs (write block multiplex secondary) request.
5604****************************************************************************/
5605
5606int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5607{
5608 size_t numtowrite;
5609 ssize_t nwritten = -1;
5610 int outsize = 0;
5611 SMB_OFF_T startpos;
5612 size_t tcount;
5613 BOOL write_through;
5614 int smb_doff;
5615 char *data;
5616 write_bmpx_struct *wbms;
5617 BOOL send_response = False;
5618 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5619 START_PROFILE(SMBwriteBs);
5620
5621 CHECK_FSP(fsp,conn);
5622 if (!CHECK_WRITE(fsp)) {
5623 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5624 }
5625
5626 tcount = SVAL(inbuf,smb_vwv1);
5627 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5628 numtowrite = SVAL(inbuf,smb_vwv6);
5629 smb_doff = SVAL(inbuf,smb_vwv7);
5630
5631 data = smb_base(inbuf) + smb_doff;
5632
5633 /* We need to send an SMBwriteC response, not an SMBwritebs */
5634 SCVAL(outbuf,smb_com,SMBwritec);
5635
5636 /* This fd should have an auxiliary struct attached,
5637 check that it does */
5638 wbms = fsp->wbmpx_ptr;
5639 if(!wbms) {
5640 END_PROFILE(SMBwriteBs);
5641 return(-1);
5642 }
5643
5644 /* If write through is set we can return errors, else we must cache them */
5645 write_through = wbms->wr_mode;
5646
5647 /* Check for an earlier error */
5648 if(wbms->wr_discard) {
5649 END_PROFILE(SMBwriteBs);
5650 return -1; /* Just discard the packet */
5651 }
5652
5653 nwritten = write_file(fsp,data,startpos,numtowrite);
5654
5655 sync_file(conn, fsp, write_through);
5656
5657 if (nwritten < (ssize_t)numtowrite) {
5658 if(write_through) {
5659 /* We are returning an error - we can delete the aux struct */
5660 if (wbms)
5661 free((char *)wbms);
5662 fsp->wbmpx_ptr = NULL;
5663 END_PROFILE(SMBwriteBs);
5664 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5665 }
5666 wbms->wr_errclass = ERRHRD;
5667 wbms->wr_error = ERRdiskfull;
5668 wbms->wr_status = NT_STATUS_DISK_FULL;
5669 wbms->wr_discard = True;
5670 END_PROFILE(SMBwriteBs);
5671 return -1;
5672 }
5673
5674 /* Increment the total written, if this matches tcount
5675 we can discard the auxiliary struct (hurrah !) and return a writeC */
5676 wbms->wr_total_written += nwritten;
5677 if(wbms->wr_total_written >= tcount) {
5678 if (write_through) {
5679 outsize = set_message(outbuf,1,0,True);
5680 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5681 send_response = True;
5682 }
5683
5684 free((char *)wbms);
5685 fsp->wbmpx_ptr = NULL;
5686 }
5687
5688 if(send_response) {
5689 END_PROFILE(SMBwriteBs);
5690 return(outsize);
5691 }
5692
5693 END_PROFILE(SMBwriteBs);
5694 return(-1);
5695}
5696
5697/****************************************************************************
5698 Reply to a SMBgetattrE.
5699****************************************************************************/
5700
5701int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5702{
5703 SMB_STRUCT_STAT sbuf;
5704 int outsize = 0;
5705 int mode;
5706 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5707 START_PROFILE(SMBgetattrE);
5708
5709 outsize = set_message(outbuf,11,0,True);
5710
5711 if(!fsp || (fsp->conn != conn)) {
5712 END_PROFILE(SMBgetattrE);
5713 return ERROR_DOS(ERRDOS,ERRbadfid);
5714 }
5715
5716 /* Do an fstat on this file */
5717 if(fsp_stat(fsp, &sbuf)) {
5718 END_PROFILE(SMBgetattrE);
5719 return(UNIXERROR(ERRDOS,ERRnoaccess));
5720 }
5721
5722 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5723
5724 /*
5725 * Convert the times into dos times. Set create
5726 * date to be last modify date as UNIX doesn't save
5727 * this.
5728 */
5729
5730 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5731 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5732 /* Should we check pending modtime here ? JRA */
5733 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5734
5735 if (mode & aDIR) {
5736 SIVAL(outbuf,smb_vwv6,0);
5737 SIVAL(outbuf,smb_vwv8,0);
5738 } else {
5739 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5740 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5741 SIVAL(outbuf,smb_vwv8,allocation_size);
5742 }
5743 SSVAL(outbuf,smb_vwv10, mode);
5744
5745 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5746
5747 END_PROFILE(SMBgetattrE);
5748 return(outsize);
5749}
Note: See TracBrowser for help on using the repository browser.