r14173: change smb interface structures to always use
[jelmer/samba4-debian.git] / source / ntvfs / posix / pvfs_unlink.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - unlink
5
6    Copyright (C) Andrew Tridgell 2004
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "vfs_posix.h"
25
26
27 /*
28   unlink a stream
29  */
30 static NTSTATUS pvfs_unlink_stream(struct pvfs_state *pvfs, 
31                                    struct ntvfs_request *req,
32                                    struct pvfs_filename *name, 
33                                    uint16_t attrib)
34 {
35         NTSTATUS status;
36         struct odb_lock *lck;
37
38         if (!name->stream_exists) {
39                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
40         }
41
42         /* make sure its matches the given attributes */
43         status = pvfs_match_attrib(pvfs, name, attrib, 0);
44         if (!NT_STATUS_IS_OK(status)) {
45                 return status;
46         }
47
48         status = pvfs_can_delete(pvfs, req, name, &lck);
49         if (!NT_STATUS_IS_OK(status)) {
50                 return status;
51         }
52
53         return pvfs_stream_delete(pvfs, name, -1);
54 }
55
56
57 /*
58   unlink one file
59 */
60 static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, 
61                                 struct ntvfs_request *req,
62                                 const char *unix_path, 
63                                 const char *fname, uint32_t attrib)
64 {
65         struct pvfs_filename *name;
66         NTSTATUS status;
67         struct odb_lock *lck;
68
69         /* get a pvfs_filename object */
70         status = pvfs_resolve_partial(pvfs, req, 
71                                       unix_path, fname, &name);
72         if (!NT_STATUS_IS_OK(status)) {
73                 return status;
74         }
75
76         /* make sure its matches the given attributes */
77         status = pvfs_match_attrib(pvfs, name, attrib, 0);
78         if (!NT_STATUS_IS_OK(status)) {
79                 talloc_free(name);
80                 return status;
81         }
82
83         status = pvfs_can_delete(pvfs, req, name, &lck);
84         if (!NT_STATUS_IS_OK(status)) {
85                 talloc_free(name);
86                 return status;
87         }
88
89         if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
90                 talloc_free(name);
91                 return NT_STATUS_FILE_IS_A_DIRECTORY;
92         }
93
94         if (name->st.st_nlink == 1) {
95                 status = pvfs_xattr_unlink_hook(pvfs, name->full_name);
96                 if (!NT_STATUS_IS_OK(status)) {
97                         return status;
98                 }
99         }
100
101         /* finally try the actual unlink */
102         if (unlink(name->full_name) == -1) {
103                 status = pvfs_map_errno(pvfs, errno);
104         }
105
106         talloc_free(name);
107
108         return status;
109 }
110
111 /*
112   delete a file - the dirtype specifies the file types to include in the search. 
113   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
114 */
115 NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs,
116                      struct ntvfs_request *req,
117                      union smb_unlink *unl)
118 {
119         struct pvfs_state *pvfs = ntvfs->private_data;
120         struct pvfs_dir *dir;
121         NTSTATUS status;
122         uint32_t total_deleted=0;
123         struct pvfs_filename *name;
124         const char *fname;
125         uint_t ofs;
126
127         /* resolve the cifs name to a posix name */
128         status = pvfs_resolve_name(pvfs, req, unl->unlink.in.pattern, 
129                                    PVFS_RESOLVE_WILDCARD | PVFS_RESOLVE_STREAMS, &name);
130         if (!NT_STATUS_IS_OK(status)) {
131                 return status;
132         }
133
134         if (!name->exists && !name->has_wildcard) {
135                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
136         }
137
138         if (name->exists && 
139             (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
140                 return NT_STATUS_FILE_IS_A_DIRECTORY;
141         }
142
143         if (name->stream_name) {
144                 return pvfs_unlink_stream(pvfs, req, name, unl->unlink.in.attrib);
145         }
146
147         /* get list of matching files */
148         status = pvfs_list_start(pvfs, name, req, &dir);
149         if (!NT_STATUS_IS_OK(status)) {
150                 return status;
151         }
152
153         status = NT_STATUS_NO_SUCH_FILE;
154
155         ofs = 0;
156
157         while ((fname = pvfs_list_next(dir, &ofs))) {
158                 /* this seems to be a special case */
159                 if ((unl->unlink.in.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
160                     (strcmp(fname, ".") == 0 ||
161                      strcmp(fname, "..") == 0)) {
162                         return NT_STATUS_OBJECT_NAME_INVALID;
163                 }
164
165                 status = pvfs_unlink_one(pvfs, req, pvfs_list_unix_path(dir), fname, unl->unlink.in.attrib);
166                 if (NT_STATUS_IS_OK(status)) {
167                         total_deleted++;
168                 }
169         }
170
171         if (total_deleted > 0) {
172                 status = NT_STATUS_OK;
173         }
174
175         return status;
176 }
177
178