*/
#include "includes.h"
+#include "smbd/globals.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
struct vfs_init_function_entry *prev, *next;
};
-static struct vfs_init_function_entry *backends = NULL;
-
/****************************************************************************
maintain the list of available backends
****************************************************************************/
}
/* First, try to load the module with the new module system */
- if((entry = vfs_find_backend_entry(module_name)) ||
- (NT_STATUS_IS_OK(smb_probe_module("vfs", module_path)) &&
- (entry = vfs_find_backend_entry(module_name)))) {
-
- DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
-
- if ((ops = entry->vfs_op_tuples) == NULL) {
- DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object));
+ entry = vfs_find_backend_entry(module_name);
+ if (!entry) {
+ NTSTATUS status;
+
+ DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
+ vfs_object));
+
+ status = smb_probe_module("vfs", module_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("error probing vfs module '%s': %s\n",
+ module_path, nt_errstr(status)));
+ goto fail;
+ }
+
+ entry = vfs_find_backend_entry(module_name);
+ if (!entry) {
+ DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
goto fail;
- }
- } else {
- DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
+ }
+ }
+
+ DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
+ if ((ops = entry->vfs_op_tuples) == NULL) {
+ DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object));
goto fail;
}
#define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
-void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp, size_t ext_size)
+void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
+ files_struct *fsp, size_t ext_size,
+ void (*destroy_fn)(void *p_data))
{
struct vfs_fsp_data *ext;
void * ext_data;
ext->owner = handle;
ext->next = fsp->vfs_extension;
+ ext->destroy = destroy_fn;
fsp->vfs_extension = ext;
return EXT_DATA_AREA(ext);
}
} else {
fsp->vfs_extension = curr->next;
}
+ if (curr->destroy) {
+ curr->destroy(EXT_DATA_AREA(curr));
+ }
TALLOC_FREE(curr);
return;
}
if (SMB_VFS_STAT(conn,dname,st) != 0)
return(False);
- ret = S_ISDIR(st->st_mode);
+ ret = S_ISDIR(st->st_ex_mode);
if(!ret)
errno = ENOTDIR;
if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
return False;
- return(S_ISREG(sbuf->st_mode));
+ return(S_ISREG(sbuf->st_ex_mode));
}
/****************************************************************************
uint64_t space_avail;
uint64_t bsize,dfree,dsize;
- release_level_2_oplocks_on_change(fsp);
-
/*
* Actually try and commit the space on disk....
*/
if (ret == -1)
return ret;
- if (len == (uint64_t)st.st_size)
+ if (len == (uint64_t)st.st_ex_size)
return 0;
- if (len < (uint64_t)st.st_size) {
+ if (len < (uint64_t)st.st_ex_size) {
/* Shrink - use ftruncate. */
DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
- fsp->fsp_name, (double)st.st_size ));
+ fsp->fsp_name, (double)st.st_ex_size ));
+
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, (SMB_OFF_T)len)) != -1) {
set_filelen_write_cache(fsp, len);
}
+
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
+
return ret;
}
/* Grow - we need to test if we have enough space. */
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
+
if (!lp_strict_allocate(SNUM(fsp->conn)))
return 0;
- len -= st.st_size;
+ len -= st.st_ex_size;
len /= 1024; /* Len is now number of 1k blocks needed. */
space_avail = get_dfree_info(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize);
if (space_avail == (uint64_t)-1) {
}
DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n",
- fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail ));
+ fsp->fsp_name, (double)st.st_ex_size, (double)len, (double)space_avail ));
if (len > space_avail) {
errno = ENOSPC;
{
int ret;
- release_level_2_oplocks_on_change(fsp);
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
+
DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len));
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
fsp->fsp_name);
}
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
+
return ret;
}
Returns 0 on success, -1 on failure.
****************************************************************************/
-static char *sparse_buf;
#define SPARSE_BUF_WRITE_SIZE (32*1024)
int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
size_t num_to_write;
ssize_t pwrite_ret;
- release_level_2_oplocks_on_change(fsp);
ret = SMB_VFS_FSTAT(fsp, &st);
if (ret == -1) {
return ret;
}
- if (len <= st.st_size) {
+ if (len <= st.st_ex_size) {
return 0;
}
DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n",
- fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size)));
+ fsp->fsp_name, (double)st.st_ex_size, (double)len, (double)(len - st.st_ex_size)));
+
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
flush_write_cache(fsp, SIZECHANGE_FLUSH);
sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
if (!sparse_buf) {
errno = ENOMEM;
- return -1;
+ ret = -1;
+ goto out;
}
}
- offset = st.st_size;
- num_to_write = len - st.st_size;
+ offset = st.st_ex_size;
+ num_to_write = len - st.st_ex_size;
total = 0;
while (total < num_to_write) {
if (pwrite_ret == -1) {
DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
- return -1;
+ ret = -1;
+ goto out;
}
if (pwrite_ret == 0) {
- return 0;
+ ret = 0;
+ goto out;
}
total += pwrite_ret;
}
set_filelen_write_cache(fsp, len);
- return 0;
+
+ ret = 0;
+ out:
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
+ return ret;
}
/****************************************************************************
A vfs_readdir wrapper which just returns the file name.
********************************************************************/
-char *vfs_readdirname(connection_struct *conn, void *p)
+char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
{
SMB_STRUCT_DIRENT *ptr= NULL;
char *dname;
if (!p)
return(NULL);
- ptr = SMB_VFS_READDIR(conn, (DIR *)p);
+ ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
if (!ptr)
return(NULL);
int vfs_ChDir(connection_struct *conn, const char *path)
{
int res;
- static char *LastDir = NULL;
if (!LastDir) {
LastDir = SMB_STRDUP("");
format. Note this can be called with conn == NULL.
********************************************************************/
-struct getwd_cache_key {
- SMB_DEV_T dev;
- SMB_INO_T ino;
-};
-
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
{
char s[PATH_MAX+1];
SMB_STRUCT_STAT st, st2;
char *result;
DATA_BLOB cache_value;
- struct getwd_cache_key key;
+ struct file_id key;
*s = 0;
goto nocache;
}
- ZERO_STRUCT(key); /* unlikely, but possible padding */
- key.dev = st.st_dev;
- key.ino = st.st_ino;
+ key = vfs_file_id_from_sbuf(conn, &st);
if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
&& (cache_value.data[cache_value.length-1] == '\0'));
if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0)
- && (st.st_dev == st2.st_dev) && (st.st_ino == st2.st_ino)
- && (S_ISDIR(st.st_mode))) {
+ && (st.st_ex_dev == st2.st_ex_dev) && (st.st_ex_ino == st2.st_ex_ino)
+ && (S_ISDIR(st.st_ex_mode))) {
/*
* Ok, we're done
*/
}
if (lp_getwd_cache() && VALID_STAT(st)) {
- ZERO_STRUCT(key); /* unlikely, but possible padding */
- key.dev = st.st_dev;
- key.ino = st.st_ino;
+ key = vfs_file_id_from_sbuf(conn, &st);
memcache_add(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
bool free_resolved_name = False;
#endif
char *resolved_name = NULL;
- size_t con_path_len = strlen(conn->connectpath);
char *p = NULL;
DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
}
/* Check for widelinks allowed. */
- if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) {
- DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
- if (free_resolved_name) {
- SAFE_FREE(resolved_name);
- }
- return NT_STATUS_ACCESS_DENIED;
+ if (!lp_widelinks(SNUM(conn))) {
+ const char *conn_rootdir;
+
+ conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
+ if (conn_rootdir == NULL) {
+ DEBUG(2, ("check_reduced_name: Could not get conn_rootdir\n"));
+ if (free_resolved_name) {
+ SAFE_FREE(resolved_name);
+ }
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (strncmp(conn_rootdir, resolved_name,
+ strlen(conn_rootdir)) != 0) {
+ DEBUG(2, ("reduce_name: Bad access attempt: %s is "
+ "a symlink outside the share path",
+ fname));
+ if (free_resolved_name) {
+ SAFE_FREE(resolved_name);
+ }
+ return NT_STATUS_ACCESS_DENIED;
+ }
}
/* Check if we are allowing users to follow symlinks */
if (!lp_symlinks(SNUM(conn))) {
SMB_STRUCT_STAT statbuf;
if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
- (S_ISLNK(statbuf.st_mode)) ) {
+ (S_ISLNK(statbuf.st_ex_mode)) ) {
if (free_resolved_name) {
SAFE_FREE(resolved_name);
}