source: branches/samba-3.0/source/smbd/reply.c@ 396

Last change on this file since 396 was 191, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #90 (by diver)

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