smb_common_open.c revision 6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2e
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This module provides the common open functionality to the various
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * open and create SMB interface functions.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This macro is used to delete a newly created object
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * if any error happens after creation of object.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_access_generic_to_file
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Search MSDN for IoCreateFile to see following mapping.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * FILE_READ_ATTRIBUTES and FILE_READ_EA
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_omode_to_amask
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function converts open modes used by Open and Open AndX
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * commands to desired access bits used by NT Create AndX command.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* invalid open mode */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_denymode_to_sharemode
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function converts deny modes used by Open and Open AndX
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * commands to share access bits used by NT Create AndX command.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_denymode_to_sharemode(uint32_t desired_access, char *fname)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* invalid deny mode */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_ofun_to_crdisposition
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function converts open function values used by Open and Open AndX
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * commands to create disposition values used by NT Create AndX command.
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * Retry opens to avoid spurious sharing violations, due to timing
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * issues between closes and opens. The client that already has the
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * file open may be in the process of closing it.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_open_subr
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Notes on write-through behaviour. It looks like pre-LM0.12 versions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of the protocol specify the write-through mode when a file is opened,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SmbWriteAndUnlock) don't need to contain a write-through flag.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * don't indicate which write-through mode to use. Instead the write
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We don't care which open call was used to get us here, we just need
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to ensure that the write-through mode flag is copied from the open
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * parameters to the node. We test the omode write-through flag in all
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * write functions.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function will return NT status codes but it also raises errors,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in which case it won't return to the caller. Be careful how you
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * handle things in here.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned int granted_oplock;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * The object being created or opened is a directory,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * and the Disposition parameter must be one of
7b59d02d2a384be9a08087b14defadd214b3c1ddjb * FILE_CREATE, FILE_OPEN, or FILE_OPEN_IF
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw op->desired_access = smb_access_generic_to_file(op->desired_access);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* This must be NULL at this point */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * No further processing for IPC, we need to either
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * raise an exception or return success here.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Some clients pass null file names; NT interprets this as "\".
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pathlen == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((status = smb_validate_object_name(op->fqi.path, is_dir)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc = smb_pathname_reduce(sr, sr->user_cr, op->fqi.path,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the access mask has only DELETE set (ignore
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * FILE_READ_ATTRIBUTES), then assume that this
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is a request to delete the link (if a link)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and do not follow links. Otherwise, follow
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the link to the target.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sr->tid_tree->t_snode, op->fqi.dir_snode, op->fqi.last_comp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == 0) {
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * which is used to uniquely identify open instances for the
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * VFS share reservation mechanism (accessed via smb_fsop_shrlock()).
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Enter critical region for share reservations.
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * (See comments above smb_fsop_shrlock().)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Reject this request if the target is a directory
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and the client has specified that it must not be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * a directory (required by Lotus Notes).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Directories cannot be opened
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * with the above commands
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * No more open should be accepted when "Delete on close"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * flag is set.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Specified file already exists so the operation should fail.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Windows seems to check read-only access before file
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * sharing check.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Files data only */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * The following check removes the need to check share
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * reservations again when a truncate is done.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Break the oplock before share checks. If another client
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * has the file open, this will force a flush or close,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * which may affect the outcome of any share checking.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If file is being replaced,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * we should remove existing streams
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * FILE_OPEN or FILE_OPEN_IF.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Last component was not found. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * lock the parent dir node in case another create
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * request to the same parent directory comes in.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (is_dir == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * A problem with setting the readonly bit at
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * create time is that this bit will prevent
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * writes to the file from the same fid (which
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * should be allowed).
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * The solution is to set the bit at close time.
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * Meanwhile, to prevent racing opens from being
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * able to write to the file, set share reservations
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * to prevent write and delete access.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_ofile_open() will copy node to of->node. Hence
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the hold on node (i.e. op->fqi.last_snode) will be "transferred"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to the "of" structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op->desired_access,
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as op->create_options, share_access, SMB_FTYPE_DISK, NULL, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Propagate the write-through mode from the open params
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to the node: see the notes in the function header.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * IR #102318 Mirroring may force synchronous
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * writes regardless of what we specify here.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* We don't oplock directories */
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * smb_fsop_unshrlock() and smb_fsop_close()
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * are called from smb_ofile_close()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Clients may set the DOS readonly bit on create but they
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * expect subsequent write operations on the open fid to
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * succeed. Thus the DOS readonly bit is not set until
6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2eas * the file is closed. The NODE_CREATED_READONLY flag
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * will act as the indicator to set the DOS readonly bit on
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (op->utime.tv_sec == 0 || op->utime.tv_sec == UINT_MAX)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_node_set_time(node, NULL, &op->utime, 0, 0, SMB_AT_MTIME);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If we reach here, it means that file already exists
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and if create disposition is one of: FILE_SUPERSEDE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * FILE_OVERWRITE_IF, or FILE_OVERWRITE it
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * means that client wants to overwrite (or truncate)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the existing file. So we should overwrite the dos
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * attributes of destination file with the dos attributes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of source file.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Set up the file type in open_param for the response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_validate_object_name
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Very basic file name validation. Directory validation is handed off
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to smb_validate_dirname. For filenames, we check for names of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * form "AAAn:". Names that contain three characters, a single digit
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and a colon (:) are reserved as DOS device names, i.e. "COM1:".
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns NT status codes.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Basename with backslashes.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_preset_delete_on_close
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Set the DeleteOnClose flag on the smb file. When the file is closed,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the flag will be transferred to the smb node, which will commit the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * delete operation and inhibit subsequent open requests.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When DeleteOnClose is set on an smb_node, the common open code will
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * reject subsequent open requests for the file. Observation of Windows
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 2000 indicates that subsequent opens should be allowed (assuming
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * there would be no sharing violation) until the file is closed using
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the fid on which the DeleteOnClose was requested.