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