root/source4/ntvfs/posix/vfs_posix.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pvfs_setup_options
  2. pvfs_state_destructor
  3. pvfs_connect
  4. pvfs_disconnect
  5. pvfs_chkpath
  6. pvfs_copy
  7. pvfs_lpq
  8. pvfs_trans
  9. ntvfs_posix_init

   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 3 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, see <http://www.gnu.org/licenses/>.
  20 */
  21 /*
  22   this implements most of the POSIX NTVFS backend
  23   This is the default backend
  24 */
  25 
  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"
  34 
  35 /*
  36   setup config options for a posix share
  37 */
  38 static void pvfs_setup_options(struct pvfs_state *pvfs)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         struct share_config *scfg = pvfs->ntvfs->ctx->config;
  41         const char *eadb;
  42 
  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;
  61 
  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);
  79 
  80         pvfs->search.inactivity_time = share_int_option(scfg,
  81                                                         PVFS_SEARCH_INACTIVITY,
  82                                                         PVFS_SEARCH_INACTIVITY_DEFAULT);
  83 
  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
  88 
  89         pvfs->sharing_violation_delay = share_int_option(scfg,
  90                                                         PVFS_SHARE_DELAY,
  91                                                         PVFS_SHARE_DELAY_DEFAULT);
  92 
  93         pvfs->oplock_break_timeout = share_int_option(scfg,
  94                                                       PVFS_OPLOCK_TIMEOUT,
  95                                                       PVFS_OPLOCK_TIMEOUT_DEFAULT);
  96 
  97         pvfs->writetime_delay = share_int_option(scfg,
  98                                                  PVFS_WRITETIME_DELAY,
  99                                                  PVFS_WRITETIME_DELAY_DEFAULT);
 100 
 101         pvfs->share_name = talloc_strdup(pvfs, scfg->name);
 102 
 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;
 108 
 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;
 120                 }
 121         }
 122 
 123         if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
 124                 pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS;
 125         }
 126         if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
 127                 pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS;
 128         }
 129 
 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);
 132 
 133         /* check if the system really supports xattrs */
 134         if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) {
 135                 pvfs_xattr_probe(pvfs);
 136         }
 137 
 138         /* enable an ACL backend */
 139         pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr"));
 140 }
 141 
 142 static int pvfs_state_destructor(struct pvfs_state *pvfs)
     /* [<][>][^][v][top][bottom][index][help] */
 143 {
 144         struct pvfs_file *f, *fn;
 145         struct pvfs_search_state *s, *sn;
 146 
 147         /* 
 148          * make sure we cleanup files and searches before anything else
 149          * because there destructors need to acess the pvfs_state struct
 150          */
 151         for (f=pvfs->files.list; f; f=fn) {
 152                 fn = f->next;
 153                 talloc_free(f);
 154         }
 155 
 156         for (s=pvfs->search.list; s; s=sn) {
 157                 sn = s->next;
 158                 talloc_free(s);
 159         }
 160 
 161         return 0;
 162 }
 163 
 164 /*
 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)
 169 */
 170 static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 171                              struct ntvfs_request *req, const char *sharename)
 172 {
 173         struct pvfs_state *pvfs;
 174         struct stat st;
 175         char *base_directory;
 176         NTSTATUS status;
 177 
 178         /*
 179          * TODO: call this from ntvfs_posix_init()
 180          *       but currently we don't have a lp_ctx there
 181          */
 182         status = pvfs_acl_init(ntvfs->ctx->lp_ctx);
 183         NT_STATUS_NOT_OK_RETURN(status);
 184 
 185         pvfs = talloc_zero(ntvfs, struct pvfs_state);
 186         NT_STATUS_HAVE_NO_MEMORY(pvfs);
 187 
 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, "/");
 193         }
 194 
 195         pvfs->ntvfs = ntvfs;
 196         pvfs->base_directory = base_directory;
 197 
 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;
 204         }
 205 
 206         ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
 207         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
 208 
 209         ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
 210         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
 211 
 212         ntvfs->private_data = pvfs;
 213 
 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;
 220         }
 221 
 222         pvfs->odb_context = odb_init(pvfs, pvfs->ntvfs->ctx);
 223         if (pvfs->odb_context == NULL) {
 224                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
 225         }
 226 
 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);
 234 
 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;
 240         }
 241 
 242         /* allocate the search handle -> ptr tree */
 243         pvfs->search.idtree = idr_init(pvfs);
 244         NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree);
 245 
 246         status = pvfs_mangle_init(pvfs);
 247         NT_STATUS_NOT_OK_RETURN(status);
 248 
 249         pvfs_setup_options(pvfs);
 250 
 251         talloc_set_destructor(pvfs, pvfs_state_destructor);
 252 
 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
 258 
 259         return NT_STATUS_OK;
 260 }
 261 
 262 /*
 263   disconnect from a share
 264 */
 265 static NTSTATUS pvfs_disconnect(struct ntvfs_module_context *ntvfs)
     /* [<][>][^][v][top][bottom][index][help] */
 266 {
 267         return NT_STATUS_OK;
 268 }
 269 
 270 /*
 271   check if a directory exists
 272 */
 273 static NTSTATUS pvfs_chkpath(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 274                              struct ntvfs_request *req,
 275                              union smb_chkpath *cp)
 276 {
 277         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 278                                   struct pvfs_state);
 279         struct pvfs_filename *name;
 280         NTSTATUS status;
 281 
 282         /* resolve the cifs name to a posix name */
 283         status = pvfs_resolve_name(pvfs, req, cp->chkpath.in.path, 0, &name);
 284         NT_STATUS_NOT_OK_RETURN(status);
 285 
 286         if (!name->exists) {
 287                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 288         }
 289 
 290         if (!S_ISDIR(name->st.st_mode)) {
 291                 return NT_STATUS_NOT_A_DIRECTORY;
 292         }
 293 
 294         return NT_STATUS_OK;
 295 }
 296 
 297 /*
 298   copy a set of files
 299 */
 300 static NTSTATUS pvfs_copy(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 301                           struct ntvfs_request *req, struct smb_copy *cp)
 302 {
 303         DEBUG(0,("pvfs_copy not implemented\n"));
 304         return NT_STATUS_NOT_SUPPORTED;
 305 }
 306 
 307 /*
 308   return print queue info
 309 */
 310 static NTSTATUS pvfs_lpq(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 311                          struct ntvfs_request *req, union smb_lpq *lpq)
 312 {
 313         return NT_STATUS_NOT_SUPPORTED;
 314 }
 315 
 316 /* SMBtrans - not used on file shares */
 317 static NTSTATUS pvfs_trans(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 318                            struct ntvfs_request *req, struct smb_trans2 *trans2)
 319 {
 320         return NT_STATUS_ACCESS_DENIED;
 321 }
 322 
 323 /*
 324   initialialise the POSIX disk backend, registering ourselves with the ntvfs subsystem
 325  */
 326 NTSTATUS ntvfs_posix_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 327 {
 328         NTSTATUS ret;
 329         struct ntvfs_ops ops;
 330         NTVFS_CURRENT_CRITICAL_SIZES(vers);
 331 
 332         ZERO_STRUCT(ops);
 333 
 334         ops.type = NTVFS_DISK;
 335         
 336         /* fill in all the operations */
 337         ops.connect = pvfs_connect;
 338         ops.disconnect = pvfs_disconnect;
 339         ops.unlink = pvfs_unlink;
 340         ops.chkpath = pvfs_chkpath;
 341         ops.qpathinfo = pvfs_qpathinfo;
 342         ops.setpathinfo = pvfs_setpathinfo;
 343         ops.open = pvfs_open;
 344         ops.mkdir = pvfs_mkdir;
 345         ops.rmdir = pvfs_rmdir;
 346         ops.rename = pvfs_rename;
 347         ops.copy = pvfs_copy;
 348         ops.ioctl = pvfs_ioctl;
 349         ops.read = pvfs_read;
 350         ops.write = pvfs_write;
 351         ops.seek = pvfs_seek;
 352         ops.flush = pvfs_flush; 
 353         ops.close = pvfs_close;
 354         ops.exit = pvfs_exit;
 355         ops.lock = pvfs_lock;
 356         ops.setfileinfo = pvfs_setfileinfo;
 357         ops.qfileinfo = pvfs_qfileinfo;
 358         ops.fsinfo = pvfs_fsinfo;
 359         ops.lpq = pvfs_lpq;
 360         ops.search_first = pvfs_search_first;
 361         ops.search_next = pvfs_search_next;
 362         ops.search_close = pvfs_search_close;
 363         ops.trans = pvfs_trans;
 364         ops.logoff = pvfs_logoff;
 365         ops.async_setup = pvfs_async_setup;
 366         ops.cancel = pvfs_cancel;
 367         ops.notify = pvfs_notify;
 368 
 369         /* register ourselves with the NTVFS subsystem. We register
 370            under the name 'default' as we wish to be the default
 371            backend, and also register as 'posix' */
 372         ops.name = "default";
 373         ret = ntvfs_register(&ops, &vers);
 374 
 375         if (!NT_STATUS_IS_OK(ret)) {
 376                 DEBUG(0,("Failed to register POSIX backend as '%s'!\n", ops.name));
 377         }
 378 
 379         ops.name = "posix";
 380         ret = ntvfs_register(&ops, &vers);
 381 
 382         if (!NT_STATUS_IS_OK(ret)) {
 383                 DEBUG(0,("Failed to register POSIX backend as '%s'!\n", ops.name));
 384         }
 385 
 386         if (NT_STATUS_IS_OK(ret)) {
 387                 ret = ntvfs_common_init();
 388         }
 389 
 390         return ret;
 391 }

/* [<][>][^][v][top][bottom][index][help] */