smb_delete.c revision f8a1d300ed7ddc7275868141e3f7a5b9d1b2bb76
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_fsops.h>
/*
* smb_com_delete
*
* The delete file message is sent to delete a data file. The appropriate
* Tid and additional pathname are passed. Read only files may not be
* deleted, the read-only attribute must be reset prior to file deletion.
*
* NT supports a hidden permission known as File Delete Child (FDC). If
* the user has FullControl access to a directory, the user is permitted
* to delete any object in the directory regardless of the permissions
* on the object.
*
* Client Request Description
* ================================== =================================
* UCHAR WordCount; Count of parameter words = 1
* USHORT SearchAttributes;
* USHORT ByteCount; Count of data bytes; min = 2
* UCHAR BufferFormat; 0x04
* STRING FileName[]; File name
*
* Multiple files may be deleted in response to a single request as
* SMB_COM_DELETE supports wildcards
*
* SearchAttributes indicates the attributes that the target file(s) must
* have. If the attribute is zero then only normal files are deleted. If
* the system file or hidden attributes are specified then the delete is
* inclusive -both the specified type(s) of files and normal files are
* deleted. Attributes are described in the "Attribute Encoding" section
* of this document.
*
* If bit0 of the Flags2 field of the SMB header is set, a pattern is
* passed in, and the file has a long name, then the passed pattern much
* match the long file name for the delete to succeed. If bit0 is clear, a
* pattern is passed in, and the file has a long name, then the passed
* pattern must match the file's short name for the deletion to succeed.
*
* Server Response Description
* ================================== =================================
* UCHAR WordCount; Count of parameter words = 0
* USHORT ByteCount; Count of data bytes = 0
*
* 4.2.10.1 Errors
*
* ERRDOS/ERRbadshare # returned by NT for files that are already open
*/
{
int rc;
}
void
{
}
/*
* smb_com_delete
*
* 1. pre-process pathname - smb_delete_check_path()
* checks dot, bad path syntax, wildcards in path
*
* 2. process the path to get directory node & last_comp,
* store these in fqi
* - If smb_pathname_reduce cannot find the specified path,
* the error (ENOTDIR) is translated to NT_STATUS_OBJECT_PATH_NOT_FOUND
* if the target is a single file (no wildcards). If there are
* wildcards in the last_comp, NT_STATUS_OBJECT_NAME_NOT_FOUND is
* used instead.
* - If the directory node is the mount point and the last component
* is ".." NT_STATUS_OBJECT_PATH_SYNTAX_BAD is returned.
*
* 3. check access permissions
*
* 4. invoke the appropriate deletion routine to find and remove
* the specified file(s).
* - if target is a single file (no wildcards) - smb_delete_single_file
* - if the target contains wildcards - smb_delete_multiple_files
*
* Returns: SDRC_SUCCESS or SDRC_ERROR
*/
{
int rc;
return (SDRC_ERROR);
if (rc == 0) {
}
}
if (rc != 0) {
if (wildcards)
else
} else {
}
return (SDRC_ERROR);
}
return (SDRC_ERROR);
}
if (rc != 0) {
return (SDRC_ERROR);
}
if (wildcards)
else
if (rc != 0)
else
}
/*
* smb_delete_single_file
*
* Find the specified file and, if its attributes match the search
* criteria, delete it.
*
* Returns 0 - success (file deleted)
* -1 - error, err is populated with error details
*/
static int
{
return (-1);
}
return (-1);
}
return (-1);
}
return (0);
}
/*
* smb_delete_multiple_files
*
* For each matching file found by smb_delete_find_name:
* 1. lookup file
* 2. check the file's attributes
* - The search ends with an error if a readonly file
* (NT_STATUS_CANNOT_DELETE) is matched.
* - The search ends (but not an error) if a directory is
* matched and the request's search did not include
* directories.
* - Otherwise, if smb_delete_check_attr fails the file
* is skipped and the search continues (at step 1)
* 3. delete the file
*
* Returns 0 - success
* -1 - error, err is populated with error details
*/
static int
{
for (;;) {
if (rc != 0)
break;
if (rc != 0)
break;
return (-1);
}
break;
continue;
}
++deleted;
continue;
}
continue;
}
return (-1);
}
return (-1);
}
if (deleted == 0) {
return (-1);
}
return (0);
}
/*
* smb_delete_find_fname
*
* Find next filename that matches search pattern (fqi->last_comp)
* and save it in fqi->last_comp_od.
*
* Returns: 0 - success
* errno
*/
static int
{
char name83[SMB_SHORTNAMELEN];
char shortname[SMB_SHORTNAMELEN];
for (;;) {
if (rc != 0)
return (rc);
/* check for EOF */
if (n_name == 0)
return (ENOENT);
return (0);
}
}
/*
* smb_delete_check_attr
*
* Check file's dos atributes to ensure that
* 1. the file is not a directory - NT_STATUS_FILE_IS_A_DIRECTORY
* 2. the file is not readonly - NT_STATUS_CANNOT_DELETE
* 3. the file's dos attributes comply with the specified search attributes
* If the file is either hidden or system and those attributes
* are not specified in the search attributes - NT_STATUS_NO_SUCH_FILE
*
* Returns: 0 - file's attributes pass all checks
* -1 - err populated with error details
*/
static int
{
if (dosattr & FILE_ATTRIBUTE_DIRECTORY) {
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (0);
}
/*
* smb_delete_remove_file
*
* For consistency with Windows 2000, the range check should be done
* after checking for sharing violations. Attempting to delete a
* locked file will result in sharing violation, which is the same
* thing that will happen if you try to delete a non-locked open file.
*
* Note that windows 2000 rejects lock requests on open files that
* have been opened with metadata open modes. The error is
* STATUS_ACCESS_DENIED.
*
* NT does not always close a file immediately, which can cause the
* share and access checking to fail (the node refcnt is greater
* than one), and the file doesn't get deleted. Breaking the oplock
* before share and access checking gives the client a chance to
* close the file.
*
* Returns: 0 - success
* -1 - error, err populated with error details
*/
static int
{
int rc;
if (status != NT_STATUS_SUCCESS) {
return (-1);
}
if (status != NT_STATUS_SUCCESS) {
return (-1);
}
if (rc != 0) {
else
return (-1);
}
return (0);
}
/*
* smb_delete_check_path
*
* Perform initial validation on the pathname and last_comp.
*
* wildcards in path:
* Wildcards in the path (excluding the last_comp) should result
* in NT_STATUS_OBJECT_NAME_INVALID.
*
* bad path syntax:
* On unix .. at the root of a file system links to the root. Thus
* an attempt to lookup "/../../.." will be the same as looking up "/"
* CIFs clients expect the above to result in
* NT_STATUS_OBJECT_PATH_SYNTAX_BAD. It is currently not possible
* (and questionable if it's desirable) to deal with all cases
* but paths beginning with \\.. are handled. See bad_paths[].
* Cases like "\\dir\\..\\.." will be caught and handled after the
* pnreduce. Cases like "\\dir\\..\\..\\filename" will still result
* in "\\filename" which is contrary to windows behavior.
*
* dot:
* A filename of '.' should result in NT_STATUS_OBJECT_NAME_INVALID
* Any wildcard filename that resolves to '.' should result in
* NT_STATUS_OBJECT_NAME_INVALID if the search attributes include
* FILE_ATTRIBUTE_DIRECTORY
*
* Returns:
* 0: path is valid. Sets *wildcard to TRUE if wildcard delete
* i.e. if wildcards in last component
* -1: path is invalid. Sets error information in sr.
*/
static int
{
char *p, *last_comp;
int i, wildcards;
struct {
char *name;
int len;
{"\\..\0", 4},
{"\\..\\", 4},
{"..\0", 3},
{"..\\", 3}
};
/* check for wildcards in path */
/* find last component, strip trailing '\\' */
while (*p == '\\') {
*p = '\0';
--p;
}
} else {
last_comp = ++p;
/* wildcards in path > wildcards in last_comp */
return (-1);
}
}
/* path above the mount point */
return (-1);
}
}
/* last component is, or resolves to, '.' (dot) */
return (-1);
}
return (0);
}
/*
* smb_delete_error
*/
static void
{
}