1/* 2 Unix SMB/CIFS implementation. 3 client file operations 4 Copyright (C) Andrew Tridgell 1994-1998 5 Copyright (C) Jeremy Allison 2001-2009 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22 23/*********************************************************** 24 Common function for pushing stings, used by smb_bytes_push_str() 25 and trans_bytes_push_str(). Only difference is the align_odd 26 parameter setting. 27***********************************************************/ 28 29static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2, 30 const char *str, size_t str_len, 31 bool align_odd, 32 size_t *pconverted_size) 33{ 34 size_t buflen; 35 char *converted; 36 size_t converted_size; 37 38 if (buf == NULL) { 39 return NULL; 40 } 41 42 buflen = talloc_get_size(buf); 43 44 if (align_odd && ucs2 && (buflen % 2 == 0)) { 45 /* 46 * We're pushing into an SMB buffer, align odd 47 */ 48 buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1); 49 if (buf == NULL) { 50 return NULL; 51 } 52 buf[buflen] = '\0'; 53 buflen += 1; 54 } 55 56 if (!convert_string_talloc(talloc_tos(), CH_UNIX, 57 ucs2 ? CH_UTF16LE : CH_DOS, 58 str, str_len, &converted, 59 &converted_size, true)) { 60 return NULL; 61 } 62 63 buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, 64 buflen + converted_size); 65 if (buf == NULL) { 66 TALLOC_FREE(converted); 67 return NULL; 68 } 69 70 memcpy(buf + buflen, converted, converted_size); 71 72 TALLOC_FREE(converted); 73 74 if (pconverted_size) { 75 *pconverted_size = converted_size; 76 } 77 78 return buf; 79} 80 81/*********************************************************** 82 Push a string into an SMB buffer, with odd byte alignment 83 if it's a UCS2 string. 84***********************************************************/ 85 86uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, 87 const char *str, size_t str_len, 88 size_t *pconverted_size) 89{ 90 return internal_bytes_push_str(buf, ucs2, str, str_len, 91 true, pconverted_size); 92} 93 94/*********************************************************** 95 Same as smb_bytes_push_str(), but without the odd byte 96 align for ucs2 (we're pushing into a param or data block). 97 static for now, although this will probably change when 98 other modules use async trans calls. 99***********************************************************/ 100 101static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2, 102 const char *str, size_t str_len, 103 size_t *pconverted_size) 104{ 105 return internal_bytes_push_str(buf, ucs2, str, str_len, 106 false, pconverted_size); 107} 108 109/**************************************************************************** 110 Hard/Symlink a file (UNIX extensions). 111 Creates new name (sym)linked to oldname. 112****************************************************************************/ 113 114struct link_state { 115 uint16_t setup; 116 uint8_t *param; 117 uint8_t *data; 118}; 119 120static void cli_posix_link_internal_done(struct tevent_req *subreq) 121{ 122 struct tevent_req *req = tevent_req_callback_data( 123 subreq, struct tevent_req); 124 struct link_state *state = tevent_req_data(req, struct link_state); 125 NTSTATUS status; 126 127 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); 128 TALLOC_FREE(subreq); 129 if (!NT_STATUS_IS_OK(status)) { 130 tevent_req_nterror(req, status); 131 return; 132 } 133 tevent_req_done(req); 134} 135 136static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx, 137 struct event_context *ev, 138 struct cli_state *cli, 139 const char *oldname, 140 const char *newname, 141 bool hardlink) 142{ 143 struct tevent_req *req = NULL, *subreq = NULL; 144 struct link_state *state = NULL; 145 146 req = tevent_req_create(mem_ctx, &state, struct link_state); 147 if (req == NULL) { 148 return NULL; 149 } 150 151 /* Setup setup word. */ 152 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO); 153 154 /* Setup param array. */ 155 state->param = talloc_array(state, uint8_t, 6); 156 if (tevent_req_nomem(state->param, req)) { 157 return tevent_req_post(req, ev); 158 } 159 memset(state->param, '\0', 6); 160 SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK); 161 162 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname, 163 strlen(newname)+1, NULL); 164 165 if (tevent_req_nomem(state->param, req)) { 166 return tevent_req_post(req, ev); 167 } 168 169 /* Setup data array. */ 170 state->data = talloc_array(state, uint8_t, 0); 171 if (tevent_req_nomem(state->data, req)) { 172 return tevent_req_post(req, ev); 173 } 174 state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname, 175 strlen(oldname)+1, NULL); 176 177 subreq = cli_trans_send(state, /* mem ctx. */ 178 ev, /* event ctx. */ 179 cli, /* cli_state. */ 180 SMBtrans2, /* cmd. */ 181 NULL, /* pipe name. */ 182 -1, /* fid. */ 183 0, /* function. */ 184 0, /* flags. */ 185 &state->setup, /* setup. */ 186 1, /* num setup uint16_t words. */ 187 0, /* max returned setup. */ 188 state->param, /* param. */ 189 talloc_get_size(state->param), /* num param. */ 190 2, /* max returned param. */ 191 state->data, /* data. */ 192 talloc_get_size(state->data), /* num data. */ 193 0); /* max returned data. */ 194 195 if (tevent_req_nomem(subreq, req)) { 196 return tevent_req_post(req, ev); 197 } 198 tevent_req_set_callback(subreq, cli_posix_link_internal_done, req); 199 return req; 200} 201 202/**************************************************************************** 203 Symlink a file (UNIX extensions). 204****************************************************************************/ 205 206struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx, 207 struct event_context *ev, 208 struct cli_state *cli, 209 const char *oldname, 210 const char *newname) 211{ 212 return cli_posix_link_internal_send(mem_ctx, ev, cli, 213 oldname, newname, false); 214} 215 216NTSTATUS cli_posix_symlink_recv(struct tevent_req *req) 217{ 218 NTSTATUS status; 219 220 if (tevent_req_is_nterror(req, &status)) { 221 return status; 222 } 223 return NT_STATUS_OK; 224} 225 226NTSTATUS cli_posix_symlink(struct cli_state *cli, 227 const char *oldname, 228 const char *newname) 229{ 230 TALLOC_CTX *frame = talloc_stackframe(); 231 struct event_context *ev = NULL; 232 struct tevent_req *req = NULL; 233 NTSTATUS status = NT_STATUS_OK; 234 235 if (cli_has_async_calls(cli)) { 236 /* 237 * Can't use sync call while an async call is in flight 238 */ 239 status = NT_STATUS_INVALID_PARAMETER; 240 goto fail; 241 } 242 243 ev = event_context_init(frame); 244 if (ev == NULL) { 245 status = NT_STATUS_NO_MEMORY; 246 goto fail; 247 } 248 249 req = cli_posix_symlink_send(frame, 250 ev, 251 cli, 252 oldname, 253 newname); 254 if (req == NULL) { 255 status = NT_STATUS_NO_MEMORY; 256 goto fail; 257 } 258 259 if (!tevent_req_poll(req, ev)) { 260 status = map_nt_error_from_unix(errno); 261 goto fail; 262 } 263 264 status = cli_posix_symlink_recv(req); 265 266 fail: 267 TALLOC_FREE(frame); 268 if (!NT_STATUS_IS_OK(status)) { 269 cli_set_error(cli, status); 270 } 271 return status; 272} 273 274/**************************************************************************** 275 Read a POSIX symlink. 276****************************************************************************/ 277 278struct readlink_state { 279 uint16_t setup; 280 uint8_t *param; 281 uint8_t *data; 282 uint32_t num_data; 283}; 284 285static void cli_posix_readlink_done(struct tevent_req *subreq) 286{ 287 struct tevent_req *req = tevent_req_callback_data( 288 subreq, struct tevent_req); 289 struct readlink_state *state = tevent_req_data(req, struct readlink_state); 290 NTSTATUS status; 291 292 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, 293 &state->data, &state->num_data); 294 TALLOC_FREE(subreq); 295 if (!NT_STATUS_IS_OK(status)) { 296 tevent_req_nterror(req, status); 297 return; 298 } 299 if (state->num_data == 0) { 300 tevent_req_nterror(req, NT_STATUS_DATA_ERROR); 301 return; 302 } 303 if (state->data[state->num_data-1] != '\0') { 304 tevent_req_nterror(req, NT_STATUS_DATA_ERROR); 305 return; 306 } 307 tevent_req_done(req); 308} 309 310struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx, 311 struct event_context *ev, 312 struct cli_state *cli, 313 const char *fname, 314 size_t len) 315{ 316 struct tevent_req *req = NULL, *subreq = NULL; 317 struct readlink_state *state = NULL; 318 uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len); 319 320 if (maxbytelen < len) { 321 return NULL; 322 } 323 324 req = tevent_req_create(mem_ctx, &state, struct readlink_state); 325 if (req == NULL) { 326 return NULL; 327 } 328 329 /* Setup setup word. */ 330 SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO); 331 332 /* Setup param array. */ 333 state->param = talloc_array(state, uint8_t, 6); 334 if (tevent_req_nomem(state->param, req)) { 335 return tevent_req_post(req, ev); 336 } 337 memset(state->param, '\0', 6); 338 SSVAL(state->param,0,SMB_QUERY_FILE_UNIX_LINK); 339 340 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, 341 strlen(fname)+1, NULL); 342 343 if (tevent_req_nomem(state->param, req)) { 344 return tevent_req_post(req, ev); 345 } 346 347 subreq = cli_trans_send(state, /* mem ctx. */ 348 ev, /* event ctx. */ 349 cli, /* cli_state. */ 350 SMBtrans2, /* cmd. */ 351 NULL, /* pipe name. */ 352 -1, /* fid. */ 353 0, /* function. */ 354 0, /* flags. */ 355 &state->setup, /* setup. */ 356 1, /* num setup uint16_t words. */ 357 0, /* max returned setup. */ 358 state->param, /* param. */ 359 talloc_get_size(state->param), /* num param. */ 360 2, /* max returned param. */ 361 NULL, /* data. */ 362 0, /* num data. */ 363 maxbytelen); /* max returned data. */ 364 365 if (tevent_req_nomem(subreq, req)) { 366 return tevent_req_post(req, ev); 367 } 368 tevent_req_set_callback(subreq, cli_posix_readlink_done, req); 369 return req; 370} 371 372NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli, 373 char *retpath, size_t len) 374{ 375 NTSTATUS status; 376 char *converted = NULL; 377 size_t converted_size = 0; 378 struct readlink_state *state = tevent_req_data(req, struct readlink_state); 379 380 if (tevent_req_is_nterror(req, &status)) { 381 return status; 382 } 383 /* The returned data is a pushed string, not raw data. */ 384 if (!convert_string_talloc(state, 385 cli_ucs2(cli) ? CH_UTF16LE : CH_DOS, 386 CH_UNIX, 387 state->data, 388 state->num_data, 389 &converted, 390 &converted_size, 391 true)) { 392 return NT_STATUS_NO_MEMORY; 393 } 394 395 len = MIN(len,converted_size); 396 if (len == 0) { 397 return NT_STATUS_DATA_ERROR; 398 } 399 memcpy(retpath, converted, len); 400 return NT_STATUS_OK; 401} 402 403NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname, 404 char *linkpath, size_t len) 405{ 406 TALLOC_CTX *frame = talloc_stackframe(); 407 struct event_context *ev = NULL; 408 struct tevent_req *req = NULL; 409 NTSTATUS status = NT_STATUS_OK; 410 411 if (cli_has_async_calls(cli)) { 412 /* 413 * Can't use sync call while an async call is in flight 414 */ 415 status = NT_STATUS_INVALID_PARAMETER; 416 goto fail; 417 } 418 419 ev = event_context_init(frame); 420 if (ev == NULL) { 421 status = NT_STATUS_NO_MEMORY; 422 goto fail; 423 } 424 425 /* Len is in bytes, we need it in UCS2 units. */ 426 if (2*len < len) { 427 status = NT_STATUS_INVALID_PARAMETER; 428 goto fail; 429 } 430 431 req = cli_posix_readlink_send(frame, 432 ev, 433 cli, 434 fname, 435 len); 436 if (req == NULL) { 437 status = NT_STATUS_NO_MEMORY; 438 goto fail; 439 } 440 441 if (!tevent_req_poll(req, ev)) { 442 status = map_nt_error_from_unix(errno); 443 goto fail; 444 } 445 446 status = cli_posix_readlink_recv(req, cli, linkpath, len); 447 448 fail: 449 TALLOC_FREE(frame); 450 if (!NT_STATUS_IS_OK(status)) { 451 cli_set_error(cli, status); 452 } 453 return status; 454} 455 456/**************************************************************************** 457 Hard link a file (UNIX extensions). 458****************************************************************************/ 459 460struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx, 461 struct event_context *ev, 462 struct cli_state *cli, 463 const char *oldname, 464 const char *newname) 465{ 466 return cli_posix_link_internal_send(mem_ctx, ev, cli, 467 oldname, newname, true); 468} 469 470NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req) 471{ 472 NTSTATUS status; 473 474 if (tevent_req_is_nterror(req, &status)) { 475 return status; 476 } 477 return NT_STATUS_OK; 478} 479 480NTSTATUS cli_posix_hardlink(struct cli_state *cli, 481 const char *oldname, 482 const char *newname) 483{ 484 TALLOC_CTX *frame = talloc_stackframe(); 485 struct event_context *ev = NULL; 486 struct tevent_req *req = NULL; 487 NTSTATUS status = NT_STATUS_OK; 488 489 if (cli_has_async_calls(cli)) { 490 /* 491 * Can't use sync call while an async call is in flight 492 */ 493 status = NT_STATUS_INVALID_PARAMETER; 494 goto fail; 495 } 496 497 ev = event_context_init(frame); 498 if (ev == NULL) { 499 status = NT_STATUS_NO_MEMORY; 500 goto fail; 501 } 502 503 req = cli_posix_hardlink_send(frame, 504 ev, 505 cli, 506 oldname, 507 newname); 508 if (req == NULL) { 509 status = NT_STATUS_NO_MEMORY; 510 goto fail; 511 } 512 513 if (!tevent_req_poll(req, ev)) { 514 status = map_nt_error_from_unix(errno); 515 goto fail; 516 } 517 518 status = cli_posix_hardlink_recv(req); 519 520 fail: 521 TALLOC_FREE(frame); 522 if (!NT_STATUS_IS_OK(status)) { 523 cli_set_error(cli, status); 524 } 525 return status; 526} 527 528/**************************************************************************** 529 Map standard UNIX permissions onto wire representations. 530****************************************************************************/ 531 532uint32_t unix_perms_to_wire(mode_t perms) 533{ 534 unsigned int ret = 0; 535 536 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0); 537 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0); 538 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0); 539 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0); 540 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0); 541 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0); 542 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0); 543 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0); 544 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0); 545#ifdef S_ISVTX 546 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0); 547#endif 548#ifdef S_ISGID 549 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0); 550#endif 551#ifdef S_ISUID 552 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0); 553#endif 554 return ret; 555} 556 557/**************************************************************************** 558 Map wire permissions to standard UNIX. 559****************************************************************************/ 560 561mode_t wire_perms_to_unix(uint32_t perms) 562{ 563 mode_t ret = (mode_t)0; 564 565 ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0); 566 ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0); 567 ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0); 568 ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0); 569 ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0); 570 ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0); 571 ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0); 572 ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0); 573 ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0); 574#ifdef S_ISVTX 575 ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0); 576#endif 577#ifdef S_ISGID 578 ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0); 579#endif 580#ifdef S_ISUID 581 ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0); 582#endif 583 return ret; 584} 585 586/**************************************************************************** 587 Return the file type from the wire filetype for UNIX extensions. 588****************************************************************************/ 589 590static mode_t unix_filetype_from_wire(uint32_t wire_type) 591{ 592 switch (wire_type) { 593 case UNIX_TYPE_FILE: 594 return S_IFREG; 595 case UNIX_TYPE_DIR: 596 return S_IFDIR; 597#ifdef S_IFLNK 598 case UNIX_TYPE_SYMLINK: 599 return S_IFLNK; 600#endif 601#ifdef S_IFCHR 602 case UNIX_TYPE_CHARDEV: 603 return S_IFCHR; 604#endif 605#ifdef S_IFBLK 606 case UNIX_TYPE_BLKDEV: 607 return S_IFBLK; 608#endif 609#ifdef S_IFIFO 610 case UNIX_TYPE_FIFO: 611 return S_IFIFO; 612#endif 613#ifdef S_IFSOCK 614 case UNIX_TYPE_SOCKET: 615 return S_IFSOCK; 616#endif 617 default: 618 return (mode_t)0; 619 } 620} 621 622/**************************************************************************** 623 Do a POSIX getfacl (UNIX extensions). 624****************************************************************************/ 625 626struct getfacl_state { 627 uint16_t setup; 628 uint8_t *param; 629 uint32_t num_data; 630 uint8_t *data; 631}; 632 633static void cli_posix_getfacl_done(struct tevent_req *subreq) 634{ 635 struct tevent_req *req = tevent_req_callback_data( 636 subreq, struct tevent_req); 637 struct getfacl_state *state = tevent_req_data(req, struct getfacl_state); 638 NTSTATUS status; 639 640 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, 641 &state->data, &state->num_data); 642 TALLOC_FREE(subreq); 643 if (!NT_STATUS_IS_OK(status)) { 644 tevent_req_nterror(req, status); 645 return; 646 } 647 tevent_req_done(req); 648} 649 650struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx, 651 struct event_context *ev, 652 struct cli_state *cli, 653 const char *fname) 654{ 655 struct tevent_req *req = NULL, *subreq = NULL; 656 struct link_state *state = NULL; 657 658 req = tevent_req_create(mem_ctx, &state, struct getfacl_state); 659 if (req == NULL) { 660 return NULL; 661 } 662 663 /* Setup setup word. */ 664 SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO); 665 666 /* Setup param array. */ 667 state->param = talloc_array(state, uint8_t, 6); 668 if (tevent_req_nomem(state->param, req)) { 669 return tevent_req_post(req, ev); 670 } 671 memset(state->param, '\0', 6); 672 SSVAL(state->param, 0, SMB_QUERY_POSIX_ACL); 673 674 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, 675 strlen(fname)+1, NULL); 676 677 if (tevent_req_nomem(state->param, req)) { 678 return tevent_req_post(req, ev); 679 } 680 681 subreq = cli_trans_send(state, /* mem ctx. */ 682 ev, /* event ctx. */ 683 cli, /* cli_state. */ 684 SMBtrans2, /* cmd. */ 685 NULL, /* pipe name. */ 686 -1, /* fid. */ 687 0, /* function. */ 688 0, /* flags. */ 689 &state->setup, /* setup. */ 690 1, /* num setup uint16_t words. */ 691 0, /* max returned setup. */ 692 state->param, /* param. */ 693 talloc_get_size(state->param), /* num param. */ 694 2, /* max returned param. */ 695 NULL, /* data. */ 696 0, /* num data. */ 697 cli->max_xmit); /* max returned data. */ 698 699 if (tevent_req_nomem(subreq, req)) { 700 return tevent_req_post(req, ev); 701 } 702 tevent_req_set_callback(subreq, cli_posix_getfacl_done, req); 703 return req; 704} 705 706NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req, 707 TALLOC_CTX *mem_ctx, 708 size_t *prb_size, 709 char **retbuf) 710{ 711 struct getfacl_state *state = tevent_req_data(req, struct getfacl_state); 712 NTSTATUS status; 713 714 if (tevent_req_is_nterror(req, &status)) { 715 return status; 716 } 717 *prb_size = (size_t)state->num_data; 718 *retbuf = (char *)talloc_move(mem_ctx, &state->data); 719 return NT_STATUS_OK; 720} 721 722NTSTATUS cli_posix_getfacl(struct cli_state *cli, 723 const char *fname, 724 TALLOC_CTX *mem_ctx, 725 size_t *prb_size, 726 char **retbuf) 727{ 728 TALLOC_CTX *frame = talloc_stackframe(); 729 struct event_context *ev = NULL; 730 struct tevent_req *req = NULL; 731 NTSTATUS status = NT_STATUS_OK; 732 733 if (cli_has_async_calls(cli)) { 734 /* 735 * Can't use sync call while an async call is in flight 736 */ 737 status = NT_STATUS_INVALID_PARAMETER; 738 goto fail; 739 } 740 741 ev = event_context_init(frame); 742 if (ev == NULL) { 743 status = NT_STATUS_NO_MEMORY; 744 goto fail; 745 } 746 747 req = cli_posix_getfacl_send(frame, 748 ev, 749 cli, 750 fname); 751 if (req == NULL) { 752 status = NT_STATUS_NO_MEMORY; 753 goto fail; 754 } 755 756 if (!tevent_req_poll(req, ev)) { 757 status = map_nt_error_from_unix(errno); 758 goto fail; 759 } 760 761 status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf); 762 763 fail: 764 TALLOC_FREE(frame); 765 if (!NT_STATUS_IS_OK(status)) { 766 cli_set_error(cli, status); 767 } 768 return status; 769} 770 771/**************************************************************************** 772 Stat a file (UNIX extensions). 773****************************************************************************/ 774 775struct stat_state { 776 uint16_t setup; 777 uint8_t *param; 778 uint32_t num_data; 779 uint8_t *data; 780}; 781 782static void cli_posix_stat_done(struct tevent_req *subreq) 783{ 784 struct tevent_req *req = tevent_req_callback_data( 785 subreq, struct tevent_req); 786 struct stat_state *state = tevent_req_data(req, struct stat_state); 787 NTSTATUS status; 788 789 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, 790 &state->data, &state->num_data); 791 TALLOC_FREE(subreq); 792 if (!NT_STATUS_IS_OK(status)) { 793 tevent_req_nterror(req, status); 794 return; 795 } 796 tevent_req_done(req); 797} 798 799struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx, 800 struct event_context *ev, 801 struct cli_state *cli, 802 const char *fname) 803{ 804 struct tevent_req *req = NULL, *subreq = NULL; 805 struct stat_state *state = NULL; 806 807 req = tevent_req_create(mem_ctx, &state, struct stat_state); 808 if (req == NULL) { 809 return NULL; 810 } 811 812 /* Setup setup word. */ 813 SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO); 814 815 /* Setup param array. */ 816 state->param = talloc_array(state, uint8_t, 6); 817 if (tevent_req_nomem(state->param, req)) { 818 return tevent_req_post(req, ev); 819 } 820 memset(state->param, '\0', 6); 821 SSVAL(state->param, 0, SMB_QUERY_FILE_UNIX_BASIC); 822 823 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, 824 strlen(fname)+1, NULL); 825 826 if (tevent_req_nomem(state->param, req)) { 827 return tevent_req_post(req, ev); 828 } 829 830 subreq = cli_trans_send(state, /* mem ctx. */ 831 ev, /* event ctx. */ 832 cli, /* cli_state. */ 833 SMBtrans2, /* cmd. */ 834 NULL, /* pipe name. */ 835 -1, /* fid. */ 836 0, /* function. */ 837 0, /* flags. */ 838 &state->setup, /* setup. */ 839 1, /* num setup uint16_t words. */ 840 0, /* max returned setup. */ 841 state->param, /* param. */ 842 talloc_get_size(state->param), /* num param. */ 843 2, /* max returned param. */ 844 NULL, /* data. */ 845 0, /* num data. */ 846 96); /* max returned data. */ 847 848 if (tevent_req_nomem(subreq, req)) { 849 return tevent_req_post(req, ev); 850 } 851 tevent_req_set_callback(subreq, cli_posix_stat_done, req); 852 return req; 853} 854 855NTSTATUS cli_posix_stat_recv(struct tevent_req *req, 856 SMB_STRUCT_STAT *sbuf) 857{ 858 struct stat_state *state = tevent_req_data(req, struct stat_state); 859 NTSTATUS status; 860 861 if (tevent_req_is_nterror(req, &status)) { 862 return status; 863 } 864 865 if (state->num_data != 96) { 866 return NT_STATUS_DATA_ERROR; 867 } 868 869 sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(state->data,0); /* total size, in bytes */ 870 sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(state->data,8); /* number of blocks allocated */ 871#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) 872 sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE; 873#else 874 /* assume 512 byte blocks */ 875 sbuf->st_ex_blocks /= 512; 876#endif 877 sbuf->st_ex_ctime = interpret_long_date((char *)(state->data + 16)); /* time of last change */ 878 sbuf->st_ex_atime = interpret_long_date((char *)(state->data + 24)); /* time of last access */ 879 sbuf->st_ex_mtime = interpret_long_date((char *)(state->data + 32)); /* time of last modification */ 880 881 sbuf->st_ex_uid = (uid_t) IVAL(state->data,40); /* user ID of owner */ 882 sbuf->st_ex_gid = (gid_t) IVAL(state->data,48); /* group ID of owner */ 883 sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(state->data, 56)); 884#if defined(HAVE_MAKEDEV) 885 { 886 uint32_t dev_major = IVAL(state->data,60); 887 uint32_t dev_minor = IVAL(state->data,68); 888 sbuf->st_ex_rdev = makedev(dev_major, dev_minor); 889 } 890#endif 891 sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76); /* inode */ 892 sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84)); /* protection */ 893 sbuf->st_ex_nlink = IVAL(state->data,92); /* number of hard links */ 894 895 return NT_STATUS_OK; 896} 897 898NTSTATUS cli_posix_stat(struct cli_state *cli, 899 const char *fname, 900 SMB_STRUCT_STAT *sbuf) 901{ 902 TALLOC_CTX *frame = talloc_stackframe(); 903 struct event_context *ev = NULL; 904 struct tevent_req *req = NULL; 905 NTSTATUS status = NT_STATUS_OK; 906 907 if (cli_has_async_calls(cli)) { 908 /* 909 * Can't use sync call while an async call is in flight 910 */ 911 status = NT_STATUS_INVALID_PARAMETER; 912 goto fail; 913 } 914 915 ev = event_context_init(frame); 916 if (ev == NULL) { 917 status = NT_STATUS_NO_MEMORY; 918 goto fail; 919 } 920 921 req = cli_posix_stat_send(frame, 922 ev, 923 cli, 924 fname); 925 if (req == NULL) { 926 status = NT_STATUS_NO_MEMORY; 927 goto fail; 928 } 929 930 if (!tevent_req_poll(req, ev)) { 931 status = map_nt_error_from_unix(errno); 932 goto fail; 933 } 934 935 status = cli_posix_stat_recv(req, sbuf); 936 937 fail: 938 TALLOC_FREE(frame); 939 if (!NT_STATUS_IS_OK(status)) { 940 cli_set_error(cli, status); 941 } 942 return status; 943} 944 945/**************************************************************************** 946 Chmod or chown a file internal (UNIX extensions). 947****************************************************************************/ 948 949struct ch_state { 950 uint16_t setup; 951 uint8_t *param; 952 uint8_t *data; 953}; 954 955static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq) 956{ 957 struct tevent_req *req = tevent_req_callback_data( 958 subreq, struct tevent_req); 959 struct ch_state *state = tevent_req_data(req, struct ch_state); 960 NTSTATUS status; 961 962 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); 963 TALLOC_FREE(subreq); 964 if (!NT_STATUS_IS_OK(status)) { 965 tevent_req_nterror(req, status); 966 return; 967 } 968 tevent_req_done(req); 969} 970 971static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx, 972 struct event_context *ev, 973 struct cli_state *cli, 974 const char *fname, 975 uint32_t mode, 976 uint32_t uid, 977 uint32_t gid) 978{ 979 struct tevent_req *req = NULL, *subreq = NULL; 980 struct ch_state *state = NULL; 981 982 req = tevent_req_create(mem_ctx, &state, struct ch_state); 983 if (req == NULL) { 984 return NULL; 985 } 986 987 /* Setup setup word. */ 988 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO); 989 990 /* Setup param array. */ 991 state->param = talloc_array(state, uint8_t, 6); 992 if (tevent_req_nomem(state->param, req)) { 993 return tevent_req_post(req, ev); 994 } 995 memset(state->param, '\0', 6); 996 SSVAL(state->param,0,SMB_SET_FILE_UNIX_BASIC); 997 998 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, 999 strlen(fname)+1, NULL); 1000 1001 if (tevent_req_nomem(state->param, req)) { 1002 return tevent_req_post(req, ev); 1003 } 1004 1005 /* Setup data array. */ 1006 state->data = talloc_array(state, uint8_t, 100); 1007 if (tevent_req_nomem(state->data, req)) { 1008 return tevent_req_post(req, ev); 1009 } 1010 memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */ 1011 memset(&state->data[40], '\0', 60); 1012 SIVAL(state->data,40,uid); 1013 SIVAL(state->data,48,gid); 1014 SIVAL(state->data,84,mode); 1015 1016 subreq = cli_trans_send(state, /* mem ctx. */ 1017 ev, /* event ctx. */ 1018 cli, /* cli_state. */ 1019 SMBtrans2, /* cmd. */ 1020 NULL, /* pipe name. */ 1021 -1, /* fid. */ 1022 0, /* function. */ 1023 0, /* flags. */ 1024 &state->setup, /* setup. */ 1025 1, /* num setup uint16_t words. */ 1026 0, /* max returned setup. */ 1027 state->param, /* param. */ 1028 talloc_get_size(state->param), /* num param. */ 1029 2, /* max returned param. */ 1030 state->data, /* data. */ 1031 talloc_get_size(state->data), /* num data. */ 1032 0); /* max returned data. */ 1033 1034 if (tevent_req_nomem(subreq, req)) { 1035 return tevent_req_post(req, ev); 1036 } 1037 tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done, req); 1038 return req; 1039} 1040 1041/**************************************************************************** 1042 chmod a file (UNIX extensions). 1043****************************************************************************/ 1044 1045struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx, 1046 struct event_context *ev, 1047 struct cli_state *cli, 1048 const char *fname, 1049 mode_t mode) 1050{ 1051 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli, 1052 fname, 1053 unix_perms_to_wire(mode), 1054 SMB_UID_NO_CHANGE, 1055 SMB_GID_NO_CHANGE); 1056} 1057 1058NTSTATUS cli_posix_chmod_recv(struct tevent_req *req) 1059{ 1060 NTSTATUS status; 1061 1062 if (tevent_req_is_nterror(req, &status)) { 1063 return status; 1064 } 1065 return NT_STATUS_OK; 1066} 1067 1068NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode) 1069{ 1070 TALLOC_CTX *frame = talloc_stackframe(); 1071 struct event_context *ev = NULL; 1072 struct tevent_req *req = NULL; 1073 NTSTATUS status = NT_STATUS_OK; 1074 1075 if (cli_has_async_calls(cli)) { 1076 /* 1077 * Can't use sync call while an async call is in flight 1078 */ 1079 status = NT_STATUS_INVALID_PARAMETER; 1080 goto fail; 1081 } 1082 1083 ev = event_context_init(frame); 1084 if (ev == NULL) { 1085 status = NT_STATUS_NO_MEMORY; 1086 goto fail; 1087 } 1088 1089 req = cli_posix_chmod_send(frame, 1090 ev, 1091 cli, 1092 fname, 1093 mode); 1094 if (req == NULL) { 1095 status = NT_STATUS_NO_MEMORY; 1096 goto fail; 1097 } 1098 1099 if (!tevent_req_poll(req, ev)) { 1100 status = map_nt_error_from_unix(errno); 1101 goto fail; 1102 } 1103 1104 status = cli_posix_chmod_recv(req); 1105 1106 fail: 1107 TALLOC_FREE(frame); 1108 if (!NT_STATUS_IS_OK(status)) { 1109 cli_set_error(cli, status); 1110 } 1111 return status; 1112} 1113 1114/**************************************************************************** 1115 chown a file (UNIX extensions). 1116****************************************************************************/ 1117 1118struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx, 1119 struct event_context *ev, 1120 struct cli_state *cli, 1121 const char *fname, 1122 uid_t uid, 1123 gid_t gid) 1124{ 1125 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli, 1126 fname, 1127 SMB_MODE_NO_CHANGE, 1128 (uint32_t)uid, 1129 (uint32_t)gid); 1130} 1131 1132NTSTATUS cli_posix_chown_recv(struct tevent_req *req) 1133{ 1134 NTSTATUS status; 1135 1136 if (tevent_req_is_nterror(req, &status)) { 1137 return status; 1138 } 1139 return NT_STATUS_OK; 1140} 1141 1142NTSTATUS cli_posix_chown(struct cli_state *cli, 1143 const char *fname, 1144 uid_t uid, 1145 gid_t gid) 1146{ 1147 TALLOC_CTX *frame = talloc_stackframe(); 1148 struct event_context *ev = NULL; 1149 struct tevent_req *req = NULL; 1150 NTSTATUS status = NT_STATUS_OK; 1151 1152 if (cli_has_async_calls(cli)) { 1153 /* 1154 * Can't use sync call while an async call is in flight 1155 */ 1156 status = NT_STATUS_INVALID_PARAMETER; 1157 goto fail; 1158 } 1159 1160 ev = event_context_init(frame); 1161 if (ev == NULL) { 1162 status = NT_STATUS_NO_MEMORY; 1163 goto fail; 1164 } 1165 1166 req = cli_posix_chown_send(frame, 1167 ev, 1168 cli, 1169 fname, 1170 uid, 1171 gid); 1172 if (req == NULL) { 1173 status = NT_STATUS_NO_MEMORY; 1174 goto fail; 1175 } 1176 1177 if (!tevent_req_poll(req, ev)) { 1178 status = map_nt_error_from_unix(errno); 1179 goto fail; 1180 } 1181 1182 status = cli_posix_chown_recv(req); 1183 1184 fail: 1185 TALLOC_FREE(frame); 1186 if (!NT_STATUS_IS_OK(status)) { 1187 cli_set_error(cli, status); 1188 } 1189 return status; 1190} 1191 1192/**************************************************************************** 1193 Rename a file. 1194****************************************************************************/ 1195 1196static void cli_rename_done(struct tevent_req *subreq); 1197 1198struct cli_rename_state { 1199 uint16_t vwv[1]; 1200}; 1201 1202struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx, 1203 struct event_context *ev, 1204 struct cli_state *cli, 1205 const char *fname_src, 1206 const char *fname_dst) 1207{ 1208 struct tevent_req *req = NULL, *subreq = NULL; 1209 struct cli_rename_state *state = NULL; 1210 uint8_t additional_flags = 0; 1211 uint8_t *bytes = NULL; 1212 1213 req = tevent_req_create(mem_ctx, &state, struct cli_rename_state); 1214 if (req == NULL) { 1215 return NULL; 1216 } 1217 1218 SSVAL(state->vwv+0, 0, aSYSTEM | aHIDDEN | aDIR); 1219 1220 bytes = talloc_array(state, uint8_t, 1); 1221 if (tevent_req_nomem(bytes, req)) { 1222 return tevent_req_post(req, ev); 1223 } 1224 bytes[0] = 4; 1225 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src, 1226 strlen(fname_src)+1, NULL); 1227 if (tevent_req_nomem(bytes, req)) { 1228 return tevent_req_post(req, ev); 1229 } 1230 1231 bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t, 1232 talloc_get_size(bytes)+1); 1233 if (tevent_req_nomem(bytes, req)) { 1234 return tevent_req_post(req, ev); 1235 } 1236 1237 bytes[talloc_get_size(bytes)-1] = 4; 1238 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst, 1239 strlen(fname_dst)+1, NULL); 1240 if (tevent_req_nomem(bytes, req)) { 1241 return tevent_req_post(req, ev); 1242 } 1243 1244 subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags, 1245 1, state->vwv, talloc_get_size(bytes), bytes); 1246 if (tevent_req_nomem(subreq, req)) { 1247 return tevent_req_post(req, ev); 1248 } 1249 tevent_req_set_callback(subreq, cli_rename_done, req); 1250 return req; 1251} 1252 1253static void cli_rename_done(struct tevent_req *subreq) 1254{ 1255 struct tevent_req *req = tevent_req_callback_data( 1256 subreq, struct tevent_req); 1257 NTSTATUS status; 1258 1259 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 1260 TALLOC_FREE(subreq); 1261 if (!NT_STATUS_IS_OK(status)) { 1262 tevent_req_nterror(req, status); 1263 return; 1264 } 1265 tevent_req_done(req); 1266} 1267 1268NTSTATUS cli_rename_recv(struct tevent_req *req) 1269{ 1270 return tevent_req_simple_recv_ntstatus(req); 1271} 1272 1273NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst) 1274{ 1275 TALLOC_CTX *frame = talloc_stackframe(); 1276 struct event_context *ev; 1277 struct tevent_req *req; 1278 NTSTATUS status = NT_STATUS_OK; 1279 1280 if (cli_has_async_calls(cli)) { 1281 /* 1282 * Can't use sync call while an async call is in flight 1283 */ 1284 status = NT_STATUS_INVALID_PARAMETER; 1285 goto fail; 1286 } 1287 1288 ev = event_context_init(frame); 1289 if (ev == NULL) { 1290 status = NT_STATUS_NO_MEMORY; 1291 goto fail; 1292 } 1293 1294 req = cli_rename_send(frame, ev, cli, fname_src, fname_dst); 1295 if (req == NULL) { 1296 status = NT_STATUS_NO_MEMORY; 1297 goto fail; 1298 } 1299 1300 if (!tevent_req_poll(req, ev)) { 1301 status = map_nt_error_from_unix(errno); 1302 goto fail; 1303 } 1304 1305 status = cli_rename_recv(req); 1306 1307 fail: 1308 TALLOC_FREE(frame); 1309 if (!NT_STATUS_IS_OK(status)) { 1310 cli_set_error(cli, status); 1311 } 1312 return status; 1313} 1314 1315/**************************************************************************** 1316 NT Rename a file. 1317****************************************************************************/ 1318 1319static void cli_ntrename_internal_done(struct tevent_req *subreq); 1320 1321struct cli_ntrename_internal_state { 1322 uint16_t vwv[4]; 1323}; 1324 1325static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx, 1326 struct event_context *ev, 1327 struct cli_state *cli, 1328 const char *fname_src, 1329 const char *fname_dst, 1330 uint16_t rename_flag) 1331{ 1332 struct tevent_req *req = NULL, *subreq = NULL; 1333 struct cli_ntrename_internal_state *state = NULL; 1334 uint8_t additional_flags = 0; 1335 uint8_t *bytes = NULL; 1336 1337 req = tevent_req_create(mem_ctx, &state, 1338 struct cli_ntrename_internal_state); 1339 if (req == NULL) { 1340 return NULL; 1341 } 1342 1343 SSVAL(state->vwv+0, 0 ,aSYSTEM | aHIDDEN | aDIR); 1344 SSVAL(state->vwv+1, 0, rename_flag); 1345 1346 bytes = talloc_array(state, uint8_t, 1); 1347 if (tevent_req_nomem(bytes, req)) { 1348 return tevent_req_post(req, ev); 1349 } 1350 bytes[0] = 4; 1351 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src, 1352 strlen(fname_src)+1, NULL); 1353 if (tevent_req_nomem(bytes, req)) { 1354 return tevent_req_post(req, ev); 1355 } 1356 1357 bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t, 1358 talloc_get_size(bytes)+1); 1359 if (tevent_req_nomem(bytes, req)) { 1360 return tevent_req_post(req, ev); 1361 } 1362 1363 bytes[talloc_get_size(bytes)-1] = 4; 1364 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst, 1365 strlen(fname_dst)+1, NULL); 1366 if (tevent_req_nomem(bytes, req)) { 1367 return tevent_req_post(req, ev); 1368 } 1369 1370 subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags, 1371 4, state->vwv, talloc_get_size(bytes), bytes); 1372 if (tevent_req_nomem(subreq, req)) { 1373 return tevent_req_post(req, ev); 1374 } 1375 tevent_req_set_callback(subreq, cli_ntrename_internal_done, req); 1376 return req; 1377} 1378 1379static void cli_ntrename_internal_done(struct tevent_req *subreq) 1380{ 1381 struct tevent_req *req = tevent_req_callback_data( 1382 subreq, struct tevent_req); 1383 NTSTATUS status; 1384 1385 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 1386 TALLOC_FREE(subreq); 1387 if (!NT_STATUS_IS_OK(status)) { 1388 tevent_req_nterror(req, status); 1389 return; 1390 } 1391 tevent_req_done(req); 1392} 1393 1394static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req) 1395{ 1396 return tevent_req_simple_recv_ntstatus(req); 1397} 1398 1399struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx, 1400 struct event_context *ev, 1401 struct cli_state *cli, 1402 const char *fname_src, 1403 const char *fname_dst) 1404{ 1405 return cli_ntrename_internal_send(mem_ctx, 1406 ev, 1407 cli, 1408 fname_src, 1409 fname_dst, 1410 RENAME_FLAG_RENAME); 1411} 1412 1413NTSTATUS cli_ntrename_recv(struct tevent_req *req) 1414{ 1415 return cli_ntrename_internal_recv(req); 1416} 1417 1418NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst) 1419{ 1420 TALLOC_CTX *frame = talloc_stackframe(); 1421 struct event_context *ev; 1422 struct tevent_req *req; 1423 NTSTATUS status = NT_STATUS_OK; 1424 1425 if (cli_has_async_calls(cli)) { 1426 /* 1427 * Can't use sync call while an async call is in flight 1428 */ 1429 status = NT_STATUS_INVALID_PARAMETER; 1430 goto fail; 1431 } 1432 1433 ev = event_context_init(frame); 1434 if (ev == NULL) { 1435 status = NT_STATUS_NO_MEMORY; 1436 goto fail; 1437 } 1438 1439 req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst); 1440 if (req == NULL) { 1441 status = NT_STATUS_NO_MEMORY; 1442 goto fail; 1443 } 1444 1445 if (!tevent_req_poll(req, ev)) { 1446 status = map_nt_error_from_unix(errno); 1447 goto fail; 1448 } 1449 1450 status = cli_ntrename_recv(req); 1451 1452 fail: 1453 TALLOC_FREE(frame); 1454 if (!NT_STATUS_IS_OK(status)) { 1455 cli_set_error(cli, status); 1456 } 1457 return status; 1458} 1459 1460/**************************************************************************** 1461 NT hardlink a file. 1462****************************************************************************/ 1463 1464struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx, 1465 struct event_context *ev, 1466 struct cli_state *cli, 1467 const char *fname_src, 1468 const char *fname_dst) 1469{ 1470 return cli_ntrename_internal_send(mem_ctx, 1471 ev, 1472 cli, 1473 fname_src, 1474 fname_dst, 1475 RENAME_FLAG_HARD_LINK); 1476} 1477 1478NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req) 1479{ 1480 return cli_ntrename_internal_recv(req); 1481} 1482 1483NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst) 1484{ 1485 TALLOC_CTX *frame = talloc_stackframe(); 1486 struct event_context *ev; 1487 struct tevent_req *req; 1488 NTSTATUS status = NT_STATUS_OK; 1489 1490 if (cli_has_async_calls(cli)) { 1491 /* 1492 * Can't use sync call while an async call is in flight 1493 */ 1494 status = NT_STATUS_INVALID_PARAMETER; 1495 goto fail; 1496 } 1497 1498 ev = event_context_init(frame); 1499 if (ev == NULL) { 1500 status = NT_STATUS_NO_MEMORY; 1501 goto fail; 1502 } 1503 1504 req = cli_nt_hardlink_send(frame, ev, cli, fname_src, fname_dst); 1505 if (req == NULL) { 1506 status = NT_STATUS_NO_MEMORY; 1507 goto fail; 1508 } 1509 1510 if (!tevent_req_poll(req, ev)) { 1511 status = map_nt_error_from_unix(errno); 1512 goto fail; 1513 } 1514 1515 status = cli_nt_hardlink_recv(req); 1516 1517 fail: 1518 TALLOC_FREE(frame); 1519 if (!NT_STATUS_IS_OK(status)) { 1520 cli_set_error(cli, status); 1521 } 1522 return status; 1523} 1524 1525/**************************************************************************** 1526 Delete a file. 1527****************************************************************************/ 1528 1529static void cli_unlink_done(struct tevent_req *subreq); 1530 1531struct cli_unlink_state { 1532 uint16_t vwv[1]; 1533}; 1534 1535struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx, 1536 struct event_context *ev, 1537 struct cli_state *cli, 1538 const char *fname, 1539 uint16_t mayhave_attrs) 1540{ 1541 struct tevent_req *req = NULL, *subreq = NULL; 1542 struct cli_unlink_state *state = NULL; 1543 uint8_t additional_flags = 0; 1544 uint8_t *bytes = NULL; 1545 1546 req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state); 1547 if (req == NULL) { 1548 return NULL; 1549 } 1550 1551 SSVAL(state->vwv+0, 0, mayhave_attrs); 1552 1553 bytes = talloc_array(state, uint8_t, 1); 1554 if (tevent_req_nomem(bytes, req)) { 1555 return tevent_req_post(req, ev); 1556 } 1557 bytes[0] = 4; 1558 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, 1559 strlen(fname)+1, NULL); 1560 1561 if (tevent_req_nomem(bytes, req)) { 1562 return tevent_req_post(req, ev); 1563 } 1564 1565 subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags, 1566 1, state->vwv, talloc_get_size(bytes), bytes); 1567 if (tevent_req_nomem(subreq, req)) { 1568 return tevent_req_post(req, ev); 1569 } 1570 tevent_req_set_callback(subreq, cli_unlink_done, req); 1571 return req; 1572} 1573 1574static void cli_unlink_done(struct tevent_req *subreq) 1575{ 1576 struct tevent_req *req = tevent_req_callback_data( 1577 subreq, struct tevent_req); 1578 NTSTATUS status; 1579 1580 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 1581 TALLOC_FREE(subreq); 1582 if (!NT_STATUS_IS_OK(status)) { 1583 tevent_req_nterror(req, status); 1584 return; 1585 } 1586 tevent_req_done(req); 1587} 1588 1589NTSTATUS cli_unlink_recv(struct tevent_req *req) 1590{ 1591 return tevent_req_simple_recv_ntstatus(req); 1592} 1593 1594NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs) 1595{ 1596 TALLOC_CTX *frame = talloc_stackframe(); 1597 struct event_context *ev; 1598 struct tevent_req *req; 1599 NTSTATUS status = NT_STATUS_OK; 1600 1601 if (cli_has_async_calls(cli)) { 1602 /* 1603 * Can't use sync call while an async call is in flight 1604 */ 1605 status = NT_STATUS_INVALID_PARAMETER; 1606 goto fail; 1607 } 1608 1609 ev = event_context_init(frame); 1610 if (ev == NULL) { 1611 status = NT_STATUS_NO_MEMORY; 1612 goto fail; 1613 } 1614 1615 req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs); 1616 if (req == NULL) { 1617 status = NT_STATUS_NO_MEMORY; 1618 goto fail; 1619 } 1620 1621 if (!tevent_req_poll(req, ev)) { 1622 status = map_nt_error_from_unix(errno); 1623 goto fail; 1624 } 1625 1626 status = cli_unlink_recv(req); 1627 1628 fail: 1629 TALLOC_FREE(frame); 1630 if (!NT_STATUS_IS_OK(status)) { 1631 cli_set_error(cli, status); 1632 } 1633 return status; 1634} 1635 1636/**************************************************************************** 1637 Create a directory. 1638****************************************************************************/ 1639 1640static void cli_mkdir_done(struct tevent_req *subreq); 1641 1642struct cli_mkdir_state { 1643 int dummy; 1644}; 1645 1646struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx, 1647 struct event_context *ev, 1648 struct cli_state *cli, 1649 const char *dname) 1650{ 1651 struct tevent_req *req = NULL, *subreq = NULL; 1652 struct cli_mkdir_state *state = NULL; 1653 uint8_t additional_flags = 0; 1654 uint8_t *bytes = NULL; 1655 1656 req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state); 1657 if (req == NULL) { 1658 return NULL; 1659 } 1660 1661 bytes = talloc_array(state, uint8_t, 1); 1662 if (tevent_req_nomem(bytes, req)) { 1663 return tevent_req_post(req, ev); 1664 } 1665 bytes[0] = 4; 1666 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname, 1667 strlen(dname)+1, NULL); 1668 1669 if (tevent_req_nomem(bytes, req)) { 1670 return tevent_req_post(req, ev); 1671 } 1672 1673 subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags, 1674 0, NULL, talloc_get_size(bytes), bytes); 1675 if (tevent_req_nomem(subreq, req)) { 1676 return tevent_req_post(req, ev); 1677 } 1678 tevent_req_set_callback(subreq, cli_mkdir_done, req); 1679 return req; 1680} 1681 1682static void cli_mkdir_done(struct tevent_req *subreq) 1683{ 1684 struct tevent_req *req = tevent_req_callback_data( 1685 subreq, struct tevent_req); 1686 NTSTATUS status; 1687 1688 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 1689 TALLOC_FREE(subreq); 1690 if (!NT_STATUS_IS_OK(status)) { 1691 tevent_req_nterror(req, status); 1692 return; 1693 } 1694 tevent_req_done(req); 1695} 1696 1697NTSTATUS cli_mkdir_recv(struct tevent_req *req) 1698{ 1699 return tevent_req_simple_recv_ntstatus(req); 1700} 1701 1702NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname) 1703{ 1704 TALLOC_CTX *frame = talloc_stackframe(); 1705 struct event_context *ev; 1706 struct tevent_req *req; 1707 NTSTATUS status = NT_STATUS_OK; 1708 1709 if (cli_has_async_calls(cli)) { 1710 /* 1711 * Can't use sync call while an async call is in flight 1712 */ 1713 status = NT_STATUS_INVALID_PARAMETER; 1714 goto fail; 1715 } 1716 1717 ev = event_context_init(frame); 1718 if (ev == NULL) { 1719 status = NT_STATUS_NO_MEMORY; 1720 goto fail; 1721 } 1722 1723 req = cli_mkdir_send(frame, ev, cli, dname); 1724 if (req == NULL) { 1725 status = NT_STATUS_NO_MEMORY; 1726 goto fail; 1727 } 1728 1729 if (!tevent_req_poll(req, ev)) { 1730 status = map_nt_error_from_unix(errno); 1731 goto fail; 1732 } 1733 1734 status = cli_mkdir_recv(req); 1735 1736 fail: 1737 TALLOC_FREE(frame); 1738 if (!NT_STATUS_IS_OK(status)) { 1739 cli_set_error(cli, status); 1740 } 1741 return status; 1742} 1743 1744/**************************************************************************** 1745 Remove a directory. 1746****************************************************************************/ 1747 1748static void cli_rmdir_done(struct tevent_req *subreq); 1749 1750struct cli_rmdir_state { 1751 int dummy; 1752}; 1753 1754struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx, 1755 struct event_context *ev, 1756 struct cli_state *cli, 1757 const char *dname) 1758{ 1759 struct tevent_req *req = NULL, *subreq = NULL; 1760 struct cli_rmdir_state *state = NULL; 1761 uint8_t additional_flags = 0; 1762 uint8_t *bytes = NULL; 1763 1764 req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state); 1765 if (req == NULL) { 1766 return NULL; 1767 } 1768 1769 bytes = talloc_array(state, uint8_t, 1); 1770 if (tevent_req_nomem(bytes, req)) { 1771 return tevent_req_post(req, ev); 1772 } 1773 bytes[0] = 4; 1774 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname, 1775 strlen(dname)+1, NULL); 1776 1777 if (tevent_req_nomem(bytes, req)) { 1778 return tevent_req_post(req, ev); 1779 } 1780 1781 subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags, 1782 0, NULL, talloc_get_size(bytes), bytes); 1783 if (tevent_req_nomem(subreq, req)) { 1784 return tevent_req_post(req, ev); 1785 } 1786 tevent_req_set_callback(subreq, cli_rmdir_done, req); 1787 return req; 1788} 1789 1790static void cli_rmdir_done(struct tevent_req *subreq) 1791{ 1792 struct tevent_req *req = tevent_req_callback_data( 1793 subreq, struct tevent_req); 1794 NTSTATUS status; 1795 1796 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 1797 TALLOC_FREE(subreq); 1798 if (!NT_STATUS_IS_OK(status)) { 1799 tevent_req_nterror(req, status); 1800 return; 1801 } 1802 tevent_req_done(req); 1803} 1804 1805NTSTATUS cli_rmdir_recv(struct tevent_req *req) 1806{ 1807 return tevent_req_simple_recv_ntstatus(req); 1808} 1809 1810NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname) 1811{ 1812 TALLOC_CTX *frame = talloc_stackframe(); 1813 struct event_context *ev; 1814 struct tevent_req *req; 1815 NTSTATUS status = NT_STATUS_OK; 1816 1817 if (cli_has_async_calls(cli)) { 1818 /* 1819 * Can't use sync call while an async call is in flight 1820 */ 1821 status = NT_STATUS_INVALID_PARAMETER; 1822 goto fail; 1823 } 1824 1825 ev = event_context_init(frame); 1826 if (ev == NULL) { 1827 status = NT_STATUS_NO_MEMORY; 1828 goto fail; 1829 } 1830 1831 req = cli_rmdir_send(frame, ev, cli, dname); 1832 if (req == NULL) { 1833 status = NT_STATUS_NO_MEMORY; 1834 goto fail; 1835 } 1836 1837 if (!tevent_req_poll(req, ev)) { 1838 status = map_nt_error_from_unix(errno); 1839 goto fail; 1840 } 1841 1842 status = cli_rmdir_recv(req); 1843 1844 fail: 1845 TALLOC_FREE(frame); 1846 if (!NT_STATUS_IS_OK(status)) { 1847 cli_set_error(cli, status); 1848 } 1849 return status; 1850} 1851 1852/**************************************************************************** 1853 Set or clear the delete on close flag. 1854****************************************************************************/ 1855 1856struct doc_state { 1857 uint16_t setup; 1858 uint8_t param[6]; 1859 uint8_t data[1]; 1860}; 1861 1862static void cli_nt_delete_on_close_done(struct tevent_req *subreq) 1863{ 1864 struct tevent_req *req = tevent_req_callback_data( 1865 subreq, struct tevent_req); 1866 struct doc_state *state = tevent_req_data(req, struct doc_state); 1867 NTSTATUS status; 1868 1869 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); 1870 TALLOC_FREE(subreq); 1871 if (!NT_STATUS_IS_OK(status)) { 1872 tevent_req_nterror(req, status); 1873 return; 1874 } 1875 tevent_req_done(req); 1876} 1877 1878struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx, 1879 struct event_context *ev, 1880 struct cli_state *cli, 1881 uint16_t fnum, 1882 bool flag) 1883{ 1884 struct tevent_req *req = NULL, *subreq = NULL; 1885 struct doc_state *state = NULL; 1886 1887 req = tevent_req_create(mem_ctx, &state, struct doc_state); 1888 if (req == NULL) { 1889 return NULL; 1890 } 1891 1892 /* Setup setup word. */ 1893 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); 1894 1895 /* Setup param array. */ 1896 SSVAL(state->param,0,fnum); 1897 SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO); 1898 1899 /* Setup data array. */ 1900 SCVAL(&state->data[0], 0, flag ? 1 : 0); 1901 1902 subreq = cli_trans_send(state, /* mem ctx. */ 1903 ev, /* event ctx. */ 1904 cli, /* cli_state. */ 1905 SMBtrans2, /* cmd. */ 1906 NULL, /* pipe name. */ 1907 -1, /* fid. */ 1908 0, /* function. */ 1909 0, /* flags. */ 1910 &state->setup, /* setup. */ 1911 1, /* num setup uint16_t words. */ 1912 0, /* max returned setup. */ 1913 state->param, /* param. */ 1914 6, /* num param. */ 1915 2, /* max returned param. */ 1916 state->data, /* data. */ 1917 1, /* num data. */ 1918 0); /* max returned data. */ 1919 1920 if (tevent_req_nomem(subreq, req)) { 1921 return tevent_req_post(req, ev); 1922 } 1923 tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req); 1924 return req; 1925} 1926 1927NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req) 1928{ 1929 NTSTATUS status; 1930 1931 if (tevent_req_is_nterror(req, &status)) { 1932 return status; 1933 } 1934 return NT_STATUS_OK; 1935} 1936 1937NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag) 1938{ 1939 TALLOC_CTX *frame = talloc_stackframe(); 1940 struct event_context *ev = NULL; 1941 struct tevent_req *req = NULL; 1942 NTSTATUS status = NT_STATUS_OK; 1943 1944 if (cli_has_async_calls(cli)) { 1945 /* 1946 * Can't use sync call while an async call is in flight 1947 */ 1948 status = NT_STATUS_INVALID_PARAMETER; 1949 goto fail; 1950 } 1951 1952 ev = event_context_init(frame); 1953 if (ev == NULL) { 1954 status = NT_STATUS_NO_MEMORY; 1955 goto fail; 1956 } 1957 1958 req = cli_nt_delete_on_close_send(frame, 1959 ev, 1960 cli, 1961 fnum, 1962 flag); 1963 if (req == NULL) { 1964 status = NT_STATUS_NO_MEMORY; 1965 goto fail; 1966 } 1967 1968 if (!tevent_req_poll(req, ev)) { 1969 status = map_nt_error_from_unix(errno); 1970 goto fail; 1971 } 1972 1973 status = cli_nt_delete_on_close_recv(req); 1974 1975 fail: 1976 TALLOC_FREE(frame); 1977 if (!NT_STATUS_IS_OK(status)) { 1978 cli_set_error(cli, status); 1979 } 1980 return status; 1981} 1982 1983struct cli_ntcreate_state { 1984 uint16_t vwv[24]; 1985 uint16_t fnum; 1986}; 1987 1988static void cli_ntcreate_done(struct tevent_req *subreq); 1989 1990struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, 1991 struct event_context *ev, 1992 struct cli_state *cli, 1993 const char *fname, 1994 uint32_t CreatFlags, 1995 uint32_t DesiredAccess, 1996 uint32_t FileAttributes, 1997 uint32_t ShareAccess, 1998 uint32_t CreateDisposition, 1999 uint32_t CreateOptions, 2000 uint8_t SecurityFlags) 2001{ 2002 struct tevent_req *req, *subreq; 2003 struct cli_ntcreate_state *state; 2004 uint16_t *vwv; 2005 uint8_t *bytes; 2006 size_t converted_len; 2007 2008 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state); 2009 if (req == NULL) { 2010 return NULL; 2011 } 2012 2013 vwv = state->vwv; 2014 2015 SCVAL(vwv+0, 0, 0xFF); 2016 SCVAL(vwv+0, 1, 0); 2017 SSVAL(vwv+1, 0, 0); 2018 SCVAL(vwv+2, 0, 0); 2019 2020 if (cli->use_oplocks) { 2021 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); 2022 } 2023 SIVAL(vwv+3, 1, CreatFlags); 2024 SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */ 2025 SIVAL(vwv+7, 1, DesiredAccess); 2026 SIVAL(vwv+9, 1, 0x0); /* AllocationSize */ 2027 SIVAL(vwv+11, 1, 0x0); /* AllocationSize */ 2028 SIVAL(vwv+13, 1, FileAttributes); 2029 SIVAL(vwv+15, 1, ShareAccess); 2030 SIVAL(vwv+17, 1, CreateDisposition); 2031 SIVAL(vwv+19, 1, CreateOptions); 2032 SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */ 2033 SCVAL(vwv+23, 1, SecurityFlags); 2034 2035 bytes = talloc_array(state, uint8_t, 0); 2036 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), 2037 fname, strlen(fname)+1, 2038 &converted_len); 2039 2040 /* sigh. this copes with broken netapp filer behaviour */ 2041 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL); 2042 2043 if (tevent_req_nomem(bytes, req)) { 2044 return tevent_req_post(req, ev); 2045 } 2046 2047 SSVAL(vwv+2, 1, converted_len); 2048 2049 subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv, 2050 talloc_get_size(bytes), bytes); 2051 if (tevent_req_nomem(subreq, req)) { 2052 return tevent_req_post(req, ev); 2053 } 2054 tevent_req_set_callback(subreq, cli_ntcreate_done, req); 2055 return req; 2056} 2057 2058static void cli_ntcreate_done(struct tevent_req *subreq) 2059{ 2060 struct tevent_req *req = tevent_req_callback_data( 2061 subreq, struct tevent_req); 2062 struct cli_ntcreate_state *state = tevent_req_data( 2063 req, struct cli_ntcreate_state); 2064 uint8_t wct; 2065 uint16_t *vwv; 2066 uint32_t num_bytes; 2067 uint8_t *bytes; 2068 NTSTATUS status; 2069 2070 status = cli_smb_recv(subreq, 3, &wct, &vwv, &num_bytes, &bytes); 2071 if (!NT_STATUS_IS_OK(status)) { 2072 TALLOC_FREE(subreq); 2073 tevent_req_nterror(req, status); 2074 return; 2075 } 2076 state->fnum = SVAL(vwv+2, 1); 2077 tevent_req_done(req); 2078} 2079 2080NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum) 2081{ 2082 struct cli_ntcreate_state *state = tevent_req_data( 2083 req, struct cli_ntcreate_state); 2084 NTSTATUS status; 2085 2086 if (tevent_req_is_nterror(req, &status)) { 2087 return status; 2088 } 2089 *pfnum = state->fnum; 2090 return NT_STATUS_OK; 2091} 2092 2093NTSTATUS cli_ntcreate(struct cli_state *cli, 2094 const char *fname, 2095 uint32_t CreatFlags, 2096 uint32_t DesiredAccess, 2097 uint32_t FileAttributes, 2098 uint32_t ShareAccess, 2099 uint32_t CreateDisposition, 2100 uint32_t CreateOptions, 2101 uint8_t SecurityFlags, 2102 uint16_t *pfid) 2103{ 2104 TALLOC_CTX *frame = talloc_stackframe(); 2105 struct event_context *ev; 2106 struct tevent_req *req; 2107 NTSTATUS status = NT_STATUS_OK; 2108 2109 if (cli_has_async_calls(cli)) { 2110 /* 2111 * Can't use sync call while an async call is in flight 2112 */ 2113 status = NT_STATUS_INVALID_PARAMETER; 2114 goto fail; 2115 } 2116 2117 ev = event_context_init(frame); 2118 if (ev == NULL) { 2119 status = NT_STATUS_NO_MEMORY; 2120 goto fail; 2121 } 2122 2123 req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags, 2124 DesiredAccess, FileAttributes, ShareAccess, 2125 CreateDisposition, CreateOptions, 2126 SecurityFlags); 2127 if (req == NULL) { 2128 status = NT_STATUS_NO_MEMORY; 2129 goto fail; 2130 } 2131 2132 if (!tevent_req_poll(req, ev)) { 2133 status = map_nt_error_from_unix(errno); 2134 goto fail; 2135 } 2136 2137 status = cli_ntcreate_recv(req, pfid); 2138 fail: 2139 TALLOC_FREE(frame); 2140 if (!NT_STATUS_IS_OK(status)) { 2141 cli_set_error(cli, status); 2142 } 2143 return status; 2144} 2145 2146/**************************************************************************** 2147 Open a file 2148 WARNING: if you open with O_WRONLY then getattrE won't work! 2149****************************************************************************/ 2150 2151struct cli_open_state { 2152 struct tevent_context *ev; 2153 struct cli_state *cli; 2154 const char *fname; 2155 uint16_t vwv[15]; 2156 uint16_t fnum; 2157 unsigned openfn; 2158 unsigned dos_deny; 2159 uint8_t additional_flags; 2160 struct iovec bytes; 2161}; 2162 2163static void cli_open_done(struct tevent_req *subreq); 2164static void cli_open_ntcreate_done(struct tevent_req *subreq); 2165 2166struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx, 2167 struct event_context *ev, 2168 struct cli_state *cli, const char *fname, 2169 int flags, int share_mode, 2170 struct tevent_req **psmbreq) 2171{ 2172 struct tevent_req *req, *subreq; 2173 struct cli_open_state *state; 2174 uint8_t *bytes; 2175 2176 req = tevent_req_create(mem_ctx, &state, struct cli_open_state); 2177 if (req == NULL) { 2178 return NULL; 2179 } 2180 state->ev = ev; 2181 state->cli = cli; 2182 state->fname = fname; 2183 2184 if (flags & O_CREAT) { 2185 state->openfn |= (1<<4); 2186 } 2187 if (!(flags & O_EXCL)) { 2188 if (flags & O_TRUNC) 2189 state->openfn |= (1<<1); 2190 else 2191 state->openfn |= (1<<0); 2192 } 2193 2194 state->dos_deny = (share_mode<<4); 2195 2196 if ((flags & O_ACCMODE) == O_RDWR) { 2197 state->dos_deny |= 2; 2198 } else if ((flags & O_ACCMODE) == O_WRONLY) { 2199 state->dos_deny |= 1; 2200 } 2201 2202#if defined(O_SYNC) 2203 if ((flags & O_SYNC) == O_SYNC) { 2204 state->dos_deny |= (1<<14); 2205 } 2206#endif /* O_SYNC */ 2207 2208 if (share_mode == DENY_FCB) { 2209 state->dos_deny = 0xFF; 2210 } 2211 2212 SCVAL(state->vwv + 0, 0, 0xFF); 2213 SCVAL(state->vwv + 0, 1, 0); 2214 SSVAL(state->vwv + 1, 0, 0); 2215 SSVAL(state->vwv + 2, 0, 0); /* no additional info */ 2216 SSVAL(state->vwv + 3, 0, state->dos_deny); 2217 SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN); 2218 SSVAL(state->vwv + 5, 0, 0); 2219 SIVAL(state->vwv + 6, 0, 0); 2220 SSVAL(state->vwv + 8, 0, state->openfn); 2221 SIVAL(state->vwv + 9, 0, 0); 2222 SIVAL(state->vwv + 11, 0, 0); 2223 SIVAL(state->vwv + 13, 0, 0); 2224 2225 if (cli->use_oplocks) { 2226 /* if using oplocks then ask for a batch oplock via 2227 core and extended methods */ 2228 state->additional_flags = 2229 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK; 2230 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6); 2231 } 2232 2233 bytes = talloc_array(state, uint8_t, 0); 2234 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, 2235 strlen(fname)+1, NULL); 2236 2237 if (tevent_req_nomem(bytes, req)) { 2238 return tevent_req_post(req, ev); 2239 } 2240 2241 state->bytes.iov_base = (void *)bytes; 2242 state->bytes.iov_len = talloc_get_size(bytes); 2243 2244 subreq = cli_smb_req_create(state, ev, cli, SMBopenX, 2245 state->additional_flags, 2246 15, state->vwv, 1, &state->bytes); 2247 if (subreq == NULL) { 2248 TALLOC_FREE(req); 2249 return NULL; 2250 } 2251 tevent_req_set_callback(subreq, cli_open_done, req); 2252 *psmbreq = subreq; 2253 return req; 2254} 2255 2256struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, 2257 struct cli_state *cli, const char *fname, 2258 int flags, int share_mode) 2259{ 2260 struct tevent_req *req, *subreq; 2261 NTSTATUS status; 2262 2263 req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode, 2264 &subreq); 2265 if (req == NULL) { 2266 return NULL; 2267 } 2268 2269 status = cli_smb_req_send(subreq); 2270 if (!NT_STATUS_IS_OK(status)) { 2271 tevent_req_nterror(req, status); 2272 return tevent_req_post(req, ev); 2273 } 2274 return req; 2275} 2276 2277static void cli_open_done(struct tevent_req *subreq) 2278{ 2279 struct tevent_req *req = tevent_req_callback_data( 2280 subreq, struct tevent_req); 2281 struct cli_open_state *state = tevent_req_data( 2282 req, struct cli_open_state); 2283 uint8_t wct; 2284 uint16_t *vwv; 2285 NTSTATUS status; 2286 uint32_t access_mask, share_mode, create_disposition, create_options; 2287 2288 status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL); 2289 TALLOC_FREE(subreq); 2290 2291 if (NT_STATUS_IS_OK(status)) { 2292 state->fnum = SVAL(vwv+2, 0); 2293 tevent_req_done(req); 2294 return; 2295 } 2296 2297 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { 2298 tevent_req_nterror(req, status); 2299 return; 2300 } 2301 2302 /* 2303 * For the new shiny OS/X Lion SMB server, try a ntcreate 2304 * fallback. 2305 */ 2306 2307 if (!map_open_params_to_ntcreate(state->fname, state->dos_deny, 2308 state->openfn, &access_mask, 2309 &share_mode, &create_disposition, 2310 &create_options)) { 2311 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); 2312 return; 2313 } 2314 2315 subreq = cli_ntcreate_send(state, state->ev, state->cli, 2316 state->fname, 0, access_mask, 2317 0, share_mode, create_disposition, 2318 create_options, 0); 2319 if (tevent_req_nomem(subreq, req)) { 2320 return; 2321 } 2322 tevent_req_set_callback(subreq, cli_open_ntcreate_done, req); 2323} 2324 2325static void cli_open_ntcreate_done(struct tevent_req *subreq) 2326{ 2327 struct tevent_req *req = tevent_req_callback_data( 2328 subreq, struct tevent_req); 2329 struct cli_open_state *state = tevent_req_data( 2330 req, struct cli_open_state); 2331 NTSTATUS status; 2332 2333 status = cli_ntcreate_recv(subreq, &state->fnum); 2334 TALLOC_FREE(subreq); 2335 2336 if (!NT_STATUS_IS_OK(status)) { 2337 tevent_req_nterror(req, status); 2338 return; 2339 } 2340 tevent_req_done(req); 2341} 2342 2343NTSTATUS cli_open_recv(struct tevent_req *req, uint16_t *pfnum) 2344{ 2345 struct cli_open_state *state = tevent_req_data( 2346 req, struct cli_open_state); 2347 NTSTATUS status; 2348 2349 if (tevent_req_is_nterror(req, &status)) { 2350 return status; 2351 } 2352 *pfnum = state->fnum; 2353 return NT_STATUS_OK; 2354} 2355 2356NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags, 2357 int share_mode, uint16_t *pfnum) 2358{ 2359 TALLOC_CTX *frame = talloc_stackframe(); 2360 struct event_context *ev; 2361 struct tevent_req *req; 2362 NTSTATUS status = NT_STATUS_OK; 2363 2364 if (cli_has_async_calls(cli)) { 2365 /* 2366 * Can't use sync call while an async call is in flight 2367 */ 2368 status = NT_STATUS_INVALID_PARAMETER; 2369 goto fail; 2370 } 2371 2372 ev = event_context_init(frame); 2373 if (ev == NULL) { 2374 status = NT_STATUS_NO_MEMORY; 2375 goto fail; 2376 } 2377 2378 req = cli_open_send(frame, ev, cli, fname, flags, share_mode); 2379 if (req == NULL) { 2380 status = NT_STATUS_NO_MEMORY; 2381 goto fail; 2382 } 2383 2384 if (!tevent_req_poll(req, ev)) { 2385 status = map_nt_error_from_unix(errno); 2386 goto fail; 2387 } 2388 2389 status = cli_open_recv(req, pfnum); 2390 fail: 2391 TALLOC_FREE(frame); 2392 if (!NT_STATUS_IS_OK(status)) { 2393 cli_set_error(cli, status); 2394 } 2395 return status; 2396} 2397 2398/**************************************************************************** 2399 Close a file. 2400****************************************************************************/ 2401 2402struct cli_close_state { 2403 uint16_t vwv[3]; 2404}; 2405 2406static void cli_close_done(struct tevent_req *subreq); 2407 2408struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx, 2409 struct event_context *ev, 2410 struct cli_state *cli, 2411 uint16_t fnum, 2412 struct tevent_req **psubreq) 2413{ 2414 struct tevent_req *req, *subreq; 2415 struct cli_close_state *state; 2416 2417 req = tevent_req_create(mem_ctx, &state, struct cli_close_state); 2418 if (req == NULL) { 2419 return NULL; 2420 } 2421 2422 SSVAL(state->vwv+0, 0, fnum); 2423 SIVALS(state->vwv+1, 0, -1); 2424 2425 subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv, 2426 0, NULL); 2427 if (subreq == NULL) { 2428 TALLOC_FREE(req); 2429 return NULL; 2430 } 2431 tevent_req_set_callback(subreq, cli_close_done, req); 2432 *psubreq = subreq; 2433 return req; 2434} 2435 2436struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx, 2437 struct event_context *ev, 2438 struct cli_state *cli, 2439 uint16_t fnum) 2440{ 2441 struct tevent_req *req, *subreq; 2442 NTSTATUS status; 2443 2444 req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq); 2445 if (req == NULL) { 2446 return NULL; 2447 } 2448 2449 status = cli_smb_req_send(subreq); 2450 if (!NT_STATUS_IS_OK(status)) { 2451 tevent_req_nterror(req, status); 2452 return tevent_req_post(req, ev); 2453 } 2454 return req; 2455} 2456 2457static void cli_close_done(struct tevent_req *subreq) 2458{ 2459 struct tevent_req *req = tevent_req_callback_data( 2460 subreq, struct tevent_req); 2461 NTSTATUS status; 2462 2463 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 2464 TALLOC_FREE(subreq); 2465 if (!NT_STATUS_IS_OK(status)) { 2466 tevent_req_nterror(req, status); 2467 return; 2468 } 2469 tevent_req_done(req); 2470} 2471 2472NTSTATUS cli_close_recv(struct tevent_req *req) 2473{ 2474 return tevent_req_simple_recv_ntstatus(req); 2475} 2476 2477NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum) 2478{ 2479 TALLOC_CTX *frame = talloc_stackframe(); 2480 struct event_context *ev; 2481 struct tevent_req *req; 2482 NTSTATUS status = NT_STATUS_OK; 2483 2484 if (cli_has_async_calls(cli)) { 2485 /* 2486 * Can't use sync call while an async call is in flight 2487 */ 2488 status = NT_STATUS_INVALID_PARAMETER; 2489 goto fail; 2490 } 2491 2492 ev = event_context_init(frame); 2493 if (ev == NULL) { 2494 status = NT_STATUS_NO_MEMORY; 2495 goto fail; 2496 } 2497 2498 req = cli_close_send(frame, ev, cli, fnum); 2499 if (req == NULL) { 2500 status = NT_STATUS_NO_MEMORY; 2501 goto fail; 2502 } 2503 2504 if (!tevent_req_poll(req, ev)) { 2505 status = map_nt_error_from_unix(errno); 2506 goto fail; 2507 } 2508 2509 status = cli_close_recv(req); 2510 fail: 2511 TALLOC_FREE(frame); 2512 if (!NT_STATUS_IS_OK(status)) { 2513 cli_set_error(cli, status); 2514 } 2515 return status; 2516} 2517 2518/**************************************************************************** 2519 Truncate a file to a specified size 2520****************************************************************************/ 2521 2522struct ftrunc_state { 2523 uint16_t setup; 2524 uint8_t param[6]; 2525 uint8_t data[8]; 2526}; 2527 2528static void cli_ftruncate_done(struct tevent_req *subreq) 2529{ 2530 struct tevent_req *req = tevent_req_callback_data( 2531 subreq, struct tevent_req); 2532 struct ftrunc_state *state = tevent_req_data(req, struct ftrunc_state); 2533 NTSTATUS status; 2534 2535 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); 2536 TALLOC_FREE(subreq); 2537 if (!NT_STATUS_IS_OK(status)) { 2538 tevent_req_nterror(req, status); 2539 return; 2540 } 2541 tevent_req_done(req); 2542} 2543 2544struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx, 2545 struct event_context *ev, 2546 struct cli_state *cli, 2547 uint16_t fnum, 2548 uint64_t size) 2549{ 2550 struct tevent_req *req = NULL, *subreq = NULL; 2551 struct ftrunc_state *state = NULL; 2552 2553 req = tevent_req_create(mem_ctx, &state, struct ftrunc_state); 2554 if (req == NULL) { 2555 return NULL; 2556 } 2557 2558 /* Setup setup word. */ 2559 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); 2560 2561 /* Setup param array. */ 2562 SSVAL(state->param,0,fnum); 2563 SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO); 2564 SSVAL(state->param,4,0); 2565 2566 /* Setup data array. */ 2567 SBVAL(state->data, 0, size); 2568 2569 subreq = cli_trans_send(state, /* mem ctx. */ 2570 ev, /* event ctx. */ 2571 cli, /* cli_state. */ 2572 SMBtrans2, /* cmd. */ 2573 NULL, /* pipe name. */ 2574 -1, /* fid. */ 2575 0, /* function. */ 2576 0, /* flags. */ 2577 &state->setup, /* setup. */ 2578 1, /* num setup uint16_t words. */ 2579 0, /* max returned setup. */ 2580 state->param, /* param. */ 2581 6, /* num param. */ 2582 2, /* max returned param. */ 2583 state->data, /* data. */ 2584 8, /* num data. */ 2585 0); /* max returned data. */ 2586 2587 if (tevent_req_nomem(subreq, req)) { 2588 return tevent_req_post(req, ev); 2589 } 2590 tevent_req_set_callback(subreq, cli_ftruncate_done, req); 2591 return req; 2592} 2593 2594NTSTATUS cli_ftruncate_recv(struct tevent_req *req) 2595{ 2596 NTSTATUS status; 2597 2598 if (tevent_req_is_nterror(req, &status)) { 2599 return status; 2600 } 2601 return NT_STATUS_OK; 2602} 2603 2604NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size) 2605{ 2606 TALLOC_CTX *frame = talloc_stackframe(); 2607 struct event_context *ev = NULL; 2608 struct tevent_req *req = NULL; 2609 NTSTATUS status = NT_STATUS_OK; 2610 2611 if (cli_has_async_calls(cli)) { 2612 /* 2613 * Can't use sync call while an async call is in flight 2614 */ 2615 status = NT_STATUS_INVALID_PARAMETER; 2616 goto fail; 2617 } 2618 2619 ev = event_context_init(frame); 2620 if (ev == NULL) { 2621 status = NT_STATUS_NO_MEMORY; 2622 goto fail; 2623 } 2624 2625 req = cli_ftruncate_send(frame, 2626 ev, 2627 cli, 2628 fnum, 2629 size); 2630 if (req == NULL) { 2631 status = NT_STATUS_NO_MEMORY; 2632 goto fail; 2633 } 2634 2635 if (!tevent_req_poll(req, ev)) { 2636 status = map_nt_error_from_unix(errno); 2637 goto fail; 2638 } 2639 2640 status = cli_ftruncate_recv(req); 2641 2642 fail: 2643 TALLOC_FREE(frame); 2644 if (!NT_STATUS_IS_OK(status)) { 2645 cli_set_error(cli, status); 2646 } 2647 return status; 2648} 2649 2650/**************************************************************************** 2651 send a lock with a specified locktype 2652 this is used for testing LOCKING_ANDX_CANCEL_LOCK 2653****************************************************************************/ 2654 2655NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum, 2656 uint32_t offset, uint32_t len, 2657 int timeout, unsigned char locktype) 2658{ 2659 char *p; 2660 int saved_timeout = cli->timeout; 2661 2662 memset(cli->outbuf,'\0',smb_size); 2663 memset(cli->inbuf,'\0', smb_size); 2664 2665 cli_set_message(cli->outbuf,8,0,True); 2666 2667 SCVAL(cli->outbuf,smb_com,SMBlockingX); 2668 SSVAL(cli->outbuf,smb_tid,cli->cnum); 2669 cli_setup_packet(cli); 2670 2671 SCVAL(cli->outbuf,smb_vwv0,0xFF); 2672 SSVAL(cli->outbuf,smb_vwv2,fnum); 2673 SCVAL(cli->outbuf,smb_vwv3,locktype); 2674 SIVALS(cli->outbuf, smb_vwv4, timeout); 2675 SSVAL(cli->outbuf,smb_vwv6,0); 2676 SSVAL(cli->outbuf,smb_vwv7,1); 2677 2678 p = smb_buf(cli->outbuf); 2679 SSVAL(p, 0, cli->pid); 2680 SIVAL(p, 2, offset); 2681 SIVAL(p, 6, len); 2682 2683 p += 10; 2684 2685 cli_setup_bcc(cli, p); 2686 2687 cli_send_smb(cli); 2688 2689 if (timeout != 0) { 2690 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000); 2691 } 2692 2693 if (!cli_receive_smb(cli)) { 2694 cli->timeout = saved_timeout; 2695 return NT_STATUS_UNSUCCESSFUL; 2696 } 2697 2698 cli->timeout = saved_timeout; 2699 2700 return cli_nt_error(cli); 2701} 2702 2703/**************************************************************************** 2704 Lock a file. 2705 note that timeout is in units of 2 milliseconds 2706****************************************************************************/ 2707 2708bool cli_lock(struct cli_state *cli, uint16_t fnum, 2709 uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type) 2710{ 2711 char *p; 2712 int saved_timeout = cli->timeout; 2713 2714 memset(cli->outbuf,'\0',smb_size); 2715 memset(cli->inbuf,'\0', smb_size); 2716 2717 cli_set_message(cli->outbuf,8,0,True); 2718 2719 SCVAL(cli->outbuf,smb_com,SMBlockingX); 2720 SSVAL(cli->outbuf,smb_tid,cli->cnum); 2721 cli_setup_packet(cli); 2722 2723 SCVAL(cli->outbuf,smb_vwv0,0xFF); 2724 SSVAL(cli->outbuf,smb_vwv2,fnum); 2725 SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0)); 2726 SIVALS(cli->outbuf, smb_vwv4, timeout); 2727 SSVAL(cli->outbuf,smb_vwv6,0); 2728 SSVAL(cli->outbuf,smb_vwv7,1); 2729 2730 p = smb_buf(cli->outbuf); 2731 SSVAL(p, 0, cli->pid); 2732 SIVAL(p, 2, offset); 2733 SIVAL(p, 6, len); 2734 2735 p += 10; 2736 2737 cli_setup_bcc(cli, p); 2738 2739 cli_send_smb(cli); 2740 2741 if (timeout != 0) { 2742 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000); 2743 } 2744 2745 if (!cli_receive_smb(cli)) { 2746 cli->timeout = saved_timeout; 2747 return False; 2748 } 2749 2750 cli->timeout = saved_timeout; 2751 2752 if (cli_is_error(cli)) { 2753 return False; 2754 } 2755 2756 return True; 2757} 2758 2759/**************************************************************************** 2760 Unlock a file. 2761****************************************************************************/ 2762 2763struct cli_unlock_state { 2764 uint16_t vwv[8]; 2765 uint8_t data[10]; 2766}; 2767 2768static void cli_unlock_done(struct tevent_req *subreq); 2769 2770struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx, 2771 struct event_context *ev, 2772 struct cli_state *cli, 2773 uint16_t fnum, 2774 uint64_t offset, 2775 uint64_t len) 2776 2777{ 2778 struct tevent_req *req = NULL, *subreq = NULL; 2779 struct cli_unlock_state *state = NULL; 2780 uint8_t additional_flags = 0; 2781 2782 req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state); 2783 if (req == NULL) { 2784 return NULL; 2785 } 2786 2787 SCVAL(state->vwv+0, 0, 0xFF); 2788 SSVAL(state->vwv+2, 0, fnum); 2789 SCVAL(state->vwv+3, 0, 0); 2790 SIVALS(state->vwv+4, 0, 0); 2791 SSVAL(state->vwv+6, 0, 1); 2792 SSVAL(state->vwv+7, 0, 0); 2793 2794 SSVAL(state->data, 0, cli->pid); 2795 SIVAL(state->data, 2, offset); 2796 SIVAL(state->data, 6, len); 2797 2798 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, 2799 8, state->vwv, 10, state->data); 2800 if (tevent_req_nomem(subreq, req)) { 2801 return tevent_req_post(req, ev); 2802 } 2803 tevent_req_set_callback(subreq, cli_unlock_done, req); 2804 return req; 2805} 2806 2807static void cli_unlock_done(struct tevent_req *subreq) 2808{ 2809 struct tevent_req *req = tevent_req_callback_data( 2810 subreq, struct tevent_req); 2811 NTSTATUS status; 2812 2813 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 2814 TALLOC_FREE(subreq); 2815 if (!NT_STATUS_IS_OK(status)) { 2816 tevent_req_nterror(req, status); 2817 return; 2818 } 2819 tevent_req_done(req); 2820} 2821 2822NTSTATUS cli_unlock_recv(struct tevent_req *req) 2823{ 2824 return tevent_req_simple_recv_ntstatus(req); 2825} 2826 2827NTSTATUS cli_unlock(struct cli_state *cli, 2828 uint16_t fnum, 2829 uint32_t offset, 2830 uint32_t len) 2831{ 2832 TALLOC_CTX *frame = talloc_stackframe(); 2833 struct event_context *ev; 2834 struct tevent_req *req; 2835 NTSTATUS status = NT_STATUS_OK; 2836 2837 if (cli_has_async_calls(cli)) { 2838 /* 2839 * Can't use sync call while an async call is in flight 2840 */ 2841 status = NT_STATUS_INVALID_PARAMETER; 2842 goto fail; 2843 } 2844 2845 ev = event_context_init(frame); 2846 if (ev == NULL) { 2847 status = NT_STATUS_NO_MEMORY; 2848 goto fail; 2849 } 2850 2851 req = cli_unlock_send(frame, ev, cli, 2852 fnum, offset, len); 2853 if (req == NULL) { 2854 status = NT_STATUS_NO_MEMORY; 2855 goto fail; 2856 } 2857 2858 if (!tevent_req_poll(req, ev)) { 2859 status = map_nt_error_from_unix(errno); 2860 goto fail; 2861 } 2862 2863 status = cli_unlock_recv(req); 2864 2865 fail: 2866 TALLOC_FREE(frame); 2867 if (!NT_STATUS_IS_OK(status)) { 2868 cli_set_error(cli, status); 2869 } 2870 return status; 2871} 2872 2873/**************************************************************************** 2874 Lock a file with 64 bit offsets. 2875****************************************************************************/ 2876 2877bool cli_lock64(struct cli_state *cli, uint16_t fnum, 2878 uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type) 2879{ 2880 char *p; 2881 int saved_timeout = cli->timeout; 2882 int ltype; 2883 2884 if (! (cli->capabilities & CAP_LARGE_FILES)) { 2885 return cli_lock(cli, fnum, offset, len, timeout, lock_type); 2886 } 2887 2888 ltype = (lock_type == READ_LOCK? 1 : 0); 2889 ltype |= LOCKING_ANDX_LARGE_FILES; 2890 2891 memset(cli->outbuf,'\0',smb_size); 2892 memset(cli->inbuf,'\0', smb_size); 2893 2894 cli_set_message(cli->outbuf,8,0,True); 2895 2896 SCVAL(cli->outbuf,smb_com,SMBlockingX); 2897 SSVAL(cli->outbuf,smb_tid,cli->cnum); 2898 cli_setup_packet(cli); 2899 2900 SCVAL(cli->outbuf,smb_vwv0,0xFF); 2901 SSVAL(cli->outbuf,smb_vwv2,fnum); 2902 SCVAL(cli->outbuf,smb_vwv3,ltype); 2903 SIVALS(cli->outbuf, smb_vwv4, timeout); 2904 SSVAL(cli->outbuf,smb_vwv6,0); 2905 SSVAL(cli->outbuf,smb_vwv7,1); 2906 2907 p = smb_buf(cli->outbuf); 2908 SIVAL(p, 0, cli->pid); 2909 SOFF_T_R(p, 4, offset); 2910 SOFF_T_R(p, 12, len); 2911 p += 20; 2912 2913 cli_setup_bcc(cli, p); 2914 cli_send_smb(cli); 2915 2916 if (timeout != 0) { 2917 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000); 2918 } 2919 2920 if (!cli_receive_smb(cli)) { 2921 cli->timeout = saved_timeout; 2922 return False; 2923 } 2924 2925 cli->timeout = saved_timeout; 2926 2927 if (cli_is_error(cli)) { 2928 return False; 2929 } 2930 2931 return True; 2932} 2933 2934/**************************************************************************** 2935 Unlock a file with 64 bit offsets. 2936****************************************************************************/ 2937 2938struct cli_unlock64_state { 2939 uint16_t vwv[8]; 2940 uint8_t data[20]; 2941}; 2942 2943static void cli_unlock64_done(struct tevent_req *subreq); 2944 2945struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx, 2946 struct event_context *ev, 2947 struct cli_state *cli, 2948 uint16_t fnum, 2949 uint64_t offset, 2950 uint64_t len) 2951 2952{ 2953 struct tevent_req *req = NULL, *subreq = NULL; 2954 struct cli_unlock64_state *state = NULL; 2955 uint8_t additional_flags = 0; 2956 2957 req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state); 2958 if (req == NULL) { 2959 return NULL; 2960 } 2961 2962 SCVAL(state->vwv+0, 0, 0xff); 2963 SSVAL(state->vwv+2, 0, fnum); 2964 SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES); 2965 SIVALS(state->vwv+4, 0, 0); 2966 SSVAL(state->vwv+6, 0, 1); 2967 SSVAL(state->vwv+7, 0, 0); 2968 2969 SIVAL(state->data, 0, cli->pid); 2970 SOFF_T_R(state->data, 4, offset); 2971 SOFF_T_R(state->data, 12, len); 2972 2973 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, 2974 8, state->vwv, 20, state->data); 2975 if (tevent_req_nomem(subreq, req)) { 2976 return tevent_req_post(req, ev); 2977 } 2978 tevent_req_set_callback(subreq, cli_unlock64_done, req); 2979 return req; 2980} 2981 2982static void cli_unlock64_done(struct tevent_req *subreq) 2983{ 2984 struct tevent_req *req = tevent_req_callback_data( 2985 subreq, struct tevent_req); 2986 NTSTATUS status; 2987 2988 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 2989 TALLOC_FREE(subreq); 2990 if (!NT_STATUS_IS_OK(status)) { 2991 tevent_req_nterror(req, status); 2992 return; 2993 } 2994 tevent_req_done(req); 2995} 2996 2997NTSTATUS cli_unlock64_recv(struct tevent_req *req) 2998{ 2999 return tevent_req_simple_recv_ntstatus(req); 3000} 3001 3002NTSTATUS cli_unlock64(struct cli_state *cli, 3003 uint16_t fnum, 3004 uint64_t offset, 3005 uint64_t len) 3006{ 3007 TALLOC_CTX *frame = talloc_stackframe(); 3008 struct event_context *ev; 3009 struct tevent_req *req; 3010 NTSTATUS status = NT_STATUS_OK; 3011 3012 if (! (cli->capabilities & CAP_LARGE_FILES)) { 3013 return cli_unlock(cli, fnum, offset, len); 3014 } 3015 3016 if (cli_has_async_calls(cli)) { 3017 /* 3018 * Can't use sync call while an async call is in flight 3019 */ 3020 status = NT_STATUS_INVALID_PARAMETER; 3021 goto fail; 3022 } 3023 3024 ev = event_context_init(frame); 3025 if (ev == NULL) { 3026 status = NT_STATUS_NO_MEMORY; 3027 goto fail; 3028 } 3029 3030 req = cli_unlock64_send(frame, ev, cli, 3031 fnum, offset, len); 3032 if (req == NULL) { 3033 status = NT_STATUS_NO_MEMORY; 3034 goto fail; 3035 } 3036 3037 if (!tevent_req_poll(req, ev)) { 3038 status = map_nt_error_from_unix(errno); 3039 goto fail; 3040 } 3041 3042 status = cli_unlock64_recv(req); 3043 3044 fail: 3045 TALLOC_FREE(frame); 3046 if (!NT_STATUS_IS_OK(status)) { 3047 cli_set_error(cli, status); 3048 } 3049 return status; 3050} 3051 3052/**************************************************************************** 3053 Get/unlock a POSIX lock on a file - internal function. 3054****************************************************************************/ 3055 3056struct posix_lock_state { 3057 uint16_t setup; 3058 uint8_t param[4]; 3059 uint8_t data[POSIX_LOCK_DATA_SIZE]; 3060}; 3061 3062static void cli_posix_unlock_internal_done(struct tevent_req *subreq) 3063{ 3064 struct tevent_req *req = tevent_req_callback_data( 3065 subreq, struct tevent_req); 3066 struct posix_lock_state *state = tevent_req_data(req, struct posix_lock_state); 3067 NTSTATUS status; 3068 3069 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); 3070 TALLOC_FREE(subreq); 3071 if (!NT_STATUS_IS_OK(status)) { 3072 tevent_req_nterror(req, status); 3073 return; 3074 } 3075 tevent_req_done(req); 3076} 3077 3078static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx, 3079 struct event_context *ev, 3080 struct cli_state *cli, 3081 uint16_t fnum, 3082 uint64_t offset, 3083 uint64_t len, 3084 bool wait_lock, 3085 enum brl_type lock_type) 3086{ 3087 struct tevent_req *req = NULL, *subreq = NULL; 3088 struct posix_lock_state *state = NULL; 3089 3090 req = tevent_req_create(mem_ctx, &state, struct posix_lock_state); 3091 if (req == NULL) { 3092 return NULL; 3093 } 3094 3095 /* Setup setup word. */ 3096 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); 3097 3098 /* Setup param array. */ 3099 SSVAL(&state->param, 0, fnum); 3100 SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK); 3101 3102 /* Setup data array. */ 3103 switch (lock_type) { 3104 case READ_LOCK: 3105 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET, 3106 POSIX_LOCK_TYPE_READ); 3107 break; 3108 case WRITE_LOCK: 3109 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET, 3110 POSIX_LOCK_TYPE_WRITE); 3111 break; 3112 case UNLOCK_LOCK: 3113 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET, 3114 POSIX_LOCK_TYPE_UNLOCK); 3115 break; 3116 default: 3117 return NULL; 3118 } 3119 3120 if (wait_lock) { 3121 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET, 3122 POSIX_LOCK_FLAG_WAIT); 3123 } else { 3124 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET, 3125 POSIX_LOCK_FLAG_NOWAIT); 3126 } 3127 3128 SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli->pid); 3129 SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset); 3130 SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len); 3131 3132 subreq = cli_trans_send(state, /* mem ctx. */ 3133 ev, /* event ctx. */ 3134 cli, /* cli_state. */ 3135 SMBtrans2, /* cmd. */ 3136 NULL, /* pipe name. */ 3137 -1, /* fid. */ 3138 0, /* function. */ 3139 0, /* flags. */ 3140 &state->setup, /* setup. */ 3141 1, /* num setup uint16_t words. */ 3142 0, /* max returned setup. */ 3143 state->param, /* param. */ 3144 4, /* num param. */ 3145 2, /* max returned param. */ 3146 state->data, /* data. */ 3147 POSIX_LOCK_DATA_SIZE, /* num data. */ 3148 0); /* max returned data. */ 3149 3150 if (tevent_req_nomem(subreq, req)) { 3151 return tevent_req_post(req, ev); 3152 } 3153 tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req); 3154 return req; 3155} 3156 3157/**************************************************************************** 3158 POSIX Lock a file. 3159****************************************************************************/ 3160 3161struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx, 3162 struct event_context *ev, 3163 struct cli_state *cli, 3164 uint16_t fnum, 3165 uint64_t offset, 3166 uint64_t len, 3167 bool wait_lock, 3168 enum brl_type lock_type) 3169{ 3170 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len, 3171 wait_lock, lock_type); 3172} 3173 3174NTSTATUS cli_posix_lock_recv(struct tevent_req *req) 3175{ 3176 NTSTATUS status; 3177 3178 if (tevent_req_is_nterror(req, &status)) { 3179 return status; 3180 } 3181 return NT_STATUS_OK; 3182} 3183 3184NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum, 3185 uint64_t offset, uint64_t len, 3186 bool wait_lock, enum brl_type lock_type) 3187{ 3188 TALLOC_CTX *frame = talloc_stackframe(); 3189 struct event_context *ev = NULL; 3190 struct tevent_req *req = NULL; 3191 NTSTATUS status = NT_STATUS_OK; 3192 3193 if (cli_has_async_calls(cli)) { 3194 /* 3195 * Can't use sync call while an async call is in flight 3196 */ 3197 status = NT_STATUS_INVALID_PARAMETER; 3198 goto fail; 3199 } 3200 3201 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) { 3202 status = NT_STATUS_INVALID_PARAMETER; 3203 goto fail; 3204 } 3205 3206 ev = event_context_init(frame); 3207 if (ev == NULL) { 3208 status = NT_STATUS_NO_MEMORY; 3209 goto fail; 3210 } 3211 3212 req = cli_posix_lock_send(frame, 3213 ev, 3214 cli, 3215 fnum, 3216 offset, 3217 len, 3218 wait_lock, 3219 lock_type); 3220 if (req == NULL) { 3221 status = NT_STATUS_NO_MEMORY; 3222 goto fail; 3223 } 3224 3225 if (!tevent_req_poll(req, ev)) { 3226 status = map_nt_error_from_unix(errno); 3227 goto fail; 3228 } 3229 3230 status = cli_posix_lock_recv(req); 3231 3232 fail: 3233 TALLOC_FREE(frame); 3234 if (!NT_STATUS_IS_OK(status)) { 3235 cli_set_error(cli, status); 3236 } 3237 return status; 3238} 3239 3240/**************************************************************************** 3241 POSIX Unlock a file. 3242****************************************************************************/ 3243 3244struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx, 3245 struct event_context *ev, 3246 struct cli_state *cli, 3247 uint16_t fnum, 3248 uint64_t offset, 3249 uint64_t len) 3250{ 3251 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len, 3252 false, UNLOCK_LOCK); 3253} 3254 3255NTSTATUS cli_posix_unlock_recv(struct tevent_req *req) 3256{ 3257 NTSTATUS status; 3258 3259 if (tevent_req_is_nterror(req, &status)) { 3260 return status; 3261 } 3262 return NT_STATUS_OK; 3263} 3264 3265NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len) 3266{ 3267 TALLOC_CTX *frame = talloc_stackframe(); 3268 struct event_context *ev = NULL; 3269 struct tevent_req *req = NULL; 3270 NTSTATUS status = NT_STATUS_OK; 3271 3272 if (cli_has_async_calls(cli)) { 3273 /* 3274 * Can't use sync call while an async call is in flight 3275 */ 3276 status = NT_STATUS_INVALID_PARAMETER; 3277 goto fail; 3278 } 3279 3280 ev = event_context_init(frame); 3281 if (ev == NULL) { 3282 status = NT_STATUS_NO_MEMORY; 3283 goto fail; 3284 } 3285 3286 req = cli_posix_unlock_send(frame, 3287 ev, 3288 cli, 3289 fnum, 3290 offset, 3291 len); 3292 if (req == NULL) { 3293 status = NT_STATUS_NO_MEMORY; 3294 goto fail; 3295 } 3296 3297 if (!tevent_req_poll(req, ev)) { 3298 status = map_nt_error_from_unix(errno); 3299 goto fail; 3300 } 3301 3302 status = cli_posix_unlock_recv(req); 3303 3304 fail: 3305 TALLOC_FREE(frame); 3306 if (!NT_STATUS_IS_OK(status)) { 3307 cli_set_error(cli, status); 3308 } 3309 return status; 3310} 3311 3312/**************************************************************************** 3313 Do a SMBgetattrE call. 3314****************************************************************************/ 3315 3316static void cli_getattrE_done(struct tevent_req *subreq); 3317 3318struct cli_getattrE_state { 3319 uint16_t vwv[1]; 3320 int zone_offset; 3321 uint16_t attr; 3322 SMB_OFF_T size; 3323 time_t change_time; 3324 time_t access_time; 3325 time_t write_time; 3326}; 3327 3328struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx, 3329 struct event_context *ev, 3330 struct cli_state *cli, 3331 uint16_t fnum) 3332{ 3333 struct tevent_req *req = NULL, *subreq = NULL; 3334 struct cli_getattrE_state *state = NULL; 3335 uint8_t additional_flags = 0; 3336 3337 req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state); 3338 if (req == NULL) { 3339 return NULL; 3340 } 3341 3342 state->zone_offset = cli->serverzone; 3343 SSVAL(state->vwv+0,0,fnum); 3344 3345 subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags, 3346 1, state->vwv, 0, NULL); 3347 if (tevent_req_nomem(subreq, req)) { 3348 return tevent_req_post(req, ev); 3349 } 3350 tevent_req_set_callback(subreq, cli_getattrE_done, req); 3351 return req; 3352} 3353 3354static void cli_getattrE_done(struct tevent_req *subreq) 3355{ 3356 struct tevent_req *req = tevent_req_callback_data( 3357 subreq, struct tevent_req); 3358 struct cli_getattrE_state *state = tevent_req_data( 3359 req, struct cli_getattrE_state); 3360 uint8_t wct; 3361 uint16_t *vwv = NULL; 3362 NTSTATUS status; 3363 3364 status = cli_smb_recv(subreq, 11, &wct, &vwv, NULL, NULL); 3365 if (!NT_STATUS_IS_OK(status)) { 3366 tevent_req_nterror(req, status); 3367 return; 3368 } 3369 3370 state->size = (SMB_OFF_T)IVAL(vwv+6,0); 3371 state->attr = SVAL(vwv+10,0); 3372 state->change_time = make_unix_date2(vwv+0, state->zone_offset); 3373 state->access_time = make_unix_date2(vwv+2, state->zone_offset); 3374 state->write_time = make_unix_date2(vwv+4, state->zone_offset); 3375 3376 TALLOC_FREE(subreq); 3377 tevent_req_done(req); 3378} 3379 3380NTSTATUS cli_getattrE_recv(struct tevent_req *req, 3381 uint16_t *attr, 3382 SMB_OFF_T *size, 3383 time_t *change_time, 3384 time_t *access_time, 3385 time_t *write_time) 3386{ 3387 struct cli_getattrE_state *state = tevent_req_data( 3388 req, struct cli_getattrE_state); 3389 NTSTATUS status; 3390 3391 if (tevent_req_is_nterror(req, &status)) { 3392 return status; 3393 } 3394 if (attr) { 3395 *attr = state->attr; 3396 } 3397 if (size) { 3398 *size = state->size; 3399 } 3400 if (change_time) { 3401 *change_time = state->change_time; 3402 } 3403 if (access_time) { 3404 *access_time = state->access_time; 3405 } 3406 if (write_time) { 3407 *write_time = state->write_time; 3408 } 3409 return NT_STATUS_OK; 3410} 3411 3412NTSTATUS cli_getattrE(struct cli_state *cli, 3413 uint16_t fnum, 3414 uint16_t *attr, 3415 SMB_OFF_T *size, 3416 time_t *change_time, 3417 time_t *access_time, 3418 time_t *write_time) 3419{ 3420 TALLOC_CTX *frame = talloc_stackframe(); 3421 struct event_context *ev = NULL; 3422 struct tevent_req *req = NULL; 3423 NTSTATUS status = NT_STATUS_OK; 3424 3425 if (cli_has_async_calls(cli)) { 3426 /* 3427 * Can't use sync call while an async call is in flight 3428 */ 3429 status = NT_STATUS_INVALID_PARAMETER; 3430 goto fail; 3431 } 3432 3433 ev = event_context_init(frame); 3434 if (ev == NULL) { 3435 status = NT_STATUS_NO_MEMORY; 3436 goto fail; 3437 } 3438 3439 req = cli_getattrE_send(frame, ev, cli, fnum); 3440 if (req == NULL) { 3441 status = NT_STATUS_NO_MEMORY; 3442 goto fail; 3443 } 3444 3445 if (!tevent_req_poll(req, ev)) { 3446 status = map_nt_error_from_unix(errno); 3447 goto fail; 3448 } 3449 3450 status = cli_getattrE_recv(req, 3451 attr, 3452 size, 3453 change_time, 3454 access_time, 3455 write_time); 3456 3457 fail: 3458 TALLOC_FREE(frame); 3459 if (!NT_STATUS_IS_OK(status)) { 3460 cli_set_error(cli, status); 3461 } 3462 return status; 3463} 3464 3465/**************************************************************************** 3466 Do a SMBgetatr call 3467****************************************************************************/ 3468 3469static void cli_getatr_done(struct tevent_req *subreq); 3470 3471struct cli_getatr_state { 3472 int zone_offset; 3473 uint16_t attr; 3474 SMB_OFF_T size; 3475 time_t write_time; 3476}; 3477 3478struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx, 3479 struct event_context *ev, 3480 struct cli_state *cli, 3481 const char *fname) 3482{ 3483 struct tevent_req *req = NULL, *subreq = NULL; 3484 struct cli_getatr_state *state = NULL; 3485 uint8_t additional_flags = 0; 3486 uint8_t *bytes = NULL; 3487 3488 req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state); 3489 if (req == NULL) { 3490 return NULL; 3491 } 3492 3493 state->zone_offset = cli->serverzone; 3494 3495 bytes = talloc_array(state, uint8_t, 1); 3496 if (tevent_req_nomem(bytes, req)) { 3497 return tevent_req_post(req, ev); 3498 } 3499 bytes[0] = 4; 3500 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, 3501 strlen(fname)+1, NULL); 3502 3503 if (tevent_req_nomem(bytes, req)) { 3504 return tevent_req_post(req, ev); 3505 } 3506 3507 subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags, 3508 0, NULL, talloc_get_size(bytes), bytes); 3509 if (tevent_req_nomem(subreq, req)) { 3510 return tevent_req_post(req, ev); 3511 } 3512 tevent_req_set_callback(subreq, cli_getatr_done, req); 3513 return req; 3514} 3515 3516static void cli_getatr_done(struct tevent_req *subreq) 3517{ 3518 struct tevent_req *req = tevent_req_callback_data( 3519 subreq, struct tevent_req); 3520 struct cli_getatr_state *state = tevent_req_data( 3521 req, struct cli_getatr_state); 3522 uint8_t wct; 3523 uint16_t *vwv = NULL; 3524 NTSTATUS status; 3525 3526 status = cli_smb_recv(subreq, 4, &wct, &vwv, NULL, NULL); 3527 if (!NT_STATUS_IS_OK(status)) { 3528 tevent_req_nterror(req, status); 3529 return; 3530 } 3531 3532 state->attr = SVAL(vwv+0,0); 3533 state->size = (SMB_OFF_T)IVAL(vwv+3,0); 3534 state->write_time = make_unix_date3(vwv+1, state->zone_offset); 3535 3536 TALLOC_FREE(subreq); 3537 tevent_req_done(req); 3538} 3539 3540NTSTATUS cli_getatr_recv(struct tevent_req *req, 3541 uint16_t *attr, 3542 SMB_OFF_T *size, 3543 time_t *write_time) 3544{ 3545 struct cli_getatr_state *state = tevent_req_data( 3546 req, struct cli_getatr_state); 3547 NTSTATUS status; 3548 3549 if (tevent_req_is_nterror(req, &status)) { 3550 return status; 3551 } 3552 if (attr) { 3553 *attr = state->attr; 3554 } 3555 if (size) { 3556 *size = state->size; 3557 } 3558 if (write_time) { 3559 *write_time = state->write_time; 3560 } 3561 return NT_STATUS_OK; 3562} 3563 3564NTSTATUS cli_getatr(struct cli_state *cli, 3565 const char *fname, 3566 uint16_t *attr, 3567 SMB_OFF_T *size, 3568 time_t *write_time) 3569{ 3570 TALLOC_CTX *frame = talloc_stackframe(); 3571 struct event_context *ev = NULL; 3572 struct tevent_req *req = NULL; 3573 NTSTATUS status = NT_STATUS_OK; 3574 3575 if (cli_has_async_calls(cli)) { 3576 /* 3577 * Can't use sync call while an async call is in flight 3578 */ 3579 status = NT_STATUS_INVALID_PARAMETER; 3580 goto fail; 3581 } 3582 3583 ev = event_context_init(frame); 3584 if (ev == NULL) { 3585 status = NT_STATUS_NO_MEMORY; 3586 goto fail; 3587 } 3588 3589 req = cli_getatr_send(frame, ev, cli, fname); 3590 if (req == NULL) { 3591 status = NT_STATUS_NO_MEMORY; 3592 goto fail; 3593 } 3594 3595 if (!tevent_req_poll(req, ev)) { 3596 status = map_nt_error_from_unix(errno); 3597 goto fail; 3598 } 3599 3600 status = cli_getatr_recv(req, 3601 attr, 3602 size, 3603 write_time); 3604 3605 fail: 3606 TALLOC_FREE(frame); 3607 if (!NT_STATUS_IS_OK(status)) { 3608 cli_set_error(cli, status); 3609 } 3610 return status; 3611} 3612 3613/**************************************************************************** 3614 Do a SMBsetattrE call. 3615****************************************************************************/ 3616 3617static void cli_setattrE_done(struct tevent_req *subreq); 3618 3619struct cli_setattrE_state { 3620 uint16_t vwv[7]; 3621}; 3622 3623struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx, 3624 struct event_context *ev, 3625 struct cli_state *cli, 3626 uint16_t fnum, 3627 time_t change_time, 3628 time_t access_time, 3629 time_t write_time) 3630{ 3631 struct tevent_req *req = NULL, *subreq = NULL; 3632 struct cli_setattrE_state *state = NULL; 3633 uint8_t additional_flags = 0; 3634 3635 req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state); 3636 if (req == NULL) { 3637 return NULL; 3638 } 3639 3640 SSVAL(state->vwv+0, 0, fnum); 3641 cli_put_dos_date2(cli, (char *)&state->vwv[1], 0, change_time); 3642 cli_put_dos_date2(cli, (char *)&state->vwv[3], 0, access_time); 3643 cli_put_dos_date2(cli, (char *)&state->vwv[5], 0, write_time); 3644 3645 subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, 3646 7, state->vwv, 0, NULL); 3647 if (tevent_req_nomem(subreq, req)) { 3648 return tevent_req_post(req, ev); 3649 } 3650 tevent_req_set_callback(subreq, cli_setattrE_done, req); 3651 return req; 3652} 3653 3654static void cli_setattrE_done(struct tevent_req *subreq) 3655{ 3656 struct tevent_req *req = tevent_req_callback_data( 3657 subreq, struct tevent_req); 3658 NTSTATUS status; 3659 3660 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 3661 TALLOC_FREE(subreq); 3662 if (!NT_STATUS_IS_OK(status)) { 3663 tevent_req_nterror(req, status); 3664 return; 3665 } 3666 tevent_req_done(req); 3667} 3668 3669NTSTATUS cli_setattrE_recv(struct tevent_req *req) 3670{ 3671 return tevent_req_simple_recv_ntstatus(req); 3672} 3673 3674NTSTATUS cli_setattrE(struct cli_state *cli, 3675 uint16_t fnum, 3676 time_t change_time, 3677 time_t access_time, 3678 time_t write_time) 3679{ 3680 TALLOC_CTX *frame = talloc_stackframe(); 3681 struct event_context *ev = NULL; 3682 struct tevent_req *req = NULL; 3683 NTSTATUS status = NT_STATUS_OK; 3684 3685 if (cli_has_async_calls(cli)) { 3686 /* 3687 * Can't use sync call while an async call is in flight 3688 */ 3689 status = NT_STATUS_INVALID_PARAMETER; 3690 goto fail; 3691 } 3692 3693 ev = event_context_init(frame); 3694 if (ev == NULL) { 3695 status = NT_STATUS_NO_MEMORY; 3696 goto fail; 3697 } 3698 3699 req = cli_setattrE_send(frame, ev, 3700 cli, 3701 fnum, 3702 change_time, 3703 access_time, 3704 write_time); 3705 3706 if (req == NULL) { 3707 status = NT_STATUS_NO_MEMORY; 3708 goto fail; 3709 } 3710 3711 if (!tevent_req_poll(req, ev)) { 3712 status = map_nt_error_from_unix(errno); 3713 goto fail; 3714 } 3715 3716 status = cli_setattrE_recv(req); 3717 3718 fail: 3719 TALLOC_FREE(frame); 3720 if (!NT_STATUS_IS_OK(status)) { 3721 cli_set_error(cli, status); 3722 } 3723 return status; 3724} 3725 3726/**************************************************************************** 3727 Do a SMBsetatr call. 3728****************************************************************************/ 3729 3730static void cli_setatr_done(struct tevent_req *subreq); 3731 3732struct cli_setatr_state { 3733 uint16_t vwv[8]; 3734}; 3735 3736struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx, 3737 struct event_context *ev, 3738 struct cli_state *cli, 3739 const char *fname, 3740 uint16_t attr, 3741 time_t mtime) 3742{ 3743 struct tevent_req *req = NULL, *subreq = NULL; 3744 struct cli_setatr_state *state = NULL; 3745 uint8_t additional_flags = 0; 3746 uint8_t *bytes = NULL; 3747 3748 req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state); 3749 if (req == NULL) { 3750 return NULL; 3751 } 3752 3753 SSVAL(state->vwv+0, 0, attr); 3754 cli_put_dos_date3(cli, (char *)&state->vwv[1], 0, mtime); 3755 3756 bytes = talloc_array(state, uint8_t, 1); 3757 if (tevent_req_nomem(bytes, req)) { 3758 return tevent_req_post(req, ev); 3759 } 3760 bytes[0] = 4; 3761 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, 3762 strlen(fname)+1, NULL); 3763 if (tevent_req_nomem(bytes, req)) { 3764 return tevent_req_post(req, ev); 3765 } 3766 bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t, 3767 talloc_get_size(bytes)+1); 3768 if (tevent_req_nomem(bytes, req)) { 3769 return tevent_req_post(req, ev); 3770 } 3771 3772 bytes[talloc_get_size(bytes)-1] = 4; 3773 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 3774 1, NULL); 3775 if (tevent_req_nomem(bytes, req)) { 3776 return tevent_req_post(req, ev); 3777 } 3778 3779 subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags, 3780 8, state->vwv, talloc_get_size(bytes), bytes); 3781 if (tevent_req_nomem(subreq, req)) { 3782 return tevent_req_post(req, ev); 3783 } 3784 tevent_req_set_callback(subreq, cli_setatr_done, req); 3785 return req; 3786} 3787 3788static void cli_setatr_done(struct tevent_req *subreq) 3789{ 3790 struct tevent_req *req = tevent_req_callback_data( 3791 subreq, struct tevent_req); 3792 NTSTATUS status; 3793 3794 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 3795 TALLOC_FREE(subreq); 3796 if (!NT_STATUS_IS_OK(status)) { 3797 tevent_req_nterror(req, status); 3798 return; 3799 } 3800 tevent_req_done(req); 3801} 3802 3803NTSTATUS cli_setatr_recv(struct tevent_req *req) 3804{ 3805 return tevent_req_simple_recv_ntstatus(req); 3806} 3807 3808NTSTATUS cli_setatr(struct cli_state *cli, 3809 const char *fname, 3810 uint16_t attr, 3811 time_t mtime) 3812{ 3813 TALLOC_CTX *frame = talloc_stackframe(); 3814 struct event_context *ev = NULL; 3815 struct tevent_req *req = NULL; 3816 NTSTATUS status = NT_STATUS_OK; 3817 3818 if (cli_has_async_calls(cli)) { 3819 /* 3820 * Can't use sync call while an async call is in flight 3821 */ 3822 status = NT_STATUS_INVALID_PARAMETER; 3823 goto fail; 3824 } 3825 3826 ev = event_context_init(frame); 3827 if (ev == NULL) { 3828 status = NT_STATUS_NO_MEMORY; 3829 goto fail; 3830 } 3831 3832 req = cli_setatr_send(frame, ev, cli, fname, attr, mtime); 3833 if (req == NULL) { 3834 status = NT_STATUS_NO_MEMORY; 3835 goto fail; 3836 } 3837 3838 if (!tevent_req_poll(req, ev)) { 3839 status = map_nt_error_from_unix(errno); 3840 goto fail; 3841 } 3842 3843 status = cli_setatr_recv(req); 3844 3845 fail: 3846 TALLOC_FREE(frame); 3847 if (!NT_STATUS_IS_OK(status)) { 3848 cli_set_error(cli, status); 3849 } 3850 return status; 3851} 3852 3853/**************************************************************************** 3854 Check for existance of a dir. 3855****************************************************************************/ 3856 3857static void cli_chkpath_done(struct tevent_req *subreq); 3858 3859struct cli_chkpath_state { 3860 int dummy; 3861}; 3862 3863struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx, 3864 struct event_context *ev, 3865 struct cli_state *cli, 3866 const char *fname) 3867{ 3868 struct tevent_req *req = NULL, *subreq = NULL; 3869 struct cli_chkpath_state *state = NULL; 3870 uint8_t additional_flags = 0; 3871 uint8_t *bytes = NULL; 3872 3873 req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state); 3874 if (req == NULL) { 3875 return NULL; 3876 } 3877 3878 bytes = talloc_array(state, uint8_t, 1); 3879 if (tevent_req_nomem(bytes, req)) { 3880 return tevent_req_post(req, ev); 3881 } 3882 bytes[0] = 4; 3883 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, 3884 strlen(fname)+1, NULL); 3885 3886 if (tevent_req_nomem(bytes, req)) { 3887 return tevent_req_post(req, ev); 3888 } 3889 3890 subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags, 3891 0, NULL, talloc_get_size(bytes), bytes); 3892 if (tevent_req_nomem(subreq, req)) { 3893 return tevent_req_post(req, ev); 3894 } 3895 tevent_req_set_callback(subreq, cli_chkpath_done, req); 3896 return req; 3897} 3898 3899static void cli_chkpath_done(struct tevent_req *subreq) 3900{ 3901 struct tevent_req *req = tevent_req_callback_data( 3902 subreq, struct tevent_req); 3903 NTSTATUS status; 3904 3905 status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); 3906 TALLOC_FREE(subreq); 3907 if (!NT_STATUS_IS_OK(status)) { 3908 tevent_req_nterror(req, status); 3909 return; 3910 } 3911 tevent_req_done(req); 3912} 3913 3914NTSTATUS cli_chkpath_recv(struct tevent_req *req) 3915{ 3916 return tevent_req_simple_recv_ntstatus(req); 3917} 3918 3919NTSTATUS cli_chkpath(struct cli_state *cli, const char *path) 3920{ 3921 TALLOC_CTX *frame = talloc_stackframe(); 3922 struct event_context *ev = NULL; 3923 struct tevent_req *req = NULL; 3924 char *path2 = NULL; 3925 NTSTATUS status = NT_STATUS_OK; 3926 3927 if (cli_has_async_calls(cli)) { 3928 /* 3929 * Can't use sync call while an async call is in flight 3930 */ 3931 status = NT_STATUS_INVALID_PARAMETER; 3932 goto fail; 3933 } 3934 3935 path2 = talloc_strdup(frame, path); 3936 if (!path2) { 3937 status = NT_STATUS_NO_MEMORY; 3938 goto fail; 3939 } 3940 trim_char(path2,'\0','\\'); 3941 if (!*path2) { 3942 path2 = talloc_strdup(frame, "\\"); 3943 if (!path2) { 3944 status = NT_STATUS_NO_MEMORY; 3945 goto fail; 3946 } 3947 } 3948 3949 ev = event_context_init(frame); 3950 if (ev == NULL) { 3951 status = NT_STATUS_NO_MEMORY; 3952 goto fail; 3953 } 3954 3955 req = cli_chkpath_send(frame, ev, cli, path2); 3956 if (req == NULL) { 3957 status = NT_STATUS_NO_MEMORY; 3958 goto fail; 3959 } 3960 3961 if (!tevent_req_poll(req, ev)) { 3962 status = map_nt_error_from_unix(errno); 3963 goto fail; 3964 } 3965 3966 status = cli_chkpath_recv(req); 3967 3968 fail: 3969 TALLOC_FREE(frame); 3970 if (!NT_STATUS_IS_OK(status)) { 3971 cli_set_error(cli, status); 3972 } 3973 return status; 3974} 3975 3976/**************************************************************************** 3977 Query disk space. 3978****************************************************************************/ 3979 3980static void cli_dskattr_done(struct tevent_req *subreq); 3981 3982struct cli_dskattr_state { 3983 int bsize; 3984 int total; 3985 int avail; 3986}; 3987 3988struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx, 3989 struct event_context *ev, 3990 struct cli_state *cli) 3991{ 3992 struct tevent_req *req = NULL, *subreq = NULL; 3993 struct cli_dskattr_state *state = NULL; 3994 uint8_t additional_flags = 0; 3995 3996 req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state); 3997 if (req == NULL) { 3998 return NULL; 3999 } 4000 4001 subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags, 4002 0, NULL, 0, NULL); 4003 if (tevent_req_nomem(subreq, req)) { 4004 return tevent_req_post(req, ev); 4005 } 4006 tevent_req_set_callback(subreq, cli_dskattr_done, req); 4007 return req; 4008} 4009 4010static void cli_dskattr_done(struct tevent_req *subreq) 4011{ 4012 struct tevent_req *req = tevent_req_callback_data( 4013 subreq, struct tevent_req); 4014 struct cli_dskattr_state *state = tevent_req_data( 4015 req, struct cli_dskattr_state); 4016 uint8_t wct; 4017 uint16_t *vwv = NULL; 4018 NTSTATUS status; 4019 4020 status = cli_smb_recv(subreq, 4, &wct, &vwv, NULL, NULL); 4021 if (!NT_STATUS_IS_OK(status)) { 4022 tevent_req_nterror(req, status); 4023 return; 4024 } 4025 state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0); 4026 state->total = SVAL(vwv+0, 0); 4027 state->avail = SVAL(vwv+3, 0); 4028 TALLOC_FREE(subreq); 4029 tevent_req_done(req); 4030} 4031 4032NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail) 4033{ 4034 struct cli_dskattr_state *state = tevent_req_data( 4035 req, struct cli_dskattr_state); 4036 NTSTATUS status; 4037 4038 if (tevent_req_is_nterror(req, &status)) { 4039 return status; 4040 } 4041 *bsize = state->bsize; 4042 *total = state->total; 4043 *avail = state->avail; 4044 return NT_STATUS_OK; 4045} 4046 4047NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) 4048{ 4049 TALLOC_CTX *frame = talloc_stackframe(); 4050 struct event_context *ev = NULL; 4051 struct tevent_req *req = NULL; 4052 NTSTATUS status = NT_STATUS_OK; 4053 4054 if (cli_has_async_calls(cli)) { 4055 /* 4056 * Can't use sync call while an async call is in flight 4057 */ 4058 status = NT_STATUS_INVALID_PARAMETER; 4059 goto fail; 4060 } 4061 4062 ev = event_context_init(frame); 4063 if (ev == NULL) { 4064 status = NT_STATUS_NO_MEMORY; 4065 goto fail; 4066 } 4067 4068 req = cli_dskattr_send(frame, ev, cli); 4069 if (req == NULL) { 4070 status = NT_STATUS_NO_MEMORY; 4071 goto fail; 4072 } 4073 4074 if (!tevent_req_poll(req, ev)) { 4075 status = map_nt_error_from_unix(errno); 4076 goto fail; 4077 } 4078 4079 status = cli_dskattr_recv(req, bsize, total, avail); 4080 4081 fail: 4082 TALLOC_FREE(frame); 4083 if (!NT_STATUS_IS_OK(status)) { 4084 cli_set_error(cli, status); 4085 } 4086 return status; 4087} 4088 4089/**************************************************************************** 4090 Create and open a temporary file. 4091****************************************************************************/ 4092 4093static void cli_ctemp_done(struct tevent_req *subreq); 4094 4095struct ctemp_state { 4096 uint16_t vwv[3]; 4097 char *ret_path; 4098 uint16_t fnum; 4099}; 4100 4101struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx, 4102 struct event_context *ev, 4103 struct cli_state *cli, 4104 const char *path) 4105{ 4106 struct tevent_req *req = NULL, *subreq = NULL; 4107 struct ctemp_state *state = NULL; 4108 uint8_t additional_flags = 0; 4109 uint8_t *bytes = NULL; 4110 4111 req = tevent_req_create(mem_ctx, &state, struct ctemp_state); 4112 if (req == NULL) { 4113 return NULL; 4114 } 4115 4116 SSVAL(state->vwv,0,0); 4117 SIVALS(state->vwv+1,0,-1); 4118 4119 bytes = talloc_array(state, uint8_t, 1); 4120 if (tevent_req_nomem(bytes, req)) { 4121 return tevent_req_post(req, ev); 4122 } 4123 bytes[0] = 4; 4124 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), path, 4125 strlen(path)+1, NULL); 4126 if (tevent_req_nomem(bytes, req)) { 4127 return tevent_req_post(req, ev); 4128 } 4129 4130 subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags, 4131 3, state->vwv, talloc_get_size(bytes), bytes); 4132 if (tevent_req_nomem(subreq, req)) { 4133 return tevent_req_post(req, ev); 4134 } 4135 tevent_req_set_callback(subreq, cli_ctemp_done, req); 4136 return req; 4137} 4138 4139static void cli_ctemp_done(struct tevent_req *subreq) 4140{ 4141 struct tevent_req *req = tevent_req_callback_data( 4142 subreq, struct tevent_req); 4143 struct ctemp_state *state = tevent_req_data( 4144 req, struct ctemp_state); 4145 NTSTATUS status; 4146 uint8_t wcnt; 4147 uint16_t *vwv; 4148 uint32_t num_bytes = 0; 4149 uint8_t *bytes = NULL; 4150 4151 status = cli_smb_recv(subreq, 1, &wcnt, &vwv, &num_bytes, &bytes); 4152 if (!NT_STATUS_IS_OK(status)) { 4153 TALLOC_FREE(subreq); 4154 tevent_req_nterror(req, status); 4155 return; 4156 } 4157 4158 state->fnum = SVAL(vwv+0, 0); 4159 4160 TALLOC_FREE(subreq); 4161 4162 /* From W2K3, the result is just the ASCII name */ 4163 if (num_bytes < 2) { 4164 tevent_req_nterror(req, NT_STATUS_DATA_ERROR); 4165 return; 4166 } 4167 4168 if (pull_string_talloc(state, 4169 NULL, 4170 0, 4171 &state->ret_path, 4172 bytes, 4173 num_bytes, 4174 STR_ASCII) == 0) { 4175 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 4176 return; 4177 } 4178 tevent_req_done(req); 4179} 4180 4181NTSTATUS cli_ctemp_recv(struct tevent_req *req, 4182 TALLOC_CTX *ctx, 4183 uint16_t *pfnum, 4184 char **outfile) 4185{ 4186 struct ctemp_state *state = tevent_req_data(req, 4187 struct ctemp_state); 4188 NTSTATUS status; 4189 4190 if (tevent_req_is_nterror(req, &status)) { 4191 return status; 4192 } 4193 *pfnum = state->fnum; 4194 *outfile = talloc_strdup(ctx, state->ret_path); 4195 if (!*outfile) { 4196 return NT_STATUS_NO_MEMORY; 4197 } 4198 return NT_STATUS_OK; 4199} 4200 4201NTSTATUS cli_ctemp(struct cli_state *cli, 4202 TALLOC_CTX *ctx, 4203 const char *path, 4204 uint16_t *pfnum, 4205 char **out_path) 4206{ 4207 TALLOC_CTX *frame = talloc_stackframe(); 4208 struct event_context *ev; 4209 struct tevent_req *req; 4210 NTSTATUS status = NT_STATUS_OK; 4211 4212 if (cli_has_async_calls(cli)) { 4213 /* 4214 * Can't use sync call while an async call is in flight 4215 */ 4216 status = NT_STATUS_INVALID_PARAMETER; 4217 goto fail; 4218 } 4219 4220 ev = event_context_init(frame); 4221 if (ev == NULL) { 4222 status = NT_STATUS_NO_MEMORY; 4223 goto fail; 4224 } 4225 4226 req = cli_ctemp_send(frame, ev, cli, path); 4227 if (req == NULL) { 4228 status = NT_STATUS_NO_MEMORY; 4229 goto fail; 4230 } 4231 4232 if (!tevent_req_poll(req, ev)) { 4233 status = map_nt_error_from_unix(errno); 4234 goto fail; 4235 } 4236 4237 status = cli_ctemp_recv(req, ctx, pfnum, out_path); 4238 4239 fail: 4240 TALLOC_FREE(frame); 4241 if (!NT_STATUS_IS_OK(status)) { 4242 cli_set_error(cli, status); 4243 } 4244 return status; 4245} 4246 4247/* 4248 send a raw ioctl - used by the torture code 4249*/ 4250NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob) 4251{ 4252 memset(cli->outbuf,'\0',smb_size); 4253 memset(cli->inbuf,'\0',smb_size); 4254 4255 cli_set_message(cli->outbuf, 3, 0, True); 4256 SCVAL(cli->outbuf,smb_com,SMBioctl); 4257 cli_setup_packet(cli); 4258 4259 SSVAL(cli->outbuf, smb_vwv0, fnum); 4260 SSVAL(cli->outbuf, smb_vwv1, code>>16); 4261 SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF)); 4262 4263 cli_send_smb(cli); 4264 if (!cli_receive_smb(cli)) { 4265 return NT_STATUS_UNEXPECTED_NETWORK_ERROR; 4266 } 4267 4268 if (cli_is_error(cli)) { 4269 return cli_nt_error(cli); 4270 } 4271 4272 *blob = data_blob_null; 4273 4274 return NT_STATUS_OK; 4275} 4276 4277/********************************************************* 4278 Set an extended attribute utility fn. 4279*********************************************************/ 4280 4281static bool cli_set_ea(struct cli_state *cli, uint16_t setup, char *param, unsigned int param_len, 4282 const char *ea_name, const char *ea_val, size_t ea_len) 4283{ 4284 unsigned int data_len = 0; 4285 char *data = NULL; 4286 char *rparam=NULL, *rdata=NULL; 4287 char *p; 4288 size_t ea_namelen = strlen(ea_name); 4289 4290 if (ea_namelen == 0 && ea_len == 0) { 4291 data_len = 4; 4292 data = (char *)SMB_MALLOC(data_len); 4293 if (!data) { 4294 return False; 4295 } 4296 p = data; 4297 SIVAL(p,0,data_len); 4298 } else { 4299 data_len = 4 + 4 + ea_namelen + 1 + ea_len; 4300 data = (char *)SMB_MALLOC(data_len); 4301 if (!data) { 4302 return False; 4303 } 4304 p = data; 4305 SIVAL(p,0,data_len); 4306 p += 4; 4307 SCVAL(p, 0, 0); /* EA flags. */ 4308 SCVAL(p, 1, ea_namelen); 4309 SSVAL(p, 2, ea_len); 4310 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */ 4311 memcpy(p+4+ea_namelen+1, ea_val, ea_len); 4312 } 4313 4314 if (!cli_send_trans(cli, SMBtrans2, 4315 NULL, /* name */ 4316 -1, 0, /* fid, flags */ 4317 &setup, 1, 0, /* setup, length, max */ 4318 param, param_len, 2, /* param, length, max */ 4319 data, data_len, cli->max_xmit /* data, length, max */ 4320 )) { 4321 SAFE_FREE(data); 4322 return False; 4323 } 4324 4325 if (!cli_receive_trans(cli, SMBtrans2, 4326 &rparam, ¶m_len, 4327 &rdata, &data_len)) { 4328 SAFE_FREE(data); 4329 return false; 4330 } 4331 4332 SAFE_FREE(data); 4333 SAFE_FREE(rdata); 4334 SAFE_FREE(rparam); 4335 4336 return True; 4337} 4338 4339/********************************************************* 4340 Set an extended attribute on a pathname. 4341*********************************************************/ 4342 4343bool cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len) 4344{ 4345 uint16_t setup = TRANSACT2_SETPATHINFO; 4346 unsigned int param_len = 0; 4347 char *param; 4348 size_t srclen = 2*(strlen(path)+1); 4349 char *p; 4350 bool ret; 4351 4352 param = SMB_MALLOC_ARRAY(char, 6+srclen+2); 4353 if (!param) { 4354 return false; 4355 } 4356 memset(param, '\0', 6); 4357 SSVAL(param,0,SMB_INFO_SET_EA); 4358 p = ¶m[6]; 4359 4360 p += clistr_push(cli, p, path, srclen, STR_TERMINATE); 4361 param_len = PTR_DIFF(p, param); 4362 4363 ret = cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len); 4364 SAFE_FREE(param); 4365 return ret; 4366} 4367 4368/********************************************************* 4369 Set an extended attribute on an fnum. 4370*********************************************************/ 4371 4372bool cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum, const char *ea_name, const char *ea_val, size_t ea_len) 4373{ 4374 char param[6]; 4375 uint16_t setup = TRANSACT2_SETFILEINFO; 4376 4377 memset(param, 0, 6); 4378 SSVAL(param,0,fnum); 4379 SSVAL(param,2,SMB_INFO_SET_EA); 4380 4381 return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len); 4382} 4383 4384/********************************************************* 4385 Get an extended attribute list utility fn. 4386*********************************************************/ 4387 4388static bool cli_get_ea_list(struct cli_state *cli, 4389 uint16_t setup, char *param, unsigned int param_len, 4390 TALLOC_CTX *ctx, 4391 size_t *pnum_eas, 4392 struct ea_struct **pea_list) 4393{ 4394 unsigned int data_len = 0; 4395 unsigned int rparam_len, rdata_len; 4396 char *rparam=NULL, *rdata=NULL; 4397 char *p; 4398 size_t ea_size; 4399 size_t num_eas; 4400 bool ret = False; 4401 struct ea_struct *ea_list; 4402 4403 *pnum_eas = 0; 4404 if (pea_list) { 4405 *pea_list = NULL; 4406 } 4407 4408 if (!cli_send_trans(cli, SMBtrans2, 4409 NULL, /* Name */ 4410 -1, 0, /* fid, flags */ 4411 &setup, 1, 0, /* setup, length, max */ 4412 param, param_len, 10, /* param, length, max */ 4413 NULL, data_len, cli->max_xmit /* data, length, max */ 4414 )) { 4415 return False; 4416 } 4417 4418 if (!cli_receive_trans(cli, SMBtrans2, 4419 &rparam, &rparam_len, 4420 &rdata, &rdata_len)) { 4421 return False; 4422 } 4423 4424 if (!rdata || rdata_len < 4) { 4425 goto out; 4426 } 4427 4428 ea_size = (size_t)IVAL(rdata,0); 4429 if (ea_size > rdata_len) { 4430 goto out; 4431 } 4432 4433 if (ea_size == 0) { 4434 /* No EA's present. */ 4435 ret = True; 4436 goto out; 4437 } 4438 4439 p = rdata + 4; 4440 ea_size -= 4; 4441 4442 /* Validate the EA list and count it. */ 4443 for (num_eas = 0; ea_size >= 4; num_eas++) { 4444 unsigned int ea_namelen = CVAL(p,1); 4445 unsigned int ea_valuelen = SVAL(p,2); 4446 if (ea_namelen == 0) { 4447 goto out; 4448 } 4449 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) { 4450 goto out; 4451 } 4452 ea_size -= 4 + ea_namelen + 1 + ea_valuelen; 4453 p += 4 + ea_namelen + 1 + ea_valuelen; 4454 } 4455 4456 if (num_eas == 0) { 4457 ret = True; 4458 goto out; 4459 } 4460 4461 *pnum_eas = num_eas; 4462 if (!pea_list) { 4463 /* Caller only wants number of EA's. */ 4464 ret = True; 4465 goto out; 4466 } 4467 4468 ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas); 4469 if (!ea_list) { 4470 goto out; 4471 } 4472 4473 ea_size = (size_t)IVAL(rdata,0); 4474 p = rdata + 4; 4475 4476 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) { 4477 struct ea_struct *ea = &ea_list[num_eas]; 4478 fstring unix_ea_name; 4479 unsigned int ea_namelen = CVAL(p,1); 4480 unsigned int ea_valuelen = SVAL(p,2); 4481 4482 ea->flags = CVAL(p,0); 4483 unix_ea_name[0] = '\0'; 4484 pull_ascii_fstring(unix_ea_name, p + 4); 4485 ea->name = talloc_strdup(ctx, unix_ea_name); 4486 /* Ensure the value is null terminated (in case it's a string). */ 4487 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1); 4488 if (!ea->value.data) { 4489 goto out; 4490 } 4491 if (ea_valuelen) { 4492 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen); 4493 } 4494 ea->value.data[ea_valuelen] = 0; 4495 ea->value.length--; 4496 p += 4 + ea_namelen + 1 + ea_valuelen; 4497 } 4498 4499 *pea_list = ea_list; 4500 ret = True; 4501 4502 out : 4503 4504 SAFE_FREE(rdata); 4505 SAFE_FREE(rparam); 4506 return ret; 4507} 4508 4509/********************************************************* 4510 Get an extended attribute list from a pathname. 4511*********************************************************/ 4512 4513bool cli_get_ea_list_path(struct cli_state *cli, const char *path, 4514 TALLOC_CTX *ctx, 4515 size_t *pnum_eas, 4516 struct ea_struct **pea_list) 4517{ 4518 uint16_t setup = TRANSACT2_QPATHINFO; 4519 unsigned int param_len = 0; 4520 char *param; 4521 char *p; 4522 size_t srclen = 2*(strlen(path)+1); 4523 bool ret; 4524 4525 param = SMB_MALLOC_ARRAY(char, 6+srclen+2); 4526 if (!param) { 4527 return false; 4528 } 4529 p = param; 4530 memset(p, 0, 6); 4531 SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS); 4532 p += 6; 4533 p += clistr_push(cli, p, path, srclen, STR_TERMINATE); 4534 param_len = PTR_DIFF(p, param); 4535 4536 ret = cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list); 4537 SAFE_FREE(param); 4538 return ret; 4539} 4540 4541/********************************************************* 4542 Get an extended attribute list from an fnum. 4543*********************************************************/ 4544 4545bool cli_get_ea_list_fnum(struct cli_state *cli, uint16_t fnum, 4546 TALLOC_CTX *ctx, 4547 size_t *pnum_eas, 4548 struct ea_struct **pea_list) 4549{ 4550 uint16_t setup = TRANSACT2_QFILEINFO; 4551 char param[6]; 4552 4553 memset(param, 0, 6); 4554 SSVAL(param,0,fnum); 4555 SSVAL(param,2,SMB_INFO_SET_EA); 4556 4557 return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list); 4558} 4559 4560/**************************************************************************** 4561 Convert open "flags" arg to uint32_t on wire. 4562****************************************************************************/ 4563 4564static uint32_t open_flags_to_wire(int flags) 4565{ 4566 int open_mode = flags & O_ACCMODE; 4567 uint32_t ret = 0; 4568 4569 switch (open_mode) { 4570 case O_WRONLY: 4571 ret |= SMB_O_WRONLY; 4572 break; 4573 case O_RDWR: 4574 ret |= SMB_O_RDWR; 4575 break; 4576 default: 4577 case O_RDONLY: 4578 ret |= SMB_O_RDONLY; 4579 break; 4580 } 4581 4582 if (flags & O_CREAT) { 4583 ret |= SMB_O_CREAT; 4584 } 4585 if (flags & O_EXCL) { 4586 ret |= SMB_O_EXCL; 4587 } 4588 if (flags & O_TRUNC) { 4589 ret |= SMB_O_TRUNC; 4590 } 4591#if defined(O_SYNC) 4592 if (flags & O_SYNC) { 4593 ret |= SMB_O_SYNC; 4594 } 4595#endif /* O_SYNC */ 4596 if (flags & O_APPEND) { 4597 ret |= SMB_O_APPEND; 4598 } 4599#if defined(O_DIRECT) 4600 if (flags & O_DIRECT) { 4601 ret |= SMB_O_DIRECT; 4602 } 4603#endif 4604#if defined(O_DIRECTORY) 4605 if (flags & O_DIRECTORY) { 4606 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY); 4607 ret |= SMB_O_DIRECTORY; 4608 } 4609#endif 4610 return ret; 4611} 4612 4613/**************************************************************************** 4614 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock. 4615****************************************************************************/ 4616 4617struct posix_open_state { 4618 uint16_t setup; 4619 uint8_t *param; 4620 uint8_t data[18]; 4621 uint16_t fnum; /* Out */ 4622}; 4623 4624static void cli_posix_open_internal_done(struct tevent_req *subreq) 4625{ 4626 struct tevent_req *req = tevent_req_callback_data( 4627 subreq, struct tevent_req); 4628 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state); 4629 NTSTATUS status; 4630 uint8_t *data; 4631 uint32_t num_data; 4632 4633 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &data, &num_data); 4634 TALLOC_FREE(subreq); 4635 if (!NT_STATUS_IS_OK(status)) { 4636 tevent_req_nterror(req, status); 4637 return; 4638 } 4639 if (num_data < 12) { 4640 tevent_req_nterror(req, status); 4641 return; 4642 } 4643 state->fnum = SVAL(data,2); 4644 tevent_req_done(req); 4645} 4646 4647static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx, 4648 struct event_context *ev, 4649 struct cli_state *cli, 4650 const char *fname, 4651 int flags, 4652 mode_t mode, 4653 bool is_dir) 4654{ 4655 struct tevent_req *req = NULL, *subreq = NULL; 4656 struct posix_open_state *state = NULL; 4657 uint32_t wire_flags = open_flags_to_wire(flags); 4658 4659 req = tevent_req_create(mem_ctx, &state, struct posix_open_state); 4660 if (req == NULL) { 4661 return NULL; 4662 } 4663 4664 /* Setup setup word. */ 4665 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO); 4666 4667 /* Setup param array. */ 4668 state->param = talloc_array(state, uint8_t, 6); 4669 if (tevent_req_nomem(state->param, req)) { 4670 return tevent_req_post(req, ev); 4671 } 4672 memset(state->param, '\0', 6); 4673 SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN); 4674 4675 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, 4676 strlen(fname)+1, NULL); 4677 4678 if (tevent_req_nomem(state->param, req)) { 4679 return tevent_req_post(req, ev); 4680 } 4681 4682 /* Setup data words. */ 4683 if (is_dir) { 4684 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY); 4685 wire_flags |= SMB_O_DIRECTORY; 4686 } 4687 4688 SIVAL(state->data,0,0); /* No oplock. */ 4689 SIVAL(state->data,4,wire_flags); 4690 SIVAL(state->data,8,unix_perms_to_wire(mode)); 4691 SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */ 4692 SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */ 4693 4694 subreq = cli_trans_send(state, /* mem ctx. */ 4695 ev, /* event ctx. */ 4696 cli, /* cli_state. */ 4697 SMBtrans2, /* cmd. */ 4698 NULL, /* pipe name. */ 4699 -1, /* fid. */ 4700 0, /* function. */ 4701 0, /* flags. */ 4702 &state->setup, /* setup. */ 4703 1, /* num setup uint16_t words. */ 4704 0, /* max returned setup. */ 4705 state->param, /* param. */ 4706 talloc_get_size(state->param),/* num param. */ 4707 2, /* max returned param. */ 4708 state->data, /* data. */ 4709 18, /* num data. */ 4710 12); /* max returned data. */ 4711 4712 if (tevent_req_nomem(subreq, req)) { 4713 return tevent_req_post(req, ev); 4714 } 4715 tevent_req_set_callback(subreq, cli_posix_open_internal_done, req); 4716 return req; 4717} 4718 4719struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx, 4720 struct event_context *ev, 4721 struct cli_state *cli, 4722 const char *fname, 4723 int flags, 4724 mode_t mode) 4725{ 4726 return cli_posix_open_internal_send(mem_ctx, ev, 4727 cli, fname, flags, mode, false); 4728} 4729 4730NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum) 4731{ 4732 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state); 4733 NTSTATUS status; 4734 4735 if (tevent_req_is_nterror(req, &status)) { 4736 return status; 4737 } 4738 *pfnum = state->fnum; 4739 return NT_STATUS_OK; 4740} 4741 4742/**************************************************************************** 4743 Open - POSIX semantics. Doesn't request oplock. 4744****************************************************************************/ 4745 4746NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname, 4747 int flags, mode_t mode, uint16_t *pfnum) 4748{ 4749 4750 TALLOC_CTX *frame = talloc_stackframe(); 4751 struct event_context *ev = NULL; 4752 struct tevent_req *req = NULL; 4753 NTSTATUS status = NT_STATUS_OK; 4754 4755 if (cli_has_async_calls(cli)) { 4756 /* 4757 * Can't use sync call while an async call is in flight 4758 */ 4759 status = NT_STATUS_INVALID_PARAMETER; 4760 goto fail; 4761 } 4762 4763 ev = event_context_init(frame); 4764 if (ev == NULL) { 4765 status = NT_STATUS_NO_MEMORY; 4766 goto fail; 4767 } 4768 4769 req = cli_posix_open_send(frame, 4770 ev, 4771 cli, 4772 fname, 4773 flags, 4774 mode); 4775 if (req == NULL) { 4776 status = NT_STATUS_NO_MEMORY; 4777 goto fail; 4778 } 4779 4780 if (!tevent_req_poll(req, ev)) { 4781 status = map_nt_error_from_unix(errno); 4782 goto fail; 4783 } 4784 4785 status = cli_posix_open_recv(req, pfnum); 4786 4787 fail: 4788 TALLOC_FREE(frame); 4789 if (!NT_STATUS_IS_OK(status)) { 4790 cli_set_error(cli, status); 4791 } 4792 return status; 4793} 4794 4795struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx, 4796 struct event_context *ev, 4797 struct cli_state *cli, 4798 const char *fname, 4799 mode_t mode) 4800{ 4801 return cli_posix_open_internal_send(mem_ctx, ev, 4802 cli, fname, O_CREAT, mode, true); 4803} 4804 4805NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req) 4806{ 4807 NTSTATUS status; 4808 4809 if (tevent_req_is_nterror(req, &status)) { 4810 return status; 4811 } 4812 return NT_STATUS_OK; 4813} 4814 4815NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode) 4816{ 4817 TALLOC_CTX *frame = talloc_stackframe(); 4818 struct event_context *ev = NULL; 4819 struct tevent_req *req = NULL; 4820 NTSTATUS status = NT_STATUS_OK; 4821 4822 if (cli_has_async_calls(cli)) { 4823 /* 4824 * Can't use sync call while an async call is in flight 4825 */ 4826 status = NT_STATUS_INVALID_PARAMETER; 4827 goto fail; 4828 } 4829 4830 ev = event_context_init(frame); 4831 if (ev == NULL) { 4832 status = NT_STATUS_NO_MEMORY; 4833 goto fail; 4834 } 4835 4836 req = cli_posix_mkdir_send(frame, 4837 ev, 4838 cli, 4839 fname, 4840 mode); 4841 if (req == NULL) { 4842 status = NT_STATUS_NO_MEMORY; 4843 goto fail; 4844 } 4845 4846 if (!tevent_req_poll(req, ev)) { 4847 status = map_nt_error_from_unix(errno); 4848 goto fail; 4849 } 4850 4851 status = cli_posix_mkdir_recv(req); 4852 4853 fail: 4854 TALLOC_FREE(frame); 4855 if (!NT_STATUS_IS_OK(status)) { 4856 cli_set_error(cli, status); 4857 } 4858 return status; 4859} 4860 4861/**************************************************************************** 4862 unlink or rmdir - POSIX semantics. 4863****************************************************************************/ 4864 4865struct unlink_state { 4866 uint16_t setup; 4867 uint8_t data[2]; 4868}; 4869 4870static void cli_posix_unlink_internal_done(struct tevent_req *subreq) 4871{ 4872 struct tevent_req *req = tevent_req_callback_data( 4873 subreq, struct tevent_req); 4874 struct unlink_state *state = tevent_req_data(req, struct unlink_state); 4875 NTSTATUS status; 4876 4877 status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); 4878 TALLOC_FREE(subreq); 4879 if (!NT_STATUS_IS_OK(status)) { 4880 tevent_req_nterror(req, status); 4881 return; 4882 } 4883 tevent_req_done(req); 4884} 4885 4886static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx, 4887 struct event_context *ev, 4888 struct cli_state *cli, 4889 const char *fname, 4890 bool is_dir) 4891{ 4892 struct tevent_req *req = NULL, *subreq = NULL; 4893 struct unlink_state *state = NULL; 4894 uint8_t *param = NULL; 4895 4896 req = tevent_req_create(mem_ctx, &state, struct unlink_state); 4897 if (req == NULL) { 4898 return NULL; 4899 } 4900 4901 /* Setup setup word. */ 4902 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO); 4903 4904 /* Setup param array. */ 4905 param = talloc_array(state, uint8_t, 6); 4906 if (tevent_req_nomem(param, req)) { 4907 return tevent_req_post(req, ev); 4908 } 4909 memset(param, '\0', 6); 4910 SSVAL(param, 0, SMB_POSIX_PATH_UNLINK); 4911 4912 param = trans2_bytes_push_str(param, cli_ucs2(cli), fname, 4913 strlen(fname)+1, NULL); 4914 4915 if (tevent_req_nomem(param, req)) { 4916 return tevent_req_post(req, ev); 4917 } 4918 4919 /* Setup data word. */ 4920 SSVAL(state->data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET : 4921 SMB_POSIX_UNLINK_FILE_TARGET); 4922 4923 subreq = cli_trans_send(state, /* mem ctx. */ 4924 ev, /* event ctx. */ 4925 cli, /* cli_state. */ 4926 SMBtrans2, /* cmd. */ 4927 NULL, /* pipe name. */ 4928 -1, /* fid. */ 4929 0, /* function. */ 4930 0, /* flags. */ 4931 &state->setup, /* setup. */ 4932 1, /* num setup uint16_t words. */ 4933 0, /* max returned setup. */ 4934 param, /* param. */ 4935 talloc_get_size(param), /* num param. */ 4936 2, /* max returned param. */ 4937 state->data, /* data. */ 4938 2, /* num data. */ 4939 0); /* max returned data. */ 4940 4941 if (tevent_req_nomem(subreq, req)) { 4942 return tevent_req_post(req, ev); 4943 } 4944 tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req); 4945 return req; 4946} 4947 4948struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx, 4949 struct event_context *ev, 4950 struct cli_state *cli, 4951 const char *fname) 4952{ 4953 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, false); 4954} 4955 4956NTSTATUS cli_posix_unlink_recv(struct tevent_req *req) 4957{ 4958 NTSTATUS status; 4959 4960 if (tevent_req_is_nterror(req, &status)) { 4961 return status; 4962 } 4963 return NT_STATUS_OK; 4964} 4965 4966/**************************************************************************** 4967 unlink - POSIX semantics. 4968****************************************************************************/ 4969 4970NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname) 4971{ 4972 TALLOC_CTX *frame = talloc_stackframe(); 4973 struct event_context *ev = NULL; 4974 struct tevent_req *req = NULL; 4975 NTSTATUS status = NT_STATUS_OK; 4976 4977 if (cli_has_async_calls(cli)) { 4978 /* 4979 * Can't use sync call while an async call is in flight 4980 */ 4981 status = NT_STATUS_INVALID_PARAMETER; 4982 goto fail; 4983 } 4984 4985 ev = event_context_init(frame); 4986 if (ev == NULL) { 4987 status = NT_STATUS_NO_MEMORY; 4988 goto fail; 4989 } 4990 4991 req = cli_posix_unlink_send(frame, 4992 ev, 4993 cli, 4994 fname); 4995 if (req == NULL) { 4996 status = NT_STATUS_NO_MEMORY; 4997 goto fail; 4998 } 4999 5000 if (!tevent_req_poll(req, ev)) { 5001 status = map_nt_error_from_unix(errno); 5002 goto fail; 5003 } 5004 5005 status = cli_posix_unlink_recv(req); 5006 5007 fail: 5008 TALLOC_FREE(frame); 5009 if (!NT_STATUS_IS_OK(status)) { 5010 cli_set_error(cli, status); 5011 } 5012 return status; 5013} 5014 5015/**************************************************************************** 5016 rmdir - POSIX semantics. 5017****************************************************************************/ 5018 5019struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx, 5020 struct event_context *ev, 5021 struct cli_state *cli, 5022 const char *fname) 5023{ 5024 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, true); 5025} 5026 5027NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx) 5028{ 5029 NTSTATUS status; 5030 5031 if (tevent_req_is_nterror(req, &status)) { 5032 return status; 5033 } 5034 return NT_STATUS_OK; 5035} 5036 5037NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname) 5038{ 5039 TALLOC_CTX *frame = talloc_stackframe(); 5040 struct event_context *ev = NULL; 5041 struct tevent_req *req = NULL; 5042 NTSTATUS status = NT_STATUS_OK; 5043 5044 if (cli_has_async_calls(cli)) { 5045 /* 5046 * Can't use sync call while an async call is in flight 5047 */ 5048 status = NT_STATUS_INVALID_PARAMETER; 5049 goto fail; 5050 } 5051 5052 ev = event_context_init(frame); 5053 if (ev == NULL) { 5054 status = NT_STATUS_NO_MEMORY; 5055 goto fail; 5056 } 5057 5058 req = cli_posix_rmdir_send(frame, 5059 ev, 5060 cli, 5061 fname); 5062 if (req == NULL) { 5063 status = NT_STATUS_NO_MEMORY; 5064 goto fail; 5065 } 5066 5067 if (!tevent_req_poll(req, ev)) { 5068 status = map_nt_error_from_unix(errno); 5069 goto fail; 5070 } 5071 5072 status = cli_posix_rmdir_recv(req, frame); 5073 5074 fail: 5075 TALLOC_FREE(frame); 5076 if (!NT_STATUS_IS_OK(status)) { 5077 cli_set_error(cli, status); 5078 } 5079 return status; 5080} 5081 5082/**************************************************************************** 5083 filechangenotify 5084****************************************************************************/ 5085 5086struct cli_notify_state { 5087 uint8_t setup[8]; 5088 uint32_t num_changes; 5089 struct notify_change *changes; 5090}; 5091 5092static void cli_notify_done(struct tevent_req *subreq); 5093 5094struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, 5095 struct tevent_context *ev, 5096 struct cli_state *cli, uint16_t fnum, 5097 uint32_t buffer_size, 5098 uint32_t completion_filter, bool recursive) 5099{ 5100 struct tevent_req *req, *subreq; 5101 struct cli_notify_state *state; 5102 5103 req = tevent_req_create(mem_ctx, &state, struct cli_notify_state); 5104 if (req == NULL) { 5105 return NULL; 5106 } 5107 5108 SIVAL(state->setup, 0, completion_filter); 5109 SSVAL(state->setup, 4, fnum); 5110 SSVAL(state->setup, 6, recursive); 5111 5112 subreq = cli_trans_send( 5113 state, /* mem ctx. */ 5114 ev, /* event ctx. */ 5115 cli, /* cli_state. */ 5116 SMBnttrans, /* cmd. */ 5117 NULL, /* pipe name. */ 5118 -1, /* fid. */ 5119 NT_TRANSACT_NOTIFY_CHANGE, /* function. */ 5120 0, /* flags. */ 5121 (uint16_t *)state->setup, /* setup. */ 5122 4, /* num setup uint16_t words. */ 5123 0, /* max returned setup. */ 5124 NULL, /* param. */ 5125 0, /* num param. */ 5126 buffer_size, /* max returned param. */ 5127 NULL, /* data. */ 5128 0, /* num data. */ 5129 0); /* max returned data. */ 5130 5131 if (tevent_req_nomem(subreq, req)) { 5132 return tevent_req_post(req, ev); 5133 } 5134 tevent_req_set_callback(subreq, cli_notify_done, req); 5135 return req; 5136} 5137 5138static void cli_notify_done(struct tevent_req *subreq) 5139{ 5140 struct tevent_req *req = tevent_req_callback_data( 5141 subreq, struct tevent_req); 5142 struct cli_notify_state *state = tevent_req_data( 5143 req, struct cli_notify_state); 5144 NTSTATUS status; 5145 uint8_t *params; 5146 uint32_t i, ofs, num_params; 5147 5148 status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL, 5149 ¶ms, &num_params, NULL, NULL); 5150 TALLOC_FREE(subreq); 5151 if (!NT_STATUS_IS_OK(status)) { 5152 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status))); 5153 tevent_req_nterror(req, status); 5154 return; 5155 } 5156 5157 state->num_changes = 0; 5158 ofs = 0; 5159 5160 while (num_params - ofs > 12) { 5161 uint32_t len = IVAL(params, ofs); 5162 state->num_changes += 1; 5163 5164 if ((len == 0) || (ofs+len >= num_params)) { 5165 break; 5166 } 5167 ofs += len; 5168 } 5169 5170 state->changes = talloc_array(state, struct notify_change, 5171 state->num_changes); 5172 if (tevent_req_nomem(state->changes, req)) { 5173 TALLOC_FREE(params); 5174 return; 5175 } 5176 5177 ofs = 0; 5178 5179 for (i=0; i<state->num_changes; i++) { 5180 uint32_t next = IVAL(params, ofs); 5181 uint32_t len = IVAL(params, ofs+8); 5182 ssize_t ret; 5183 char *name; 5184 5185 if ((next != 0) && (len+12 != next)) { 5186 TALLOC_FREE(params); 5187 tevent_req_nterror( 5188 req, NT_STATUS_INVALID_NETWORK_RESPONSE); 5189 return; 5190 } 5191 5192 state->changes[i].action = IVAL(params, ofs+4); 5193 ret = clistr_pull_talloc(params, (char *)params, &name, 5194 params+ofs+12, len, 5195 STR_TERMINATE|STR_UNICODE); 5196 if (ret == -1) { 5197 TALLOC_FREE(params); 5198 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 5199 return; 5200 } 5201 state->changes[i].name = name; 5202 ofs += next; 5203 } 5204 5205 TALLOC_FREE(params); 5206 tevent_req_done(req); 5207} 5208 5209NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, 5210 uint32_t *pnum_changes, 5211 struct notify_change **pchanges) 5212{ 5213 struct cli_notify_state *state = tevent_req_data( 5214 req, struct cli_notify_state); 5215 NTSTATUS status; 5216 5217 if (tevent_req_is_nterror(req, &status)) { 5218 return status; 5219 } 5220 5221 *pnum_changes = state->num_changes; 5222 *pchanges = talloc_move(mem_ctx, &state->changes); 5223 return NT_STATUS_OK; 5224} 5225