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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <smbsrv/smb_kproto.h> 26 27 #define SMB_CREATE_NAMEBUF_SZ 16 28 29 /* 30 * Create a new file, or truncate an existing file to zero length, 31 * open the file and return a fid. The file is specified using a 32 * fully qualified name relative to the tree. 33 */ 34 smb_sdrc_t 35 smb_pre_create(smb_request_t *sr) 36 { 37 struct open_param *op = &sr->arg.open; 38 int rc; 39 40 bzero(op, sizeof (sr->arg.open)); 41 42 rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec); 43 if (rc == 0) 44 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 45 46 op->create_disposition = FILE_OVERWRITE_IF; 47 op->create_options = FILE_NON_DIRECTORY_FILE; 48 49 DTRACE_SMB_2(op__Create__start, smb_request_t *, sr, 50 struct open_param *, op); 51 52 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 53 } 54 55 void 56 smb_post_create(smb_request_t *sr) 57 { 58 DTRACE_SMB_1(op__Create__done, smb_request_t *, sr); 59 } 60 61 smb_sdrc_t 62 smb_com_create(smb_request_t *sr) 63 { 64 if (smb_common_create(sr) != NT_STATUS_SUCCESS) 65 return (SDRC_ERROR); 66 67 if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0)) 68 return (SDRC_ERROR); 69 70 return (SDRC_SUCCESS); 71 } 72 73 /* 74 * Create a new file and return a fid. The file is specified using 75 * a fully qualified name relative to the tree. 76 */ 77 smb_sdrc_t 78 smb_pre_create_new(smb_request_t *sr) 79 { 80 struct open_param *op = &sr->arg.open; 81 int rc; 82 83 bzero(op, sizeof (sr->arg.open)); 84 85 rc = smbsr_decode_vwv(sr, "wl", &op->dattr, &op->mtime.tv_sec); 86 if (rc == 0) 87 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 88 89 op->create_disposition = FILE_CREATE; 90 91 DTRACE_SMB_2(op__CreateNew__start, smb_request_t *, sr, 92 struct open_param *, op); 93 94 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 95 } 96 97 void 98 smb_post_create_new(smb_request_t *sr) 99 { 100 DTRACE_SMB_1(op__CreateNew__done, smb_request_t *, sr); 101 } 102 103 smb_sdrc_t 104 smb_com_create_new(smb_request_t *sr) 105 { 106 if (smb_common_create(sr) != NT_STATUS_SUCCESS) 107 return (SDRC_ERROR); 108 109 if (smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0)) 110 return (SDRC_ERROR); 111 112 return (SDRC_SUCCESS); 113 } 114 115 /* 116 * Create a unique file in the specified directory relative to the 117 * current tree. No attributes are specified. 118 */ 119 smb_sdrc_t 120 smb_pre_create_temporary(smb_request_t *sr) 121 { 122 struct open_param *op = &sr->arg.open; 123 uint16_t reserved; 124 int rc; 125 126 bzero(op, sizeof (sr->arg.open)); 127 128 rc = smbsr_decode_vwv(sr, "wl", &reserved, &op->mtime.tv_sec); 129 if (rc == 0) 130 rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); 131 132 op->create_disposition = FILE_CREATE; 133 134 DTRACE_SMB_2(op__CreateTemporary__start, smb_request_t *, sr, 135 struct open_param *, op); 136 137 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 138 } 139 140 void 141 smb_post_create_temporary(smb_request_t *sr) 142 { 143 DTRACE_SMB_1(op__CreateTemporary__done, smb_request_t *, sr); 144 } 145 146 smb_sdrc_t 147 smb_com_create_temporary(smb_request_t *sr) 148 { 149 static uint16_t tmp_id = 10000; 150 struct open_param *op = &sr->arg.open; 151 char name[SMB_CREATE_NAMEBUF_SZ]; 152 char *buf; 153 uint16_t bcc; 154 155 ++tmp_id; 156 bcc = 1; /* null terminator */ 157 bcc += snprintf(name, SMB_CREATE_NAMEBUF_SZ, "tt%05d.tmp", tmp_id); 158 159 buf = smb_srm_zalloc(sr, MAXPATHLEN); 160 (void) snprintf(buf, MAXPATHLEN, "%s\\%s", 161 op->fqi.fq_path.pn_path, name); 162 op->fqi.fq_path.pn_path = buf; 163 164 if (smb_common_create(sr) != NT_STATUS_SUCCESS) 165 return (SDRC_ERROR); 166 167 if (smbsr_encode_result(sr, 1, VAR_BCC, "bww%S", 1, sr->smb_fid, 168 VAR_BCC, sr, name)) 169 return (SDRC_ERROR); 170 171 return (SDRC_SUCCESS); 172 } 173 174 /* 175 * Common create file function. The file is opened in compatibility 176 * mode with read/write access. 177 */ 178 uint32_t 179 smb_common_create(smb_request_t *sr) 180 { 181 struct open_param *op = &sr->arg.open; 182 uint32_t status; 183 184 if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) 185 op->mtime.tv_sec = smb_time_local_to_gmt(sr, op->mtime.tv_sec); 186 op->mtime.tv_nsec = 0; 187 op->dsize = 0; 188 op->omode = SMB_DA_ACCESS_READ_WRITE | SMB_DA_SHARE_COMPATIBILITY; 189 op->desired_access = smb_omode_to_amask(op->omode); 190 op->share_access = smb_denymode_to_sharemode(op->omode, 191 op->fqi.fq_path.pn_path); 192 193 if (sr->smb_flg & SMB_FLAGS_OPLOCK) { 194 if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY) 195 op->op_oplock_level = SMB_OPLOCK_BATCH; 196 else 197 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 198 } else { 199 op->op_oplock_level = SMB_OPLOCK_NONE; 200 } 201 op->op_oplock_levelII = B_FALSE; 202 203 status = smb_common_open(sr); 204 205 if (op->op_oplock_level == SMB_OPLOCK_NONE) { 206 sr->smb_flg &= 207 ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY); 208 } 209 210 return (status); 211 } 212