1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Trans2 Set File/Path Information Levels: 28 * 29 * SMB_INFO_STANDARD 30 * SMB_INFO_SET_EAS 31 * SMB_SET_FILE_BASIC_INFO 32 * SMB_SET_FILE_DISPOSITION_INFO 33 * SMB_SET_FILE_END_OF_FILE_INFO 34 * SMB_SET_FILE_ALLOCATION_INFO 35 * 36 * Handled Passthrough levels: 37 * SMB_FILE_BASIC_INFORMATION 38 * SMB_FILE_RENAME_INFORMATION 39 * SMB_FILE_LINK_INFORMATION 40 * SMB_FILE_DISPOSITION_INFORMATION 41 * SMB_FILE_END_OF_FILE_INFORMATION 42 * SMB_FILE_ALLOCATION_INFORMATION 43 * 44 * Internal levels representing non trans2 requests 45 * SMB_SET_INFORMATION 46 * SMB_SET_INFORMATION2 47 */ 48 49 /* 50 * Setting timestamps: 51 * The behaviour when the time field is set to -1 is not documented 52 * but is generally treated like 0, meaning that that server file 53 * system assigned value need not be changed. 54 * 55 * Setting attributes - FILE_ATTRIBUTE_NORMAL: 56 * SMB_SET_INFORMATION - 57 * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set 58 * do NOT change the file's attributes. 59 * SMB_SET_BASIC_INFO - 60 * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set 61 * clear (0) the file's attributes. 62 * - if the specified attributes are 0 do NOT change the file's 63 * attributes. 64 */ 65 66 #include <smbsrv/smb_kproto.h> 67 #include <smbsrv/smb_fsops.h> 68 69 typedef struct smb_setinfo { 70 uint16_t si_infolev; 71 smb_xa_t *si_xa; 72 smb_node_t *si_node; 73 } smb_setinfo_t; 74 75 /* 76 * These functions all return 0 (success) or -1 (error). 77 * They set error details in the sr when appropriate. 78 */ 79 static int smb_set_by_fid(smb_request_t *, smb_xa_t *, uint16_t); 80 static int smb_set_by_path(smb_request_t *, smb_xa_t *, uint16_t, char *); 81 static int smb_set_fileinfo(smb_request_t *, smb_setinfo_t *); 82 static int smb_set_information(smb_request_t *, smb_setinfo_t *); 83 static int smb_set_information2(smb_request_t *, smb_setinfo_t *); 84 static int smb_set_standard_info(smb_request_t *, smb_setinfo_t *); 85 static int smb_set_basic_info(smb_request_t *, smb_setinfo_t *); 86 static int smb_set_disposition_info(smb_request_t *, smb_setinfo_t *); 87 static int smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *); 88 static int smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *); 89 static int smb_set_rename_info(smb_request_t *sr, smb_setinfo_t *); 90 91 /* 92 * smb_com_trans2_set_file_information 93 */ 94 smb_sdrc_t 95 smb_com_trans2_set_file_information(smb_request_t *sr, smb_xa_t *xa) 96 { 97 uint16_t infolev; 98 99 if (smb_mbc_decodef(&xa->req_param_mb, "ww", 100 &sr->smb_fid, &infolev) != 0) 101 return (SDRC_ERROR); 102 103 if (smb_set_by_fid(sr, xa, infolev) != 0) 104 return (SDRC_ERROR); 105 106 return (SDRC_SUCCESS); 107 } 108 109 /* 110 * smb_com_trans2_set_path_information 111 */ 112 smb_sdrc_t 113 smb_com_trans2_set_path_information(smb_request_t *sr, smb_xa_t *xa) 114 { 115 uint16_t infolev; 116 char *path; 117 118 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { 119 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 120 ERRDOS, ERROR_INVALID_FUNCTION); 121 return (SDRC_ERROR); 122 } 123 124 if (smb_mbc_decodef(&xa->req_param_mb, "%w4.u", 125 sr, &infolev, &path) != 0) 126 return (SDRC_ERROR); 127 128 if (smb_set_by_path(sr, xa, infolev, path) != 0) 129 return (SDRC_ERROR); 130 131 return (SDRC_SUCCESS); 132 } 133 134 /* 135 * smb_com_set_information (aka setattr) 136 */ 137 smb_sdrc_t 138 smb_pre_set_information(smb_request_t *sr) 139 { 140 DTRACE_SMB_1(op__SetInformation__start, smb_request_t *, sr); 141 return (SDRC_SUCCESS); 142 } 143 144 void 145 smb_post_set_information(smb_request_t *sr) 146 { 147 DTRACE_SMB_1(op__SetInformation__done, smb_request_t *, sr); 148 } 149 150 smb_sdrc_t 151 smb_com_set_information(smb_request_t *sr) 152 { 153 uint16_t infolev = SMB_SET_INFORMATION; 154 char *path; 155 156 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { 157 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 158 ERRDOS, ERROR_ACCESS_DENIED); 159 return (SDRC_ERROR); 160 } 161 162 if (smbsr_decode_data(sr, "%S", sr, &path) != 0) 163 return (SDRC_ERROR); 164 165 if (smb_set_by_path(sr, NULL, infolev, path) != 0) 166 return (SDRC_ERROR); 167 168 if (smbsr_encode_empty_result(sr) != 0) 169 return (SDRC_ERROR); 170 171 return (SDRC_SUCCESS); 172 } 173 174 /* 175 * smb_com_set_information2 (aka setattre) 176 */ 177 smb_sdrc_t 178 smb_pre_set_information2(smb_request_t *sr) 179 { 180 DTRACE_SMB_1(op__SetInformation2__start, smb_request_t *, sr); 181 return (SDRC_SUCCESS); 182 } 183 184 void 185 smb_post_set_information2(smb_request_t *sr) 186 { 187 DTRACE_SMB_1(op__SetInformation2__done, smb_request_t *, sr); 188 } 189 190 smb_sdrc_t 191 smb_com_set_information2(smb_request_t *sr) 192 { 193 uint16_t infolev = SMB_SET_INFORMATION2; 194 195 if (smbsr_decode_vwv(sr, "w", &sr->smb_fid) != 0) 196 return (SDRC_ERROR); 197 198 if (smb_set_by_fid(sr, NULL, infolev) != 0) 199 return (SDRC_ERROR); 200 201 if (smbsr_encode_empty_result(sr) != 0) 202 return (SDRC_ERROR); 203 204 return (SDRC_SUCCESS); 205 } 206 207 /* 208 * smb_set_by_fid 209 * 210 * Common code for setting file information by open file id. 211 * Use the id to identify the node object and invoke smb_set_fileinfo 212 * for that node. 213 * 214 * Setting attributes on a named pipe by id is handled by simply 215 * returning success. 216 */ 217 static int 218 smb_set_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev) 219 { 220 int rc; 221 smb_setinfo_t sinfo; 222 223 if (SMB_TREE_IS_READONLY(sr)) { 224 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 225 ERRDOS, ERROR_ACCESS_DENIED); 226 return (-1); 227 } 228 229 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) 230 return (0); 231 232 smbsr_lookup_file(sr); 233 if (sr->fid_ofile == NULL) { 234 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 235 return (-1); 236 } 237 238 if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) { 239 smbsr_release_file(sr); 240 return (0); 241 } 242 243 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 244 245 sinfo.si_xa = xa; 246 sinfo.si_infolev = infolev; 247 sinfo.si_node = sr->fid_ofile->f_node; 248 rc = smb_set_fileinfo(sr, &sinfo); 249 250 smbsr_release_file(sr); 251 return (rc); 252 } 253 254 /* 255 * smb_set_by_path 256 * 257 * Common code for setting file information by file name. 258 * Use the file name to identify the node object and invoke 259 * smb_set_fileinfo for that node. 260 * 261 * Setting attributes on a named pipe by name is an error and 262 * is handled in the calling functions so that they can return 263 * the appropriate error status code (which differs by caller). 264 */ 265 static int 266 smb_set_by_path(smb_request_t *sr, smb_xa_t *xa, 267 uint16_t infolev, char *path) 268 { 269 int rc; 270 smb_setinfo_t sinfo; 271 smb_node_t *node, *dnode; 272 char *name; 273 274 if (SMB_TREE_IS_READONLY(sr)) { 275 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 276 ERRDOS, ERROR_ACCESS_DENIED); 277 return (-1); 278 } 279 280 name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 281 rc = smb_pathname_reduce(sr, sr->user_cr, path, 282 sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode, name); 283 if (rc == 0) { 284 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS, 285 sr->tid_tree->t_snode, dnode, name, &node); 286 smb_node_release(dnode); 287 } 288 kmem_free(name, MAXNAMELEN); 289 290 if (rc != 0) { 291 if (rc == ENOENT) { 292 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 293 ERRDOS, ERROR_FILE_NOT_FOUND); 294 } else { 295 smbsr_errno(sr, rc); 296 } 297 return (-1); 298 } 299 300 /* Break any conflicting oplock for subsequent attribute setting */ 301 if (smb_oplock_conflict(node, sr->session, NULL)) { 302 (void) smb_oplock_break(node, sr->session, B_FALSE); 303 } 304 305 sinfo.si_xa = xa; 306 sinfo.si_infolev = infolev; 307 sinfo.si_node = node; 308 rc = smb_set_fileinfo(sr, &sinfo); 309 310 smb_node_release(node); 311 return (rc); 312 } 313 314 /* 315 * smb_set_fileinfo 316 * 317 * For compatibility with windows servers, SMB_FILE_LINK_INFORMATION 318 * is handled by returning NT_STATUS_NOT_SUPPORTED. 319 */ 320 static int 321 smb_set_fileinfo(smb_request_t *sr, smb_setinfo_t *sinfo) 322 { 323 switch (sinfo->si_infolev) { 324 case SMB_SET_INFORMATION: 325 return (smb_set_information(sr, sinfo)); 326 327 case SMB_SET_INFORMATION2: 328 return (smb_set_information2(sr, sinfo)); 329 330 case SMB_INFO_STANDARD: 331 return (smb_set_standard_info(sr, sinfo)); 332 333 case SMB_INFO_SET_EAS: 334 /* EAs not supported */ 335 return (0); 336 337 case SMB_SET_FILE_BASIC_INFO: 338 case SMB_FILE_BASIC_INFORMATION: 339 return (smb_set_basic_info(sr, sinfo)); 340 341 case SMB_SET_FILE_DISPOSITION_INFO: 342 case SMB_FILE_DISPOSITION_INFORMATION: 343 return (smb_set_disposition_info(sr, sinfo)); 344 345 case SMB_SET_FILE_END_OF_FILE_INFO: 346 case SMB_FILE_END_OF_FILE_INFORMATION: 347 return (smb_set_eof_info(sr, sinfo)); 348 349 case SMB_SET_FILE_ALLOCATION_INFO: 350 case SMB_FILE_ALLOCATION_INFORMATION: 351 return (smb_set_alloc_info(sr, sinfo)); 352 353 case SMB_FILE_RENAME_INFORMATION: 354 return (smb_set_rename_info(sr, sinfo)); 355 356 case SMB_FILE_LINK_INFORMATION: 357 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 358 ERRDOS, ERROR_NOT_SUPPORTED); 359 return (-1); 360 default: 361 break; 362 } 363 364 smbsr_error(sr, NT_STATUS_INVALID_INFO_CLASS, 365 ERRDOS, ERROR_INVALID_PARAMETER); 366 return (-1); 367 } 368 369 /* 370 * smb_set_information 371 * 372 * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the 373 * target is not a directory. 374 * 375 * For compatibility with Windows Servers, if the specified 376 * attributes have ONLY FILE_ATTRIBUTE_NORMAL set do NOT change 377 * the file's attributes. 378 */ 379 static int 380 smb_set_information(smb_request_t *sr, smb_setinfo_t *sinfo) 381 { 382 int rc; 383 uint16_t attributes; 384 smb_node_t *node = sinfo->si_node; 385 smb_attr_t attr; 386 uint32_t mtime; 387 388 if (smbsr_decode_vwv(sr, "wl10.", &attributes, &mtime) != 0) 389 return (-1); 390 391 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) && 392 (!smb_node_is_dir(node))) { 393 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 394 ERRDOS, ERROR_INVALID_PARAMETER); 395 return (-1); 396 } 397 398 bzero(&attr, sizeof (smb_attr_t)); 399 if (attributes != FILE_ATTRIBUTE_NORMAL) { 400 attr.sa_dosattr = attributes; 401 attr.sa_mask |= SMB_AT_DOSATTR; 402 } 403 404 if (mtime != 0 && mtime != UINT_MAX) { 405 attr.sa_vattr.va_mtime.tv_sec = 406 smb_time_local_to_gmt(sr, mtime); 407 attr.sa_mask |= SMB_AT_MTIME; 408 } 409 410 rc = smb_node_setattr(sr, node, sr->user_cr, NULL, &attr); 411 if (rc != 0) { 412 smbsr_errno(sr, rc); 413 return (-1); 414 } 415 416 return (0); 417 } 418 419 /* 420 * smb_set_information2 421 */ 422 static int 423 smb_set_information2(smb_request_t *sr, smb_setinfo_t *sinfo) 424 { 425 int rc; 426 uint32_t crtime, atime, mtime; 427 smb_attr_t attr; 428 429 if (smbsr_decode_vwv(sr, "yyy", &crtime, &atime, &mtime) != 0) 430 return (-1); 431 432 bzero(&attr, sizeof (smb_attr_t)); 433 if (mtime != 0 && mtime != UINT_MAX) { 434 attr.sa_vattr.va_mtime.tv_sec = 435 smb_time_local_to_gmt(sr, mtime); 436 attr.sa_mask |= SMB_AT_MTIME; 437 } 438 439 if (crtime != 0 && crtime != UINT_MAX) { 440 attr.sa_crtime.tv_sec = smb_time_local_to_gmt(sr, crtime); 441 attr.sa_mask |= SMB_AT_CRTIME; 442 } 443 444 if (atime != 0 && atime != UINT_MAX) { 445 attr.sa_vattr.va_atime.tv_sec = 446 smb_time_local_to_gmt(sr, atime); 447 attr.sa_mask |= SMB_AT_ATIME; 448 } 449 450 rc = smb_node_setattr(sr, sinfo->si_node, sr->user_cr, 451 sr->fid_ofile, &attr); 452 if (rc != 0) { 453 smbsr_errno(sr, rc); 454 return (-1); 455 } 456 457 return (0); 458 } 459 460 /* 461 * smb_set_standard_info 462 * 463 * Sets standard file/path information. 464 */ 465 static int 466 smb_set_standard_info(smb_request_t *sr, smb_setinfo_t *sinfo) 467 { 468 smb_attr_t attr; 469 uint32_t crtime, atime, mtime; 470 smb_node_t *node = sinfo->si_node; 471 int rc; 472 473 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "yyy", 474 &crtime, &atime, &mtime) != 0) { 475 return (-1); 476 } 477 478 bzero(&attr, sizeof (smb_attr_t)); 479 if (mtime != 0 && mtime != (uint32_t)-1) { 480 attr.sa_vattr.va_mtime.tv_sec = 481 smb_time_local_to_gmt(sr, mtime); 482 attr.sa_mask |= SMB_AT_MTIME; 483 } 484 485 if (crtime != 0 && crtime != (uint32_t)-1) { 486 attr.sa_crtime.tv_sec = smb_time_local_to_gmt(sr, crtime); 487 attr.sa_mask |= SMB_AT_CRTIME; 488 } 489 490 if (atime != 0 && atime != (uint32_t)-1) { 491 attr.sa_vattr.va_atime.tv_sec = 492 smb_time_local_to_gmt(sr, atime); 493 attr.sa_mask |= SMB_AT_ATIME; 494 } 495 496 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 497 if (rc != 0) { 498 smbsr_errno(sr, rc); 499 return (-1); 500 } 501 502 return (0); 503 } 504 505 /* 506 * smb_set_basic_info 507 * 508 * Sets basic file/path information. 509 * 510 * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the 511 * target is not a directory. 512 * 513 * For compatibility with windows servers: 514 * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set 515 * clear (0) the file's attributes. 516 * - if the specified attributes are 0 do NOT change the file's attributes. 517 */ 518 static int 519 smb_set_basic_info(smb_request_t *sr, smb_setinfo_t *sinfo) 520 { 521 int rc; 522 uint64_t crtime, atime, mtime, ctime; 523 uint16_t attributes; 524 smb_attr_t attr; 525 smb_node_t *node = sinfo->si_node; 526 527 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "qqqqw", 528 &crtime, &atime, &mtime, &ctime, &attributes) != 0) { 529 return (-1); 530 } 531 532 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) && 533 (!smb_node_is_dir(node))) { 534 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 535 ERRDOS, ERROR_INVALID_PARAMETER); 536 return (-1); 537 } 538 539 bzero(&attr, sizeof (smb_attr_t)); 540 if (ctime != 0 && ctime != (uint64_t)-1) { 541 smb_time_nt_to_unix(ctime, &attr.sa_vattr.va_ctime); 542 attr.sa_mask |= SMB_AT_CTIME; 543 } 544 545 if (crtime != 0 && crtime != (uint64_t)-1) { 546 smb_time_nt_to_unix(crtime, &attr.sa_crtime); 547 attr.sa_mask |= SMB_AT_CRTIME; 548 } 549 550 if (mtime != 0 && mtime != (uint64_t)-1) { 551 smb_time_nt_to_unix(mtime, &attr.sa_vattr.va_mtime); 552 attr.sa_mask |= SMB_AT_MTIME; 553 } 554 555 if (atime != 0 && atime != (uint64_t)-1) { 556 smb_time_nt_to_unix(atime, &attr.sa_vattr.va_atime); 557 attr.sa_mask |= SMB_AT_ATIME; 558 } 559 560 if (attributes != 0) { 561 attr.sa_dosattr = attributes; 562 attr.sa_mask |= SMB_AT_DOSATTR; 563 } 564 565 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 566 if (rc != 0) { 567 smbsr_errno(sr, rc); 568 return (-1); 569 } 570 571 return (0); 572 } 573 574 /* 575 * smb_set_eof_info 576 */ 577 static int 578 smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *sinfo) 579 { 580 int rc; 581 smb_attr_t attr; 582 uint64_t eof; 583 smb_node_t *node = sinfo->si_node; 584 585 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "q", &eof) != 0) 586 return (-1); 587 588 if (smb_node_is_dir(node)) { 589 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 590 ERRDOS, ERROR_INVALID_PARAMETER); 591 return (-1); 592 } 593 594 bzero(&attr, sizeof (smb_attr_t)); 595 attr.sa_mask = SMB_AT_SIZE; 596 attr.sa_vattr.va_size = (u_offset_t)eof; 597 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 598 if (rc != 0) { 599 smbsr_errno(sr, rc); 600 return (-1); 601 } 602 603 return (0); 604 } 605 606 /* 607 * smb_set_alloc_info 608 */ 609 static int 610 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *sinfo) 611 { 612 int rc; 613 smb_attr_t attr; 614 uint64_t allocsz; 615 smb_node_t *node = sinfo->si_node; 616 617 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "q", &allocsz) != 0) 618 return (-1); 619 620 if (smb_node_is_dir(node)) { 621 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 622 ERRDOS, ERROR_INVALID_PARAMETER); 623 return (-1); 624 } 625 626 bzero(&attr, sizeof (smb_attr_t)); 627 attr.sa_mask = SMB_AT_ALLOCSZ; 628 attr.sa_allocsz = (u_offset_t)allocsz; 629 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 630 if (rc != 0) { 631 smbsr_errno(sr, rc); 632 return (-1); 633 } 634 635 return (0); 636 } 637 638 /* 639 * smb_set_disposition_info 640 * 641 * Set/Clear DELETE_ON_CLOSE flag for an open file. 642 * File should have been opened with DELETE access otherwise 643 * the operation is not permitted. 644 * 645 * NOTE: The node should be marked delete-on-close upon the receipt 646 * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set. 647 * It is different than both SmbNtCreateAndX and SmbNtTransact, which 648 * set delete-on-close on the ofile and defer setting the flag on the 649 * node until the file is closed. 650 * 651 * Observation of Windows 2000 indicates the following: 652 * 653 * 1) If a file is not opened with delete-on-close create options and 654 * the delete-on-close is set via Trans2SetFileInfo(SetDispositionInfo) 655 * using that open file handle, any subsequent open requests will fail 656 * with DELETE_PENDING. 657 * 658 * 2) If a file is opened with delete-on-close create options and the 659 * client attempts to unset delete-on-close via Trans2SetFileInfo 660 * (SetDispositionInfo) prior to the file close, any subsequent open 661 * requests will still fail with DELETE_PENDING after the file is closed. 662 * 663 * 3) If a file is opened with delete-on-close create options and that 664 * file handle (not the last open handle and the only file handle 665 * with delete-on-close set) is closed. Any subsequent open requests 666 * will fail with DELETE_PENDING. Unsetting delete-on-close via 667 * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the 668 * node delete-on-close flag, which will result in the file not being 669 * removed even after the last file handle is closed. 670 */ 671 static int 672 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *sinfo) 673 { 674 unsigned char mark_delete; 675 uint32_t flags = 0; 676 677 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "b", &mark_delete) != 0) 678 return (-1); 679 680 if ((sr->fid_ofile == NULL) || 681 !(smb_ofile_granted_access(sr->fid_ofile) & DELETE)) { 682 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 683 ERRDOS, ERROR_ACCESS_DENIED); 684 return (-1); 685 } 686 687 if (mark_delete) { 688 if (SMB_TREE_SUPPORTS_CATIA(sr)) 689 flags |= SMB_CATIA; 690 691 if (smb_node_set_delete_on_close(sinfo->si_node, 692 sr->user_cr, flags)) { 693 smbsr_error(sr, NT_STATUS_CANNOT_DELETE, 694 ERRDOS, ERROR_ACCESS_DENIED); 695 return (-1); 696 } 697 } else { 698 smb_node_reset_delete_on_close(sinfo->si_node); 699 } 700 return (0); 701 } 702 703 /* 704 * smb_set_rename_info 705 * 706 * Explicity specified parameter validation rules: 707 * - If rootdir is not NULL respond with NT_STATUS_INVALID_PARAMETER. 708 * - If the filename contains a separator character respond with 709 * NT_STATUS_INVALID_PARAMETER. 710 */ 711 static int 712 smb_set_rename_info(smb_request_t *sr, smb_setinfo_t *sinfo) 713 { 714 int rc; 715 uint32_t flags, rootdir, namelen; 716 char *fname; 717 718 rc = smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "lll", 719 &flags, &rootdir, &namelen); 720 if (rc == 0) { 721 rc = smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "%#U", 722 sr, namelen, &fname); 723 } 724 if (rc != 0) 725 return (-1); 726 727 if ((rootdir != 0) || (namelen == 0) || (namelen >= MAXNAMELEN)) { 728 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 729 ERRDOS, ERROR_INVALID_PARAMETER); 730 return (-1); 731 } 732 733 if (strchr(fname, '\\') != NULL) { 734 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 735 ERRDOS, ERROR_NOT_SUPPORTED); 736 return (-1); 737 } 738 739 rc = smb_trans2_rename(sr, sinfo->si_node, fname, flags); 740 741 return ((rc == 0) ? 0 : -1); 742 } 743