r2751: this is a new ntvfs design which tries to solve:
[jelmer/samba4-debian.git] / source / ntvfs / posix / vfs_posix.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend
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   this implements most of the POSIX NTVFS backend
24   This is the default backend
25 */
26
27 #include "include/includes.h"
28 #include "vfs_posix.h"
29
30
31 /*
32   setup config options for a posix share
33 */
34 static void pvfs_setup_options(struct pvfs_state *pvfs)
35 {
36         int snum = pvfs->tcon->service;
37
38         if (lp_map_hidden(snum)) pvfs->flags |= PVFS_FLAG_MAP_HIDDEN;
39         if (lp_map_archive(snum)) pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE;
40         if (lp_map_system(snum)) pvfs->flags |= PVFS_FLAG_MAP_SYSTEM;
41         if (lp_readonly(snum)) pvfs->flags |= PVFS_FLAG_READONLY;
42
43         pvfs->share_name = talloc_strdup(pvfs, lp_servicename(snum));
44 }
45
46
47 /*
48   connect to a share - used when a tree_connect operation comes
49   in. For a disk based backend we needs to ensure that the base
50   directory exists (tho it doesn't need to be accessible by the user,
51   that comes later)
52 */
53 static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
54                              struct smbsrv_request *req, const char *sharename)
55 {
56         struct smbsrv_tcon *tcon = req->tcon;
57         struct pvfs_state *pvfs;
58         struct stat st;
59         char *base_directory;
60
61         DEBUG(0,("WARNING: the posix vfs handler is incomplete - you probably want \"ntvfs handler = simple\"\n"));
62
63         pvfs = talloc_p(tcon, struct pvfs_state);
64         if (pvfs == NULL) {
65                 return NT_STATUS_NO_MEMORY;
66         }
67         ZERO_STRUCTP(pvfs);
68
69         /* for simplicity of path construction, remove any trailing slash now */
70         base_directory = talloc_strdup(pvfs, lp_pathname(tcon->service));
71         trim_string(base_directory, NULL, "/");
72
73         pvfs->tcon = tcon;
74         pvfs->base_directory = base_directory;
75
76         /* the directory must exist. Note that we deliberately don't
77            check that it is readable */
78         if (stat(pvfs->base_directory, &st) != 0 || !S_ISDIR(st.st_mode)) {
79                 DEBUG(0,("pvfs_connect: '%s' is not a directory, when connecting to [%s]\n", 
80                          pvfs->base_directory, sharename));
81                 return NT_STATUS_BAD_NETWORK_NAME;
82         }
83
84         tcon->fs_type = talloc_strdup(tcon, "NTFS");
85         tcon->dev_type = talloc_strdup(tcon, "A:");
86
87         ntvfs->private_data = pvfs;
88
89         pvfs_setup_options(pvfs);
90
91         return NT_STATUS_OK;
92 }
93
94 /*
95   disconnect from a share
96 */
97 static NTSTATUS pvfs_disconnect(struct ntvfs_module_context *ntvfs,
98                                 struct smbsrv_tcon *tcon)
99 {
100         return NT_STATUS_OK;
101 }
102
103 /*
104   ioctl interface - we don't do any
105 */
106 static NTSTATUS pvfs_ioctl(struct ntvfs_module_context *ntvfs,
107                            struct smbsrv_request *req, union smb_ioctl *io)
108 {
109         return NT_STATUS_INVALID_PARAMETER;
110 }
111
112 /*
113   check if a directory exists
114 */
115 static NTSTATUS pvfs_chkpath(struct ntvfs_module_context *ntvfs,
116                              struct smbsrv_request *req, struct smb_chkpath *cp)
117 {
118         struct pvfs_state *pvfs = ntvfs->private_data;
119         struct pvfs_filename *name;
120         NTSTATUS status;
121
122         /* resolve the cifs name to a posix name */
123         status = pvfs_resolve_name(pvfs, req, cp->in.path, 0, &name);
124         if (!NT_STATUS_IS_OK(status)) {
125                 return status;
126         }
127
128         if (!name->exists) {
129                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
130         }
131
132         if (!S_ISDIR(name->st.st_mode)) {
133                 return NT_STATUS_NOT_A_DIRECTORY;
134         }
135
136         return NT_STATUS_OK;
137 }
138
139 /*
140   copy a set of files
141 */
142 static NTSTATUS pvfs_copy(struct ntvfs_module_context *ntvfs,
143                           struct smbsrv_request *req, struct smb_copy *cp)
144 {
145         DEBUG(0,("pvfs_copy not implemented\n"));
146         return NT_STATUS_NOT_SUPPORTED;
147 }
148
149 /*
150   seek in a file
151 */
152 static NTSTATUS pvfs_seek(struct ntvfs_module_context *ntvfs,
153                           struct smbsrv_request *req, struct smb_seek *io)
154 {
155         DEBUG(0,("pvfs_seek not implemented\n"));
156         return NT_STATUS_NOT_SUPPORTED;
157 }
158
159 /*
160   flush a file
161 */
162 static NTSTATUS pvfs_flush(struct ntvfs_module_context *ntvfs,
163                            struct smbsrv_request *req, struct smb_flush *io)
164 {
165         DEBUG(0,("pvfs_flush not implemented\n"));
166         return NT_STATUS_NOT_IMPLEMENTED;
167 }
168
169 /*
170   lock a byte range
171 */
172 static NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
173                           struct smbsrv_request *req, union smb_lock *lck)
174 {
175         DEBUG(0,("pvfs_lock not implemented\n"));
176         return NT_STATUS_NOT_IMPLEMENTED;
177 }
178
179 /*
180   set info on a pathname
181 */
182 static NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
183                                  struct smbsrv_request *req, union smb_setfileinfo *st)
184 {
185         DEBUG(0,("pvfs_setpathinfo not implemented\n"));
186         return NT_STATUS_NOT_SUPPORTED;
187 }
188
189 /*
190   return print queue info
191 */
192 static NTSTATUS pvfs_lpq(struct ntvfs_module_context *ntvfs,
193                          struct smbsrv_request *req, union smb_lpq *lpq)
194 {
195         return NT_STATUS_NOT_SUPPORTED;
196 }
197
198 /* SMBtrans - not used on file shares */
199 static NTSTATUS pvfs_trans(struct ntvfs_module_context *ntvfs,
200                            struct smbsrv_request *req, struct smb_trans2 *trans2)
201 {
202         return NT_STATUS_ACCESS_DENIED;
203 }
204
205 /*
206   initialialise the POSIX disk backend, registering ourselves with the ntvfs subsystem
207  */
208 NTSTATUS ntvfs_posix_init(void)
209 {
210         NTSTATUS ret;
211         struct ntvfs_ops ops;
212
213         ZERO_STRUCT(ops);
214
215         ops.type = NTVFS_DISK;
216         
217         /* fill in all the operations */
218         ops.connect = pvfs_connect;
219         ops.disconnect = pvfs_disconnect;
220         ops.unlink = pvfs_unlink;
221         ops.chkpath = pvfs_chkpath;
222         ops.qpathinfo = pvfs_qpathinfo;
223         ops.setpathinfo = pvfs_setpathinfo;
224         ops.open = pvfs_open;
225         ops.mkdir = pvfs_mkdir;
226         ops.rmdir = pvfs_rmdir;
227         ops.rename = pvfs_rename;
228         ops.copy = pvfs_copy;
229         ops.ioctl = pvfs_ioctl;
230         ops.read = pvfs_read;
231         ops.write = pvfs_write;
232         ops.seek = pvfs_seek;
233         ops.flush = pvfs_flush; 
234         ops.close = pvfs_close;
235         ops.exit = pvfs_exit;
236         ops.lock = pvfs_lock;
237         ops.setfileinfo = pvfs_setfileinfo;
238         ops.qfileinfo = pvfs_qfileinfo;
239         ops.fsinfo = pvfs_fsinfo;
240         ops.lpq = pvfs_lpq;
241         ops.search_first = pvfs_search_first;
242         ops.search_next = pvfs_search_next;
243         ops.search_close = pvfs_search_close;
244         ops.trans = pvfs_trans;
245         ops.logoff = pvfs_logoff;
246
247         /* register ourselves with the NTVFS subsystem. We register
248            under the name 'default' as we wish to be the default
249            backend, and also register as 'posix' */
250         ops.name = "default";
251         ret = register_backend("ntvfs", &ops);
252
253         ops.name = "posix";
254         ret = register_backend("ntvfs", &ops);
255
256         if (!NT_STATUS_IS_OK(ret)) {
257                 DEBUG(0,("Failed to register POSIX backend!\n"));
258         }
259
260         return ret;
261 }