root/source3/smbd/reply.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_path_syntax_internal
  2. check_path_syntax
  3. check_path_syntax_wcard
  4. check_path_syntax_posix
  5. srvstr_get_path_wcard
  6. srvstr_get_path
  7. srvstr_get_path_req_wcard
  8. srvstr_get_path_req
  9. check_fsp_open
  10. check_fsp
  11. check_fsp_ntquota_handle
  12. fsp_belongs_conn
  13. reply_special
  14. reply_tcon
  15. reply_tcon_and_X
  16. reply_unknown_new
  17. reply_ioctl
  18. map_checkpath_error
  19. reply_checkpath
  20. reply_getatr
  21. reply_setatr
  22. reply_dskattr
  23. reply_search
  24. reply_fclose
  25. reply_open
  26. reply_open_and_X
  27. reply_ulogoffX
  28. reply_mknew
  29. reply_ctemp
  30. can_rename
  31. do_unlink
  32. unlink_internals
  33. reply_unlink
  34. fail_readraw
  35. fake_sendfile
  36. sendfile_short_send
  37. reply_readbraw_error
  38. send_file_readbraw
  39. reply_readbraw
  40. reply_lockread
  41. reply_read
  42. setup_readX_header
  43. send_file_readX
  44. reply_read_and_X
  45. error_to_writebrawerr
  46. reply_writebraw
  47. reply_writeunlock
  48. reply_write
  49. is_valid_writeX_buffer
  50. reply_write_and_X
  51. reply_lseek
  52. reply_flush
  53. reply_exit
  54. reply_close
  55. reply_writeclose
  56. reply_lock
  57. reply_unlock
  58. reply_tdis
  59. reply_echo
  60. reply_printopen
  61. reply_printclose
  62. reply_printqueue
  63. reply_printwrite
  64. reply_mkdir
  65. recursive_rmdir
  66. rmdir_internals
  67. reply_rmdir
  68. resolve_wildcards
  69. rename_open_files
  70. rename_path_prefix_equal
  71. notify_rename
  72. rename_internals_fsp
  73. rename_internals
  74. reply_mv
  75. copy_file
  76. reply_copy
  77. get_lock_pid
  78. get_lock_count
  79. map_lock_offset
  80. get_lock_offset
  81. reply_lockingX
  82. reply_readbmpx
  83. reply_readbs
  84. reply_setattrE
  85. reply_writebmpx
  86. reply_writebs
  87. 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 }

/* [<][>][^][v][top][bottom][index][help] */