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 */
2112508Samw@Sun.COM
225331Samw /*
2312508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw */
255331Samw
2610966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
275331Samw #include <smbsrv/smb_fsops.h>
285331Samw #include <smbsrv/smbinfo.h>
295772Sas200622 #include <sys/nbmlock.h>
305331Samw
3111337SWilliam.Krier@Sun.COM static int smb_delete_check_path(smb_request_t *);
327961SNatalie.Li@Sun.COM static int smb_delete_single_file(smb_request_t *, smb_error_t *);
337961SNatalie.Li@Sun.COM static int smb_delete_multiple_files(smb_request_t *, smb_error_t *);
3410504SKeyur.Desai@Sun.COM static int smb_delete_find_fname(smb_request_t *, smb_odir_t *, char *, int);
3510001SJoyce.McIntosh@Sun.COM static int smb_delete_check_dosattr(smb_request_t *, smb_error_t *);
367961SNatalie.Li@Sun.COM static int smb_delete_remove_file(smb_request_t *, smb_error_t *);
377961SNatalie.Li@Sun.COM
387961SNatalie.Li@Sun.COM static void smb_delete_error(smb_error_t *, uint32_t, uint16_t, uint16_t);
395331Samw
405331Samw /*
415331Samw * smb_com_delete
425331Samw *
435331Samw * The delete file message is sent to delete a data file. The appropriate
445331Samw * Tid and additional pathname are passed. Read only files may not be
455331Samw * deleted, the read-only attribute must be reset prior to file deletion.
465331Samw *
475331Samw * NT supports a hidden permission known as File Delete Child (FDC). If
485331Samw * the user has FullControl access to a directory, the user is permitted
495331Samw * to delete any object in the directory regardless of the permissions
505331Samw * on the object.
515331Samw *
525331Samw * Client Request Description
535331Samw * ================================== =================================
545331Samw * UCHAR WordCount; Count of parameter words = 1
555331Samw * USHORT SearchAttributes;
565331Samw * USHORT ByteCount; Count of data bytes; min = 2
575331Samw * UCHAR BufferFormat; 0x04
585331Samw * STRING FileName[]; File name
595331Samw *
605331Samw * Multiple files may be deleted in response to a single request as
615331Samw * SMB_COM_DELETE supports wildcards
625331Samw *
635331Samw * SearchAttributes indicates the attributes that the target file(s) must
645331Samw * have. If the attribute is zero then only normal files are deleted. If
655331Samw * the system file or hidden attributes are specified then the delete is
665331Samw * inclusive -both the specified type(s) of files and normal files are
675331Samw * deleted. Attributes are described in the "Attribute Encoding" section
685331Samw * of this document.
695331Samw *
705331Samw * If bit0 of the Flags2 field of the SMB header is set, a pattern is
715331Samw * passed in, and the file has a long name, then the passed pattern much
725331Samw * match the long file name for the delete to succeed. If bit0 is clear, a
735331Samw * pattern is passed in, and the file has a long name, then the passed
745331Samw * pattern must match the file's short name for the deletion to succeed.
755331Samw *
765331Samw * Server Response Description
775331Samw * ================================== =================================
785331Samw * UCHAR WordCount; Count of parameter words = 0
795331Samw * USHORT ByteCount; Count of data bytes = 0
805331Samw *
815331Samw * 4.2.10.1 Errors
825331Samw *
835331Samw * ERRDOS/ERRbadpath
845331Samw * ERRDOS/ERRbadfile
855331Samw * ERRDOS/ERRnoaccess
865331Samw * ERRDOS/ERRbadshare # returned by NT for files that are already open
875331Samw * ERRHRD/ERRnowrite
885331Samw * ERRSRV/ERRaccess
895331Samw * ERRSRV/ERRinvdevice
905331Samw * ERRSRV/ERRinvid
915331Samw * ERRSRV/ERRbaduid
925331Samw */
936030Sjb150015 smb_sdrc_t
smb_pre_delete(smb_request_t * sr)946139Sjb150015 smb_pre_delete(smb_request_t *sr)
955331Samw {
966139Sjb150015 int rc;
977961SNatalie.Li@Sun.COM smb_fqi_t *fqi;
987961SNatalie.Li@Sun.COM
997961SNatalie.Li@Sun.COM fqi = &sr->arg.dirop.fqi;
1006139Sjb150015
1019343SAfshin.Ardakani@Sun.COM if ((rc = smbsr_decode_vwv(sr, "w", &fqi->fq_sattr)) == 0)
1029343SAfshin.Ardakani@Sun.COM rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
1036139Sjb150015
1047961SNatalie.Li@Sun.COM DTRACE_SMB_2(op__Delete__start, smb_request_t *, sr, smb_fqi_t *, fqi);
1056139Sjb150015
1066139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1076139Sjb150015 }
1086139Sjb150015
1096139Sjb150015 void
smb_post_delete(smb_request_t * sr)1106139Sjb150015 smb_post_delete(smb_request_t *sr)
1116139Sjb150015 {
1126139Sjb150015 DTRACE_SMB_1(op__Delete__done, smb_request_t *, sr);
1136139Sjb150015 }
1146139Sjb150015
1157348SJose.Borrego@Sun.COM /*
1167348SJose.Borrego@Sun.COM * smb_com_delete
1177348SJose.Borrego@Sun.COM *
11811337SWilliam.Krier@Sun.COM * 1. intialize, pre-process and validate pathname
1197348SJose.Borrego@Sun.COM *
1207961SNatalie.Li@Sun.COM * 2. process the path to get directory node & last_comp,
1217961SNatalie.Li@Sun.COM * store these in fqi
1227961SNatalie.Li@Sun.COM * - If smb_pathname_reduce cannot find the specified path,
1237961SNatalie.Li@Sun.COM * the error (ENOTDIR) is translated to NT_STATUS_OBJECT_PATH_NOT_FOUND
1247961SNatalie.Li@Sun.COM * if the target is a single file (no wildcards). If there are
1257961SNatalie.Li@Sun.COM * wildcards in the last_comp, NT_STATUS_OBJECT_NAME_NOT_FOUND is
1267961SNatalie.Li@Sun.COM * used instead.
1277961SNatalie.Li@Sun.COM * - If the directory node is the mount point and the last component
1287961SNatalie.Li@Sun.COM * is ".." NT_STATUS_OBJECT_PATH_SYNTAX_BAD is returned.
1297348SJose.Borrego@Sun.COM *
1307961SNatalie.Li@Sun.COM * 3. check access permissions
1317348SJose.Borrego@Sun.COM *
1327961SNatalie.Li@Sun.COM * 4. invoke the appropriate deletion routine to find and remove
1337961SNatalie.Li@Sun.COM * the specified file(s).
1347961SNatalie.Li@Sun.COM * - if target is a single file (no wildcards) - smb_delete_single_file
1357961SNatalie.Li@Sun.COM * - if the target contains wildcards - smb_delete_multiple_files
1367961SNatalie.Li@Sun.COM *
1377961SNatalie.Li@Sun.COM * Returns: SDRC_SUCCESS or SDRC_ERROR
1387348SJose.Borrego@Sun.COM */
1396139Sjb150015 smb_sdrc_t
smb_com_delete(smb_request_t * sr)1406139Sjb150015 smb_com_delete(smb_request_t *sr)
1416139Sjb150015 {
1427348SJose.Borrego@Sun.COM int rc;
1437961SNatalie.Li@Sun.COM smb_error_t err;
1447961SNatalie.Li@Sun.COM uint32_t status;
14511337SWilliam.Krier@Sun.COM boolean_t wildcards = B_FALSE;
1467961SNatalie.Li@Sun.COM smb_fqi_t *fqi;
14711337SWilliam.Krier@Sun.COM smb_pathname_t *pn;
1485331Samw
1497961SNatalie.Li@Sun.COM fqi = &sr->arg.dirop.fqi;
15011337SWilliam.Krier@Sun.COM pn = &fqi->fq_path;
1517961SNatalie.Li@Sun.COM
15211337SWilliam.Krier@Sun.COM smb_pathname_init(sr, pn, pn->pn_path);
15311337SWilliam.Krier@Sun.COM if (!smb_pathname_validate(sr, pn))
1546139Sjb150015 return (SDRC_ERROR);
15511337SWilliam.Krier@Sun.COM if (smb_delete_check_path(sr) != 0)
15611337SWilliam.Krier@Sun.COM return (SDRC_ERROR);
15711337SWilliam.Krier@Sun.COM
15811337SWilliam.Krier@Sun.COM wildcards = smb_contains_wildcards(pn->pn_fname);
1595772Sas200622
1609343SAfshin.Ardakani@Sun.COM rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
1617961SNatalie.Li@Sun.COM sr->tid_tree->t_snode, sr->tid_tree->t_snode,
1629343SAfshin.Ardakani@Sun.COM &fqi->fq_dnode, fqi->fq_last_comp);
1637961SNatalie.Li@Sun.COM if (rc == 0) {
16411963SAfshin.Ardakani@Sun.COM if (!smb_node_is_dir(fqi->fq_dnode)) {
1659343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_dnode);
1667961SNatalie.Li@Sun.COM rc = ENOTDIR;
1677961SNatalie.Li@Sun.COM }
1687961SNatalie.Li@Sun.COM }
1697961SNatalie.Li@Sun.COM if (rc != 0) {
1707961SNatalie.Li@Sun.COM if (rc == ENOTDIR) {
1717961SNatalie.Li@Sun.COM if (wildcards)
1727961SNatalie.Li@Sun.COM status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1737961SNatalie.Li@Sun.COM else
1747961SNatalie.Li@Sun.COM status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1757961SNatalie.Li@Sun.COM smbsr_error(sr, status, ERRDOS, ERROR_FILE_NOT_FOUND);
1767961SNatalie.Li@Sun.COM } else {
1777961SNatalie.Li@Sun.COM smbsr_errno(sr, rc);
1787348SJose.Borrego@Sun.COM }
1797348SJose.Borrego@Sun.COM
1807348SJose.Borrego@Sun.COM return (SDRC_ERROR);
1817348SJose.Borrego@Sun.COM }
1827348SJose.Borrego@Sun.COM
1839343SAfshin.Ardakani@Sun.COM if ((fqi->fq_dnode == sr->tid_tree->t_snode) &&
1849343SAfshin.Ardakani@Sun.COM (strcmp(fqi->fq_last_comp, "..") == 0)) {
1859343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_dnode);
1867961SNatalie.Li@Sun.COM smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD,
1877961SNatalie.Li@Sun.COM ERRDOS, ERROR_BAD_PATHNAME);
1887961SNatalie.Li@Sun.COM return (SDRC_ERROR);
1897961SNatalie.Li@Sun.COM }
1907961SNatalie.Li@Sun.COM
1919343SAfshin.Ardakani@Sun.COM rc = smb_fsop_access(sr, sr->user_cr, fqi->fq_dnode,
1927961SNatalie.Li@Sun.COM FILE_LIST_DIRECTORY);
1937961SNatalie.Li@Sun.COM if (rc != 0) {
1949343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_dnode);
1957961SNatalie.Li@Sun.COM smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
1967961SNatalie.Li@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
1977961SNatalie.Li@Sun.COM return (SDRC_ERROR);
1987961SNatalie.Li@Sun.COM }
1997961SNatalie.Li@Sun.COM
2007961SNatalie.Li@Sun.COM if (wildcards)
2017961SNatalie.Li@Sun.COM rc = smb_delete_multiple_files(sr, &err);
2027961SNatalie.Li@Sun.COM else
2037961SNatalie.Li@Sun.COM rc = smb_delete_single_file(sr, &err);
2047961SNatalie.Li@Sun.COM
2059343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_dnode);
2068026SJoyce.McIntosh@Sun.COM
2077961SNatalie.Li@Sun.COM if (rc != 0)
2087961SNatalie.Li@Sun.COM smbsr_set_error(sr, &err);
2097961SNatalie.Li@Sun.COM else
2107961SNatalie.Li@Sun.COM rc = smbsr_encode_empty_result(sr);
2115331Samw
2127961SNatalie.Li@Sun.COM return (rc == 0 ? SDRC_SUCCESS : SDRC_ERROR);
2137961SNatalie.Li@Sun.COM }
2147961SNatalie.Li@Sun.COM
2157961SNatalie.Li@Sun.COM /*
2167961SNatalie.Li@Sun.COM * smb_delete_single_file
2177961SNatalie.Li@Sun.COM *
2187961SNatalie.Li@Sun.COM * Find the specified file and, if its attributes match the search
2197961SNatalie.Li@Sun.COM * criteria, delete it.
2207961SNatalie.Li@Sun.COM *
2217961SNatalie.Li@Sun.COM * Returns 0 - success (file deleted)
2227961SNatalie.Li@Sun.COM * -1 - error, err is populated with error details
2237961SNatalie.Li@Sun.COM */
2247961SNatalie.Li@Sun.COM static int
smb_delete_single_file(smb_request_t * sr,smb_error_t * err)2257961SNatalie.Li@Sun.COM smb_delete_single_file(smb_request_t *sr, smb_error_t *err)
2267961SNatalie.Li@Sun.COM {
2277961SNatalie.Li@Sun.COM smb_fqi_t *fqi;
22811337SWilliam.Krier@Sun.COM smb_pathname_t *pn;
2297961SNatalie.Li@Sun.COM
2307961SNatalie.Li@Sun.COM fqi = &sr->arg.dirop.fqi;
23111337SWilliam.Krier@Sun.COM pn = &fqi->fq_path;
2327961SNatalie.Li@Sun.COM
23311337SWilliam.Krier@Sun.COM /* pn already initialized and validated */
23411337SWilliam.Krier@Sun.COM if (!smb_validate_object_name(sr, pn)) {
23511337SWilliam.Krier@Sun.COM smb_delete_error(err, sr->smb_error.status,
23611337SWilliam.Krier@Sun.COM ERRDOS, ERROR_INVALID_NAME);
2378334SJose.Borrego@Sun.COM return (-1);
2388334SJose.Borrego@Sun.COM }
2398334SJose.Borrego@Sun.COM
2407961SNatalie.Li@Sun.COM if (smb_fsop_lookup_name(sr, sr->user_cr, 0, sr->tid_tree->t_snode,
24110001SJoyce.McIntosh@Sun.COM fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode) != 0) {
2427961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_OBJECT_NAME_NOT_FOUND,
2437961SNatalie.Li@Sun.COM ERRDOS, ERROR_FILE_NOT_FOUND);
2447961SNatalie.Li@Sun.COM return (-1);
2457961SNatalie.Li@Sun.COM }
2465331Samw
24710001SJoyce.McIntosh@Sun.COM if (smb_delete_check_dosattr(sr, err) != 0) {
2489343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
2497961SNatalie.Li@Sun.COM return (-1);
2507961SNatalie.Li@Sun.COM }
2517961SNatalie.Li@Sun.COM
2527961SNatalie.Li@Sun.COM if (smb_delete_remove_file(sr, err) != 0) {
2539343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
2547961SNatalie.Li@Sun.COM return (-1);
2557961SNatalie.Li@Sun.COM }
2567961SNatalie.Li@Sun.COM
2579343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
2587961SNatalie.Li@Sun.COM return (0);
2597961SNatalie.Li@Sun.COM }
2607961SNatalie.Li@Sun.COM
2617961SNatalie.Li@Sun.COM /*
2627961SNatalie.Li@Sun.COM * smb_delete_multiple_files
2637961SNatalie.Li@Sun.COM *
2648670SJose.Borrego@Sun.COM * For each matching file found by smb_delete_find_fname:
2657961SNatalie.Li@Sun.COM * 1. lookup file
2667961SNatalie.Li@Sun.COM * 2. check the file's attributes
2677961SNatalie.Li@Sun.COM * - The search ends with an error if a readonly file
2687961SNatalie.Li@Sun.COM * (NT_STATUS_CANNOT_DELETE) is matched.
2697961SNatalie.Li@Sun.COM * - The search ends (but not an error) if a directory is
2707961SNatalie.Li@Sun.COM * matched and the request's search did not include
2717961SNatalie.Li@Sun.COM * directories.
27210001SJoyce.McIntosh@Sun.COM * - Otherwise, if smb_delete_check_dosattr fails the file
2737961SNatalie.Li@Sun.COM * is skipped and the search continues (at step 1)
2747961SNatalie.Li@Sun.COM * 3. delete the file
2757961SNatalie.Li@Sun.COM *
2767961SNatalie.Li@Sun.COM * Returns 0 - success
2777961SNatalie.Li@Sun.COM * -1 - error, err is populated with error details
2787961SNatalie.Li@Sun.COM */
2797961SNatalie.Li@Sun.COM static int
smb_delete_multiple_files(smb_request_t * sr,smb_error_t * err)2807961SNatalie.Li@Sun.COM smb_delete_multiple_files(smb_request_t *sr, smb_error_t *err)
2817961SNatalie.Li@Sun.COM {
2827961SNatalie.Li@Sun.COM int rc, deleted = 0;
2837961SNatalie.Li@Sun.COM smb_fqi_t *fqi;
2848670SJose.Borrego@Sun.COM uint16_t odid;
2858670SJose.Borrego@Sun.COM smb_odir_t *od;
28610504SKeyur.Desai@Sun.COM char namebuf[MAXNAMELEN];
2877961SNatalie.Li@Sun.COM
2887961SNatalie.Li@Sun.COM fqi = &sr->arg.dirop.fqi;
2897961SNatalie.Li@Sun.COM
2908670SJose.Borrego@Sun.COM /*
2918670SJose.Borrego@Sun.COM * Specify all search attributes (SMB_SEARCH_ATTRIBUTES) so that
29210001SJoyce.McIntosh@Sun.COM * delete-specific checking can be done (smb_delete_check_dosattr).
2938670SJose.Borrego@Sun.COM */
2949343SAfshin.Ardakani@Sun.COM odid = smb_odir_open(sr, fqi->fq_path.pn_path,
2959343SAfshin.Ardakani@Sun.COM SMB_SEARCH_ATTRIBUTES, 0);
2969343SAfshin.Ardakani@Sun.COM if (odid == 0)
2978670SJose.Borrego@Sun.COM return (-1);
2989343SAfshin.Ardakani@Sun.COM
2998670SJose.Borrego@Sun.COM if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL)
3008670SJose.Borrego@Sun.COM return (-1);
3018670SJose.Borrego@Sun.COM
3027961SNatalie.Li@Sun.COM for (;;) {
30310504SKeyur.Desai@Sun.COM rc = smb_delete_find_fname(sr, od, namebuf, MAXNAMELEN);
3047961SNatalie.Li@Sun.COM if (rc != 0)
3057961SNatalie.Li@Sun.COM break;
3067961SNatalie.Li@Sun.COM
30712508Samw@Sun.COM rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_CASE_SENSITIVE,
3089343SAfshin.Ardakani@Sun.COM sr->tid_tree->t_snode, fqi->fq_dnode,
30910504SKeyur.Desai@Sun.COM namebuf, &fqi->fq_fnode);
3107961SNatalie.Li@Sun.COM if (rc != 0)
3117961SNatalie.Li@Sun.COM break;
3127961SNatalie.Li@Sun.COM
31310001SJoyce.McIntosh@Sun.COM if (smb_delete_check_dosattr(sr, err) != 0) {
3149343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
3157961SNatalie.Li@Sun.COM if (err->status == NT_STATUS_CANNOT_DELETE) {
3169635SJoyce.McIntosh@Sun.COM smb_odir_close(od);
3178670SJose.Borrego@Sun.COM smb_odir_release(od);
3187961SNatalie.Li@Sun.COM return (-1);
3197348SJose.Borrego@Sun.COM }
3207961SNatalie.Li@Sun.COM if ((err->status == NT_STATUS_FILE_IS_A_DIRECTORY) &&
3219343SAfshin.Ardakani@Sun.COM (SMB_SEARCH_DIRECTORY(fqi->fq_sattr) != 0))
3227961SNatalie.Li@Sun.COM break;
3237961SNatalie.Li@Sun.COM continue;
3245772Sas200622 }
3255772Sas200622
3267961SNatalie.Li@Sun.COM if (smb_delete_remove_file(sr, err) == 0) {
3277961SNatalie.Li@Sun.COM ++deleted;
3289343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
3297961SNatalie.Li@Sun.COM continue;
3307961SNatalie.Li@Sun.COM }
3317961SNatalie.Li@Sun.COM if (err->status == NT_STATUS_OBJECT_NAME_NOT_FOUND) {
3329343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
3337961SNatalie.Li@Sun.COM continue;
3345331Samw }
3355331Samw
3369635SJoyce.McIntosh@Sun.COM smb_odir_close(od);
3378670SJose.Borrego@Sun.COM smb_odir_release(od);
3389343SAfshin.Ardakani@Sun.COM smb_node_release(fqi->fq_fnode);
3397961SNatalie.Li@Sun.COM return (-1);
3405331Samw }
3415331Samw
3429635SJoyce.McIntosh@Sun.COM smb_odir_close(od);
3438670SJose.Borrego@Sun.COM smb_odir_release(od);
3447961SNatalie.Li@Sun.COM
3455331Samw if ((rc != 0) && (rc != ENOENT)) {
3467961SNatalie.Li@Sun.COM smbsr_map_errno(rc, err);
3477961SNatalie.Li@Sun.COM return (-1);
3485331Samw }
3495331Samw
3505331Samw if (deleted == 0) {
3517961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_NO_SUCH_FILE,
3527961SNatalie.Li@Sun.COM ERRDOS, ERROR_FILE_NOT_FOUND);
3537961SNatalie.Li@Sun.COM return (-1);
3547961SNatalie.Li@Sun.COM }
3557961SNatalie.Li@Sun.COM
3567961SNatalie.Li@Sun.COM return (0);
3577961SNatalie.Li@Sun.COM }
3587961SNatalie.Li@Sun.COM
3597961SNatalie.Li@Sun.COM /*
3607961SNatalie.Li@Sun.COM * smb_delete_find_fname
3617961SNatalie.Li@Sun.COM *
36210504SKeyur.Desai@Sun.COM * Find next filename that matches search pattern and return it
36310504SKeyur.Desai@Sun.COM * in namebuf.
3647961SNatalie.Li@Sun.COM *
3657961SNatalie.Li@Sun.COM * Returns: 0 - success
3667961SNatalie.Li@Sun.COM * errno
3677961SNatalie.Li@Sun.COM */
3687961SNatalie.Li@Sun.COM static int
smb_delete_find_fname(smb_request_t * sr,smb_odir_t * od,char * namebuf,int len)36910504SKeyur.Desai@Sun.COM smb_delete_find_fname(smb_request_t *sr, smb_odir_t *od, char *namebuf, int len)
3707961SNatalie.Li@Sun.COM {
3718670SJose.Borrego@Sun.COM int rc;
3728670SJose.Borrego@Sun.COM smb_odirent_t *odirent;
3738670SJose.Borrego@Sun.COM boolean_t eos;
3747961SNatalie.Li@Sun.COM
3758670SJose.Borrego@Sun.COM odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
3767961SNatalie.Li@Sun.COM
3778670SJose.Borrego@Sun.COM rc = smb_odir_read(sr, od, odirent, &eos);
37812508Samw@Sun.COM if (rc == 0) {
37912508Samw@Sun.COM if (eos)
38012508Samw@Sun.COM rc = ENOENT;
38112508Samw@Sun.COM else
38212508Samw@Sun.COM (void) strlcpy(namebuf, odirent->od_name, len);
3838670SJose.Borrego@Sun.COM }
3848670SJose.Borrego@Sun.COM kmem_free(odirent, sizeof (smb_odirent_t));
38512508Samw@Sun.COM return (rc);
3867961SNatalie.Li@Sun.COM }
3877961SNatalie.Li@Sun.COM
3887961SNatalie.Li@Sun.COM /*
38910001SJoyce.McIntosh@Sun.COM * smb_delete_check_dosattr
3907961SNatalie.Li@Sun.COM *
3917961SNatalie.Li@Sun.COM * Check file's dos atributes to ensure that
3927961SNatalie.Li@Sun.COM * 1. the file is not a directory - NT_STATUS_FILE_IS_A_DIRECTORY
3937961SNatalie.Li@Sun.COM * 2. the file is not readonly - NT_STATUS_CANNOT_DELETE
3947961SNatalie.Li@Sun.COM * 3. the file's dos attributes comply with the specified search attributes
3957961SNatalie.Li@Sun.COM * If the file is either hidden or system and those attributes
3967961SNatalie.Li@Sun.COM * are not specified in the search attributes - NT_STATUS_NO_SUCH_FILE
3977961SNatalie.Li@Sun.COM *
3987961SNatalie.Li@Sun.COM * Returns: 0 - file's attributes pass all checks
3997961SNatalie.Li@Sun.COM * -1 - err populated with error details
4007961SNatalie.Li@Sun.COM */
4017961SNatalie.Li@Sun.COM static int
smb_delete_check_dosattr(smb_request_t * sr,smb_error_t * err)40210001SJoyce.McIntosh@Sun.COM smb_delete_check_dosattr(smb_request_t *sr, smb_error_t *err)
4037961SNatalie.Li@Sun.COM {
4047961SNatalie.Li@Sun.COM smb_fqi_t *fqi;
4057961SNatalie.Li@Sun.COM smb_node_t *node;
40610001SJoyce.McIntosh@Sun.COM smb_attr_t attr;
40710001SJoyce.McIntosh@Sun.COM uint16_t sattr;
4087961SNatalie.Li@Sun.COM
4097961SNatalie.Li@Sun.COM fqi = &sr->arg.dirop.fqi;
4109343SAfshin.Ardakani@Sun.COM sattr = fqi->fq_sattr;
4119343SAfshin.Ardakani@Sun.COM node = fqi->fq_fnode;
4127961SNatalie.Li@Sun.COM
41310001SJoyce.McIntosh@Sun.COM if (smb_node_getattr(sr, node, &attr) != 0) {
41410001SJoyce.McIntosh@Sun.COM smb_delete_error(err, NT_STATUS_INTERNAL_ERROR,
41510001SJoyce.McIntosh@Sun.COM ERRDOS, ERROR_INTERNAL_ERROR);
41610001SJoyce.McIntosh@Sun.COM return (-1);
41710001SJoyce.McIntosh@Sun.COM }
41810001SJoyce.McIntosh@Sun.COM
41910001SJoyce.McIntosh@Sun.COM if (attr.sa_dosattr & FILE_ATTRIBUTE_DIRECTORY) {
4207961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_FILE_IS_A_DIRECTORY,
4217961SNatalie.Li@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
4227961SNatalie.Li@Sun.COM return (-1);
4235331Samw }
4245331Samw
4257961SNatalie.Li@Sun.COM if (SMB_PATHFILE_IS_READONLY(sr, node)) {
4267961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_CANNOT_DELETE,
4277961SNatalie.Li@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
4287961SNatalie.Li@Sun.COM return (-1);
4297961SNatalie.Li@Sun.COM }
4306030Sjb150015
43110001SJoyce.McIntosh@Sun.COM if ((attr.sa_dosattr & FILE_ATTRIBUTE_HIDDEN) &&
43210001SJoyce.McIntosh@Sun.COM !(SMB_SEARCH_HIDDEN(sattr))) {
4337961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_NO_SUCH_FILE,
4347961SNatalie.Li@Sun.COM ERRDOS, ERROR_FILE_NOT_FOUND);
4357961SNatalie.Li@Sun.COM return (-1);
4367961SNatalie.Li@Sun.COM }
4377961SNatalie.Li@Sun.COM
43810001SJoyce.McIntosh@Sun.COM if ((attr.sa_dosattr & FILE_ATTRIBUTE_SYSTEM) &&
43910001SJoyce.McIntosh@Sun.COM !(SMB_SEARCH_SYSTEM(sattr))) {
4407961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_NO_SUCH_FILE,
4417961SNatalie.Li@Sun.COM ERRDOS, ERROR_FILE_NOT_FOUND);
4427961SNatalie.Li@Sun.COM return (-1);
4437961SNatalie.Li@Sun.COM }
4447961SNatalie.Li@Sun.COM
4457961SNatalie.Li@Sun.COM return (0);
4467961SNatalie.Li@Sun.COM }
4475331Samw
4487961SNatalie.Li@Sun.COM /*
4497961SNatalie.Li@Sun.COM * smb_delete_remove_file
4507961SNatalie.Li@Sun.COM *
4517961SNatalie.Li@Sun.COM * For consistency with Windows 2000, the range check should be done
4527961SNatalie.Li@Sun.COM * after checking for sharing violations. Attempting to delete a
4537961SNatalie.Li@Sun.COM * locked file will result in sharing violation, which is the same
4547961SNatalie.Li@Sun.COM * thing that will happen if you try to delete a non-locked open file.
4557961SNatalie.Li@Sun.COM *
4567961SNatalie.Li@Sun.COM * Note that windows 2000 rejects lock requests on open files that
4577961SNatalie.Li@Sun.COM * have been opened with metadata open modes. The error is
4587961SNatalie.Li@Sun.COM * STATUS_ACCESS_DENIED.
4597961SNatalie.Li@Sun.COM *
4607961SNatalie.Li@Sun.COM * NT does not always close a file immediately, which can cause the
4617961SNatalie.Li@Sun.COM * share and access checking to fail (the node refcnt is greater
4627961SNatalie.Li@Sun.COM * than one), and the file doesn't get deleted. Breaking the oplock
4637961SNatalie.Li@Sun.COM * before share and access checking gives the client a chance to
4647961SNatalie.Li@Sun.COM * close the file.
4657961SNatalie.Li@Sun.COM *
4667961SNatalie.Li@Sun.COM * Returns: 0 - success
4677961SNatalie.Li@Sun.COM * -1 - error, err populated with error details
4687961SNatalie.Li@Sun.COM */
4697961SNatalie.Li@Sun.COM static int
smb_delete_remove_file(smb_request_t * sr,smb_error_t * err)4707961SNatalie.Li@Sun.COM smb_delete_remove_file(smb_request_t *sr, smb_error_t *err)
4717961SNatalie.Li@Sun.COM {
4727961SNatalie.Li@Sun.COM int rc;
4737961SNatalie.Li@Sun.COM uint32_t status;
4747961SNatalie.Li@Sun.COM smb_fqi_t *fqi;
4757961SNatalie.Li@Sun.COM smb_node_t *node;
4769231SAfshin.Ardakani@Sun.COM uint32_t flags = 0;
4777961SNatalie.Li@Sun.COM
4787961SNatalie.Li@Sun.COM fqi = &sr->arg.dirop.fqi;
4799343SAfshin.Ardakani@Sun.COM node = fqi->fq_fnode;
4807961SNatalie.Li@Sun.COM
481*12890SJoyce.McIntosh@Sun.COM (void) smb_oplock_break(sr, node,
482*12890SJoyce.McIntosh@Sun.COM SMB_OPLOCK_BREAK_TO_LEVEL_II | SMB_OPLOCK_BREAK_BATCH);
4837961SNatalie.Li@Sun.COM
4847961SNatalie.Li@Sun.COM smb_node_start_crit(node, RW_READER);
4857961SNatalie.Li@Sun.COM
4867961SNatalie.Li@Sun.COM status = smb_node_delete_check(node);
4877961SNatalie.Li@Sun.COM if (status != NT_STATUS_SUCCESS) {
4887961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_SHARING_VIOLATION,
4897961SNatalie.Li@Sun.COM ERRDOS, ERROR_SHARING_VIOLATION);
4907961SNatalie.Li@Sun.COM smb_node_end_crit(node);
4917961SNatalie.Li@Sun.COM return (-1);
4927961SNatalie.Li@Sun.COM }
4937961SNatalie.Li@Sun.COM
4947961SNatalie.Li@Sun.COM status = smb_range_check(sr, node, 0, UINT64_MAX, B_TRUE);
4957961SNatalie.Li@Sun.COM if (status != NT_STATUS_SUCCESS) {
4967961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_ACCESS_DENIED,
4977961SNatalie.Li@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
4987961SNatalie.Li@Sun.COM smb_node_end_crit(node);
4997961SNatalie.Li@Sun.COM return (-1);
5007961SNatalie.Li@Sun.COM }
5017961SNatalie.Li@Sun.COM
5029231SAfshin.Ardakani@Sun.COM if (SMB_TREE_SUPPORTS_CATIA(sr))
5039231SAfshin.Ardakani@Sun.COM flags |= SMB_CATIA;
5049231SAfshin.Ardakani@Sun.COM
50510122SJordan.Brown@Sun.COM rc = smb_fsop_remove(sr, sr->user_cr, node->n_dnode,
5069231SAfshin.Ardakani@Sun.COM node->od_name, flags);
5077961SNatalie.Li@Sun.COM if (rc != 0) {
5087961SNatalie.Li@Sun.COM if (rc == ENOENT)
5097961SNatalie.Li@Sun.COM smb_delete_error(err, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5107961SNatalie.Li@Sun.COM ERRDOS, ERROR_FILE_NOT_FOUND);
5117961SNatalie.Li@Sun.COM else
5127961SNatalie.Li@Sun.COM smbsr_map_errno(rc, err);
5137961SNatalie.Li@Sun.COM
5147961SNatalie.Li@Sun.COM smb_node_end_crit(node);
5157961SNatalie.Li@Sun.COM return (-1);
5167961SNatalie.Li@Sun.COM }
5177961SNatalie.Li@Sun.COM
5187961SNatalie.Li@Sun.COM smb_node_end_crit(node);
5197961SNatalie.Li@Sun.COM return (0);
5205331Samw }
5215331Samw
5227961SNatalie.Li@Sun.COM
5236139Sjb150015 /*
5247348SJose.Borrego@Sun.COM * smb_delete_check_path
5257348SJose.Borrego@Sun.COM *
52611337SWilliam.Krier@Sun.COM * smb_pathname_validate() should already have been used to
52711337SWilliam.Krier@Sun.COM * perform initial validation on the pathname. Additional
52811337SWilliam.Krier@Sun.COM * request specific validation of the filename is performed
52911337SWilliam.Krier@Sun.COM * here.
5307348SJose.Borrego@Sun.COM *
53111337SWilliam.Krier@Sun.COM * - pn->pn_fname is NULL should result in NT_STATUS_FILE_IS_A_DIRECTORY
5327348SJose.Borrego@Sun.COM *
53311337SWilliam.Krier@Sun.COM * - Any wildcard filename that resolves to '.' should result in
53411337SWilliam.Krier@Sun.COM * NT_STATUS_OBJECT_NAME_INVALID if the search attributes include
53511337SWilliam.Krier@Sun.COM * FILE_ATTRIBUTE_DIRECTORY
5367348SJose.Borrego@Sun.COM *
5377348SJose.Borrego@Sun.COM * Returns:
53811337SWilliam.Krier@Sun.COM * 0: path is valid.
5397961SNatalie.Li@Sun.COM * -1: path is invalid. Sets error information in sr.
5407348SJose.Borrego@Sun.COM */
5417961SNatalie.Li@Sun.COM static int
smb_delete_check_path(smb_request_t * sr)54211337SWilliam.Krier@Sun.COM smb_delete_check_path(smb_request_t *sr)
5437348SJose.Borrego@Sun.COM {
5447961SNatalie.Li@Sun.COM smb_fqi_t *fqi = &sr->arg.dirop.fqi;
5459343SAfshin.Ardakani@Sun.COM smb_pathname_t *pn = &fqi->fq_path;
5467348SJose.Borrego@Sun.COM
54711337SWilliam.Krier@Sun.COM if (pn->pn_fname == NULL) {
54811337SWilliam.Krier@Sun.COM smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
54911337SWilliam.Krier@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
55011337SWilliam.Krier@Sun.COM return (-1);
5517348SJose.Borrego@Sun.COM }
5528938Samw@Sun.COM
55311337SWilliam.Krier@Sun.COM /* fname component is, or resolves to, '.' (dot) */
55411337SWilliam.Krier@Sun.COM if ((strcmp(pn->pn_fname, ".") == 0) ||
5559343SAfshin.Ardakani@Sun.COM (SMB_SEARCH_DIRECTORY(fqi->fq_sattr) &&
55611337SWilliam.Krier@Sun.COM (smb_match(pn->pn_fname, ".")))) {
5577348SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
5587348SJose.Borrego@Sun.COM ERRDOS, ERROR_INVALID_NAME);
5597961SNatalie.Li@Sun.COM return (-1);
5607348SJose.Borrego@Sun.COM }
5617348SJose.Borrego@Sun.COM
5627961SNatalie.Li@Sun.COM return (0);
5637348SJose.Borrego@Sun.COM }
5647348SJose.Borrego@Sun.COM
5657348SJose.Borrego@Sun.COM /*
5667961SNatalie.Li@Sun.COM * smb_delete_error
5676139Sjb150015 */
5687961SNatalie.Li@Sun.COM static void
smb_delete_error(smb_error_t * err,uint32_t status,uint16_t errcls,uint16_t errcode)5697961SNatalie.Li@Sun.COM smb_delete_error(smb_error_t *err,
5707961SNatalie.Li@Sun.COM uint32_t status, uint16_t errcls, uint16_t errcode)
5715331Samw {
5727961SNatalie.Li@Sun.COM err->status = status;
5737961SNatalie.Li@Sun.COM err->errcls = errcls;
5747961SNatalie.Li@Sun.COM err->errcode = errcode;
5755331Samw }
576