1 /* 2 * Copyright (c) 2000, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: file.c,v 1.4 2004/12/13 00:25:21 lindak Exp $ 33 */ 34 35 /* 36 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 37 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 38 * Use is subject to license terms. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/ioctl.h> 43 #include <sys/time.h> 44 #include <sys/mount.h> 45 #include <fcntl.h> 46 #include <ctype.h> 47 #include <errno.h> 48 #include <stdio.h> 49 #include <string.h> 50 #include <strings.h> 51 #include <stdlib.h> 52 #include <pwd.h> 53 #include <grp.h> 54 #include <unistd.h> 55 #include <libintl.h> 56 57 #include <sys/types.h> 58 #include <sys/file.h> 59 60 #include <netsmb/smb.h> 61 #include <netsmb/smb_lib.h> 62 63 #include "private.h" 64 65 int 66 smb_fh_close(int fd) 67 { 68 return (close(fd)); 69 } 70 71 int 72 smb_fh_ntcreate( 73 struct smb_ctx *ctx, char *path, 74 int req_acc, int efattr, int share_acc, 75 int open_disp, int create_opts) 76 { 77 smbioc_ntcreate_t ioc; 78 int err, nmlen; 79 int new_fd = -1; 80 int32_t from_fd; 81 82 nmlen = strlen(path); 83 if (nmlen >= SMBIOC_MAX_NAME) { 84 err = EINVAL; 85 goto errout; 86 } 87 88 /* 89 * Will represent this SMB-level open as a new 90 * open device handle. Get one, then duplicate 91 * the driver session and tree bindings. 92 */ 93 new_fd = smb_open_driver(); 94 if (new_fd < 0) { 95 err = errno; 96 goto errout; 97 } 98 from_fd = ctx->ct_dev_fd; 99 if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) { 100 err = errno; 101 goto errout; 102 } 103 104 /* 105 * Do the SMB-level open with the new dev handle. 106 */ 107 bzero(&ioc, sizeof (ioc)); 108 strlcpy(ioc.ioc_name, path, SMBIOC_MAX_NAME); 109 ioc.ioc_req_acc = req_acc; 110 ioc.ioc_efattr = efattr; 111 ioc.ioc_share_acc = share_acc; 112 ioc.ioc_open_disp = open_disp; 113 ioc.ioc_creat_opts = create_opts; 114 if (ioctl(new_fd, SMBIOC_NTCREATE, &ioc) == -1) { 115 err = errno; 116 goto errout; 117 } 118 119 return (new_fd); 120 121 errout: 122 if (new_fd != -1) 123 close(new_fd); 124 errno = err; 125 return (-1); 126 } 127 128 /* 129 * Conveinence wrapper for smb_fh_ntcreate 130 * Converts Unix-style open call to NTCreate. 131 */ 132 int 133 smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag) 134 { 135 int mode, open_disp, req_acc, share_acc; 136 char *p, *ntpath = NULL; 137 int fd = -1; 138 139 /* 140 * Convert Unix path to NT (backslashes) 141 */ 142 ntpath = strdup(path); 143 if (ntpath == NULL) 144 return (-1); /* errno was set */ 145 for (p = ntpath; *p; p++) 146 if (*p == '/') 147 *p = '\\'; 148 149 /* 150 * Map O_RDONLY, O_WRONLY, O_RDWR 151 * to FREAD, FWRITE 152 */ 153 mode = (oflag & 3) + 1; 154 155 /* 156 * Compute requested access, share access. 157 */ 158 req_acc = ( 159 STD_RIGHT_READ_CONTROL_ACCESS | 160 STD_RIGHT_SYNCHRONIZE_ACCESS); 161 share_acc = NTCREATEX_SHARE_ACCESS_NONE; 162 if (mode & FREAD) { 163 req_acc |= ( 164 SA_RIGHT_FILE_READ_DATA | 165 SA_RIGHT_FILE_READ_EA | 166 SA_RIGHT_FILE_READ_ATTRIBUTES); 167 share_acc |= NTCREATEX_SHARE_ACCESS_READ; 168 } 169 if (mode & FWRITE) { 170 req_acc |= ( 171 SA_RIGHT_FILE_WRITE_DATA | 172 SA_RIGHT_FILE_APPEND_DATA | 173 SA_RIGHT_FILE_WRITE_EA | 174 SA_RIGHT_FILE_WRITE_ATTRIBUTES); 175 share_acc |= NTCREATEX_SHARE_ACCESS_WRITE; 176 } 177 178 /* 179 * Compute open disposition 180 */ 181 if (oflag & FCREAT) { 182 /* Creat if necessary. */ 183 if (oflag & FEXCL) { 184 /* exclusive */ 185 open_disp = NTCREATEX_DISP_CREATE; 186 } else if (oflag & FTRUNC) 187 open_disp = NTCREATEX_DISP_OVERWRITE_IF; 188 else 189 open_disp = NTCREATEX_DISP_OPEN_IF; 190 } else { 191 /* Not creating. */ 192 if (oflag & FTRUNC) 193 open_disp = NTCREATEX_DISP_OVERWRITE; 194 else 195 open_disp = NTCREATEX_DISP_OPEN; 196 } 197 198 fd = smb_fh_ntcreate(ctx, ntpath, 199 req_acc, SMB_EFA_NORMAL, share_acc, open_disp, 200 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE); 201 202 free(ntpath); 203 return (fd); 204 } 205 206 int 207 smb_fh_read(int fd, off64_t offset, size_t count, 208 char *dst) 209 { 210 struct smbioc_rw rwrq; 211 212 bzero(&rwrq, sizeof (rwrq)); 213 rwrq.ioc_fh = -1; /* tell driver to supply this */ 214 rwrq.ioc_base = dst; 215 rwrq.ioc_cnt = count; 216 rwrq.ioc_offset = offset; 217 if (ioctl(fd, SMBIOC_READ, &rwrq) == -1) { 218 return (-1); 219 } 220 return (rwrq.ioc_cnt); 221 } 222 223 int 224 smb_fh_write(int fd, off64_t offset, size_t count, 225 const char *src) 226 { 227 struct smbioc_rw rwrq; 228 229 bzero(&rwrq, sizeof (rwrq)); 230 rwrq.ioc_fh = -1; /* tell driver to supply this */ 231 rwrq.ioc_base = (char *)src; 232 rwrq.ioc_cnt = count; 233 rwrq.ioc_offset = offset; 234 if (ioctl(fd, SMBIOC_WRITE, &rwrq) == -1) { 235 return (-1); 236 } 237 return (rwrq.ioc_cnt); 238 } 239 240 /* 241 * Do a TRANSACT_NAMED_PIPE, which is basically just a 242 * pipe write and pipe read, all in one round trip. 243 * 244 * tdlen, tdata describe the data to send. 245 * rdlen, rdata on input describe the receive buffer, 246 * and on output *rdlen is the received length. 247 */ 248 int 249 smb_fh_xactnp(int fd, 250 int tdlen, const char *tdata, /* transmit */ 251 int *rdlen, char *rdata, /* receive */ 252 int *more) 253 { 254 int err, rparamcnt; 255 uint16_t setup[2]; 256 257 setup[0] = TRANS_TRANSACT_NAMED_PIPE; 258 setup[1] = 0xFFFF; /* driver replaces this */ 259 rparamcnt = 0; 260 261 err = smb_t2_request(fd, 2, setup, "\\PIPE\\", 262 0, NULL, /* TX paramcnt, params */ 263 tdlen, (void *)tdata, 264 &rparamcnt, NULL, /* no RX params */ 265 rdlen, rdata, more); 266 267 if (err) 268 *rdlen = 0; 269 270 return (err); 271 } 272