/* * Copyright (c) 2000, Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Boris Popov. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: file.c,v 1.4 2004/12/13 00:25:21 lindak Exp $ */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "private.h" int smb_fh_close(int fd) { return (close(fd)); } int smb_fh_ntcreate( struct smb_ctx *ctx, char *path, int req_acc, int efattr, int share_acc, int open_disp, int create_opts) { smbioc_ntcreate_t ioc; int err, nmlen; int new_fd = -1; int32_t from_fd; nmlen = strlen(path); if (nmlen >= SMBIOC_MAX_NAME) { err = EINVAL; goto errout; } /* * Will represent this SMB-level open as a new * open device handle. Get one, then duplicate * the driver session and tree bindings. */ new_fd = smb_open_driver(); if (new_fd < 0) { err = errno; goto errout; } from_fd = ctx->ct_dev_fd; if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) { err = errno; goto errout; } /* * Do the SMB-level open with the new dev handle. */ bzero(&ioc, sizeof (ioc)); strlcpy(ioc.ioc_name, path, SMBIOC_MAX_NAME); ioc.ioc_req_acc = req_acc; ioc.ioc_efattr = efattr; ioc.ioc_share_acc = share_acc; ioc.ioc_open_disp = open_disp; ioc.ioc_creat_opts = create_opts; if (ioctl(new_fd, SMBIOC_NTCREATE, &ioc) == -1) { err = errno; goto errout; } return (new_fd); errout: if (new_fd != -1) close(new_fd); errno = err; return (-1); } /* * Conveinence wrapper for smb_fh_ntcreate * Converts Unix-style open call to NTCreate. */ int smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag) { int mode, open_disp, req_acc, share_acc; char *p, *ntpath = NULL; int fd = -1; /* * Convert Unix path to NT (backslashes) */ ntpath = strdup(path); if (ntpath == NULL) return (-1); /* errno was set */ for (p = ntpath; *p; p++) if (*p == '/') *p = '\\'; /* * Map O_RDONLY, O_WRONLY, O_RDWR * to FREAD, FWRITE */ mode = (oflag & 3) + 1; /* * Compute requested access, share access. */ req_acc = ( STD_RIGHT_READ_CONTROL_ACCESS | STD_RIGHT_SYNCHRONIZE_ACCESS); share_acc = NTCREATEX_SHARE_ACCESS_NONE; if (mode & FREAD) { req_acc |= ( SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_EA | SA_RIGHT_FILE_READ_ATTRIBUTES); share_acc |= NTCREATEX_SHARE_ACCESS_READ; } if (mode & FWRITE) { req_acc |= ( SA_RIGHT_FILE_WRITE_DATA | SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES); share_acc |= NTCREATEX_SHARE_ACCESS_WRITE; } /* * Compute open disposition */ if (oflag & FCREAT) { /* Creat if necessary. */ if (oflag & FEXCL) { /* exclusive */ open_disp = NTCREATEX_DISP_CREATE; } else if (oflag & FTRUNC) open_disp = NTCREATEX_DISP_OVERWRITE_IF; else open_disp = NTCREATEX_DISP_OPEN_IF; } else { /* Not creating. */ if (oflag & FTRUNC) open_disp = NTCREATEX_DISP_OVERWRITE; else open_disp = NTCREATEX_DISP_OPEN; } fd = smb_fh_ntcreate(ctx, ntpath, req_acc, SMB_EFA_NORMAL, share_acc, open_disp, NTCREATEX_OPTIONS_NON_DIRECTORY_FILE); free(ntpath); return (fd); } int smb_fh_read(int fd, off_t offset, size_t count, char *dst) { struct smbioc_rw rwrq; bzero(&rwrq, sizeof (rwrq)); rwrq.ioc_fh = -1; /* tell driver to supply this */ rwrq.ioc_base = dst; rwrq.ioc_cnt = count; rwrq.ioc_offset = offset; if (ioctl(fd, SMBIOC_READ, &rwrq) == -1) { return (-1); } return (rwrq.ioc_cnt); } int smb_fh_write(int fd, off_t offset, size_t count, const char *src) { struct smbioc_rw rwrq; bzero(&rwrq, sizeof (rwrq)); rwrq.ioc_fh = -1; /* tell driver to supply this */ rwrq.ioc_base = (char *)src; rwrq.ioc_cnt = count; rwrq.ioc_offset = offset; if (ioctl(fd, SMBIOC_WRITE, &rwrq) == -1) { return (-1); } return (rwrq.ioc_cnt); } /* * Do a TRANSACT_NAMED_PIPE, which is basically just a * pipe write and pipe read, all in one round trip. * * tdlen, tdata describe the data to send. * rdlen, rdata on input describe the receive buffer, * and on output *rdlen is the received length. */ int smb_fh_xactnp(int fd, int tdlen, const char *tdata, /* transmit */ int *rdlen, char *rdata, /* receive */ int *more) { int err, rparamcnt; uint16_t setup[2]; setup[0] = TRANS_TRANSACT_NAMED_PIPE; setup[1] = 0xFFFF; /* driver replaces this */ rparamcnt = 0; err = smb_t2_request(fd, 2, setup, "\\PIPE\\", 0, NULL, /* TX paramcnt, params */ tdlen, (void *)tdata, &rparamcnt, NULL, /* no RX params */ rdlen, rdata, more); if (err) *rdlen = 0; return (err); }