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 2010 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); 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 smb_fqi_t *fqi = &sr->arg.dirop.fqi; 117 118 if (STYPE_ISIPC(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, &fqi->fq_path.pn_path) != 0) 126 return (SDRC_ERROR); 127 128 if (smb_set_by_path(sr, xa, infolev) != 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 smb_fqi_t *fqi = &sr->arg.dirop.fqi; 155 156 if (STYPE_ISIPC(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, &fqi->fq_path.pn_path) != 0) 163 return (SDRC_ERROR); 164 165 if (smb_set_by_path(sr, NULL, infolev) != 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_ISIPC(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 * Path should be set in sr->arg.dirop.fqi.fq_path prior to 262 * calling smb_set_by_path. 263 * 264 * Setting attributes on a named pipe by name is an error and 265 * is handled in the calling functions so that they can return 266 * the appropriate error status code (which differs by caller). 267 */ 268 static int 269 smb_set_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev) 270 { 271 int rc; 272 smb_setinfo_t sinfo; 273 smb_node_t *node, *dnode; 274 char *name; 275 smb_pathname_t *pn; 276 277 if (SMB_TREE_IS_READONLY(sr)) { 278 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 279 ERRDOS, ERROR_ACCESS_DENIED); 280 return (-1); 281 } 282 283 pn = &sr->arg.dirop.fqi.fq_path; 284 smb_pathname_init(sr, pn, pn->pn_path); 285 if (!smb_pathname_validate(sr, pn)) 286 return (-1); 287 288 name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 289 rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path, 290 sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode, name); 291 if (rc == 0) { 292 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS, 293 sr->tid_tree->t_snode, dnode, name, &node); 294 smb_node_release(dnode); 295 } 296 kmem_free(name, MAXNAMELEN); 297 298 if (rc != 0) { 299 if (rc == ENOENT) { 300 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, 301 ERRDOS, ERROR_FILE_NOT_FOUND); 302 } else { 303 smbsr_errno(sr, rc); 304 } 305 return (-1); 306 } 307 308 /* Break any conflicting oplock for subsequent attribute setting */ 309 if (smb_oplock_conflict(node, sr->session, NULL)) { 310 (void) smb_oplock_break(node, sr->session, B_FALSE); 311 } 312 313 sinfo.si_xa = xa; 314 sinfo.si_infolev = infolev; 315 sinfo.si_node = node; 316 rc = smb_set_fileinfo(sr, &sinfo); 317 318 smb_node_release(node); 319 return (rc); 320 } 321 322 /* 323 * smb_set_fileinfo 324 * 325 * For compatibility with windows servers, SMB_FILE_LINK_INFORMATION 326 * is handled by returning NT_STATUS_NOT_SUPPORTED. 327 */ 328 static int 329 smb_set_fileinfo(smb_request_t *sr, smb_setinfo_t *sinfo) 330 { 331 switch (sinfo->si_infolev) { 332 case SMB_SET_INFORMATION: 333 return (smb_set_information(sr, sinfo)); 334 335 case SMB_SET_INFORMATION2: 336 return (smb_set_information2(sr, sinfo)); 337 338 case SMB_INFO_STANDARD: 339 return (smb_set_standard_info(sr, sinfo)); 340 341 case SMB_INFO_SET_EAS: 342 /* EAs not supported */ 343 return (0); 344 345 case SMB_SET_FILE_BASIC_INFO: 346 case SMB_FILE_BASIC_INFORMATION: 347 return (smb_set_basic_info(sr, sinfo)); 348 349 case SMB_SET_FILE_DISPOSITION_INFO: 350 case SMB_FILE_DISPOSITION_INFORMATION: 351 return (smb_set_disposition_info(sr, sinfo)); 352 353 case SMB_SET_FILE_END_OF_FILE_INFO: 354 case SMB_FILE_END_OF_FILE_INFORMATION: 355 return (smb_set_eof_info(sr, sinfo)); 356 357 case SMB_SET_FILE_ALLOCATION_INFO: 358 case SMB_FILE_ALLOCATION_INFORMATION: 359 return (smb_set_alloc_info(sr, sinfo)); 360 361 case SMB_FILE_RENAME_INFORMATION: 362 return (smb_set_rename_info(sr, sinfo)); 363 364 case SMB_FILE_LINK_INFORMATION: 365 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 366 ERRDOS, ERROR_NOT_SUPPORTED); 367 return (-1); 368 default: 369 break; 370 } 371 372 smbsr_error(sr, NT_STATUS_INVALID_INFO_CLASS, 373 ERRDOS, ERROR_INVALID_PARAMETER); 374 return (-1); 375 } 376 377 /* 378 * smb_set_information 379 * 380 * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the 381 * target is not a directory. 382 * 383 * For compatibility with Windows Servers, if the specified 384 * attributes have ONLY FILE_ATTRIBUTE_NORMAL set do NOT change 385 * the file's attributes. 386 */ 387 static int 388 smb_set_information(smb_request_t *sr, smb_setinfo_t *sinfo) 389 { 390 int rc; 391 uint16_t attributes; 392 smb_node_t *node = sinfo->si_node; 393 smb_attr_t attr; 394 uint32_t mtime; 395 396 if (smbsr_decode_vwv(sr, "wl10.", &attributes, &mtime) != 0) 397 return (-1); 398 399 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) && 400 (!smb_node_is_dir(node))) { 401 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 402 ERRDOS, ERROR_INVALID_PARAMETER); 403 return (-1); 404 } 405 406 bzero(&attr, sizeof (smb_attr_t)); 407 if (attributes != FILE_ATTRIBUTE_NORMAL) { 408 attr.sa_dosattr = attributes; 409 attr.sa_mask |= SMB_AT_DOSATTR; 410 } 411 412 if (mtime != 0 && mtime != UINT_MAX) { 413 attr.sa_vattr.va_mtime.tv_sec = 414 smb_time_local_to_gmt(sr, mtime); 415 attr.sa_mask |= SMB_AT_MTIME; 416 } 417 418 rc = smb_node_setattr(sr, node, sr->user_cr, NULL, &attr); 419 if (rc != 0) { 420 smbsr_errno(sr, rc); 421 return (-1); 422 } 423 424 return (0); 425 } 426 427 /* 428 * smb_set_information2 429 */ 430 static int 431 smb_set_information2(smb_request_t *sr, smb_setinfo_t *sinfo) 432 { 433 int rc; 434 uint32_t crtime, atime, mtime; 435 smb_attr_t attr; 436 437 if (smbsr_decode_vwv(sr, "yyy", &crtime, &atime, &mtime) != 0) 438 return (-1); 439 440 bzero(&attr, sizeof (smb_attr_t)); 441 if (mtime != 0 && mtime != UINT_MAX) { 442 attr.sa_vattr.va_mtime.tv_sec = 443 smb_time_local_to_gmt(sr, mtime); 444 attr.sa_mask |= SMB_AT_MTIME; 445 } 446 447 if (crtime != 0 && crtime != UINT_MAX) { 448 attr.sa_crtime.tv_sec = smb_time_local_to_gmt(sr, crtime); 449 attr.sa_mask |= SMB_AT_CRTIME; 450 } 451 452 if (atime != 0 && atime != UINT_MAX) { 453 attr.sa_vattr.va_atime.tv_sec = 454 smb_time_local_to_gmt(sr, atime); 455 attr.sa_mask |= SMB_AT_ATIME; 456 } 457 458 rc = smb_node_setattr(sr, sinfo->si_node, sr->user_cr, 459 sr->fid_ofile, &attr); 460 if (rc != 0) { 461 smbsr_errno(sr, rc); 462 return (-1); 463 } 464 465 return (0); 466 } 467 468 /* 469 * smb_set_standard_info 470 * 471 * Sets standard file/path information. 472 */ 473 static int 474 smb_set_standard_info(smb_request_t *sr, smb_setinfo_t *sinfo) 475 { 476 smb_attr_t attr; 477 uint32_t crtime, atime, mtime; 478 smb_node_t *node = sinfo->si_node; 479 int rc; 480 481 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "yyy", 482 &crtime, &atime, &mtime) != 0) { 483 return (-1); 484 } 485 486 bzero(&attr, sizeof (smb_attr_t)); 487 if (mtime != 0 && mtime != (uint32_t)-1) { 488 attr.sa_vattr.va_mtime.tv_sec = 489 smb_time_local_to_gmt(sr, mtime); 490 attr.sa_mask |= SMB_AT_MTIME; 491 } 492 493 if (crtime != 0 && crtime != (uint32_t)-1) { 494 attr.sa_crtime.tv_sec = smb_time_local_to_gmt(sr, crtime); 495 attr.sa_mask |= SMB_AT_CRTIME; 496 } 497 498 if (atime != 0 && atime != (uint32_t)-1) { 499 attr.sa_vattr.va_atime.tv_sec = 500 smb_time_local_to_gmt(sr, atime); 501 attr.sa_mask |= SMB_AT_ATIME; 502 } 503 504 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 505 if (rc != 0) { 506 smbsr_errno(sr, rc); 507 return (-1); 508 } 509 510 return (0); 511 } 512 513 /* 514 * smb_set_basic_info 515 * 516 * Sets basic file/path information. 517 * 518 * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the 519 * target is not a directory. 520 * 521 * For compatibility with windows servers: 522 * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set 523 * clear (0) the file's attributes. 524 * - if the specified attributes are 0 do NOT change the file's attributes. 525 */ 526 static int 527 smb_set_basic_info(smb_request_t *sr, smb_setinfo_t *sinfo) 528 { 529 int rc; 530 uint64_t crtime, atime, mtime, ctime; 531 uint16_t attributes; 532 smb_attr_t attr; 533 smb_node_t *node = sinfo->si_node; 534 535 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "qqqqw", 536 &crtime, &atime, &mtime, &ctime, &attributes) != 0) { 537 return (-1); 538 } 539 540 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) && 541 (!smb_node_is_dir(node))) { 542 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 543 ERRDOS, ERROR_INVALID_PARAMETER); 544 return (-1); 545 } 546 547 bzero(&attr, sizeof (smb_attr_t)); 548 if (ctime != 0 && ctime != (uint64_t)-1) { 549 smb_time_nt_to_unix(ctime, &attr.sa_vattr.va_ctime); 550 attr.sa_mask |= SMB_AT_CTIME; 551 } 552 553 if (crtime != 0 && crtime != (uint64_t)-1) { 554 smb_time_nt_to_unix(crtime, &attr.sa_crtime); 555 attr.sa_mask |= SMB_AT_CRTIME; 556 } 557 558 if (mtime != 0 && mtime != (uint64_t)-1) { 559 smb_time_nt_to_unix(mtime, &attr.sa_vattr.va_mtime); 560 attr.sa_mask |= SMB_AT_MTIME; 561 } 562 563 if (atime != 0 && atime != (uint64_t)-1) { 564 smb_time_nt_to_unix(atime, &attr.sa_vattr.va_atime); 565 attr.sa_mask |= SMB_AT_ATIME; 566 } 567 568 if (attributes != 0) { 569 attr.sa_dosattr = attributes; 570 attr.sa_mask |= SMB_AT_DOSATTR; 571 } 572 573 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 574 if (rc != 0) { 575 smbsr_errno(sr, rc); 576 return (-1); 577 } 578 579 return (0); 580 } 581 582 /* 583 * smb_set_eof_info 584 */ 585 static int 586 smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *sinfo) 587 { 588 int rc; 589 smb_attr_t attr; 590 uint64_t eof; 591 smb_node_t *node = sinfo->si_node; 592 593 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "q", &eof) != 0) 594 return (-1); 595 596 if (smb_node_is_dir(node)) { 597 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 598 ERRDOS, ERROR_INVALID_PARAMETER); 599 return (-1); 600 } 601 602 bzero(&attr, sizeof (smb_attr_t)); 603 attr.sa_mask = SMB_AT_SIZE; 604 attr.sa_vattr.va_size = (u_offset_t)eof; 605 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 606 if (rc != 0) { 607 smbsr_errno(sr, rc); 608 return (-1); 609 } 610 611 return (0); 612 } 613 614 /* 615 * smb_set_alloc_info 616 */ 617 static int 618 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *sinfo) 619 { 620 int rc; 621 smb_attr_t attr; 622 uint64_t allocsz; 623 smb_node_t *node = sinfo->si_node; 624 625 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "q", &allocsz) != 0) 626 return (-1); 627 628 if (smb_node_is_dir(node)) { 629 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 630 ERRDOS, ERROR_INVALID_PARAMETER); 631 return (-1); 632 } 633 634 bzero(&attr, sizeof (smb_attr_t)); 635 attr.sa_mask = SMB_AT_ALLOCSZ; 636 attr.sa_allocsz = (u_offset_t)allocsz; 637 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr); 638 if (rc != 0) { 639 smbsr_errno(sr, rc); 640 return (-1); 641 } 642 643 return (0); 644 } 645 646 /* 647 * smb_set_disposition_info 648 * 649 * Set/Clear DELETE_ON_CLOSE flag for an open file. 650 * File should have been opened with DELETE access otherwise 651 * the operation is not permitted. 652 * 653 * NOTE: The node should be marked delete-on-close upon the receipt 654 * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set. 655 * It is different than both SmbNtCreateAndX and SmbNtTransact, which 656 * set delete-on-close on the ofile and defer setting the flag on the 657 * node until the file is closed. 658 * 659 * Observation of Windows 2000 indicates the following: 660 * 661 * 1) If a file is not opened with delete-on-close create options and 662 * the delete-on-close is set via Trans2SetFileInfo(SetDispositionInfo) 663 * using that open file handle, any subsequent open requests will fail 664 * with DELETE_PENDING. 665 * 666 * 2) If a file is opened with delete-on-close create options and the 667 * client attempts to unset delete-on-close via Trans2SetFileInfo 668 * (SetDispositionInfo) prior to the file close, any subsequent open 669 * requests will still fail with DELETE_PENDING after the file is closed. 670 * 671 * 3) If a file is opened with delete-on-close create options and that 672 * file handle (not the last open handle and the only file handle 673 * with delete-on-close set) is closed. Any subsequent open requests 674 * will fail with DELETE_PENDING. Unsetting delete-on-close via 675 * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the 676 * node delete-on-close flag, which will result in the file not being 677 * removed even after the last file handle is closed. 678 */ 679 static int 680 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *sinfo) 681 { 682 unsigned char mark_delete; 683 uint32_t flags = 0; 684 685 if (smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "b", &mark_delete) != 0) 686 return (-1); 687 688 if ((sr->fid_ofile == NULL) || 689 !(smb_ofile_granted_access(sr->fid_ofile) & DELETE)) { 690 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 691 ERRDOS, ERROR_ACCESS_DENIED); 692 return (-1); 693 } 694 695 if (mark_delete) { 696 if (SMB_TREE_SUPPORTS_CATIA(sr)) 697 flags |= SMB_CATIA; 698 699 if (smb_node_set_delete_on_close(sinfo->si_node, 700 sr->user_cr, flags)) { 701 smbsr_error(sr, NT_STATUS_CANNOT_DELETE, 702 ERRDOS, ERROR_ACCESS_DENIED); 703 return (-1); 704 } 705 } else { 706 smb_node_reset_delete_on_close(sinfo->si_node); 707 } 708 return (0); 709 } 710 711 /* 712 * smb_set_rename_info 713 * 714 * Explicity specified parameter validation rules: 715 * - If rootdir is not NULL respond with NT_STATUS_INVALID_PARAMETER. 716 * - If the filename contains a separator character respond with 717 * NT_STATUS_INVALID_PARAMETER. 718 */ 719 static int 720 smb_set_rename_info(smb_request_t *sr, smb_setinfo_t *sinfo) 721 { 722 int rc; 723 uint32_t flags, rootdir, namelen; 724 char *fname; 725 726 rc = smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "lll", 727 &flags, &rootdir, &namelen); 728 if (rc == 0) { 729 rc = smb_mbc_decodef(&sinfo->si_xa->req_data_mb, "%#U", 730 sr, namelen, &fname); 731 } 732 if (rc != 0) 733 return (-1); 734 735 if ((rootdir != 0) || (namelen == 0) || (namelen >= MAXNAMELEN)) { 736 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 737 ERRDOS, ERROR_INVALID_PARAMETER); 738 return (-1); 739 } 740 741 if (strchr(fname, '\\') != NULL) { 742 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 743 ERRDOS, ERROR_NOT_SUPPORTED); 744 return (-1); 745 } 746 747 rc = smb_trans2_rename(sr, sinfo->si_node, fname, flags); 748 749 return ((rc == 0) ? 0 : -1); 750 } 751