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 /* 22*5772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw #include <smbsrv/smb_incl.h> 295331Samw 305331Samw #define SMB_CREATE_NAMEBUF_SZ 16 315331Samw 325331Samw static uint32_t smb_common_create(struct smb_request *sr); 335331Samw 345331Samw /* 355331Samw * Create a new file, or truncate an existing file to zero length, 365331Samw * open the file and return a fid. The file is specified using a 375331Samw * fully qualified name relative to the tree. 385331Samw */ 395331Samw int 405331Samw smb_com_create(struct smb_request *sr) 415331Samw { 425331Samw struct open_param *op = &sr->arg.open; 435331Samw uint32_t status; 445331Samw 455331Samw bzero(op, sizeof (sr->arg.open)); 465331Samw 475331Samw if (smbsr_decode_vwv(sr, "wl", &op->dattr, &op->utime.tv_sec) != 0) { 485331Samw smbsr_decode_error(sr); 495331Samw /* NOTREACHED */ 505331Samw } 515331Samw 525331Samw if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { 535331Samw smbsr_decode_error(sr); 545331Samw /* NOTREACHED */ 555331Samw } 565331Samw 575331Samw op->create_disposition = FILE_OVERWRITE_IF; 585331Samw status = smb_common_create(sr); 595331Samw 605331Samw switch (status) { 615331Samw case NT_STATUS_SUCCESS: 625331Samw break; 635331Samw 645331Samw case NT_STATUS_SHARING_VIOLATION: 65*5772Sas200622 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, 665331Samw ERRDOS, ERROR_SHARING_VIOLATION); 675331Samw /* NOTREACHED */ 685331Samw break; 695331Samw 705331Samw default: 71*5772Sas200622 smbsr_error(sr, status, 0, 0); 725331Samw /* NOTREACHED */ 735331Samw break; 745331Samw } 755331Samw 765331Samw smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0); 775331Samw return (SDRC_NORMAL_REPLY); 785331Samw } 795331Samw 805331Samw /* 815331Samw * Create a new file and return a fid. The file is specified using 825331Samw * a fully qualified name relative to the tree. 835331Samw */ 845331Samw int 855331Samw smb_com_create_new(struct smb_request *sr) 865331Samw { 875331Samw struct open_param *op = &sr->arg.open; 885331Samw uint32_t status; 895331Samw 905331Samw bzero(op, sizeof (sr->arg.open)); 915331Samw 925331Samw if (smbsr_decode_vwv(sr, "wl", &op->dattr, &op->utime.tv_sec) != 0) { 935331Samw smbsr_decode_error(sr); 945331Samw /* NOTREACHED */ 955331Samw } 965331Samw 975331Samw if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { 985331Samw smbsr_decode_error(sr); 995331Samw /* NOTREACHED */ 1005331Samw } 1015331Samw 1025331Samw op->create_disposition = FILE_CREATE; 1035331Samw status = smb_common_create(sr); 1045331Samw 1055331Samw switch (status) { 1065331Samw case NT_STATUS_SUCCESS: 1075331Samw break; 1085331Samw 1095331Samw case NT_STATUS_SHARING_VIOLATION: 110*5772Sas200622 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, 1115331Samw ERRDOS, ERROR_SHARING_VIOLATION); 1125331Samw /* NOTREACHED */ 1135331Samw break; 1145331Samw 1155331Samw default: 116*5772Sas200622 smbsr_error(sr, status, 0, 0); 1175331Samw /* NOTREACHED */ 1185331Samw break; 1195331Samw } 1205331Samw 1215331Samw smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0); 1225331Samw return (SDRC_NORMAL_REPLY); 1235331Samw } 1245331Samw 1255331Samw 1265331Samw /* 1275331Samw * Create a unique file in the specified directory relative to the 1285331Samw * current tree. No attributes are specified. 1295331Samw */ 1305331Samw int 1315331Samw smb_com_create_temporary(struct smb_request *sr) 1325331Samw { 1335331Samw static uint16_t tmp_id = 10000; 1345331Samw struct open_param *op = &sr->arg.open; 1355331Samw char name[SMB_CREATE_NAMEBUF_SZ]; 1365331Samw char *buf; 1375331Samw uint32_t status; 1385331Samw uint16_t reserved; 1395331Samw uint16_t bcc; 1405331Samw 1415331Samw bzero(op, sizeof (sr->arg.open)); 1425331Samw 1435331Samw if (smbsr_decode_vwv(sr, "wl", &reserved, &op->utime.tv_sec) != 0) { 1445331Samw smbsr_decode_error(sr); 1455331Samw /* NOTREACHED */ 1465331Samw } 1475331Samw 1485331Samw if (smbsr_decode_data(sr, "%S", sr, &op->fqi.path) != 0) { 1495331Samw smbsr_decode_error(sr); 1505331Samw /* NOTREACHED */ 1515331Samw } 1525331Samw 1535331Samw ++tmp_id; 1545331Samw bcc = 1; /* null terminator */ 1555331Samw bcc += snprintf(name, SMB_CREATE_NAMEBUF_SZ, "tt%05d.tmp", tmp_id); 1565331Samw 1575331Samw buf = smbsr_malloc(&sr->request_storage, MAXPATHLEN); 1585331Samw (void) snprintf(buf, MAXPATHLEN, "%s\\%s", op->fqi.path, name); 1595331Samw op->fqi.path = buf; 1605331Samw op->create_disposition = FILE_CREATE; 1615331Samw status = smb_common_create(sr); 1625331Samw 1635331Samw switch (status) { 1645331Samw case NT_STATUS_SUCCESS: 1655331Samw break; 1665331Samw 1675331Samw case NT_STATUS_SHARING_VIOLATION: 168*5772Sas200622 smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, 1695331Samw ERRDOS, ERROR_SHARING_VIOLATION); 1705331Samw /* NOTREACHED */ 1715331Samw break; 1725331Samw 1735331Samw default: 174*5772Sas200622 smbsr_error(sr, status, 0, 0); 1755331Samw /* NOTREACHED */ 1765331Samw break; 1775331Samw } 1785331Samw 1795521Sas200622 smbsr_encode_result(sr, 1, 0, "bwwbs", 1, sr->smb_fid, bcc, 4, name); 1805331Samw return (SDRC_NORMAL_REPLY); 1815331Samw } 1825331Samw 1835331Samw /* 1845331Samw * Common create file function. The file is opened in compatibility 1855331Samw * mode with read/write access. 1865331Samw */ 1875331Samw uint32_t 1885331Samw smb_common_create(struct smb_request *sr) 1895331Samw { 1905331Samw struct open_param *op = &sr->arg.open; 1915331Samw uint32_t status; 1925331Samw 1935331Samw op->utime.tv_sec = smb_local_time_to_gmt(op->utime.tv_sec); 1945331Samw op->utime.tv_nsec = 0; 1955331Samw op->omode = SMB_DA_ACCESS_READ_WRITE | SMB_DA_SHARE_COMPATIBILITY; 1965331Samw op->desired_access = smb_omode_to_amask(op->omode); 1975331Samw op->share_access = smb_denymode_to_sharemode(op->omode, op->fqi.path); 1985331Samw 1995331Samw if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || 2005331Samw (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { 201*5772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 2025331Samw ERRDOS, ERROR_INVALID_PARAMETER); 2035331Samw /* NOTREACHED */ 2045331Samw } 2055331Samw 2065331Samw op->dsize = 0; 2075331Samw 2085331Samw if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 2095331Samw if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) { 2105331Samw op->my_flags = MYF_BATCH_OPLOCK; 2115331Samw } else { 2125331Samw op->my_flags = MYF_EXCLUSIVE_OPLOCK; 2135331Samw } 2145331Samw } 2155331Samw 2165331Samw status = smb_open_subr(sr); 2175331Samw 2185331Samw if (MYF_OPLOCK_TYPE(op->my_flags) == MYF_OPLOCK_NONE) { 2195331Samw sr->smb_flg &= 2205331Samw ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); 2215331Samw } 2225331Samw 2235331Samw return (status); 2245331Samw } 225