*/
#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;
}
- handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct);
+ handle = TALLOC_ZERO_P(conn, vfs_handle_struct);
if (!handle) {
DEBUG(0,("TALLOC_ZERO() failed!\n"));
goto fail;
memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops));
handle->conn = conn;
if (module_param) {
- handle->param = talloc_strdup(conn->mem_ctx, module_param);
+ handle->param = talloc_strdup(conn, module_param);
}
DLIST_ADD(conn->vfs_handles, handle);
#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 = (struct vfs_fsp_data *)TALLOC_ZERO(
- handle->conn->mem_ctx, sizeof(struct vfs_fsp_data) + ext_size);
+ handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
if (ext == NULL) {
return NULL;
}
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;
}
while (total < byte_count)
{
- ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total,
- byte_count - total);
+ ssize_t ret = SMB_VFS_READ(fsp, buf + total,
+ byte_count - total);
if (ret == 0) return total;
if (ret == -1) {
req->unread_bytes = 0;
return SMB_VFS_RECVFILE(smbd_server_fd(),
fsp,
- fsp->fh->fd,
(SMB_OFF_T)-1,
N);
}
while (total < N) {
- ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total);
+ ret = SMB_VFS_WRITE(fsp, buffer + total, N - total);
if (ret == -1)
return -1;
req->unread_bytes = 0;
return SMB_VFS_RECVFILE(smbd_server_fd(),
fsp,
- fsp->fh->fd,
offset,
N);
}
while (total < N) {
- ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total,
- N - total, offset + total);
+ ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
+ offset + total);
if (ret == -1)
return -1;
Returns 0 on success, -1 on failure.
****************************************************************************/
-int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len)
+int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
{
int ret;
SMB_STRUCT_STAT st;
connection_struct *conn = fsp->conn;
- SMB_BIG_UINT space_avail;
- SMB_BIG_UINT bsize,dfree,dsize;
-
- release_level_2_oplocks_on_change(fsp);
+ uint64_t space_avail;
+ uint64_t bsize,dfree,dsize;
/*
* Actually try and commit the space on disk....
return -1;
}
- ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
+ ret = SMB_VFS_FSTAT(fsp, &st);
if (ret == -1)
return ret;
- if (len == (SMB_BIG_UINT)st.st_size)
+ if (len == (uint64_t)st.st_size)
return 0;
- if (len < (SMB_BIG_UINT)st.st_size) {
+ if (len < (uint64_t)st.st_size) {
/* Shrink - use ftruncate. */
DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
fsp->fsp_name, (double)st.st_size ));
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
+
flush_write_cache(fsp, SIZECHANGE_FLUSH);
- if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, (SMB_OFF_T)len)) != -1) {
+ 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 /= 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 == (SMB_BIG_UINT)-1) {
+ if (space_avail == (uint64_t)-1) {
return -1;
}
{
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, fsp->fh->fd, len)) != -1) {
+ if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
set_filelen_write_cache(fsp, len);
notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_SIZE
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,fsp->fh->fd,&st);
+ ret = SMB_VFS_FSTAT(fsp, &st);
if (ret == -1) {
return ret;
}
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)));
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
+
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if (!sparse_buf) {
sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
if (!sparse_buf) {
errno = ENOMEM;
- return -1;
+ ret = -1;
+ goto out;
}
}
while (total < num_to_write) {
size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total));
- pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, sparse_buf, curr_write_size, offset + total);
+ pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
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;
}
/****************************************************************************
Transfer some data (n bytes) between two file_struct's.
****************************************************************************/
-static files_struct *in_fsp;
-static files_struct *out_fsp;
-
-static ssize_t read_fn(int fd, void *buf, size_t len)
+static ssize_t vfs_read_fn(void *file, void *buf, size_t len)
{
- return SMB_VFS_READ(in_fsp, fd, buf, len);
+ struct files_struct *fsp = (struct files_struct *)file;
+
+ return SMB_VFS_READ(fsp, buf, len);
}
-static ssize_t write_fn(int fd, const void *buf, size_t len)
+static ssize_t vfs_write_fn(void *file, const void *buf, size_t len)
{
- return SMB_VFS_WRITE(out_fsp, fd, buf, len);
+ struct files_struct *fsp = (struct files_struct *)file;
+
+ return SMB_VFS_WRITE(fsp, buf, len);
}
SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
{
- in_fsp = in;
- out_fsp = out;
-
- return transfer_file_internal(in_fsp->fh->fd, out_fsp->fh->fd, n, read_fn, write_fn);
+ return transfer_file_internal((void *)in, (void *)out, n,
+ vfs_read_fn, vfs_write_fn);
}
/*******************************************************************
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)),
}
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)),
return map_nt_error_from_unix(errno);
case ENOENT:
{
- TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ TALLOC_CTX *ctx = talloc_tos();
char *tmp_fname = NULL;
char *last_component = NULL;
/* Last component didn't exist. Remove it and try and canonicalise the directory. */
- tmp_fname = talloc_strdup(tmp_ctx, fname);
+ tmp_fname = talloc_strdup(ctx, fname);
if (!tmp_fname) {
- TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
p = strrchr_m(tmp_fname, '/');
last_component = p;
} else {
last_component = tmp_fname;
- tmp_fname = talloc_strdup(tmp_ctx,
+ tmp_fname = talloc_strdup(ctx,
".");
if (!tmp_fname) {
- TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
}
#endif
if (!resolved_name) {
DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
- TALLOC_FREE(tmp_ctx);
return map_nt_error_from_unix(errno);
}
- tmp_fname = talloc_asprintf(tmp_ctx,
+ tmp_fname = talloc_asprintf(ctx,
"%s/%s",
resolved_name,
last_component);
if (!tmp_fname) {
- TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
#ifdef REALPATH_TAKES_NULL
safe_strcpy(resolved_name_buf, tmp_fname, PATH_MAX);
resolved_name = resolved_name_buf;
#endif
- TALLOC_FREE(tmp_ctx);
break;
}
default: