Fix the mess with ldb includes.
[Samba/vl.git] / source4 / ntvfs / posix / vfs_posix.c
blob6b0f32e65a84a41ff1a774b7f01ca3cd43c848e0
1 /*
2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend
6 Copyright (C) Andrew Tridgell 2004
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 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 this implements most of the POSIX NTVFS backend
23 This is the default backend
26 #include "includes.h"
27 #include "vfs_posix.h"
28 #include "librpc/gen_ndr/security.h"
29 #include "../tdb/include/tdb.h"
30 #include "tdb_wrap.h"
31 #include "libcli/security/security.h"
32 #include "lib/events/events.h"
33 #include "param/param.h"
36 setup config options for a posix share
38 static void pvfs_setup_options(struct pvfs_state *pvfs)
40 struct share_config *scfg = pvfs->ntvfs->ctx->config;
41 const char *eadb;
43 if (share_bool_option(scfg, SHARE_MAP_HIDDEN, SHARE_MAP_HIDDEN_DEFAULT))
44 pvfs->flags |= PVFS_FLAG_MAP_HIDDEN;
45 if (share_bool_option(scfg, SHARE_MAP_ARCHIVE, SHARE_MAP_ARCHIVE_DEFAULT))
46 pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE;
47 if (share_bool_option(scfg, SHARE_MAP_SYSTEM, SHARE_MAP_SYSTEM_DEFAULT))
48 pvfs->flags |= PVFS_FLAG_MAP_SYSTEM;
49 if (share_bool_option(scfg, SHARE_READONLY, SHARE_READONLY_DEFAULT))
50 pvfs->flags |= PVFS_FLAG_READONLY;
51 if (share_bool_option(scfg, SHARE_STRICT_SYNC, SHARE_STRICT_SYNC_DEFAULT))
52 pvfs->flags |= PVFS_FLAG_STRICT_SYNC;
53 if (share_bool_option(scfg, SHARE_STRICT_LOCKING, SHARE_STRICT_LOCKING_DEFAULT))
54 pvfs->flags |= PVFS_FLAG_STRICT_LOCKING;
55 if (share_bool_option(scfg, SHARE_CI_FILESYSTEM, SHARE_CI_FILESYSTEM_DEFAULT))
56 pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM;
57 if (share_bool_option(scfg, PVFS_FAKE_OPLOCKS, PVFS_FAKE_OPLOCKS_DEFAULT))
58 pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS;
59 if (share_bool_option(scfg, PVFS_AIO, false))
60 pvfs->flags |= PVFS_FLAG_LINUX_AIO;
62 /* file perm options */
63 pvfs->options.create_mask = share_int_option(scfg,
64 SHARE_CREATE_MASK,
65 SHARE_CREATE_MASK_DEFAULT);
66 pvfs->options.dir_mask = share_int_option(scfg,
67 SHARE_DIR_MASK,
68 SHARE_DIR_MASK_DEFAULT);
69 pvfs->options.force_dir_mode = share_int_option(scfg,
70 SHARE_FORCE_DIR_MODE,
71 SHARE_FORCE_DIR_MODE_DEFAULT);
72 pvfs->options.force_create_mode = share_int_option(scfg,
73 SHARE_FORCE_CREATE_MODE,
74 SHARE_FORCE_CREATE_MODE_DEFAULT);
75 /* this must be a power of 2 */
76 pvfs->alloc_size_rounding = share_int_option(scfg,
77 PVFS_ALLOCATION_ROUNDING,
78 PVFS_ALLOCATION_ROUNDING_DEFAULT);
80 pvfs->search.inactivity_time = share_int_option(scfg,
81 PVFS_SEARCH_INACTIVITY,
82 PVFS_SEARCH_INACTIVITY_DEFAULT);
84 #if HAVE_XATTR_SUPPORT
85 if (share_bool_option(scfg, PVFS_XATTR, PVFS_XATTR_DEFAULT))
86 pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
87 #endif
89 pvfs->sharing_violation_delay = share_int_option(scfg,
90 PVFS_SHARE_DELAY,
91 PVFS_SHARE_DELAY_DEFAULT);
93 pvfs->oplock_break_timeout = share_int_option(scfg,
94 PVFS_OPLOCK_TIMEOUT,
95 PVFS_OPLOCK_TIMEOUT_DEFAULT);
97 pvfs->writetime_delay = share_int_option(scfg,
98 PVFS_WRITETIME_DELAY,
99 PVFS_WRITETIME_DELAY_DEFAULT);
101 pvfs->share_name = talloc_strdup(pvfs, scfg->name);
103 pvfs->fs_attribs =
104 FS_ATTR_CASE_SENSITIVE_SEARCH |
105 FS_ATTR_CASE_PRESERVED_NAMES |
106 FS_ATTR_UNICODE_ON_DISK |
107 FS_ATTR_SPARSE_FILES;
109 /* allow xattrs to be stored in a external tdb */
110 eadb = share_string_option(scfg, PVFS_EADB, NULL);
111 if (eadb != NULL) {
112 pvfs->ea_db = tdb_wrap_open(pvfs, eadb, 50000,
113 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
114 if (pvfs->ea_db != NULL) {
115 pvfs->flags |= PVFS_FLAG_XATTR_ENABLE;
116 } else {
117 DEBUG(0,("Failed to open eadb '%s' - %s\n",
118 eadb, strerror(errno)));
119 pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;
123 if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
124 pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS;
126 if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
127 pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS;
130 pvfs->sid_cache.creator_owner = dom_sid_parse_talloc(pvfs, SID_CREATOR_OWNER);
131 pvfs->sid_cache.creator_group = dom_sid_parse_talloc(pvfs, SID_CREATOR_GROUP);
133 /* check if the system really supports xattrs */
134 if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
135 pvfs_xattr_probe(pvfs);
138 /* enable an ACL backend */
139 pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr"));
142 static int pvfs_state_destructor(struct pvfs_state *pvfs)
144 struct pvfs_file *f, *fn;
145 struct pvfs_search_state *s, *sn;
148 * make sure we cleanup files and searches before anything else
149 * because there destructors need to acess the pvfs_state struct
151 for (f=pvfs->files.list; f; f=fn) {
152 fn = f->next;
153 talloc_free(f);
156 for (s=pvfs->search.list; s; s=sn) {
157 sn = s->next;
158 talloc_free(s);
161 return 0;
165 connect to a share - used when a tree_connect operation comes
166 in. For a disk based backend we needs to ensure that the base
167 directory exists (tho it doesn't need to be accessible by the user,
168 that comes later)
170 static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
171 struct ntvfs_request *req, const char *sharename)
173 struct pvfs_state *pvfs;
174 struct stat st;
175 char *base_directory;
176 NTSTATUS status;
179 * TODO: call this from ntvfs_posix_init()
180 * but currently we don't have a lp_ctx there
182 status = pvfs_acl_init(ntvfs->ctx->lp_ctx);
183 NT_STATUS_NOT_OK_RETURN(status);
185 pvfs = talloc_zero(ntvfs, struct pvfs_state);
186 NT_STATUS_HAVE_NO_MEMORY(pvfs);
188 /* for simplicity of path construction, remove any trailing slash now */
189 base_directory = talloc_strdup(pvfs, share_string_option(ntvfs->ctx->config, SHARE_PATH, ""));
190 NT_STATUS_HAVE_NO_MEMORY(base_directory);
191 if (strcmp(base_directory, "/") != 0) {
192 trim_string(base_directory, NULL, "/");
195 pvfs->ntvfs = ntvfs;
196 pvfs->base_directory = base_directory;
198 /* the directory must exist. Note that we deliberately don't
199 check that it is readable */
200 if (stat(pvfs->base_directory, &st) != 0 || !S_ISDIR(st.st_mode)) {
201 DEBUG(0,("pvfs_connect: '%s' is not a directory, when connecting to [%s]\n",
202 pvfs->base_directory, sharename));
203 return NT_STATUS_BAD_NETWORK_NAME;
206 ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
207 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
209 ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
210 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
212 ntvfs->private_data = pvfs;
214 pvfs->brl_context = brl_init(pvfs,
215 pvfs->ntvfs->ctx->server_id,
216 pvfs->ntvfs->ctx->lp_ctx,
217 pvfs->ntvfs->ctx->msg_ctx);
218 if (pvfs->brl_context == NULL) {
219 return NT_STATUS_INTERNAL_DB_CORRUPTION;
222 pvfs->odb_context = odb_init(pvfs, pvfs->ntvfs->ctx);
223 if (pvfs->odb_context == NULL) {
224 return NT_STATUS_INTERNAL_DB_CORRUPTION;
227 /* allow this to be NULL - we just disable change notify */
228 pvfs->notify_context = notify_init(pvfs,
229 pvfs->ntvfs->ctx->server_id,
230 pvfs->ntvfs->ctx->msg_ctx,
231 pvfs->ntvfs->ctx->lp_ctx,
232 pvfs->ntvfs->ctx->event_ctx,
233 pvfs->ntvfs->ctx->config);
235 pvfs->wbc_ctx = wbc_init(pvfs,
236 pvfs->ntvfs->ctx->msg_ctx,
237 pvfs->ntvfs->ctx->event_ctx);
238 if (pvfs->wbc_ctx == NULL) {
239 return NT_STATUS_INTERNAL_DB_CORRUPTION;
242 /* allocate the search handle -> ptr tree */
243 pvfs->search.idtree = idr_init(pvfs);
244 NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree);
246 status = pvfs_mangle_init(pvfs);
247 NT_STATUS_NOT_OK_RETURN(status);
249 pvfs_setup_options(pvfs);
251 talloc_set_destructor(pvfs, pvfs_state_destructor);
253 #ifdef SIGXFSZ
254 /* who had the stupid idea to generate a signal on a large
255 file write instead of just failing it!? */
256 BlockSignals(true, SIGXFSZ);
257 #endif
259 return NT_STATUS_OK;
263 disconnect from a share
265 static NTSTATUS pvfs_disconnect(struct ntvfs_module_context *ntvfs)
267 return NT_STATUS_OK;
271 check if a directory exists
273 static NTSTATUS pvfs_chkpath(struct ntvfs_module_context *ntvfs,
274 struct ntvfs_request *req,
275 union smb_chkpath *cp)
277 struct pvfs_state *pvfs = ntvfs->private_data;
278 struct pvfs_filename *name;
279 NTSTATUS status;
281 /* resolve the cifs name to a posix name */
282 status = pvfs_resolve_name(pvfs, req, cp->chkpath.in.path, 0, &name);
283 NT_STATUS_NOT_OK_RETURN(status);
285 if (!name->exists) {
286 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
289 if (!S_ISDIR(name->st.st_mode)) {
290 return NT_STATUS_NOT_A_DIRECTORY;
293 return NT_STATUS_OK;
297 copy a set of files
299 static NTSTATUS pvfs_copy(struct ntvfs_module_context *ntvfs,
300 struct ntvfs_request *req, struct smb_copy *cp)
302 DEBUG(0,("pvfs_copy not implemented\n"));
303 return NT_STATUS_NOT_SUPPORTED;
307 return print queue info
309 static NTSTATUS pvfs_lpq(struct ntvfs_module_context *ntvfs,
310 struct ntvfs_request *req, union smb_lpq *lpq)
312 return NT_STATUS_NOT_SUPPORTED;
315 /* SMBtrans - not used on file shares */
316 static NTSTATUS pvfs_trans(struct ntvfs_module_context *ntvfs,
317 struct ntvfs_request *req, struct smb_trans2 *trans2)
319 return NT_STATUS_ACCESS_DENIED;
323 initialialise the POSIX disk backend, registering ourselves with the ntvfs subsystem
325 NTSTATUS ntvfs_posix_init(void)
327 NTSTATUS ret;
328 struct ntvfs_ops ops;
329 NTVFS_CURRENT_CRITICAL_SIZES(vers);
331 ZERO_STRUCT(ops);
333 ops.type = NTVFS_DISK;
335 /* fill in all the operations */
336 ops.connect = pvfs_connect;
337 ops.disconnect = pvfs_disconnect;
338 ops.unlink = pvfs_unlink;
339 ops.chkpath = pvfs_chkpath;
340 ops.qpathinfo = pvfs_qpathinfo;
341 ops.setpathinfo = pvfs_setpathinfo;
342 ops.open = pvfs_open;
343 ops.mkdir = pvfs_mkdir;
344 ops.rmdir = pvfs_rmdir;
345 ops.rename = pvfs_rename;
346 ops.copy = pvfs_copy;
347 ops.ioctl = pvfs_ioctl;
348 ops.read = pvfs_read;
349 ops.write = pvfs_write;
350 ops.seek = pvfs_seek;
351 ops.flush = pvfs_flush;
352 ops.close = pvfs_close;
353 ops.exit = pvfs_exit;
354 ops.lock = pvfs_lock;
355 ops.setfileinfo = pvfs_setfileinfo;
356 ops.qfileinfo = pvfs_qfileinfo;
357 ops.fsinfo = pvfs_fsinfo;
358 ops.lpq = pvfs_lpq;
359 ops.search_first = pvfs_search_first;
360 ops.search_next = pvfs_search_next;
361 ops.search_close = pvfs_search_close;
362 ops.trans = pvfs_trans;
363 ops.logoff = pvfs_logoff;
364 ops.async_setup = pvfs_async_setup;
365 ops.cancel = pvfs_cancel;
366 ops.notify = pvfs_notify;
368 /* register ourselves with the NTVFS subsystem. We register
369 under the name 'default' as we wish to be the default
370 backend, and also register as 'posix' */
371 ops.name = "default";
372 ret = ntvfs_register(&ops, &vers);
374 if (!NT_STATUS_IS_OK(ret)) {
375 DEBUG(0,("Failed to register POSIX backend as '%s'!\n", ops.name));
378 ops.name = "posix";
379 ret = ntvfs_register(&ops, &vers);
381 if (!NT_STATUS_IS_OK(ret)) {
382 DEBUG(0,("Failed to register POSIX backend as '%s'!\n", ops.name));
385 if (NT_STATUS_IS_OK(ret)) {
386 ret = ntvfs_common_init();
389 return ret;