15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 228934SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #include <sys/synch.h> 27*10966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h> 285331Samw #include <smbsrv/smb_fsops.h> 295772Sas200622 #include <sys/nbmlock.h> 305331Samw 319914Samw@Sun.COM /* 329914Samw@Sun.COM * NT_RENAME InformationLevels: 339914Samw@Sun.COM * 349914Samw@Sun.COM * SMB_NT_RENAME_MOVE_CLUSTER_INFO Server returns invalid parameter. 359914Samw@Sun.COM * SMB_NT_RENAME_SET_LINK_INFO Create a hard link to a file. 369914Samw@Sun.COM * SMB_NT_RENAME_RENAME_FILE In-place rename of a file. 379914Samw@Sun.COM * SMB_NT_RENAME_MOVE_FILE Move (rename) a file. 389914Samw@Sun.COM */ 399914Samw@Sun.COM #define SMB_NT_RENAME_MOVE_CLUSTER_INFO 0x0102 409914Samw@Sun.COM #define SMB_NT_RENAME_SET_LINK_INFO 0x0103 419914Samw@Sun.COM #define SMB_NT_RENAME_RENAME_FILE 0x0104 429914Samw@Sun.COM #define SMB_NT_RENAME_MOVE_FILE 0x0105 439914Samw@Sun.COM 44*10966SJordan.Brown@Sun.COM /* 45*10966SJordan.Brown@Sun.COM * SMB_TRANS2_SET_FILE/PATH_INFO (RENAME_INFORMATION level) flag 46*10966SJordan.Brown@Sun.COM */ 47*10966SJordan.Brown@Sun.COM #define SMB_RENAME_FLAG_OVERWRITE 0x001 48*10966SJordan.Brown@Sun.COM 49*10966SJordan.Brown@Sun.COM static int smb_common_rename(smb_request_t *, smb_fqi_t *, smb_fqi_t *); 509914Samw@Sun.COM static int smb_make_link(smb_request_t *, smb_fqi_t *, smb_fqi_t *); 51*10966SJordan.Brown@Sun.COM static int smb_rename_check_stream(smb_fqi_t *, smb_fqi_t *); 5210001SJoyce.McIntosh@Sun.COM static int smb_rename_check_attr(smb_request_t *, smb_node_t *, uint16_t); 539914Samw@Sun.COM static void smb_rename_set_error(smb_request_t *, int); 545331Samw 55*10966SJordan.Brown@Sun.COM static int smb_rename_lookup_src(smb_request_t *); 56*10966SJordan.Brown@Sun.COM static void smb_rename_release_src(smb_request_t *); 57*10966SJordan.Brown@Sun.COM 585331Samw /* 595331Samw * smb_com_rename 605331Samw * 615331Samw * Rename a file. Files OldFileName must exist and NewFileName must not. 625331Samw * Both pathnames must be relative to the Tid specified in the request. 635331Samw * Open files may be renamed. 645331Samw * 655331Samw * Multiple files may be renamed in response to a single request as Rename 665331Samw * File supports wildcards in the file name (last component of the path). 675331Samw * NOTE: we don't support rename with wildcards. 685331Samw * 695331Samw * SearchAttributes indicates the attributes that the target file(s) must 705331Samw * have. If SearchAttributes is zero then only normal files are renamed. 715331Samw * If the system file or hidden attributes are specified then the rename 725331Samw * is inclusive - both the specified type(s) of files and normal files are 73*10966SJordan.Brown@Sun.COM * renamed. 745331Samw */ 756030Sjb150015 smb_sdrc_t 766139Sjb150015 smb_pre_rename(smb_request_t *sr) 776139Sjb150015 { 787961SNatalie.Li@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 797961SNatalie.Li@Sun.COM smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi; 806139Sjb150015 int rc; 816139Sjb150015 829343SAfshin.Ardakani@Sun.COM if ((rc = smbsr_decode_vwv(sr, "w", &src_fqi->fq_sattr)) == 0) { 839343SAfshin.Ardakani@Sun.COM rc = smbsr_decode_data(sr, "%SS", sr, &src_fqi->fq_path.pn_path, 849343SAfshin.Ardakani@Sun.COM &dst_fqi->fq_path.pn_path); 856139Sjb150015 869343SAfshin.Ardakani@Sun.COM dst_fqi->fq_sattr = 0; 876139Sjb150015 } 886139Sjb150015 896139Sjb150015 DTRACE_SMB_2(op__Rename__start, smb_request_t *, sr, 906139Sjb150015 struct dirop *, &sr->arg.dirop); 916139Sjb150015 926139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 936139Sjb150015 } 946139Sjb150015 956139Sjb150015 void 966139Sjb150015 smb_post_rename(smb_request_t *sr) 976139Sjb150015 { 986139Sjb150015 DTRACE_SMB_1(op__Rename__done, smb_request_t *, sr); 996139Sjb150015 } 1006139Sjb150015 1016139Sjb150015 smb_sdrc_t 1026139Sjb150015 smb_com_rename(smb_request_t *sr) 1035331Samw { 1047961SNatalie.Li@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 1057961SNatalie.Li@Sun.COM smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi; 1065331Samw int rc; 1075331Samw 1085331Samw if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { 1095772Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 1105331Samw ERRDOS, ERROR_ACCESS_DENIED); 1116139Sjb150015 return (SDRC_ERROR); 1125331Samw } 1135331Samw 114*10966SJordan.Brown@Sun.COM rc = smb_common_rename(sr, src_fqi, dst_fqi); 1155331Samw 1165331Samw if (rc != 0) { 1179914Samw@Sun.COM smb_rename_set_error(sr, rc); 1186139Sjb150015 return (SDRC_ERROR); 1195331Samw } 1205331Samw 1216030Sjb150015 rc = smbsr_encode_empty_result(sr); 1226139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1235331Samw } 1245331Samw 1255331Samw /* 1269914Samw@Sun.COM * smb_com_nt_rename 1279914Samw@Sun.COM * 1289914Samw@Sun.COM * Rename a file. Files OldFileName must exist and NewFileName must not. 1299914Samw@Sun.COM * Both pathnames must be relative to the Tid specified in the request. 1309914Samw@Sun.COM * Open files may be renamed. 1319914Samw@Sun.COM * 1329914Samw@Sun.COM * SearchAttributes indicates the attributes that the target file(s) must 1339914Samw@Sun.COM * have. If SearchAttributes is zero then only normal files are renamed. 1349914Samw@Sun.COM * If the system file or hidden attributes are specified then the rename 1359914Samw@Sun.COM * is inclusive - both the specified type(s) of files and normal files are 136*10966SJordan.Brown@Sun.COM * renamed. 1379914Samw@Sun.COM */ 1389914Samw@Sun.COM smb_sdrc_t 1399914Samw@Sun.COM smb_pre_nt_rename(smb_request_t *sr) 1409914Samw@Sun.COM { 1419914Samw@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 1429914Samw@Sun.COM smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi; 1439914Samw@Sun.COM uint32_t clusters; 1449914Samw@Sun.COM int rc; 1459914Samw@Sun.COM 1469914Samw@Sun.COM rc = smbsr_decode_vwv(sr, "wwl", &src_fqi->fq_sattr, 1479914Samw@Sun.COM &sr->arg.dirop.info_level, &clusters); 1489914Samw@Sun.COM if (rc == 0) { 1499914Samw@Sun.COM rc = smbsr_decode_data(sr, "%SS", sr, 1509914Samw@Sun.COM &src_fqi->fq_path.pn_path, &dst_fqi->fq_path.pn_path); 1519914Samw@Sun.COM 1529914Samw@Sun.COM dst_fqi->fq_sattr = 0; 1539914Samw@Sun.COM } 1549914Samw@Sun.COM 1559914Samw@Sun.COM DTRACE_SMB_2(op__NtRename__start, smb_request_t *, sr, 1569914Samw@Sun.COM struct dirop *, &sr->arg.dirop); 1579914Samw@Sun.COM 1589914Samw@Sun.COM return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1599914Samw@Sun.COM } 1609914Samw@Sun.COM 1619914Samw@Sun.COM void 1629914Samw@Sun.COM smb_post_nt_rename(smb_request_t *sr) 1639914Samw@Sun.COM { 1649914Samw@Sun.COM DTRACE_SMB_1(op__NtRename__done, smb_request_t *, sr); 1659914Samw@Sun.COM } 1669914Samw@Sun.COM 1679914Samw@Sun.COM smb_sdrc_t 1689914Samw@Sun.COM smb_com_nt_rename(smb_request_t *sr) 1699914Samw@Sun.COM { 1709914Samw@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 1719914Samw@Sun.COM smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi; 1729914Samw@Sun.COM int rc; 1739914Samw@Sun.COM 1749914Samw@Sun.COM if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { 1759914Samw@Sun.COM smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 1769914Samw@Sun.COM ERRDOS, ERROR_ACCESS_DENIED); 1779914Samw@Sun.COM return (SDRC_ERROR); 1789914Samw@Sun.COM } 1799914Samw@Sun.COM 1809914Samw@Sun.COM if (smb_convert_wildcards(src_fqi->fq_path.pn_path) != 0) { 1819914Samw@Sun.COM smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD, 1829914Samw@Sun.COM ERRDOS, ERROR_BAD_PATHNAME); 1839914Samw@Sun.COM return (SDRC_ERROR); 1849914Samw@Sun.COM } 1859914Samw@Sun.COM 1869914Samw@Sun.COM switch (sr->arg.dirop.info_level) { 1879914Samw@Sun.COM case SMB_NT_RENAME_SET_LINK_INFO: 1889914Samw@Sun.COM rc = smb_make_link(sr, src_fqi, dst_fqi); 1899914Samw@Sun.COM break; 1909914Samw@Sun.COM case SMB_NT_RENAME_RENAME_FILE: 1919914Samw@Sun.COM case SMB_NT_RENAME_MOVE_FILE: 192*10966SJordan.Brown@Sun.COM rc = smb_common_rename(sr, src_fqi, dst_fqi); 1939914Samw@Sun.COM break; 1949914Samw@Sun.COM case SMB_NT_RENAME_MOVE_CLUSTER_INFO: 1959914Samw@Sun.COM rc = EINVAL; 1969914Samw@Sun.COM break; 1979914Samw@Sun.COM default: 1989914Samw@Sun.COM rc = EACCES; 1999914Samw@Sun.COM break; 2009914Samw@Sun.COM } 2019914Samw@Sun.COM 2029914Samw@Sun.COM if (rc != 0) { 2039914Samw@Sun.COM smb_rename_set_error(sr, rc); 2049914Samw@Sun.COM return (SDRC_ERROR); 2059914Samw@Sun.COM } 2069914Samw@Sun.COM 2079914Samw@Sun.COM rc = smbsr_encode_empty_result(sr); 2089914Samw@Sun.COM return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2099914Samw@Sun.COM } 2109914Samw@Sun.COM 2119914Samw@Sun.COM /* 212*10966SJordan.Brown@Sun.COM * smb_nt_transact_rename 213*10966SJordan.Brown@Sun.COM * 214*10966SJordan.Brown@Sun.COM * Windows servers return SUCCESS without renaming file. 215*10966SJordan.Brown@Sun.COM * The only check required is to check that the handle (fid) is valid. 216*10966SJordan.Brown@Sun.COM */ 217*10966SJordan.Brown@Sun.COM smb_sdrc_t 218*10966SJordan.Brown@Sun.COM smb_nt_transact_rename(smb_request_t *sr, smb_xa_t *xa) 219*10966SJordan.Brown@Sun.COM { 220*10966SJordan.Brown@Sun.COM if (smb_mbc_decodef(&xa->req_param_mb, "w", &sr->smb_fid) != 0) 221*10966SJordan.Brown@Sun.COM return (SDRC_ERROR); 222*10966SJordan.Brown@Sun.COM 223*10966SJordan.Brown@Sun.COM smbsr_lookup_file(sr); 224*10966SJordan.Brown@Sun.COM if (sr->fid_ofile == NULL) { 225*10966SJordan.Brown@Sun.COM smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 226*10966SJordan.Brown@Sun.COM return (SDRC_ERROR); 227*10966SJordan.Brown@Sun.COM } 228*10966SJordan.Brown@Sun.COM smbsr_release_file(sr); 229*10966SJordan.Brown@Sun.COM 230*10966SJordan.Brown@Sun.COM return (SDRC_SUCCESS); 231*10966SJordan.Brown@Sun.COM } 232*10966SJordan.Brown@Sun.COM 233*10966SJordan.Brown@Sun.COM /* 234*10966SJordan.Brown@Sun.COM * smb_trans2_rename 235*10966SJordan.Brown@Sun.COM * 236*10966SJordan.Brown@Sun.COM * Implements SMB_FILE_RENAME_INFORMATION level of Trans2_Set_FileInfo 237*10966SJordan.Brown@Sun.COM * and Trans2_Set_PathInfo. 238*10966SJordan.Brown@Sun.COM * If the new filename (dst_fqi) already exists it may be overwritten 239*10966SJordan.Brown@Sun.COM * if flags == 1. 240*10966SJordan.Brown@Sun.COM */ 241*10966SJordan.Brown@Sun.COM int 242*10966SJordan.Brown@Sun.COM smb_trans2_rename(smb_request_t *sr, smb_node_t *node, char *fname, int flags) 243*10966SJordan.Brown@Sun.COM { 244*10966SJordan.Brown@Sun.COM int rc; 245*10966SJordan.Brown@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 246*10966SJordan.Brown@Sun.COM smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi; 247*10966SJordan.Brown@Sun.COM 248*10966SJordan.Brown@Sun.COM sr->arg.dirop.flags = flags ? SMB_RENAME_FLAG_OVERWRITE : 0; 249*10966SJordan.Brown@Sun.COM sr->arg.dirop.info_level = SMB_NT_RENAME_RENAME_FILE; 250*10966SJordan.Brown@Sun.COM 251*10966SJordan.Brown@Sun.COM src_fqi->fq_sattr = SMB_SEARCH_ATTRIBUTES; 252*10966SJordan.Brown@Sun.COM src_fqi->fq_fnode = node; 253*10966SJordan.Brown@Sun.COM src_fqi->fq_dnode = node->n_dnode; 254*10966SJordan.Brown@Sun.COM 255*10966SJordan.Brown@Sun.COM dst_fqi->fq_path.pn_path = fname; 256*10966SJordan.Brown@Sun.COM dst_fqi->fq_dnode = node->n_dnode; 257*10966SJordan.Brown@Sun.COM (void) strlcpy(dst_fqi->fq_last_comp, fname, MAXNAMELEN); 258*10966SJordan.Brown@Sun.COM 259*10966SJordan.Brown@Sun.COM rc = smb_common_rename(sr, src_fqi, dst_fqi); 260*10966SJordan.Brown@Sun.COM if (rc != 0) { 261*10966SJordan.Brown@Sun.COM smb_rename_set_error(sr, rc); 262*10966SJordan.Brown@Sun.COM return (-1); 263*10966SJordan.Brown@Sun.COM } 264*10966SJordan.Brown@Sun.COM 265*10966SJordan.Brown@Sun.COM return (0); 266*10966SJordan.Brown@Sun.COM } 267*10966SJordan.Brown@Sun.COM 268*10966SJordan.Brown@Sun.COM /* 269*10966SJordan.Brown@Sun.COM * smb_common_rename 270*10966SJordan.Brown@Sun.COM * 271*10966SJordan.Brown@Sun.COM * Common code for renaming a file. 272*10966SJordan.Brown@Sun.COM * 273*10966SJordan.Brown@Sun.COM * If the source and destination are identical, we go through all 274*10966SJordan.Brown@Sun.COM * the checks but we don't actually do the rename. If the source 275*10966SJordan.Brown@Sun.COM * and destination files differ only in case, we do a case-sensitive 276*10966SJordan.Brown@Sun.COM * rename. Otherwise, we do a full case-insensitive rename. 277*10966SJordan.Brown@Sun.COM * 278*10966SJordan.Brown@Sun.COM * Returns errno values. 279*10966SJordan.Brown@Sun.COM */ 280*10966SJordan.Brown@Sun.COM static int 281*10966SJordan.Brown@Sun.COM smb_common_rename(smb_request_t *sr, smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi) 282*10966SJordan.Brown@Sun.COM { 283*10966SJordan.Brown@Sun.COM smb_node_t *src_fnode, *src_dnode, *dst_fnode, *dst_dnode; 284*10966SJordan.Brown@Sun.COM smb_node_t *tnode; 285*10966SJordan.Brown@Sun.COM int rc, count; 286*10966SJordan.Brown@Sun.COM DWORD status; 287*10966SJordan.Brown@Sun.COM char *new_name, *path; 288*10966SJordan.Brown@Sun.COM 289*10966SJordan.Brown@Sun.COM path = dst_fqi->fq_path.pn_path; 290*10966SJordan.Brown@Sun.COM 291*10966SJordan.Brown@Sun.COM /* Check if attempting to rename a stream - not yet supported */ 292*10966SJordan.Brown@Sun.COM rc = smb_rename_check_stream(src_fqi, dst_fqi); 293*10966SJordan.Brown@Sun.COM if (rc != 0) 294*10966SJordan.Brown@Sun.COM return (rc); 295*10966SJordan.Brown@Sun.COM 296*10966SJordan.Brown@Sun.COM /* The source node may already have been provided */ 297*10966SJordan.Brown@Sun.COM if (src_fqi->fq_fnode) { 298*10966SJordan.Brown@Sun.COM smb_node_start_crit(src_fqi->fq_fnode, RW_READER); 299*10966SJordan.Brown@Sun.COM smb_node_ref(src_fqi->fq_fnode); 300*10966SJordan.Brown@Sun.COM smb_node_ref(src_fqi->fq_dnode); 301*10966SJordan.Brown@Sun.COM } else { 302*10966SJordan.Brown@Sun.COM /* lookup and validate src node */ 303*10966SJordan.Brown@Sun.COM rc = smb_rename_lookup_src(sr); 304*10966SJordan.Brown@Sun.COM if (rc != 0) 305*10966SJordan.Brown@Sun.COM return (rc); 306*10966SJordan.Brown@Sun.COM } 307*10966SJordan.Brown@Sun.COM 308*10966SJordan.Brown@Sun.COM src_fnode = src_fqi->fq_fnode; 309*10966SJordan.Brown@Sun.COM src_dnode = src_fqi->fq_dnode; 310*10966SJordan.Brown@Sun.COM 311*10966SJordan.Brown@Sun.COM /* Find destination dnode and last_comp */ 312*10966SJordan.Brown@Sun.COM if (dst_fqi->fq_dnode) { 313*10966SJordan.Brown@Sun.COM smb_node_ref(dst_fqi->fq_dnode); 314*10966SJordan.Brown@Sun.COM } else { 315*10966SJordan.Brown@Sun.COM tnode = sr->tid_tree->t_snode; 316*10966SJordan.Brown@Sun.COM rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode, 317*10966SJordan.Brown@Sun.COM &dst_fqi->fq_dnode, dst_fqi->fq_last_comp); 318*10966SJordan.Brown@Sun.COM if (rc != 0) { 319*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 320*10966SJordan.Brown@Sun.COM return (rc); 321*10966SJordan.Brown@Sun.COM } 322*10966SJordan.Brown@Sun.COM } 323*10966SJordan.Brown@Sun.COM 324*10966SJordan.Brown@Sun.COM dst_dnode = dst_fqi->fq_dnode; 325*10966SJordan.Brown@Sun.COM new_name = dst_fqi->fq_last_comp; 326*10966SJordan.Brown@Sun.COM 327*10966SJordan.Brown@Sun.COM /* If exact name match in same directory, we're done */ 328*10966SJordan.Brown@Sun.COM if ((src_dnode == dst_dnode) && 329*10966SJordan.Brown@Sun.COM (strcmp(src_fnode->od_name, new_name) == 0)) { 330*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 331*10966SJordan.Brown@Sun.COM smb_node_release(dst_dnode); 332*10966SJordan.Brown@Sun.COM return (0); 333*10966SJordan.Brown@Sun.COM } 334*10966SJordan.Brown@Sun.COM 335*10966SJordan.Brown@Sun.COM /* Lookup destination node */ 336*10966SJordan.Brown@Sun.COM rc = smb_fsop_lookup(sr, sr->user_cr, 0, tnode, 337*10966SJordan.Brown@Sun.COM dst_dnode, new_name, &dst_fqi->fq_fnode); 338*10966SJordan.Brown@Sun.COM 339*10966SJordan.Brown@Sun.COM /* 340*10966SJordan.Brown@Sun.COM * Handle case where changing case of the same directory entry. 341*10966SJordan.Brown@Sun.COM * 342*10966SJordan.Brown@Sun.COM * If we found the dst node in the same directory as the src node, 343*10966SJordan.Brown@Sun.COM * and their names differ only in case: 344*10966SJordan.Brown@Sun.COM * 345*10966SJordan.Brown@Sun.COM * If the tree is case sensitive (or mixed): 346*10966SJordan.Brown@Sun.COM * Do case sensitive lookup to see if exact match exists. 347*10966SJordan.Brown@Sun.COM * If the exact match is the same node as src_node we're done. 348*10966SJordan.Brown@Sun.COM * 349*10966SJordan.Brown@Sun.COM * If the tree is case insensitive: 350*10966SJordan.Brown@Sun.COM * There is currently no way to tell if the case is different 351*10966SJordan.Brown@Sun.COM * or not, so do the rename (unless the specified new name was 352*10966SJordan.Brown@Sun.COM * mangled). 353*10966SJordan.Brown@Sun.COM */ 354*10966SJordan.Brown@Sun.COM if ((rc == 0) && 355*10966SJordan.Brown@Sun.COM (src_dnode == dst_dnode) && 356*10966SJordan.Brown@Sun.COM (smb_strcasecmp(src_fnode->od_name, 357*10966SJordan.Brown@Sun.COM dst_fqi->fq_fnode->od_name, 0) == 0)) { 358*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_fnode); 359*10966SJordan.Brown@Sun.COM dst_fqi->fq_fnode = NULL; 360*10966SJordan.Brown@Sun.COM 361*10966SJordan.Brown@Sun.COM if (smb_tree_has_feature(sr->tid_tree, 362*10966SJordan.Brown@Sun.COM SMB_TREE_NO_CASESENSITIVE)) { 363*10966SJordan.Brown@Sun.COM if (smb_strcasecmp(src_fnode->od_name, 364*10966SJordan.Brown@Sun.COM dst_fqi->fq_last_comp, 0) != 0) { 365*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 366*10966SJordan.Brown@Sun.COM smb_node_release(dst_dnode); 367*10966SJordan.Brown@Sun.COM return (0); 368*10966SJordan.Brown@Sun.COM } 369*10966SJordan.Brown@Sun.COM } else { 370*10966SJordan.Brown@Sun.COM rc = smb_fsop_lookup(sr, sr->user_cr, 371*10966SJordan.Brown@Sun.COM SMB_CASE_SENSITIVE, tnode, dst_dnode, new_name, 372*10966SJordan.Brown@Sun.COM &dst_fqi->fq_fnode); 373*10966SJordan.Brown@Sun.COM 374*10966SJordan.Brown@Sun.COM if ((rc == 0) && 375*10966SJordan.Brown@Sun.COM (dst_fqi->fq_fnode == src_fnode)) { 376*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 377*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_fnode); 378*10966SJordan.Brown@Sun.COM smb_node_release(dst_dnode); 379*10966SJordan.Brown@Sun.COM return (0); 380*10966SJordan.Brown@Sun.COM } 381*10966SJordan.Brown@Sun.COM } 382*10966SJordan.Brown@Sun.COM } 383*10966SJordan.Brown@Sun.COM 384*10966SJordan.Brown@Sun.COM if ((rc != 0) && (rc != ENOENT)) { 385*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 386*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_dnode); 387*10966SJordan.Brown@Sun.COM return (rc); 388*10966SJordan.Brown@Sun.COM } 389*10966SJordan.Brown@Sun.COM 390*10966SJordan.Brown@Sun.COM if (dst_fqi->fq_fnode) { 391*10966SJordan.Brown@Sun.COM dst_fnode = dst_fqi->fq_fnode; 392*10966SJordan.Brown@Sun.COM 393*10966SJordan.Brown@Sun.COM if (!(sr->arg.dirop.flags && SMB_RENAME_FLAG_OVERWRITE)) { 394*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 395*10966SJordan.Brown@Sun.COM smb_node_release(dst_fnode); 396*10966SJordan.Brown@Sun.COM smb_node_release(dst_dnode); 397*10966SJordan.Brown@Sun.COM return (EEXIST); 398*10966SJordan.Brown@Sun.COM } 399*10966SJordan.Brown@Sun.COM 400*10966SJordan.Brown@Sun.COM (void) smb_oplock_break(dst_fnode, sr->session, B_FALSE); 401*10966SJordan.Brown@Sun.COM 402*10966SJordan.Brown@Sun.COM for (count = 0; count <= 3; count++) { 403*10966SJordan.Brown@Sun.COM if (count) { 404*10966SJordan.Brown@Sun.COM smb_node_end_crit(dst_fnode); 405*10966SJordan.Brown@Sun.COM delay(MSEC_TO_TICK(400)); 406*10966SJordan.Brown@Sun.COM } 407*10966SJordan.Brown@Sun.COM 408*10966SJordan.Brown@Sun.COM smb_node_start_crit(dst_fnode, RW_READER); 409*10966SJordan.Brown@Sun.COM status = smb_node_delete_check(dst_fnode); 410*10966SJordan.Brown@Sun.COM 411*10966SJordan.Brown@Sun.COM if (status != NT_STATUS_SHARING_VIOLATION) 412*10966SJordan.Brown@Sun.COM break; 413*10966SJordan.Brown@Sun.COM } 414*10966SJordan.Brown@Sun.COM 415*10966SJordan.Brown@Sun.COM if (status != NT_STATUS_SHARING_VIOLATION) 416*10966SJordan.Brown@Sun.COM status = smb_range_check(sr, dst_fnode, 417*10966SJordan.Brown@Sun.COM 0, UINT64_MAX, B_TRUE); 418*10966SJordan.Brown@Sun.COM 419*10966SJordan.Brown@Sun.COM if (status != NT_STATUS_SUCCESS) { 420*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 421*10966SJordan.Brown@Sun.COM smb_node_end_crit(dst_fnode); 422*10966SJordan.Brown@Sun.COM smb_node_release(dst_fnode); 423*10966SJordan.Brown@Sun.COM smb_node_release(dst_dnode); 424*10966SJordan.Brown@Sun.COM return (EACCES); 425*10966SJordan.Brown@Sun.COM } 426*10966SJordan.Brown@Sun.COM 427*10966SJordan.Brown@Sun.COM if (smb_maybe_mangled_name(new_name)) { 428*10966SJordan.Brown@Sun.COM (void) strlcpy(new_name, dst_fnode->od_name, 429*10966SJordan.Brown@Sun.COM MAXNAMELEN); 430*10966SJordan.Brown@Sun.COM } 431*10966SJordan.Brown@Sun.COM } 432*10966SJordan.Brown@Sun.COM 433*10966SJordan.Brown@Sun.COM rc = smb_fsop_rename(sr, sr->user_cr, 434*10966SJordan.Brown@Sun.COM src_dnode, src_fnode->od_name, 435*10966SJordan.Brown@Sun.COM dst_dnode, new_name); 436*10966SJordan.Brown@Sun.COM 437*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 438*10966SJordan.Brown@Sun.COM 439*10966SJordan.Brown@Sun.COM if (rc == 0) 440*10966SJordan.Brown@Sun.COM smb_node_notify_change(dst_dnode); 441*10966SJordan.Brown@Sun.COM 442*10966SJordan.Brown@Sun.COM if (dst_fqi->fq_fnode) { 443*10966SJordan.Brown@Sun.COM smb_node_end_crit(dst_fnode); 444*10966SJordan.Brown@Sun.COM smb_node_release(dst_fnode); 445*10966SJordan.Brown@Sun.COM } 446*10966SJordan.Brown@Sun.COM smb_node_release(dst_dnode); 447*10966SJordan.Brown@Sun.COM 448*10966SJordan.Brown@Sun.COM return (rc); 449*10966SJordan.Brown@Sun.COM } 450*10966SJordan.Brown@Sun.COM 451*10966SJordan.Brown@Sun.COM /* 452*10966SJordan.Brown@Sun.COM * smb_rename_check_stream 453*10966SJordan.Brown@Sun.COM * 454*10966SJordan.Brown@Sun.COM * For a stream rename the dst path must begin with ':', or "\\:". 455*10966SJordan.Brown@Sun.COM * We don't yet support stream rename, Return EACCES. 456*10966SJordan.Brown@Sun.COM * 457*10966SJordan.Brown@Sun.COM * If not a stream rename, in accordance with the above rule, 458*10966SJordan.Brown@Sun.COM * it is not valid for either the src or dst to be a stream. 459*10966SJordan.Brown@Sun.COM * Return EINVAL. 460*10966SJordan.Brown@Sun.COM */ 461*10966SJordan.Brown@Sun.COM static int 462*10966SJordan.Brown@Sun.COM smb_rename_check_stream(smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi) 463*10966SJordan.Brown@Sun.COM { 464*10966SJordan.Brown@Sun.COM smb_node_t *src_fnode = src_fqi->fq_fnode; 465*10966SJordan.Brown@Sun.COM char *src_path = src_fqi->fq_path.pn_path; 466*10966SJordan.Brown@Sun.COM char *dst_path = dst_fqi->fq_path.pn_path; 467*10966SJordan.Brown@Sun.COM 468*10966SJordan.Brown@Sun.COM /* We do not yet support named stream rename - ACCESS DENIED */ 469*10966SJordan.Brown@Sun.COM if ((dst_path[0] == ':') || 470*10966SJordan.Brown@Sun.COM ((dst_path[0] == '\\') && (dst_path[1] == ':'))) { 471*10966SJordan.Brown@Sun.COM return (EACCES); 472*10966SJordan.Brown@Sun.COM } 473*10966SJordan.Brown@Sun.COM 474*10966SJordan.Brown@Sun.COM /* 475*10966SJordan.Brown@Sun.COM * If not stream rename (above) neither src or dst can be 476*10966SJordan.Brown@Sun.COM * a named stream. 477*10966SJordan.Brown@Sun.COM */ 478*10966SJordan.Brown@Sun.COM 479*10966SJordan.Brown@Sun.COM if (smb_is_stream_name(dst_path)) 480*10966SJordan.Brown@Sun.COM return (EINVAL); 481*10966SJordan.Brown@Sun.COM 482*10966SJordan.Brown@Sun.COM if (src_fqi->fq_fnode) { 483*10966SJordan.Brown@Sun.COM if (SMB_IS_STREAM(src_fnode)) 484*10966SJordan.Brown@Sun.COM return (EINVAL); 485*10966SJordan.Brown@Sun.COM } else { 486*10966SJordan.Brown@Sun.COM if (smb_is_stream_name(src_path)) 487*10966SJordan.Brown@Sun.COM return (EINVAL); 488*10966SJordan.Brown@Sun.COM } 489*10966SJordan.Brown@Sun.COM 490*10966SJordan.Brown@Sun.COM return (0); 491*10966SJordan.Brown@Sun.COM } 492*10966SJordan.Brown@Sun.COM 493*10966SJordan.Brown@Sun.COM 494*10966SJordan.Brown@Sun.COM /* 4959914Samw@Sun.COM * smb_make_link 4969914Samw@Sun.COM * 497*10966SJordan.Brown@Sun.COM * Creating a hard link (adding an additional name) for a file. 4989914Samw@Sun.COM * 4999914Samw@Sun.COM * If the source and destination are identical, we go through all 5009914Samw@Sun.COM * the checks but we don't create a link. 5019914Samw@Sun.COM * 502*10966SJordan.Brown@Sun.COM * If the file is a symlink we create the hardlink on the target 503*10966SJordan.Brown@Sun.COM * of the symlink (i.e. use SMB_FOLLOW_LINKS when looking up src). 504*10966SJordan.Brown@Sun.COM * If the target of the symlink does not exist we fail with ENOENT. 505*10966SJordan.Brown@Sun.COM * 5069914Samw@Sun.COM * Returns errno values. 5079914Samw@Sun.COM */ 5089914Samw@Sun.COM static int 5099914Samw@Sun.COM smb_make_link(smb_request_t *sr, smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi) 5109914Samw@Sun.COM { 511*10966SJordan.Brown@Sun.COM smb_node_t *tnode; 512*10966SJordan.Brown@Sun.COM char *path; 513*10966SJordan.Brown@Sun.COM int rc; 514*10966SJordan.Brown@Sun.COM 515*10966SJordan.Brown@Sun.COM /* Cannnot create link on named stream */ 516*10966SJordan.Brown@Sun.COM if (smb_is_stream_name(src_fqi->fq_path.pn_path) || 517*10966SJordan.Brown@Sun.COM smb_is_stream_name(dst_fqi->fq_path.pn_path)) { 518*10966SJordan.Brown@Sun.COM return (EINVAL); 519*10966SJordan.Brown@Sun.COM } 520*10966SJordan.Brown@Sun.COM 521*10966SJordan.Brown@Sun.COM /* lookup and validate src node */ 522*10966SJordan.Brown@Sun.COM rc = smb_rename_lookup_src(sr); 523*10966SJordan.Brown@Sun.COM if (rc != 0) 524*10966SJordan.Brown@Sun.COM return (rc); 525*10966SJordan.Brown@Sun.COM 526*10966SJordan.Brown@Sun.COM /* if src and dest paths match we're done */ 527*10966SJordan.Brown@Sun.COM if (smb_strcasecmp(src_fqi->fq_path.pn_path, 528*10966SJordan.Brown@Sun.COM dst_fqi->fq_path.pn_path, 0) == 0) { 529*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 530*10966SJordan.Brown@Sun.COM return (0); 531*10966SJordan.Brown@Sun.COM } 532*10966SJordan.Brown@Sun.COM 533*10966SJordan.Brown@Sun.COM /* find the destination dnode and last_comp */ 534*10966SJordan.Brown@Sun.COM tnode = sr->tid_tree->t_snode; 535*10966SJordan.Brown@Sun.COM path = dst_fqi->fq_path.pn_path; 536*10966SJordan.Brown@Sun.COM rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode, 537*10966SJordan.Brown@Sun.COM &dst_fqi->fq_dnode, dst_fqi->fq_last_comp); 538*10966SJordan.Brown@Sun.COM if (rc != 0) { 539*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 540*10966SJordan.Brown@Sun.COM return (rc); 541*10966SJordan.Brown@Sun.COM } 542*10966SJordan.Brown@Sun.COM 543*10966SJordan.Brown@Sun.COM /* If name match in same directory, we're done */ 544*10966SJordan.Brown@Sun.COM if ((src_fqi->fq_dnode == dst_fqi->fq_dnode) && 545*10966SJordan.Brown@Sun.COM (smb_strcasecmp(src_fqi->fq_fnode->od_name, 546*10966SJordan.Brown@Sun.COM dst_fqi->fq_last_comp, 0) == 0)) { 547*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 548*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_dnode); 549*10966SJordan.Brown@Sun.COM return (0); 550*10966SJordan.Brown@Sun.COM } 551*10966SJordan.Brown@Sun.COM 552*10966SJordan.Brown@Sun.COM /* Lookup the destination node. It MUST NOT exist. */ 553*10966SJordan.Brown@Sun.COM rc = smb_fsop_lookup(sr, sr->user_cr, 0, tnode, 554*10966SJordan.Brown@Sun.COM dst_fqi->fq_dnode, dst_fqi->fq_last_comp, &dst_fqi->fq_fnode); 555*10966SJordan.Brown@Sun.COM if (rc == 0) { 556*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_fnode); 557*10966SJordan.Brown@Sun.COM rc = EEXIST; 558*10966SJordan.Brown@Sun.COM } 559*10966SJordan.Brown@Sun.COM if (rc != ENOENT) { 560*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 561*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_dnode); 562*10966SJordan.Brown@Sun.COM return (rc); 563*10966SJordan.Brown@Sun.COM } 564*10966SJordan.Brown@Sun.COM 565*10966SJordan.Brown@Sun.COM rc = smb_fsop_link(sr, sr->user_cr, src_fqi->fq_fnode, 566*10966SJordan.Brown@Sun.COM dst_fqi->fq_dnode, dst_fqi->fq_last_comp); 567*10966SJordan.Brown@Sun.COM 568*10966SJordan.Brown@Sun.COM smb_rename_release_src(sr); 569*10966SJordan.Brown@Sun.COM if (rc == 0) 570*10966SJordan.Brown@Sun.COM smb_node_notify_change(dst_fqi->fq_dnode); 571*10966SJordan.Brown@Sun.COM smb_node_release(dst_fqi->fq_dnode); 572*10966SJordan.Brown@Sun.COM return (rc); 573*10966SJordan.Brown@Sun.COM } 574*10966SJordan.Brown@Sun.COM 575*10966SJordan.Brown@Sun.COM /* 576*10966SJordan.Brown@Sun.COM * smb_rename_lookup_src 577*10966SJordan.Brown@Sun.COM * 578*10966SJordan.Brown@Sun.COM * Lookup the src node, checking for sharing violations and 579*10966SJordan.Brown@Sun.COM * breaking any existing oplock. 580*10966SJordan.Brown@Sun.COM * Populate sr->arg.dirop.fqi 581*10966SJordan.Brown@Sun.COM * 582*10966SJordan.Brown@Sun.COM * Upon success, the dnode and fnode will have holds and the 583*10966SJordan.Brown@Sun.COM * fnode will be in a critical section. These should be 584*10966SJordan.Brown@Sun.COM * released using smb_rename_release_src(). 585*10966SJordan.Brown@Sun.COM * 586*10966SJordan.Brown@Sun.COM * Returns errno values. 587*10966SJordan.Brown@Sun.COM */ 588*10966SJordan.Brown@Sun.COM static int 589*10966SJordan.Brown@Sun.COM smb_rename_lookup_src(smb_request_t *sr) 590*10966SJordan.Brown@Sun.COM { 591*10966SJordan.Brown@Sun.COM smb_node_t *src_node, *tnode; 5929914Samw@Sun.COM DWORD status; 5939914Samw@Sun.COM int rc; 5949914Samw@Sun.COM int count; 59510504SKeyur.Desai@Sun.COM char *path; 5969914Samw@Sun.COM 597*10966SJordan.Brown@Sun.COM struct dirop *dirop = &sr->arg.dirop; 598*10966SJordan.Brown@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 59910504SKeyur.Desai@Sun.COM 600*10966SJordan.Brown@Sun.COM if (smb_is_stream_name(src_fqi->fq_path.pn_path)) 601*10966SJordan.Brown@Sun.COM return (EINVAL); 602*10966SJordan.Brown@Sun.COM 603*10966SJordan.Brown@Sun.COM /* Lookup the source node */ 604*10966SJordan.Brown@Sun.COM tnode = sr->tid_tree->t_snode; 60510504SKeyur.Desai@Sun.COM path = src_fqi->fq_path.pn_path; 60610504SKeyur.Desai@Sun.COM rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode, 60710504SKeyur.Desai@Sun.COM &src_fqi->fq_dnode, src_fqi->fq_last_comp); 60810504SKeyur.Desai@Sun.COM if (rc != 0) 6099914Samw@Sun.COM return (rc); 6109914Samw@Sun.COM 611*10966SJordan.Brown@Sun.COM rc = smb_fsop_lookup(sr, sr->user_cr, 0, tnode, 61210504SKeyur.Desai@Sun.COM src_fqi->fq_dnode, src_fqi->fq_last_comp, &src_fqi->fq_fnode); 61310504SKeyur.Desai@Sun.COM if (rc != 0) { 61410504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_dnode); 61510504SKeyur.Desai@Sun.COM return (rc); 61610504SKeyur.Desai@Sun.COM } 6179914Samw@Sun.COM 618*10966SJordan.Brown@Sun.COM /* Not valid to create hardlink for directory */ 619*10966SJordan.Brown@Sun.COM if ((dirop->info_level == SMB_NT_RENAME_SET_LINK_INFO) && 620*10966SJordan.Brown@Sun.COM (smb_node_is_dir(src_fqi->fq_fnode))) { 621*10966SJordan.Brown@Sun.COM smb_node_release(src_fqi->fq_fnode); 622*10966SJordan.Brown@Sun.COM smb_node_release(src_fqi->fq_dnode); 623*10966SJordan.Brown@Sun.COM return (EISDIR); 624*10966SJordan.Brown@Sun.COM } 625*10966SJordan.Brown@Sun.COM 626*10966SJordan.Brown@Sun.COM src_node = src_fqi->fq_fnode; 627*10966SJordan.Brown@Sun.COM 628*10966SJordan.Brown@Sun.COM rc = smb_rename_check_attr(sr, src_node, src_fqi->fq_sattr); 62910504SKeyur.Desai@Sun.COM if (rc != 0) { 63010504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_fnode); 63110504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_dnode); 63210504SKeyur.Desai@Sun.COM return (rc); 63310504SKeyur.Desai@Sun.COM } 6349914Samw@Sun.COM 6359914Samw@Sun.COM /* 6369914Samw@Sun.COM * Break the oplock before access checks. If a client 6379914Samw@Sun.COM * has a file open, this will force a flush or close, 6389914Samw@Sun.COM * which may affect the outcome of any share checking. 6399914Samw@Sun.COM */ 640*10966SJordan.Brown@Sun.COM (void) smb_oplock_break(src_node, sr->session, B_FALSE); 6419914Samw@Sun.COM 6429914Samw@Sun.COM for (count = 0; count <= 3; count++) { 6439914Samw@Sun.COM if (count) { 644*10966SJordan.Brown@Sun.COM smb_node_end_crit(src_node); 6459914Samw@Sun.COM delay(MSEC_TO_TICK(400)); 6469914Samw@Sun.COM } 6479914Samw@Sun.COM 648*10966SJordan.Brown@Sun.COM smb_node_start_crit(src_node, RW_READER); 6499914Samw@Sun.COM 650*10966SJordan.Brown@Sun.COM status = smb_node_rename_check(src_node); 6519914Samw@Sun.COM if (status != NT_STATUS_SHARING_VIOLATION) 6529914Samw@Sun.COM break; 6539914Samw@Sun.COM } 6549914Samw@Sun.COM 6559914Samw@Sun.COM if (status == NT_STATUS_SHARING_VIOLATION) { 656*10966SJordan.Brown@Sun.COM smb_node_end_crit(src_node); 65710504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_fnode); 65810504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_dnode); 65910504SKeyur.Desai@Sun.COM return (EPIPE); /* = ERRbadshare */ 6609914Samw@Sun.COM } 6619914Samw@Sun.COM 662*10966SJordan.Brown@Sun.COM status = smb_range_check(sr, src_node, 0, UINT64_MAX, B_TRUE); 6639914Samw@Sun.COM if (status != NT_STATUS_SUCCESS) { 664*10966SJordan.Brown@Sun.COM smb_node_end_crit(src_node); 66510504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_fnode); 66610504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_dnode); 66710504SKeyur.Desai@Sun.COM return (EACCES); 6689914Samw@Sun.COM } 6699914Samw@Sun.COM 670*10966SJordan.Brown@Sun.COM return (0); 671*10966SJordan.Brown@Sun.COM } 6729914Samw@Sun.COM 673*10966SJordan.Brown@Sun.COM /* 674*10966SJordan.Brown@Sun.COM * smb_rename_release_src 675*10966SJordan.Brown@Sun.COM */ 676*10966SJordan.Brown@Sun.COM static void 677*10966SJordan.Brown@Sun.COM smb_rename_release_src(smb_request_t *sr) 678*10966SJordan.Brown@Sun.COM { 679*10966SJordan.Brown@Sun.COM smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; 68010504SKeyur.Desai@Sun.COM 681*10966SJordan.Brown@Sun.COM smb_node_end_crit(src_fqi->fq_fnode); 68210504SKeyur.Desai@Sun.COM smb_node_release(src_fqi->fq_fnode); 6839914Samw@Sun.COM smb_node_release(src_fqi->fq_dnode); 6849914Samw@Sun.COM } 6859914Samw@Sun.COM 686*10966SJordan.Brown@Sun.COM 6879914Samw@Sun.COM static int 68810001SJoyce.McIntosh@Sun.COM smb_rename_check_attr(smb_request_t *sr, smb_node_t *node, uint16_t sattr) 6899914Samw@Sun.COM { 69010001SJoyce.McIntosh@Sun.COM smb_attr_t attr; 6919914Samw@Sun.COM 69210001SJoyce.McIntosh@Sun.COM if (smb_node_getattr(sr, node, &attr) != 0) 69310001SJoyce.McIntosh@Sun.COM return (EIO); 69410001SJoyce.McIntosh@Sun.COM 69510001SJoyce.McIntosh@Sun.COM if ((attr.sa_dosattr & FILE_ATTRIBUTE_HIDDEN) && 69610001SJoyce.McIntosh@Sun.COM !(SMB_SEARCH_HIDDEN(sattr))) 6979914Samw@Sun.COM return (ESRCH); 6989914Samw@Sun.COM 69910001SJoyce.McIntosh@Sun.COM if ((attr.sa_dosattr & FILE_ATTRIBUTE_SYSTEM) && 70010001SJoyce.McIntosh@Sun.COM !(SMB_SEARCH_SYSTEM(sattr))) 7019914Samw@Sun.COM return (ESRCH); 7029914Samw@Sun.COM 7039914Samw@Sun.COM return (0); 7049914Samw@Sun.COM } 7059914Samw@Sun.COM 7069914Samw@Sun.COM /* 7079914Samw@Sun.COM * The following values are based on observed WFWG, Windows 9x, Windows NT 7089914Samw@Sun.COM * and Windows 2000 behaviour. 7099914Samw@Sun.COM * 7109914Samw@Sun.COM * ERROR_FILE_EXISTS doesn't work for Windows 98 clients. 7119914Samw@Sun.COM * 7129914Samw@Sun.COM * Windows 95 clients don't see the problem because the target is deleted 7139914Samw@Sun.COM * before the rename request. 7149914Samw@Sun.COM */ 7159914Samw@Sun.COM static void 7169914Samw@Sun.COM smb_rename_set_error(smb_request_t *sr, int errnum) 7179914Samw@Sun.COM { 7189914Samw@Sun.COM static struct { 7199914Samw@Sun.COM int errnum; 7209914Samw@Sun.COM uint16_t errcode; 7219914Samw@Sun.COM uint32_t status32; 7229914Samw@Sun.COM } rc_map[] = { 7239914Samw@Sun.COM { EEXIST, ERROR_ALREADY_EXISTS, NT_STATUS_OBJECT_NAME_COLLISION }, 7249914Samw@Sun.COM { EPIPE, ERROR_SHARING_VIOLATION, NT_STATUS_SHARING_VIOLATION }, 7259914Samw@Sun.COM { ENOENT, ERROR_FILE_NOT_FOUND, NT_STATUS_OBJECT_NAME_NOT_FOUND }, 7269914Samw@Sun.COM { ESRCH, ERROR_FILE_NOT_FOUND, NT_STATUS_NO_SUCH_FILE }, 7279914Samw@Sun.COM { EINVAL, ERROR_INVALID_PARAMETER, NT_STATUS_INVALID_PARAMETER }, 72810001SJoyce.McIntosh@Sun.COM { EACCES, ERROR_ACCESS_DENIED, NT_STATUS_ACCESS_DENIED }, 729*10966SJordan.Brown@Sun.COM { EISDIR, ERROR_ACCESS_DENIED, NT_STATUS_FILE_IS_A_DIRECTORY }, 73010001SJoyce.McIntosh@Sun.COM { EIO, ERROR_INTERNAL_ERROR, NT_STATUS_INTERNAL_ERROR } 7319914Samw@Sun.COM }; 7329914Samw@Sun.COM 7339914Samw@Sun.COM int i; 7349914Samw@Sun.COM 7359914Samw@Sun.COM if (errnum == 0) 7369914Samw@Sun.COM return; 7379914Samw@Sun.COM 7389914Samw@Sun.COM for (i = 0; i < sizeof (rc_map)/sizeof (rc_map[0]); ++i) { 7399914Samw@Sun.COM if (rc_map[i].errnum == errnum) { 7409914Samw@Sun.COM smbsr_error(sr, rc_map[i].status32, 7419914Samw@Sun.COM ERRDOS, rc_map[i].errcode); 7429914Samw@Sun.COM return; 7439914Samw@Sun.COM } 7449914Samw@Sun.COM } 7459914Samw@Sun.COM 7469914Samw@Sun.COM smbsr_errno(sr, errnum); 7479914Samw@Sun.COM } 748