1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <smbsrv/smb_incl.h> 27 28 #define SMB_CREATE_NAMEBUF_SZ 16 29 30 static uint32_t smb_common_create(smb_request_t *sr); 31 32 /* 33 * Create a new file, or truncate an existing file to zero length, 34 * open the file and return a fid. The file is specified using a 35 * fully qualified name relative to the tree. 36 */ 37 smb_sdrc_t 38 smb_pre_create(smb_request_t *sr) 39 { 40 struct open_param *op = &sr->arg.open; 41 int rc; 42 43 bzero(op, sizeof (sr->arg.open)); 44 45 rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec); 46 if (rc == 0) 47 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 48 49 op->create_disposition = FILE_OVERWRITE_IF; 50 op->create_options = FILE_NON_DIRECTORY_FILE; 51 52 DTRACE_SMB_2(op__Create__start, smb_request_t *, sr, 53 struct open_param *, op); 54 55 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 56 } 57 58 void 59 smb_post_create(smb_request_t *sr) 60 { 61 DTRACE_SMB_1(op__Create__done, smb_request_t *, sr); 62 } 63 64 smb_sdrc_t 65 smb_com_create(smb_request_t *sr) 66 { 67 if (smb_common_create(sr) != NT_STATUS_SUCCESS) 68 return (SDRC_ERROR); 69 70 if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0)) 71 return (SDRC_ERROR); 72 73 return (SDRC_SUCCESS); 74 } 75 76 /* 77 * Create a new file and return a fid. The file is specified using 78 * a fully qualified name relative to the tree. 79 */ 80 smb_sdrc_t 81 smb_pre_create_new(smb_request_t *sr) 82 { 83 struct open_param *op = &sr->arg.open; 84 int rc; 85 86 bzero(op, sizeof (sr->arg.open)); 87 88 rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec); 89 if (rc == 0) 90 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 91 92 op->create_disposition = FILE_CREATE; 93 94 DTRACE_SMB_2(op__CreateNew__start, smb_request_t *, sr, 95 struct open_param *, op); 96 97 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 98 } 99 100 void 101 smb_post_create_new(smb_request_t *sr) 102 { 103 DTRACE_SMB_1(op__CreateNew__done, smb_request_t *, sr); 104 } 105 106 smb_sdrc_t 107 smb_com_create_new(smb_request_t *sr) 108 { 109 if (smb_common_create(sr) != NT_STATUS_SUCCESS) 110 return (SDRC_ERROR); 111 112 if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0)) 113 return (SDRC_ERROR); 114 115 return (SDRC_SUCCESS); 116 } 117 118 /* 119 * Create a unique file in the specified directory relative to the 120 * current tree. No attributes are specified. 121 */ 122 smb_sdrc_t 123 smb_pre_create_temporary(smb_request_t *sr) 124 { 125 struct open_param *op = &sr->arg.open; 126 uint16_t reserved; 127 int rc; 128 129 bzero(op, sizeof (sr->arg.open)); 130 131 rc = smbsr_decode_vwv(sr, "wl", &reserved, &op->mtime.tv_sec); 132 if (rc == 0) 133 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 134 135 op->create_disposition = FILE_CREATE; 136 137 DTRACE_SMB_2(op__CreateTemporary__start, smb_request_t *, sr, 138 struct open_param *, op); 139 140 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 141 } 142 143 void 144 smb_post_create_temporary(smb_request_t *sr) 145 { 146 DTRACE_SMB_1(op__CreateTemporary__done, smb_request_t *, sr); 147 } 148 149 smb_sdrc_t 150 smb_com_create_temporary(smb_request_t *sr) 151 { 152 static uint16_t tmp_id = 10000; 153 struct open_param *op = &sr->arg.open; 154 char name[SMB_CREATE_NAMEBUF_SZ]; 155 char *buf; 156 uint16_t bcc; 157 158 ++tmp_id; 159 bcc = 1; /* null terminator */ 160 bcc += snprintf(name, SMB_CREATE_NAMEBUF_SZ, "tt%05d.tmp", tmp_id); 161 162 buf = smbsr_malloc(&sr->request_storage, MAXPATHLEN); 163 (void) snprintf(buf, MAXPATHLEN, "%s\\%s", 164 op->fqi.fq_path.pn_path, name); 165 op->fqi.fq_path.pn_path = buf; 166 167 if (smb_common_create(sr) != NT_STATUS_SUCCESS) 168 return (SDRC_ERROR); 169 170 if (smbsr_encode_result(sr, 1, VAR_BCC, "bww%S", 1, sr->smb_fid, 171 VAR_BCC, sr, name)) 172 return (SDRC_ERROR); 173 174 return (SDRC_SUCCESS); 175 } 176 177 /* 178 * Common create file function. The file is opened in compatibility 179 * mode with read/write access. 180 */ 181 uint32_t 182 smb_common_create(smb_request_t *sr) 183 { 184 struct open_param *op = &sr->arg.open; 185 uint32_t status; 186 187 if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) 188 op->mtime.tv_sec = smb_time_local_to_gmt(sr, op->mtime.tv_sec); 189 op->mtime.tv_nsec = 0; 190 op->dsize = 0; 191 op->omode = SMB_DA_ACCESS_READ_WRITE | SMB_DA_SHARE_COMPATIBILITY; 192 op->desired_access = smb_omode_to_amask(op->omode); 193 op->share_access = smb_denymode_to_sharemode(op->omode, 194 op->fqi.fq_path.pn_path); 195 196 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 197 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 198 op->op_oplock_level = SMB_OPLOCK_BATCH; 199 else 200 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 201 } else { 202 op->op_oplock_level = SMB_OPLOCK_NONE; 203 } 204 205 status = smb_common_open(sr); 206 207 if (op->op_oplock_level == SMB_OPLOCK_NONE) { 208 sr->smb_flg &= 209 ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); 210 } 211 212 return (status); 213 } 214