xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_delete.c (revision 7348:73b61202d5d6)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
225772Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
26*7348SJose.Borrego@Sun.COM #pragma ident	"@(#)smb_delete.c	1.10	08/08/07 SMI"
275331Samw 
285331Samw #include <smbsrv/smb_incl.h>
295331Samw #include <smbsrv/smb_fsops.h>
305331Samw #include <smbsrv/smbinfo.h>
315772Sas200622 #include <sys/nbmlock.h>
325331Samw 
336139Sjb150015 static uint32_t smb_delete_check(smb_request_t *, smb_node_t *);
34*7348SJose.Borrego@Sun.COM static boolean_t smb_delete_check_path(smb_request_t *, boolean_t *);
355331Samw 
365331Samw /*
375331Samw  * smb_com_delete
385331Samw  *
395331Samw  * The delete file message is sent to delete a data file. The appropriate
405331Samw  * Tid and additional pathname are passed. Read only files may not be
415331Samw  * deleted, the read-only attribute must be reset prior to file deletion.
425331Samw  *
435331Samw  * NT supports a hidden permission known as File Delete Child (FDC). If
445331Samw  * the user has FullControl access to a directory, the user is permitted
455331Samw  * to delete any object in the directory regardless of the permissions
465331Samw  * on the object.
475331Samw  *
485331Samw  * Client Request                     Description
495331Samw  * ================================== =================================
505331Samw  * UCHAR WordCount;                   Count of parameter words = 1
515331Samw  * USHORT SearchAttributes;
525331Samw  * USHORT ByteCount;                  Count of data bytes; min = 2
535331Samw  * UCHAR BufferFormat;                0x04
545331Samw  * STRING FileName[];                 File name
555331Samw  *
565331Samw  * Multiple files may be deleted in response to a single request as
575331Samw  * SMB_COM_DELETE supports wildcards
585331Samw  *
595331Samw  * SearchAttributes indicates the attributes that the target file(s) must
605331Samw  * have. If the attribute is zero then only normal files are deleted. If
615331Samw  * the system file or hidden attributes are specified then the delete is
625331Samw  * inclusive -both the specified type(s) of files and normal files are
635331Samw  * deleted. Attributes are described in the "Attribute Encoding" section
645331Samw  * of this document.
655331Samw  *
665331Samw  * If bit0 of the Flags2 field of the SMB header is set, a pattern is
675331Samw  * passed in, and the file has a long name, then the passed pattern  much
685331Samw  * match the long file name for the delete to succeed. If bit0 is clear, a
695331Samw  * pattern is passed in, and the file has a long name, then the passed
705331Samw  * pattern must match the file's short name for the deletion to succeed.
715331Samw  *
725331Samw  * Server Response                    Description
735331Samw  * ================================== =================================
745331Samw  * UCHAR WordCount;                   Count of parameter words = 0
755331Samw  * USHORT ByteCount;                  Count of data bytes = 0
765331Samw  *
775331Samw  * 4.2.10.1  Errors
785331Samw  *
795331Samw  * ERRDOS/ERRbadpath
805331Samw  * ERRDOS/ERRbadfile
815331Samw  * ERRDOS/ERRnoaccess
825331Samw  * ERRDOS/ERRbadshare	# returned by NT for files that are already open
835331Samw  * ERRHRD/ERRnowrite
845331Samw  * ERRSRV/ERRaccess
855331Samw  * ERRSRV/ERRinvdevice
865331Samw  * ERRSRV/ERRinvid
875331Samw  * ERRSRV/ERRbaduid
885331Samw  */
896030Sjb150015 smb_sdrc_t
906139Sjb150015 smb_pre_delete(smb_request_t *sr)
915331Samw {
926139Sjb150015 	struct smb_fqi *fqi = &sr->arg.dirop.fqi;
936139Sjb150015 	int rc;
946139Sjb150015 
956139Sjb150015 	if ((rc = smbsr_decode_vwv(sr, "w", &fqi->srch_attr)) == 0)
966139Sjb150015 		rc = smbsr_decode_data(sr, "%S", sr, &fqi->path);
976139Sjb150015 
986139Sjb150015 	DTRACE_SMB_2(op__Delete__start, smb_request_t *, sr,
996139Sjb150015 	    struct smb_fqi *, fqi);
1006139Sjb150015 
1016139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1026139Sjb150015 }
1036139Sjb150015 
1046139Sjb150015 void
1056139Sjb150015 smb_post_delete(smb_request_t *sr)
1066139Sjb150015 {
1076139Sjb150015 	DTRACE_SMB_1(op__Delete__done, smb_request_t *, sr);
1086139Sjb150015 }
1096139Sjb150015 
110*7348SJose.Borrego@Sun.COM /*
111*7348SJose.Borrego@Sun.COM  * smb_com_delete
112*7348SJose.Borrego@Sun.COM  *
113*7348SJose.Borrego@Sun.COM  * readonly
114*7348SJose.Borrego@Sun.COM  * If a readonly entry is matched the search aborts with status
115*7348SJose.Borrego@Sun.COM  * NT_STATUS_CANNOT_DELETE. Entries found prior to the readonly
116*7348SJose.Borrego@Sun.COM  * entry will have been deleted.
117*7348SJose.Borrego@Sun.COM  *
118*7348SJose.Borrego@Sun.COM  * directories:
119*7348SJose.Borrego@Sun.COM  * smb_com_delete does not delete directories:
120*7348SJose.Borrego@Sun.COM  * A non-wildcard delete that finds a directory should result in
121*7348SJose.Borrego@Sun.COM  * NT_STATUS_FILE_IS_A_DIRECTORY.
122*7348SJose.Borrego@Sun.COM  * A wildcard delete that finds a directory will either:
123*7348SJose.Borrego@Sun.COM  *	- abort with status NT_STATUS_FILE_IS_A_DIRECTORY, if
124*7348SJose.Borrego@Sun.COM  *	  FILE_ATTRIBUTE_DIRECTORY is specified in the search attributes, or
125*7348SJose.Borrego@Sun.COM  *	- skip that entry, if FILE_ATTRIBUTE_DIRECTORY is NOT specified
126*7348SJose.Borrego@Sun.COM  *	  in the search attributes
127*7348SJose.Borrego@Sun.COM  * Entries found prior to the directory entry will have been deleted.
128*7348SJose.Borrego@Sun.COM  *
129*7348SJose.Borrego@Sun.COM  * search attribute not matched
130*7348SJose.Borrego@Sun.COM  * If an entry is found but it is either hidden or system and those
131*7348SJose.Borrego@Sun.COM  * attributes are not specified in the search attributes:
132*7348SJose.Borrego@Sun.COM  *	- if deleting a single file, status NT_STATUS_NO_SUCH_FILE
133*7348SJose.Borrego@Sun.COM  *	- if wildcard delete, skip the entry and continue
134*7348SJose.Borrego@Sun.COM  *
135*7348SJose.Borrego@Sun.COM  * path not found
136*7348SJose.Borrego@Sun.COM  * If smb_rdir_open cannot find the specified path, the error code
137*7348SJose.Borrego@Sun.COM  * is set to NT_STATUS_OBJECT_PATH_NOT_FOUND. If there are wildcards
138*7348SJose.Borrego@Sun.COM  * in the last_component, NT_STATUS_OBJECT_NAME_NOT_FOUND should be set
139*7348SJose.Borrego@Sun.COM  * instead.
140*7348SJose.Borrego@Sun.COM  *
141*7348SJose.Borrego@Sun.COM  * smb_delete_check_path() - checks dot, bad path syntax, wildcards in path
142*7348SJose.Borrego@Sun.COM  */
143*7348SJose.Borrego@Sun.COM 
1446139Sjb150015 smb_sdrc_t
1456139Sjb150015 smb_com_delete(smb_request_t *sr)
1466139Sjb150015 {
1476139Sjb150015 	struct smb_fqi *fqi = &sr->arg.dirop.fqi;
148*7348SJose.Borrego@Sun.COM 	int rc;
149*7348SJose.Borrego@Sun.COM 	int deleted = 0;
1507052Samw 	struct smb_node *node = NULL;
1515331Samw 	smb_odir_context_t *pc;
152*7348SJose.Borrego@Sun.COM 	unsigned short sattr;
153*7348SJose.Borrego@Sun.COM 	boolean_t wildcards;
1545331Samw 
155*7348SJose.Borrego@Sun.COM 	if (smb_delete_check_path(sr, &wildcards) != B_TRUE)
1566139Sjb150015 		return (SDRC_ERROR);
1575772Sas200622 
158*7348SJose.Borrego@Sun.COM 	/*
159*7348SJose.Borrego@Sun.COM 	 * specify all search attributes so that delete-specific
160*7348SJose.Borrego@Sun.COM 	 * search attribute handling can be performed
161*7348SJose.Borrego@Sun.COM 	 */
162*7348SJose.Borrego@Sun.COM 	sattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN |
163*7348SJose.Borrego@Sun.COM 	    FILE_ATTRIBUTE_SYSTEM;
164*7348SJose.Borrego@Sun.COM 
165*7348SJose.Borrego@Sun.COM 	if (smb_rdir_open(sr, fqi->path, sattr) != 0) {
166*7348SJose.Borrego@Sun.COM 		/*
167*7348SJose.Borrego@Sun.COM 		 * If there are wildcards in the last_component,
168*7348SJose.Borrego@Sun.COM 		 * NT_STATUS_OBJECT_NAME_NOT_FOUND
169*7348SJose.Borrego@Sun.COM 		 * should be used in place of NT_STATUS_OBJECT_PATH_NOT_FOUND
170*7348SJose.Borrego@Sun.COM 		 */
171*7348SJose.Borrego@Sun.COM 		if ((wildcards == B_TRUE) &&
172*7348SJose.Borrego@Sun.COM 		    (sr->smb_error.status == NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
173*7348SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
174*7348SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_FILE_NOT_FOUND);
175*7348SJose.Borrego@Sun.COM 		}
176*7348SJose.Borrego@Sun.COM 
177*7348SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
178*7348SJose.Borrego@Sun.COM 	}
179*7348SJose.Borrego@Sun.COM 
1805331Samw 	pc = kmem_zalloc(sizeof (*pc), KM_SLEEP);
1815331Samw 
1825331Samw 	/*
1835331Samw 	 * This while loop is meant to deal with wildcards.
1845331Samw 	 * It is not expected that wildcards will exist for
1855331Samw 	 * streams.  For the streams case, it is expected
1865331Samw 	 * that the below loop will be executed only once.
1875331Samw 	 */
1885331Samw 
1895331Samw 	while ((rc = smb_rdir_next(sr, &node, pc)) == 0) {
190*7348SJose.Borrego@Sun.COM 		/* check directory */
1917052Samw 		if (pc->dc_dattr & FILE_ATTRIBUTE_DIRECTORY) {
192*7348SJose.Borrego@Sun.COM 			smb_node_release(node);
193*7348SJose.Borrego@Sun.COM 			if (wildcards == B_FALSE) {
194*7348SJose.Borrego@Sun.COM 				smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
195*7348SJose.Borrego@Sun.COM 				    ERRDOS, ERROR_ACCESS_DENIED);
196*7348SJose.Borrego@Sun.COM 				goto delete_error;
197*7348SJose.Borrego@Sun.COM 			} else {
198*7348SJose.Borrego@Sun.COM 				if (SMB_SEARCH_DIRECTORY(fqi->srch_attr) != 0)
199*7348SJose.Borrego@Sun.COM 					break;
200*7348SJose.Borrego@Sun.COM 				else
201*7348SJose.Borrego@Sun.COM 					continue;
202*7348SJose.Borrego@Sun.COM 			}
203*7348SJose.Borrego@Sun.COM 		}
204*7348SJose.Borrego@Sun.COM 
205*7348SJose.Borrego@Sun.COM 		/* check readonly */
206*7348SJose.Borrego@Sun.COM 		if (SMB_PATHFILE_IS_READONLY(sr, node)) {
207*7348SJose.Borrego@Sun.COM 			smb_node_release(node);
208*7348SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_CANNOT_DELETE,
2096139Sjb150015 			    ERRDOS, ERROR_ACCESS_DENIED);
2105772Sas200622 			goto delete_error;
2115772Sas200622 		}
2125772Sas200622 
213*7348SJose.Borrego@Sun.COM 		/* check search attributes */
214*7348SJose.Borrego@Sun.COM 		if (((pc->dc_dattr & FILE_ATTRIBUTE_HIDDEN) &&
215*7348SJose.Borrego@Sun.COM 		    !(SMB_SEARCH_HIDDEN(fqi->srch_attr))) ||
216*7348SJose.Borrego@Sun.COM 		    ((pc->dc_dattr & FILE_ATTRIBUTE_SYSTEM) &&
217*7348SJose.Borrego@Sun.COM 		    !(SMB_SEARCH_SYSTEM(fqi->srch_attr)))) {
2185331Samw 			smb_node_release(node);
219*7348SJose.Borrego@Sun.COM 			if (wildcards == B_FALSE) {
220*7348SJose.Borrego@Sun.COM 				smbsr_error(sr, NT_STATUS_NO_SUCH_FILE,
221*7348SJose.Borrego@Sun.COM 				    ERRDOS, ERROR_FILE_NOT_FOUND);
222*7348SJose.Borrego@Sun.COM 				goto delete_error;
223*7348SJose.Borrego@Sun.COM 			} else {
224*7348SJose.Borrego@Sun.COM 				continue;
225*7348SJose.Borrego@Sun.COM 			}
2265331Samw 		}
2275331Samw 
2285772Sas200622 		/*
2295772Sas200622 		 * NT does not always close a file immediately, which
2305772Sas200622 		 * can cause the share and access checking to fail
2315772Sas200622 		 * (the node refcnt is greater than one), and the file
2325772Sas200622 		 * doesn't get deleted. Breaking the oplock before
2335772Sas200622 		 * share and access checking gives the client a chance
2345772Sas200622 		 * to close the file.
2355772Sas200622 		 */
2365772Sas200622 
2376600Sas200622 		smb_oplock_break(node);
2385772Sas200622 
2395772Sas200622 		smb_node_start_crit(node, RW_READER);
2405772Sas200622 
2416139Sjb150015 		if (smb_delete_check(sr, node) != NT_STATUS_SUCCESS) {
2425772Sas200622 			smb_node_end_crit(node);
2435772Sas200622 			smb_node_release(node);
2445772Sas200622 			goto delete_error;
2455772Sas200622 		}
2465331Samw 
2477052Samw 		/*
2487052Samw 		 * Use node->od_name so as to skip mangle checks and
2497052Samw 		 * stream processing (which have already been done in
2507052Samw 		 * smb_rdir_next()).
2517052Samw 		 * Use node->dir_snode to obtain the correct parent node
2527052Samw 		 * (especially for streams).
2537052Samw 		 */
2547052Samw 		rc = smb_fsop_remove(sr, sr->user_cr, node->dir_snode,
2557052Samw 		    node->od_name, 1);
2565331Samw 
2575772Sas200622 		smb_node_end_crit(node);
2585772Sas200622 		smb_node_release(node);
2595772Sas200622 		node = NULL;
2605772Sas200622 
2615331Samw 		if (rc != 0) {
2626139Sjb150015 			if (rc != ENOENT) {
2636139Sjb150015 				smbsr_errno(sr, rc);
2646139Sjb150015 				goto delete_error;
2656139Sjb150015 			}
2665331Samw 		} else {
2675331Samw 			deleted++;
2685331Samw 		}
2695331Samw 	}
2705331Samw 
2715331Samw 	if ((rc != 0) && (rc != ENOENT)) {
2726139Sjb150015 		smbsr_errno(sr, rc);
2736139Sjb150015 		goto delete_error;
2745331Samw 	}
2755331Samw 
2765331Samw 	if (deleted == 0) {
277*7348SJose.Borrego@Sun.COM 		if (wildcards == B_FALSE)
2786139Sjb150015 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
2796139Sjb150015 			    ERRDOS, ERROR_FILE_NOT_FOUND);
2806139Sjb150015 		else
2816139Sjb150015 			smbsr_error(sr, NT_STATUS_NO_SUCH_FILE,
2826139Sjb150015 			    ERRDOS, ERROR_FILE_NOT_FOUND);
2835331Samw 		goto delete_error;
2845331Samw 	}
2855331Samw 
2865331Samw 	smb_rdir_close(sr);
2875331Samw 	kmem_free(pc, sizeof (*pc));
2886030Sjb150015 
2896030Sjb150015 	rc = smbsr_encode_empty_result(sr);
2906139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2915331Samw 
2925331Samw delete_error:
2935331Samw 	smb_rdir_close(sr);
2945331Samw 	kmem_free(pc, sizeof (*pc));
2956139Sjb150015 	return (SDRC_ERROR);
2965331Samw }
2975331Samw 
2986139Sjb150015 /*
299*7348SJose.Borrego@Sun.COM  * smb_delete_check_path
300*7348SJose.Borrego@Sun.COM  *
301*7348SJose.Borrego@Sun.COM  * Perform initial validation on the pathname and last_component.
302*7348SJose.Borrego@Sun.COM  *
303*7348SJose.Borrego@Sun.COM  * dot:
304*7348SJose.Borrego@Sun.COM  * A filename of '.' should result in NT_STATUS_OBJECT_NAME_INVALID
305*7348SJose.Borrego@Sun.COM  * Any wildcard filename that resolves to '.' should result in
306*7348SJose.Borrego@Sun.COM  * NT_STATUS_OBJECT_NAME_INVALID if the search attributes include
307*7348SJose.Borrego@Sun.COM  * FILE_ATTRIBUTE_DIRECTORY, otherwise handled as directory (see above).
308*7348SJose.Borrego@Sun.COM  *
309*7348SJose.Borrego@Sun.COM  * bad path syntax:
310*7348SJose.Borrego@Sun.COM  * On unix .. at the root of a file system links to the root. Thus
311*7348SJose.Borrego@Sun.COM  * an attempt to lookup "/../../.." will be the same as looking up "/"
312*7348SJose.Borrego@Sun.COM  * CIFs clients expect the above to result in
313*7348SJose.Borrego@Sun.COM  * NT_STATUS_OBJECT_PATH_SYNTAX_BAD. It is currently not possible
314*7348SJose.Borrego@Sun.COM  * (and questionable if it's desirable) to deal with all cases
315*7348SJose.Borrego@Sun.COM  * but paths beginning with \\.. are handled. See bad_paths[].
316*7348SJose.Borrego@Sun.COM  * Cases like "\\dir\\..\\.." will still result in "\\" which is
317*7348SJose.Borrego@Sun.COM  * contrary to windows behavior.
318*7348SJose.Borrego@Sun.COM  *
319*7348SJose.Borrego@Sun.COM  * wildcards in path:
320*7348SJose.Borrego@Sun.COM  * Wildcards in the path (excluding the last_component) should result
321*7348SJose.Borrego@Sun.COM  * in NT_STATUS_OBJECT_NAME_INVALID.
322*7348SJose.Borrego@Sun.COM  *
323*7348SJose.Borrego@Sun.COM  * Returns:
324*7348SJose.Borrego@Sun.COM  *	B_TRUE:  path is valid. Sets *wildcard to TRUE if wildcard delete
325*7348SJose.Borrego@Sun.COM  *	         i.e. if wildcards in last component
326*7348SJose.Borrego@Sun.COM  *	B_FALSE: path is invalid. Sets error information in sr.
327*7348SJose.Borrego@Sun.COM  */
328*7348SJose.Borrego@Sun.COM static boolean_t
329*7348SJose.Borrego@Sun.COM smb_delete_check_path(smb_request_t *sr, boolean_t *wildcard)
330*7348SJose.Borrego@Sun.COM {
331*7348SJose.Borrego@Sun.COM 	struct smb_fqi *fqi = &sr->arg.dirop.fqi;
332*7348SJose.Borrego@Sun.COM 	char *p, *last_component;
333*7348SJose.Borrego@Sun.COM 	int i, wildcards;
334*7348SJose.Borrego@Sun.COM 
335*7348SJose.Borrego@Sun.COM 	struct {
336*7348SJose.Borrego@Sun.COM 		char *name;
337*7348SJose.Borrego@Sun.COM 		int len;
338*7348SJose.Borrego@Sun.COM 	} *bad, bad_paths[] = {
339*7348SJose.Borrego@Sun.COM 		{"\\..\0", 4},
340*7348SJose.Borrego@Sun.COM 		{"\\..\\", 4},
341*7348SJose.Borrego@Sun.COM 		{"..\0", 3},
342*7348SJose.Borrego@Sun.COM 		{"..\\", 3}
343*7348SJose.Borrego@Sun.COM 	};
344*7348SJose.Borrego@Sun.COM 
345*7348SJose.Borrego@Sun.COM 	wildcards = smb_convert_unicode_wildcards(fqi->path);
346*7348SJose.Borrego@Sun.COM 
347*7348SJose.Borrego@Sun.COM 	/* find last component, strip trailing '\\' */
348*7348SJose.Borrego@Sun.COM 	p = fqi->path + strlen(fqi->path) - 1;
349*7348SJose.Borrego@Sun.COM 	while (*p == '\\') {
350*7348SJose.Borrego@Sun.COM 		*p = '\0';
351*7348SJose.Borrego@Sun.COM 		--p;
352*7348SJose.Borrego@Sun.COM 	}
353*7348SJose.Borrego@Sun.COM 	if ((p = strrchr(fqi->path, '\\')) == NULL) {
354*7348SJose.Borrego@Sun.COM 		last_component = fqi->path;
355*7348SJose.Borrego@Sun.COM 	} else {
356*7348SJose.Borrego@Sun.COM 		last_component = ++p;
357*7348SJose.Borrego@Sun.COM 
358*7348SJose.Borrego@Sun.COM 		/*
359*7348SJose.Borrego@Sun.COM 		 * Any wildcards in path (excluding last_component) should
360*7348SJose.Borrego@Sun.COM 		 * result in NT_STATUS_OBJECT_NAME_INVALID
361*7348SJose.Borrego@Sun.COM 		 */
362*7348SJose.Borrego@Sun.COM 		if (smb_convert_unicode_wildcards(last_component)
363*7348SJose.Borrego@Sun.COM 		    != wildcards) {
364*7348SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
365*7348SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_INVALID_NAME);
366*7348SJose.Borrego@Sun.COM 			return (B_FALSE);
367*7348SJose.Borrego@Sun.COM 		}
368*7348SJose.Borrego@Sun.COM 	}
369*7348SJose.Borrego@Sun.COM 
370*7348SJose.Borrego@Sun.COM 	/*
371*7348SJose.Borrego@Sun.COM 	 * path above the mount point => NT_STATUS_OBJECT_PATH_SYNTAX_BAD
372*7348SJose.Borrego@Sun.COM 	 * This test doesn't cover all cases: e.g. \dir\..\..
373*7348SJose.Borrego@Sun.COM 	 */
374*7348SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (bad_paths) / sizeof (bad_paths[0]); ++i) {
375*7348SJose.Borrego@Sun.COM 		bad = &bad_paths[i];
376*7348SJose.Borrego@Sun.COM 		if (strncmp(fqi->path, bad->name, bad->len) == 0) {
377*7348SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD,
378*7348SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_BAD_PATHNAME);
379*7348SJose.Borrego@Sun.COM 			return (B_FALSE);
380*7348SJose.Borrego@Sun.COM 		}
381*7348SJose.Borrego@Sun.COM 	}
382*7348SJose.Borrego@Sun.COM 
383*7348SJose.Borrego@Sun.COM 	/*
384*7348SJose.Borrego@Sun.COM 	 * Any file pattern that resolves to '.' is considered invalid.
385*7348SJose.Borrego@Sun.COM 	 * In the wildcard case, only an error if FILE_ATTRIBUTE_DIRECTORY
386*7348SJose.Borrego@Sun.COM 	 * is specified in search attributes, otherwise skipped (below)
387*7348SJose.Borrego@Sun.COM 	 */
388*7348SJose.Borrego@Sun.COM 	if ((strcmp(last_component, ".") == 0) ||
389*7348SJose.Borrego@Sun.COM 	    (SMB_SEARCH_DIRECTORY(fqi->srch_attr) &&
390*7348SJose.Borrego@Sun.COM 	    (smb_match(last_component, ".")))) {
391*7348SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
392*7348SJose.Borrego@Sun.COM 		    ERRDOS, ERROR_INVALID_NAME);
393*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
394*7348SJose.Borrego@Sun.COM 	}
395*7348SJose.Borrego@Sun.COM 
396*7348SJose.Borrego@Sun.COM 	*wildcard = (wildcards != 0);
397*7348SJose.Borrego@Sun.COM 	return (B_TRUE);
398*7348SJose.Borrego@Sun.COM }
399*7348SJose.Borrego@Sun.COM 
400*7348SJose.Borrego@Sun.COM /*
4016139Sjb150015  * For consistency with Windows 2000, the range check should be done
4026139Sjb150015  * after checking for sharing violations.  Attempting to delete a
4036139Sjb150015  * locked file will result in sharing violation, which is the same
4046139Sjb150015  * thing that will happen if you try to delete a non-locked open file.
4056139Sjb150015  *
4066139Sjb150015  * Note that windows 2000 rejects lock requests on open files that
4076139Sjb150015  * have been opened with metadata open modes.  The error is
4086139Sjb150015  * STATUS_ACCESS_DENIED.
4096139Sjb150015  */
4106139Sjb150015 static uint32_t
4116139Sjb150015 smb_delete_check(smb_request_t *sr, smb_node_t *node)
4125331Samw {
4136139Sjb150015 	uint32_t status;
4145331Samw 
4156139Sjb150015 	status = smb_node_delete_check(node);
4166139Sjb150015 
4176139Sjb150015 	if (status == NT_STATUS_SHARING_VIOLATION) {
4186139Sjb150015 		smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
4196139Sjb150015 		    ERRDOS, ERROR_SHARING_VIOLATION);
4206139Sjb150015 		return (status);
4215331Samw 	}
4225331Samw 
423*7348SJose.Borrego@Sun.COM 	status = smb_range_check(sr, node, 0, UINT64_MAX, B_TRUE);
4245772Sas200622 
4256139Sjb150015 	if (status != NT_STATUS_SUCCESS) {
4266139Sjb150015 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
4276139Sjb150015 		    ERRDOS, ERROR_ACCESS_DENIED);
4285331Samw 	}
4295331Samw 
4306139Sjb150015 	return (status);
4315331Samw }
432