1/* 2 Unix SMB/CIFS implementation. 3 client file operations 4 Copyright (C) Andrew Tridgell 1994-1998 5 Copyright (C) Jeremy Allison 2001-2002 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 2 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, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22#define NO_SYSLOG 23 24#include "includes.h" 25 26/**************************************************************************** 27 Hard/Symlink a file (UNIX extensions). 28 Creates new name (sym)linked to oldname. 29****************************************************************************/ 30 31static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, BOOL hard_link) 32{ 33 unsigned int data_len = 0; 34 unsigned int param_len = 0; 35 uint16 setup = TRANSACT2_SETPATHINFO; 36 char param[sizeof(pstring)+6]; 37 pstring data; 38 char *rparam=NULL, *rdata=NULL; 39 char *p; 40 size_t oldlen = 2*(strlen(oldname)+1); 41 size_t newlen = 2*(strlen(newname)+1); 42 43 memset(param, 0, sizeof(param)); 44 SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK); 45 p = ¶m[6]; 46 47 p += clistr_push(cli, p, newname, MIN(newlen, sizeof(param)-6), STR_TERMINATE); 48 param_len = PTR_DIFF(p, param); 49 50 p = data; 51 p += clistr_push(cli, p, oldname, MIN(oldlen,sizeof(data)), STR_TERMINATE); 52 data_len = PTR_DIFF(p, data); 53 54 if (!cli_send_trans(cli, SMBtrans2, 55 NULL, /* name */ 56 -1, 0, /* fid, flags */ 57 &setup, 1, 0, /* setup, length, max */ 58 param, param_len, 2, /* param, length, max */ 59 (char *)&data, data_len, cli->max_xmit /* data, length, max */ 60 )) { 61 return False; 62 } 63 64 if (!cli_receive_trans(cli, SMBtrans2, 65 &rparam, ¶m_len, 66 &rdata, &data_len)) { 67 return False; 68 } 69 70 SAFE_FREE(rdata); 71 SAFE_FREE(rparam); 72 73 return True; 74} 75 76/**************************************************************************** 77 Map standard UNIX permissions onto wire representations. 78****************************************************************************/ 79 80uint32 unix_perms_to_wire(mode_t perms) 81{ 82 unsigned int ret = 0; 83 84 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0); 85 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0); 86 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0); 87 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0); 88 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0); 89 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0); 90 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0); 91 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0); 92 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0); 93#ifdef S_ISVTX 94 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0); 95#endif 96#ifdef S_ISGID 97 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0); 98#endif 99#ifdef S_ISUID 100 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0); 101#endif 102 return ret; 103} 104 105/**************************************************************************** 106 Map wire permissions to standard UNIX. 107****************************************************************************/ 108 109mode_t wire_perms_to_unix(uint32 perms) 110{ 111 mode_t ret = (mode_t)0; 112 113 ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0); 114 ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0); 115 ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0); 116 ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0); 117 ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0); 118 ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0); 119 ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0); 120 ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0); 121 ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0); 122#ifdef S_ISVTX 123 ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0); 124#endif 125#ifdef S_ISGID 126 ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0); 127#endif 128#ifdef S_ISUID 129 ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0); 130#endif 131 return ret; 132} 133 134/**************************************************************************** 135 Return the file type from the wire filetype for UNIX extensions. 136****************************************************************************/ 137 138static mode_t unix_filetype_from_wire(uint32 wire_type) 139{ 140 switch (wire_type) { 141 case UNIX_TYPE_FILE: 142 return S_IFREG; 143 case UNIX_TYPE_DIR: 144 return S_IFDIR; 145#ifdef S_IFLNK 146 case UNIX_TYPE_SYMLINK: 147 return S_IFLNK; 148#endif 149#ifdef S_IFCHR 150 case UNIX_TYPE_CHARDEV: 151 return S_IFCHR; 152#endif 153#ifdef S_IFBLK 154 case UNIX_TYPE_BLKDEV: 155 return S_IFBLK; 156#endif 157#ifdef S_IFIFO 158 case UNIX_TYPE_FIFO: 159 return S_IFIFO; 160#endif 161#ifdef S_IFSOCK 162 case UNIX_TYPE_SOCKET: 163 return S_IFSOCK; 164#endif 165 default: 166 return (mode_t)0; 167 } 168} 169 170/**************************************************************************** 171 Do a POSIX getfacl (UNIX extensions). 172****************************************************************************/ 173 174BOOL cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf) 175{ 176 unsigned int param_len = 0; 177 unsigned int data_len = 0; 178 uint16 setup = TRANSACT2_QPATHINFO; 179 char param[sizeof(pstring)+6]; 180 char *rparam=NULL, *rdata=NULL; 181 char *p; 182 183 p = param; 184 memset(p, 0, 6); 185 SSVAL(p, 0, SMB_QUERY_POSIX_ACL); 186 p += 6; 187 p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE); 188 param_len = PTR_DIFF(p, param); 189 190 if (!cli_send_trans(cli, SMBtrans2, 191 NULL, /* name */ 192 -1, 0, /* fid, flags */ 193 &setup, 1, 0, /* setup, length, max */ 194 param, param_len, 2, /* param, length, max */ 195 NULL, 0, cli->max_xmit /* data, length, max */ 196 )) { 197 return False; 198 } 199 200 if (!cli_receive_trans(cli, SMBtrans2, 201 &rparam, ¶m_len, 202 &rdata, &data_len)) { 203 return False; 204 } 205 206 if (data_len < 6) { 207 SAFE_FREE(rdata); 208 SAFE_FREE(rparam); 209 return False; 210 } 211 212 SAFE_FREE(rparam); 213 *retbuf = rdata; 214 *prb_size = (size_t)data_len; 215 216 return True; 217} 218 219/**************************************************************************** 220 Stat a file (UNIX extensions). 221****************************************************************************/ 222 223BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf) 224{ 225 unsigned int param_len = 0; 226 unsigned int data_len = 0; 227 uint16 setup = TRANSACT2_QPATHINFO; 228 char param[sizeof(pstring)+6]; 229 char *rparam=NULL, *rdata=NULL; 230 char *p; 231 232 ZERO_STRUCTP(sbuf); 233 234 p = param; 235 memset(p, 0, 6); 236 SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC); 237 p += 6; 238 p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE); 239 param_len = PTR_DIFF(p, param); 240 241 if (!cli_send_trans(cli, SMBtrans2, 242 NULL, /* name */ 243 -1, 0, /* fid, flags */ 244 &setup, 1, 0, /* setup, length, max */ 245 param, param_len, 2, /* param, length, max */ 246 NULL, 0, cli->max_xmit /* data, length, max */ 247 )) { 248 return False; 249 } 250 251 if (!cli_receive_trans(cli, SMBtrans2, 252 &rparam, ¶m_len, 253 &rdata, &data_len)) { 254 return False; 255 } 256 257 if (data_len < 96) { 258 SAFE_FREE(rdata); 259 SAFE_FREE(rparam); 260 return False; 261 } 262 263 sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */ 264 sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */ 265 sbuf->st_blocks /= STAT_ST_BLOCKSIZE; 266 sbuf->st_ctime = interpret_long_date(rdata + 16); /* time of last change */ 267 sbuf->st_atime = interpret_long_date(rdata + 24); /* time of last access */ 268 sbuf->st_mtime = interpret_long_date(rdata + 32); /* time of last modification */ 269 sbuf->st_uid = IVAL(rdata,40); /* user ID of owner */ 270 sbuf->st_gid = IVAL(rdata,48); /* group ID of owner */ 271 sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56)); 272#if defined(HAVE_MAKEDEV) 273 { 274 uint32 dev_major = IVAL(rdata,60); 275 uint32 dev_minor = IVAL(rdata,68); 276 sbuf->st_rdev = makedev(dev_major, dev_minor); 277 } 278#endif 279 sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */ 280 sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */ 281 sbuf->st_nlink = IVAL(rdata,92); /* number of hard links */ 282 283 SAFE_FREE(rdata); 284 SAFE_FREE(rparam); 285 286 return True; 287} 288 289/**************************************************************************** 290 Symlink a file (UNIX extensions). 291****************************************************************************/ 292 293BOOL cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname) 294{ 295 return cli_link_internal(cli, oldname, newname, False); 296} 297 298/**************************************************************************** 299 Hard a file (UNIX extensions). 300****************************************************************************/ 301 302BOOL cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname) 303{ 304 return cli_link_internal(cli, oldname, newname, True); 305} 306 307/**************************************************************************** 308 Chmod or chown a file internal (UNIX extensions). 309****************************************************************************/ 310 311static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid) 312{ 313 unsigned int data_len = 0; 314 unsigned int param_len = 0; 315 uint16 setup = TRANSACT2_SETPATHINFO; 316 char param[sizeof(pstring)+6]; 317 char data[100]; 318 char *rparam=NULL, *rdata=NULL; 319 char *p; 320 321 memset(param, 0, sizeof(param)); 322 memset(data, 0, sizeof(data)); 323 SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC); 324 p = ¶m[6]; 325 326 p += clistr_push(cli, p, fname, -1, STR_TERMINATE); 327 param_len = PTR_DIFF(p, param); 328 329 SIVAL(data,40,uid); 330 SIVAL(data,48,gid); 331 SIVAL(data,84,mode); 332 333 data_len = 100; 334 335 if (!cli_send_trans(cli, SMBtrans2, 336 NULL, /* name */ 337 -1, 0, /* fid, flags */ 338 &setup, 1, 0, /* setup, length, max */ 339 param, param_len, 2, /* param, length, max */ 340 (char *)&data, data_len, cli->max_xmit /* data, length, max */ 341 )) { 342 return False; 343 } 344 345 if (!cli_receive_trans(cli, SMBtrans2, 346 &rparam, ¶m_len, 347 &rdata, &data_len)) { 348 return False; 349 } 350 351 SAFE_FREE(rdata); 352 SAFE_FREE(rparam); 353 354 return True; 355} 356 357/**************************************************************************** 358 chmod a file (UNIX extensions). 359****************************************************************************/ 360 361BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode) 362{ 363 return cli_unix_chmod_chown_internal(cli, fname, 364 unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE); 365} 366 367/**************************************************************************** 368 chown a file (UNIX extensions). 369****************************************************************************/ 370 371BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid) 372{ 373 return cli_unix_chmod_chown_internal(cli, fname, SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid); 374} 375 376/**************************************************************************** 377 Rename a file. 378****************************************************************************/ 379 380BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst) 381{ 382 char *p; 383 384 memset(cli->outbuf,'\0',smb_size); 385 memset(cli->inbuf,'\0',smb_size); 386 387 set_message(cli->outbuf,1, 0, True); 388 389 SCVAL(cli->outbuf,smb_com,SMBmv); 390 SSVAL(cli->outbuf,smb_tid,cli->cnum); 391 cli_setup_packet(cli); 392 393 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR); 394 395 p = smb_buf(cli->outbuf); 396 *p++ = 4; 397 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE); 398 *p++ = 4; 399 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE); 400 401 cli_setup_bcc(cli, p); 402 403 cli_send_smb(cli); 404 if (!cli_receive_smb(cli)) 405 return False; 406 407 if (cli_is_error(cli)) 408 return False; 409 410 return True; 411} 412 413/**************************************************************************** 414 NT Rename a file. 415****************************************************************************/ 416 417BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst) 418{ 419 char *p; 420 421 memset(cli->outbuf,'\0',smb_size); 422 memset(cli->inbuf,'\0',smb_size); 423 424 set_message(cli->outbuf, 4, 0, True); 425 426 SCVAL(cli->outbuf,smb_com,SMBntrename); 427 SSVAL(cli->outbuf,smb_tid,cli->cnum); 428 cli_setup_packet(cli); 429 430 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR); 431 SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_RENAME); 432 433 p = smb_buf(cli->outbuf); 434 *p++ = 4; 435 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE); 436 *p++ = 4; 437 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE); 438 439 cli_setup_bcc(cli, p); 440 441 cli_send_smb(cli); 442 if (!cli_receive_smb(cli)) 443 return False; 444 445 if (cli_is_error(cli)) 446 return False; 447 448 return True; 449} 450 451/**************************************************************************** 452 NT hardlink a file. 453****************************************************************************/ 454 455BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst) 456{ 457 char *p; 458 459 memset(cli->outbuf,'\0',smb_size); 460 memset(cli->inbuf,'\0',smb_size); 461 462 set_message(cli->outbuf, 4, 0, True); 463 464 SCVAL(cli->outbuf,smb_com,SMBntrename); 465 SSVAL(cli->outbuf,smb_tid,cli->cnum); 466 cli_setup_packet(cli); 467 468 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR); 469 SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_HARD_LINK); 470 471 p = smb_buf(cli->outbuf); 472 *p++ = 4; 473 p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE); 474 *p++ = 4; 475 p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE); 476 477 cli_setup_bcc(cli, p); 478 479 cli_send_smb(cli); 480 if (!cli_receive_smb(cli)) 481 return False; 482 483 if (cli_is_error(cli)) 484 return False; 485 486 return True; 487} 488 489/**************************************************************************** 490 Delete a file. 491****************************************************************************/ 492 493BOOL cli_unlink(struct cli_state *cli, const char *fname) 494{ 495 char *p; 496 497 memset(cli->outbuf,'\0',smb_size); 498 memset(cli->inbuf,'\0',smb_size); 499 500 set_message(cli->outbuf,1, 0,True); 501 502 SCVAL(cli->outbuf,smb_com,SMBunlink); 503 SSVAL(cli->outbuf,smb_tid,cli->cnum); 504 cli_setup_packet(cli); 505 506 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN); 507 508 p = smb_buf(cli->outbuf); 509 *p++ = 4; 510 p += clistr_push(cli, p, fname, -1, STR_TERMINATE); 511 512 cli_setup_bcc(cli, p); 513 cli_send_smb(cli); 514 if (!cli_receive_smb(cli)) { 515 return False; 516 } 517 518 if (cli_is_error(cli)) { 519 return False; 520 } 521 522 return True; 523} 524 525/**************************************************************************** 526 Create a directory. 527****************************************************************************/ 528 529BOOL cli_mkdir(struct cli_state *cli, const char *dname) 530{ 531 char *p; 532 533 memset(cli->outbuf,'\0',smb_size); 534 memset(cli->inbuf,'\0',smb_size); 535 536 set_message(cli->outbuf,0, 0,True); 537 538 SCVAL(cli->outbuf,smb_com,SMBmkdir); 539 SSVAL(cli->outbuf,smb_tid,cli->cnum); 540 cli_setup_packet(cli); 541 542 p = smb_buf(cli->outbuf); 543 *p++ = 4; 544 p += clistr_push(cli, p, dname, -1, STR_TERMINATE); 545 546 cli_setup_bcc(cli, p); 547 548 cli_send_smb(cli); 549 if (!cli_receive_smb(cli)) { 550 return False; 551 } 552 553 if (cli_is_error(cli)) { 554 return False; 555 } 556 557 return True; 558} 559 560/**************************************************************************** 561 Remove a directory. 562****************************************************************************/ 563 564BOOL cli_rmdir(struct cli_state *cli, const char *dname) 565{ 566 char *p; 567 568 memset(cli->outbuf,'\0',smb_size); 569 memset(cli->inbuf,'\0',smb_size); 570 571 set_message(cli->outbuf,0, 0, True); 572 573 SCVAL(cli->outbuf,smb_com,SMBrmdir); 574 SSVAL(cli->outbuf,smb_tid,cli->cnum); 575 cli_setup_packet(cli); 576 577 p = smb_buf(cli->outbuf); 578 *p++ = 4; 579 p += clistr_push(cli, p, dname, -1, STR_TERMINATE); 580 581 cli_setup_bcc(cli, p); 582 583 cli_send_smb(cli); 584 if (!cli_receive_smb(cli)) { 585 return False; 586 } 587 588 if (cli_is_error(cli)) { 589 return False; 590 } 591 592 return True; 593} 594 595/**************************************************************************** 596 Set or clear the delete on close flag. 597****************************************************************************/ 598 599int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag) 600{ 601 unsigned int data_len = 1; 602 unsigned int param_len = 6; 603 uint16 setup = TRANSACT2_SETFILEINFO; 604 pstring param; 605 unsigned char data; 606 char *rparam=NULL, *rdata=NULL; 607 608 memset(param, 0, param_len); 609 SSVAL(param,0,fnum); 610 SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO); 611 612 data = flag ? 1 : 0; 613 614 if (!cli_send_trans(cli, SMBtrans2, 615 NULL, /* name */ 616 -1, 0, /* fid, flags */ 617 &setup, 1, 0, /* setup, length, max */ 618 param, param_len, 2, /* param, length, max */ 619 (char *)&data, data_len, cli->max_xmit /* data, length, max */ 620 )) { 621 return False; 622 } 623 624 if (!cli_receive_trans(cli, SMBtrans2, 625 &rparam, ¶m_len, 626 &rdata, &data_len)) { 627 return False; 628 } 629 630 SAFE_FREE(rdata); 631 SAFE_FREE(rparam); 632 633 return True; 634} 635 636/**************************************************************************** 637 Open a file - exposing the full horror of the NT API :-). 638 Used in smbtorture. 639****************************************************************************/ 640 641int cli_nt_create_full(struct cli_state *cli, const char *fname, 642 uint32 CreatFlags, uint32 DesiredAccess, 643 uint32 FileAttributes, uint32 ShareAccess, 644 uint32 CreateDisposition, uint32 CreateOptions, 645 uint8 SecuityFlags) 646{ 647 char *p; 648 int len; 649 650 memset(cli->outbuf,'\0',smb_size); 651 memset(cli->inbuf,'\0',smb_size); 652 653 set_message(cli->outbuf,24,0,True); 654 655 SCVAL(cli->outbuf,smb_com,SMBntcreateX); 656 SSVAL(cli->outbuf,smb_tid,cli->cnum); 657 cli_setup_packet(cli); 658 659 SSVAL(cli->outbuf,smb_vwv0,0xFF); 660 if (cli->use_oplocks) 661 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); 662 663 SIVAL(cli->outbuf,smb_ntcreate_Flags, CreatFlags); 664 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0); 665 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess); 666 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes); 667 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess); 668 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition); 669 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions); 670 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02); 671 SCVAL(cli->outbuf,smb_ntcreate_SecurityFlags, SecuityFlags); 672 673 p = smb_buf(cli->outbuf); 674 /* this alignment and termination is critical for netapp filers. Don't change */ 675 p += clistr_align_out(cli, p, 0); 676 len = clistr_push(cli, p, fname, -1, 0); 677 p += len; 678 SSVAL(cli->outbuf,smb_ntcreate_NameLength, len); 679 /* sigh. this copes with broken netapp filer behaviour */ 680 p += clistr_push(cli, p, "", -1, STR_TERMINATE); 681 682 cli_setup_bcc(cli, p); 683 684 cli_send_smb(cli); 685 if (!cli_receive_smb(cli)) { 686 return -1; 687 } 688 689 if (cli_is_error(cli)) { 690 return -1; 691 } 692 693 return SVAL(cli->inbuf,smb_vwv2 + 1); 694} 695 696/**************************************************************************** 697 Open a file. 698****************************************************************************/ 699 700int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess) 701{ 702 return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0, 703 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0, 0x0); 704} 705 706/**************************************************************************** 707 Open a file 708 WARNING: if you open with O_WRONLY then getattrE won't work! 709****************************************************************************/ 710 711int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode) 712{ 713 char *p; 714 unsigned openfn=0; 715 unsigned accessmode=0; 716 717 if (flags & O_CREAT) 718 openfn |= (1<<4); 719 if (!(flags & O_EXCL)) { 720 if (flags & O_TRUNC) 721 openfn |= (1<<1); 722 else 723 openfn |= (1<<0); 724 } 725 726 accessmode = (share_mode<<4); 727 728 if ((flags & O_ACCMODE) == O_RDWR) { 729 accessmode |= 2; 730 } else if ((flags & O_ACCMODE) == O_WRONLY) { 731 accessmode |= 1; 732 } 733 734#if defined(O_SYNC) 735 if ((flags & O_SYNC) == O_SYNC) { 736 accessmode |= (1<<14); 737 } 738#endif /* O_SYNC */ 739 740 if (share_mode == DENY_FCB) { 741 accessmode = 0xFF; 742 } 743 744 memset(cli->outbuf,'\0',smb_size); 745 memset(cli->inbuf,'\0',smb_size); 746 747 set_message(cli->outbuf,15,0,True); 748 749 SCVAL(cli->outbuf,smb_com,SMBopenX); 750 SSVAL(cli->outbuf,smb_tid,cli->cnum); 751 cli_setup_packet(cli); 752 753 SSVAL(cli->outbuf,smb_vwv0,0xFF); 754 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */ 755 SSVAL(cli->outbuf,smb_vwv3,accessmode); 756 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN); 757 SSVAL(cli->outbuf,smb_vwv5,0); 758 SSVAL(cli->outbuf,smb_vwv8,openfn); 759 760 if (cli->use_oplocks) { 761 /* if using oplocks then ask for a batch oplock via 762 core and extended methods */ 763 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)| 764 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK); 765 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6); 766 } 767 768 p = smb_buf(cli->outbuf); 769 p += clistr_push(cli, p, fname, -1, STR_TERMINATE); 770 771 cli_setup_bcc(cli, p); 772 773 cli_send_smb(cli); 774 if (!cli_receive_smb(cli)) { 775 return -1; 776 } 777 778 if (cli_is_error(cli)) { 779 return -1; 780 } 781 782 return SVAL(cli->inbuf,smb_vwv2); 783} 784 785/**************************************************************************** 786 Close a file. 787****************************************************************************/ 788 789BOOL cli_close(struct cli_state *cli, int fnum) 790{ 791 memset(cli->outbuf,'\0',smb_size); 792 memset(cli->inbuf,'\0',smb_size); 793 794 set_message(cli->outbuf,3,0,True); 795 796 SCVAL(cli->outbuf,smb_com,SMBclose); 797 SSVAL(cli->outbuf,smb_tid,cli->cnum); 798 cli_setup_packet(cli); 799 800 SSVAL(cli->outbuf,smb_vwv0,fnum); 801 SIVALS(cli->outbuf,smb_vwv1,-1); 802 803 cli_send_smb(cli); 804 if (!cli_receive_smb(cli)) { 805 return False; 806 } 807 808 return !cli_is_error(cli); 809} 810 811 812/**************************************************************************** 813 send a lock with a specified locktype 814 this is used for testing LOCKING_ANDX_CANCEL_LOCK 815****************************************************************************/ 816NTSTATUS cli_locktype(struct cli_state *cli, int fnum, 817 uint32 offset, uint32 len, int timeout, unsigned char locktype) 818{ 819 char *p; 820 int saved_timeout = cli->timeout; 821 822 memset(cli->outbuf,'\0',smb_size); 823 memset(cli->inbuf,'\0', smb_size); 824 825 set_message(cli->outbuf,8,0,True); 826 827 SCVAL(cli->outbuf,smb_com,SMBlockingX); 828 SSVAL(cli->outbuf,smb_tid,cli->cnum); 829 cli_setup_packet(cli); 830 831 SCVAL(cli->outbuf,smb_vwv0,0xFF); 832 SSVAL(cli->outbuf,smb_vwv2,fnum); 833 SCVAL(cli->outbuf,smb_vwv3,locktype); 834 SIVALS(cli->outbuf, smb_vwv4, timeout); 835 SSVAL(cli->outbuf,smb_vwv6,0); 836 SSVAL(cli->outbuf,smb_vwv7,1); 837 838 p = smb_buf(cli->outbuf); 839 SSVAL(p, 0, cli->pid); 840 SIVAL(p, 2, offset); 841 SIVAL(p, 6, len); 842 843 p += 10; 844 845 cli_setup_bcc(cli, p); 846 847 cli_send_smb(cli); 848 849 if (timeout != 0) { 850 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000); 851 } 852 853 if (!cli_receive_smb(cli)) { 854 cli->timeout = saved_timeout; 855 return NT_STATUS_UNSUCCESSFUL; 856 } 857 858 cli->timeout = saved_timeout; 859 860 return cli_nt_error(cli); 861} 862 863 864/**************************************************************************** 865 Lock a file. 866 note that timeout is in units of 2 milliseconds 867****************************************************************************/ 868BOOL cli_lock(struct cli_state *cli, int fnum, 869 uint32 offset, uint32 len, int timeout, enum brl_type lock_type) 870{ 871 char *p; 872 int saved_timeout = cli->timeout; 873 874 memset(cli->outbuf,'\0',smb_size); 875 memset(cli->inbuf,'\0', smb_size); 876 877 set_message(cli->outbuf,8,0,True); 878 879 SCVAL(cli->outbuf,smb_com,SMBlockingX); 880 SSVAL(cli->outbuf,smb_tid,cli->cnum); 881 cli_setup_packet(cli); 882 883 SCVAL(cli->outbuf,smb_vwv0,0xFF); 884 SSVAL(cli->outbuf,smb_vwv2,fnum); 885 SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0)); 886 SIVALS(cli->outbuf, smb_vwv4, timeout); 887 SSVAL(cli->outbuf,smb_vwv6,0); 888 SSVAL(cli->outbuf,smb_vwv7,1); 889 890 p = smb_buf(cli->outbuf); 891 SSVAL(p, 0, cli->pid); 892 SIVAL(p, 2, offset); 893 SIVAL(p, 6, len); 894 895 p += 10; 896 897 cli_setup_bcc(cli, p); 898 899 cli_send_smb(cli); 900 901 if (timeout != 0) { 902 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000); 903 } 904 905 if (!cli_receive_smb(cli)) { 906 cli->timeout = saved_timeout; 907 return False; 908 } 909 910 cli->timeout = saved_timeout; 911 912 if (cli_is_error(cli)) { 913 return False; 914 } 915 916 return True; 917} 918 919/**************************************************************************** 920 Unlock a file. 921****************************************************************************/ 922 923BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len) 924{ 925 char *p; 926 927 memset(cli->outbuf,'\0',smb_size); 928 memset(cli->inbuf,'\0',smb_size); 929 930 set_message(cli->outbuf,8,0,True); 931 932 SCVAL(cli->outbuf,smb_com,SMBlockingX); 933 SSVAL(cli->outbuf,smb_tid,cli->cnum); 934 cli_setup_packet(cli); 935 936 SCVAL(cli->outbuf,smb_vwv0,0xFF); 937 SSVAL(cli->outbuf,smb_vwv2,fnum); 938 SCVAL(cli->outbuf,smb_vwv3,0); 939 SIVALS(cli->outbuf, smb_vwv4, 0); 940 SSVAL(cli->outbuf,smb_vwv6,1); 941 SSVAL(cli->outbuf,smb_vwv7,0); 942 943 p = smb_buf(cli->outbuf); 944 SSVAL(p, 0, cli->pid); 945 SIVAL(p, 2, offset); 946 SIVAL(p, 6, len); 947 p += 10; 948 cli_setup_bcc(cli, p); 949 cli_send_smb(cli); 950 if (!cli_receive_smb(cli)) { 951 return False; 952 } 953 954 if (cli_is_error(cli)) { 955 return False; 956 } 957 958 return True; 959} 960 961/**************************************************************************** 962 Lock a file with 64 bit offsets. 963****************************************************************************/ 964 965BOOL cli_lock64(struct cli_state *cli, int fnum, 966 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type) 967{ 968 char *p; 969 int saved_timeout = cli->timeout; 970 int ltype; 971 972 if (! (cli->capabilities & CAP_LARGE_FILES)) { 973 return cli_lock(cli, fnum, offset, len, timeout, lock_type); 974 } 975 976 ltype = (lock_type == READ_LOCK? 1 : 0); 977 ltype |= LOCKING_ANDX_LARGE_FILES; 978 979 memset(cli->outbuf,'\0',smb_size); 980 memset(cli->inbuf,'\0', smb_size); 981 982 set_message(cli->outbuf,8,0,True); 983 984 SCVAL(cli->outbuf,smb_com,SMBlockingX); 985 SSVAL(cli->outbuf,smb_tid,cli->cnum); 986 cli_setup_packet(cli); 987 988 SCVAL(cli->outbuf,smb_vwv0,0xFF); 989 SSVAL(cli->outbuf,smb_vwv2,fnum); 990 SCVAL(cli->outbuf,smb_vwv3,ltype); 991 SIVALS(cli->outbuf, smb_vwv4, timeout); 992 SSVAL(cli->outbuf,smb_vwv6,0); 993 SSVAL(cli->outbuf,smb_vwv7,1); 994 995 p = smb_buf(cli->outbuf); 996 SIVAL(p, 0, cli->pid); 997 SOFF_T_R(p, 4, offset); 998 SOFF_T_R(p, 12, len); 999 p += 20; 1000 1001 cli_setup_bcc(cli, p); 1002 cli_send_smb(cli); 1003 1004 if (timeout != 0) { 1005 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000); 1006 } 1007 1008 if (!cli_receive_smb(cli)) { 1009 cli->timeout = saved_timeout; 1010 return False; 1011 } 1012 1013 cli->timeout = saved_timeout; 1014 1015 if (cli_is_error(cli)) { 1016 return False; 1017 } 1018 1019 return True; 1020} 1021 1022/**************************************************************************** 1023 Unlock a file with 64 bit offsets. 1024****************************************************************************/ 1025 1026BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len) 1027{ 1028 char *p; 1029 1030 if (! (cli->capabilities & CAP_LARGE_FILES)) { 1031 return cli_unlock(cli, fnum, offset, len); 1032 } 1033 1034 memset(cli->outbuf,'\0',smb_size); 1035 memset(cli->inbuf,'\0',smb_size); 1036 1037 set_message(cli->outbuf,8,0,True); 1038 1039 SCVAL(cli->outbuf,smb_com,SMBlockingX); 1040 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1041 cli_setup_packet(cli); 1042 1043 SCVAL(cli->outbuf,smb_vwv0,0xFF); 1044 SSVAL(cli->outbuf,smb_vwv2,fnum); 1045 SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES); 1046 SIVALS(cli->outbuf, smb_vwv4, 0); 1047 SSVAL(cli->outbuf,smb_vwv6,1); 1048 SSVAL(cli->outbuf,smb_vwv7,0); 1049 1050 p = smb_buf(cli->outbuf); 1051 SIVAL(p, 0, cli->pid); 1052 SOFF_T_R(p, 4, offset); 1053 SOFF_T_R(p, 12, len); 1054 p += 20; 1055 cli_setup_bcc(cli, p); 1056 cli_send_smb(cli); 1057 if (!cli_receive_smb(cli)) { 1058 return False; 1059 } 1060 1061 if (cli_is_error(cli)) { 1062 return False; 1063 } 1064 1065 return True; 1066} 1067 1068 1069/**************************************************************************** 1070 Do a SMBgetattrE call. 1071****************************************************************************/ 1072 1073BOOL cli_getattrE(struct cli_state *cli, int fd, 1074 uint16 *attr, SMB_BIG_UINT *size, 1075 time_t *c_time, time_t *a_time, time_t *m_time) 1076{ 1077 memset(cli->outbuf,'\0',smb_size); 1078 memset(cli->inbuf,'\0',smb_size); 1079 1080 set_message(cli->outbuf,1,0,True); 1081 1082 SCVAL(cli->outbuf,smb_com,SMBgetattrE); 1083 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1084 cli_setup_packet(cli); 1085 1086 SSVAL(cli->outbuf,smb_vwv0,fd); 1087 1088 cli_send_smb(cli); 1089 if (!cli_receive_smb(cli)) { 1090 return False; 1091 } 1092 1093 if (cli_is_error(cli)) { 1094 return False; 1095 } 1096 1097 if (size) { 1098 *size = IVAL(cli->inbuf, smb_vwv6); 1099 } 1100 1101 if (attr) { 1102 *attr = SVAL(cli->inbuf,smb_vwv10); 1103 } 1104 1105 if (c_time) { 1106 *c_time = make_unix_date3(cli->inbuf+smb_vwv0); 1107 } 1108 1109 if (a_time) { 1110 *a_time = make_unix_date3(cli->inbuf+smb_vwv2); 1111 } 1112 1113 if (m_time) { 1114 *m_time = make_unix_date3(cli->inbuf+smb_vwv4); 1115 } 1116 1117 return True; 1118} 1119 1120/**************************************************************************** 1121 Do a SMBgetatr call 1122****************************************************************************/ 1123 1124BOOL cli_getatr(struct cli_state *cli, const char *fname, 1125 uint16 *attr, size_t *size, time_t *t) 1126{ 1127 char *p; 1128 1129 memset(cli->outbuf,'\0',smb_size); 1130 memset(cli->inbuf,'\0',smb_size); 1131 1132 set_message(cli->outbuf,0,0,True); 1133 1134 SCVAL(cli->outbuf,smb_com,SMBgetatr); 1135 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1136 cli_setup_packet(cli); 1137 1138 p = smb_buf(cli->outbuf); 1139 *p++ = 4; 1140 p += clistr_push(cli, p, fname, -1, STR_TERMINATE); 1141 1142 cli_setup_bcc(cli, p); 1143 1144 cli_send_smb(cli); 1145 if (!cli_receive_smb(cli)) { 1146 return False; 1147 } 1148 1149 if (cli_is_error(cli)) { 1150 return False; 1151 } 1152 1153 if (size) { 1154 *size = IVAL(cli->inbuf, smb_vwv3); 1155 } 1156 1157 if (t) { 1158 *t = make_unix_date3(cli->inbuf+smb_vwv1); 1159 } 1160 1161 if (attr) { 1162 *attr = SVAL(cli->inbuf,smb_vwv0); 1163 } 1164 1165 1166 return True; 1167} 1168 1169/**************************************************************************** 1170 Do a SMBsetattrE call. 1171****************************************************************************/ 1172 1173BOOL cli_setattrE(struct cli_state *cli, int fd, 1174 time_t c_time, time_t a_time, time_t m_time) 1175 1176{ 1177 char *p; 1178 1179 memset(cli->outbuf,'\0',smb_size); 1180 memset(cli->inbuf,'\0',smb_size); 1181 1182 set_message(cli->outbuf,7,0,True); 1183 1184 SCVAL(cli->outbuf,smb_com,SMBsetattrE); 1185 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1186 cli_setup_packet(cli); 1187 1188 SSVAL(cli->outbuf,smb_vwv0, fd); 1189 put_dos_date3(cli->outbuf,smb_vwv1, c_time); 1190 put_dos_date3(cli->outbuf,smb_vwv3, a_time); 1191 put_dos_date3(cli->outbuf,smb_vwv5, m_time); 1192 1193 p = smb_buf(cli->outbuf); 1194 *p++ = 4; 1195 1196 cli_setup_bcc(cli, p); 1197 1198 cli_send_smb(cli); 1199 if (!cli_receive_smb(cli)) { 1200 return False; 1201 } 1202 1203 if (cli_is_error(cli)) { 1204 return False; 1205 } 1206 1207 return True; 1208} 1209 1210/**************************************************************************** 1211 Do a SMBsetatr call. 1212****************************************************************************/ 1213 1214BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t) 1215{ 1216 char *p; 1217 1218 memset(cli->outbuf,'\0',smb_size); 1219 memset(cli->inbuf,'\0',smb_size); 1220 1221 set_message(cli->outbuf,8,0,True); 1222 1223 SCVAL(cli->outbuf,smb_com,SMBsetatr); 1224 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1225 cli_setup_packet(cli); 1226 1227 SSVAL(cli->outbuf,smb_vwv0, attr); 1228 put_dos_date3(cli->outbuf,smb_vwv1, t); 1229 1230 p = smb_buf(cli->outbuf); 1231 *p++ = 4; 1232 p += clistr_push(cli, p, fname, -1, STR_TERMINATE); 1233 *p++ = 4; 1234 1235 cli_setup_bcc(cli, p); 1236 1237 cli_send_smb(cli); 1238 if (!cli_receive_smb(cli)) { 1239 return False; 1240 } 1241 1242 if (cli_is_error(cli)) { 1243 return False; 1244 } 1245 1246 return True; 1247} 1248 1249/**************************************************************************** 1250 Check for existance of a dir. 1251****************************************************************************/ 1252BOOL cli_chkpath(struct cli_state *cli, const char *path) 1253{ 1254 pstring path2; 1255 char *p; 1256 1257 pstrcpy(path2,path); 1258 trim_char(path2,'\0','\\'); 1259 if (!*path2) 1260 *path2 = '\\'; 1261 1262 memset(cli->outbuf,'\0',smb_size); 1263 set_message(cli->outbuf,0,0,True); 1264 SCVAL(cli->outbuf,smb_com,SMBchkpth); 1265 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1266 cli_setup_packet(cli); 1267 p = smb_buf(cli->outbuf); 1268 *p++ = 4; 1269 p += clistr_push(cli, p, path2, -1, STR_TERMINATE); 1270 1271 cli_setup_bcc(cli, p); 1272 1273 cli_send_smb(cli); 1274 if (!cli_receive_smb(cli)) { 1275 return False; 1276 } 1277 1278 if (cli_is_error(cli)) return False; 1279 1280 return True; 1281} 1282 1283/**************************************************************************** 1284 Query disk space. 1285****************************************************************************/ 1286 1287BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) 1288{ 1289 memset(cli->outbuf,'\0',smb_size); 1290 set_message(cli->outbuf,0,0,True); 1291 SCVAL(cli->outbuf,smb_com,SMBdskattr); 1292 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1293 cli_setup_packet(cli); 1294 1295 cli_send_smb(cli); 1296 if (!cli_receive_smb(cli)) { 1297 return False; 1298 } 1299 1300 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2); 1301 *total = SVAL(cli->inbuf,smb_vwv0); 1302 *avail = SVAL(cli->inbuf,smb_vwv3); 1303 1304 return True; 1305} 1306 1307/**************************************************************************** 1308 Create and open a temporary file. 1309****************************************************************************/ 1310 1311int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path) 1312{ 1313 int len; 1314 char *p; 1315 1316 memset(cli->outbuf,'\0',smb_size); 1317 memset(cli->inbuf,'\0',smb_size); 1318 1319 set_message(cli->outbuf,3,0,True); 1320 1321 SCVAL(cli->outbuf,smb_com,SMBctemp); 1322 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1323 cli_setup_packet(cli); 1324 1325 SSVAL(cli->outbuf,smb_vwv0,0); 1326 SIVALS(cli->outbuf,smb_vwv1,-1); 1327 1328 p = smb_buf(cli->outbuf); 1329 *p++ = 4; 1330 p += clistr_push(cli, p, path, -1, STR_TERMINATE); 1331 1332 cli_setup_bcc(cli, p); 1333 1334 cli_send_smb(cli); 1335 if (!cli_receive_smb(cli)) { 1336 return -1; 1337 } 1338 1339 if (cli_is_error(cli)) { 1340 return -1; 1341 } 1342 1343 /* despite the spec, the result has a -1, followed by 1344 length, followed by name */ 1345 p = smb_buf(cli->inbuf); 1346 p += 4; 1347 len = smb_buflen(cli->inbuf) - 4; 1348 if (len <= 0) return -1; 1349 1350 if (tmp_path) { 1351 pstring path2; 1352 clistr_pull(cli, path2, p, 1353 sizeof(path2), len, STR_ASCII); 1354 *tmp_path = SMB_STRDUP(path2); 1355 } 1356 1357 return SVAL(cli->inbuf,smb_vwv0); 1358} 1359 1360 1361/* 1362 send a raw ioctl - used by the torture code 1363*/ 1364NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob) 1365{ 1366 memset(cli->outbuf,'\0',smb_size); 1367 memset(cli->inbuf,'\0',smb_size); 1368 1369 set_message(cli->outbuf, 3, 0, True); 1370 SCVAL(cli->outbuf,smb_com,SMBioctl); 1371 cli_setup_packet(cli); 1372 1373 SSVAL(cli->outbuf, smb_vwv0, fnum); 1374 SSVAL(cli->outbuf, smb_vwv1, code>>16); 1375 SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF)); 1376 1377 cli_send_smb(cli); 1378 if (!cli_receive_smb(cli)) { 1379 return NT_STATUS_UNEXPECTED_NETWORK_ERROR; 1380 } 1381 1382 if (cli_is_error(cli)) { 1383 return cli_nt_error(cli); 1384 } 1385 1386 *blob = data_blob(NULL, 0); 1387 1388 return NT_STATUS_OK; 1389} 1390 1391/********************************************************* 1392 Set an extended attribute utility fn. 1393*********************************************************/ 1394 1395static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len, 1396 const char *ea_name, const char *ea_val, size_t ea_len) 1397{ 1398 unsigned int data_len = 0; 1399 char *data = NULL; 1400 char *rparam=NULL, *rdata=NULL; 1401 char *p; 1402 size_t ea_namelen = strlen(ea_name); 1403 1404 data_len = 4 + 4 + ea_namelen + 1 + ea_len; 1405 data = SMB_MALLOC(data_len); 1406 if (!data) { 1407 return False; 1408 } 1409 p = data; 1410 SIVAL(p,0,data_len); 1411 p += 4; 1412 SCVAL(p, 0, 0); /* EA flags. */ 1413 SCVAL(p, 1, ea_namelen); 1414 SSVAL(p, 2, ea_len); 1415 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */ 1416 memcpy(p+4+ea_namelen+1, ea_val, ea_len); 1417 1418 if (!cli_send_trans(cli, SMBtrans2, 1419 NULL, /* name */ 1420 -1, 0, /* fid, flags */ 1421 &setup, 1, 0, /* setup, length, max */ 1422 param, param_len, 2, /* param, length, max */ 1423 data, data_len, cli->max_xmit /* data, length, max */ 1424 )) { 1425 return False; 1426 } 1427 1428 if (!cli_receive_trans(cli, SMBtrans2, 1429 &rparam, ¶m_len, 1430 &rdata, &data_len)) { 1431 return False; 1432 } 1433 1434 SAFE_FREE(data); 1435 SAFE_FREE(rdata); 1436 SAFE_FREE(rparam); 1437 1438 return True; 1439} 1440 1441/********************************************************* 1442 Set an extended attribute on a pathname. 1443*********************************************************/ 1444 1445BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len) 1446{ 1447 uint16 setup = TRANSACT2_SETPATHINFO; 1448 unsigned int param_len = 0; 1449 char param[sizeof(pstring)+6]; 1450 size_t srclen = 2*(strlen(path)+1); 1451 char *p; 1452 1453 memset(param, 0, sizeof(param)); 1454 SSVAL(param,0,SMB_INFO_SET_EA); 1455 p = ¶m[6]; 1456 1457 p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE); 1458 param_len = PTR_DIFF(p, param); 1459 1460 return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len); 1461} 1462 1463/********************************************************* 1464 Set an extended attribute on an fnum. 1465*********************************************************/ 1466 1467BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len) 1468{ 1469 char param[6]; 1470 uint16 setup = TRANSACT2_SETFILEINFO; 1471 1472 memset(param, 0, 6); 1473 SSVAL(param,0,fnum); 1474 SSVAL(param,2,SMB_INFO_SET_EA); 1475 1476 return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len); 1477} 1478 1479/********************************************************* 1480 Get an extended attribute list tility fn. 1481*********************************************************/ 1482 1483static BOOL cli_get_ea_list(struct cli_state *cli, 1484 uint16 setup, char *param, unsigned int param_len, 1485 TALLOC_CTX *ctx, 1486 size_t *pnum_eas, 1487 struct ea_struct **pea_list) 1488{ 1489 unsigned int data_len = 0; 1490 unsigned int rparam_len, rdata_len; 1491 char *rparam=NULL, *rdata=NULL; 1492 char *p; 1493 size_t ea_size; 1494 size_t num_eas; 1495 BOOL ret = False; 1496 struct ea_struct *ea_list; 1497 1498 *pnum_eas = 0; 1499 *pea_list = NULL; 1500 1501 if (!cli_send_trans(cli, SMBtrans2, 1502 NULL, /* Name */ 1503 -1, 0, /* fid, flags */ 1504 &setup, 1, 0, /* setup, length, max */ 1505 param, param_len, 10, /* param, length, max */ 1506 NULL, data_len, cli->max_xmit /* data, length, max */ 1507 )) { 1508 return False; 1509 } 1510 1511 if (!cli_receive_trans(cli, SMBtrans2, 1512 &rparam, &rparam_len, 1513 &rdata, &rdata_len)) { 1514 return False; 1515 } 1516 1517 if (!rdata || rdata_len < 4) { 1518 goto out; 1519 } 1520 1521 ea_size = (size_t)IVAL(rdata,0); 1522 if (ea_size > rdata_len) { 1523 goto out; 1524 } 1525 1526 if (ea_size == 0) { 1527 /* No EA's present. */ 1528 ret = True; 1529 goto out; 1530 } 1531 1532 p = rdata + 4; 1533 ea_size -= 4; 1534 1535 /* Validate the EA list and count it. */ 1536 for (num_eas = 0; ea_size >= 4; num_eas++) { 1537 unsigned int ea_namelen = CVAL(p,1); 1538 unsigned int ea_valuelen = SVAL(p,2); 1539 if (ea_namelen == 0) { 1540 goto out; 1541 } 1542 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) { 1543 goto out; 1544 } 1545 ea_size -= 4 + ea_namelen + 1 + ea_valuelen; 1546 p += 4 + ea_namelen + 1 + ea_valuelen; 1547 } 1548 1549 if (num_eas == 0) { 1550 ret = True; 1551 goto out; 1552 } 1553 1554 *pnum_eas = num_eas; 1555 if (!pea_list) { 1556 /* Caller only wants number of EA's. */ 1557 ret = True; 1558 goto out; 1559 } 1560 1561 ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas); 1562 if (!ea_list) { 1563 goto out; 1564 } 1565 1566 ea_size = (size_t)IVAL(rdata,0); 1567 p = rdata + 4; 1568 1569 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) { 1570 struct ea_struct *ea = &ea_list[num_eas]; 1571 fstring unix_ea_name; 1572 unsigned int ea_namelen = CVAL(p,1); 1573 unsigned int ea_valuelen = SVAL(p,2); 1574 1575 ea->flags = CVAL(p,0); 1576 unix_ea_name[0] = '\0'; 1577 pull_ascii_fstring(unix_ea_name, p + 4); 1578 ea->name = talloc_strdup(ctx, unix_ea_name); 1579 /* Ensure the value is null terminated (in case it's a string). */ 1580 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1); 1581 if (!ea->value.data) { 1582 goto out; 1583 } 1584 if (ea_valuelen) { 1585 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen); 1586 } 1587 ea->value.data[ea_valuelen] = 0; 1588 ea->value.length--; 1589 p += 4 + ea_namelen + 1 + ea_valuelen; 1590 } 1591 1592 *pea_list = ea_list; 1593 ret = True; 1594 1595 out : 1596 1597 SAFE_FREE(rdata); 1598 SAFE_FREE(rparam); 1599 return ret; 1600} 1601 1602/********************************************************* 1603 Get an extended attribute list from a pathname. 1604*********************************************************/ 1605 1606BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path, 1607 TALLOC_CTX *ctx, 1608 size_t *pnum_eas, 1609 struct ea_struct **pea_list) 1610{ 1611 uint16 setup = TRANSACT2_QPATHINFO; 1612 unsigned int param_len = 0; 1613 char param[sizeof(pstring)+6]; 1614 char *p; 1615 1616 p = param; 1617 memset(p, 0, 6); 1618 SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS); 1619 p += 6; 1620 p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE); 1621 param_len = PTR_DIFF(p, param); 1622 1623 return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list); 1624} 1625 1626/********************************************************* 1627 Get an extended attribute list from an fnum. 1628*********************************************************/ 1629 1630BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum, 1631 TALLOC_CTX *ctx, 1632 size_t *pnum_eas, 1633 struct ea_struct **pea_list) 1634{ 1635 uint16 setup = TRANSACT2_QFILEINFO; 1636 char param[6]; 1637 1638 memset(param, 0, 6); 1639 SSVAL(param,0,fnum); 1640 SSVAL(param,2,SMB_INFO_SET_EA); 1641 1642 return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list); 1643} 1644