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