summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/include/smb_interfaces.h2
-rw-r--r--source4/ntvfs/common/opendb.c35
-rw-r--r--source4/ntvfs/posix/pvfs_flush.c4
-rw-r--r--source4/ntvfs/posix/pvfs_lock.c21
-rw-r--r--source4/ntvfs/posix/pvfs_open.c262
-rw-r--r--source4/ntvfs/posix/pvfs_qfileinfo.c16
-rw-r--r--source4/ntvfs/posix/pvfs_read.c8
-rw-r--r--source4/ntvfs/posix/pvfs_seek.c12
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c93
-rw-r--r--source4/ntvfs/posix/pvfs_write.c8
-rw-r--r--source4/ntvfs/posix/vfs_posix.c1
-rw-r--r--source4/ntvfs/posix/vfs_posix.h56
12 files changed, 310 insertions, 208 deletions
diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h
index 434f9513d2..acc2d503bb 100644
--- a/source4/include/smb_interfaces.h
+++ b/source4/include/smb_interfaces.h
@@ -794,7 +794,7 @@ union smb_setfileinfo {
enum smb_setfileinfo_level level;
union setfileinfo_file file;
- struct {
+ struct smb_rename_information {
uint8_t overwrite;
uint32_t root_fid;
const char *new_name;
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index a1d4ed1ddb..a07b657c33 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -44,7 +44,6 @@
struct odb_context {
struct tdb_wrap *w;
servid_t server;
- uint16_t tid;
struct messaging_context *messaging_ctx;
};
@@ -54,8 +53,7 @@ struct odb_context {
*/
struct odb_entry {
servid_t server;
- uint16_t tid;
- uint16_t fnum;
+ void *file_handle;
uint32_t share_access;
uint32_t create_options;
uint32_t access_mask;
@@ -78,7 +76,7 @@ struct odb_lock {
talloc_free(). We need the messaging_ctx to allow for pending open
notifications.
*/
-struct odb_context *odb_init(TALLOC_CTX *mem_ctx, servid_t server, uint16_t tid,
+struct odb_context *odb_init(TALLOC_CTX *mem_ctx, servid_t server,
struct messaging_context *messaging_ctx)
{
char *path;
@@ -100,7 +98,6 @@ struct odb_context *odb_init(TALLOC_CTX *mem_ctx, servid_t server, uint16_t tid,
}
odb->server = server;
- odb->tid = tid;
odb->messaging_ctx = messaging_ctx;
return odb;
@@ -205,7 +202,7 @@ static BOOL share_conflict(struct odb_entry *e1, struct odb_entry *e2)
register an open file in the open files database. This implements the share_access
rules
*/
-NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum,
+NTSTATUS odb_open_file(struct odb_lock *lck, void *file_handle,
uint32_t share_access, uint32_t create_options,
uint32_t access_mask)
{
@@ -219,8 +216,7 @@ NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum,
dbuf = tdb_fetch(odb->w->tdb, lck->key);
e.server = odb->server;
- e.tid = odb->tid;
- e.fnum = fnum;
+ e.file_handle = file_handle;
e.share_access = share_access;
e.create_options = create_options;
e.access_mask = access_mask;
@@ -276,8 +272,7 @@ NTSTATUS odb_open_file_pending(struct odb_lock *lck, void *private)
dbuf = tdb_fetch(odb->w->tdb, lck->key);
e.server = odb->server;
- e.tid = odb->tid;
- e.fnum = 0;
+ e.file_handle = NULL;
e.share_access = 0;
e.create_options = 0;
e.access_mask = 0;
@@ -314,7 +309,7 @@ NTSTATUS odb_open_file_pending(struct odb_lock *lck, void *private)
/*
remove a opendb entry
*/
-NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
+NTSTATUS odb_close_file(struct odb_lock *lck, void *file_handle)
{
struct odb_context *odb = lck->odb;
TDB_DATA dbuf;
@@ -344,9 +339,8 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
/* find the entry, and delete it */
for (i=0;i<count;i++) {
- if (fnum == elist[i].fnum &&
- odb->server == elist[i].server &&
- odb->tid == elist[i].tid) {
+ if (file_handle == elist[i].file_handle &&
+ odb->server == elist[i].server) {
if (i < count-1) {
memmove(elist+i, elist+i+1,
(count - (i+1)) * sizeof(struct odb_entry));
@@ -399,8 +393,7 @@ NTSTATUS odb_remove_pending(struct odb_lock *lck, void *private)
/* find the entry, and delete it */
for (i=0;i<count;i++) {
if (private == elist[i].notify_ptr &&
- odb->server == elist[i].server &&
- odb->tid == elist[i].tid) {
+ odb->server == elist[i].server) {
if (i < count-1) {
memmove(elist+i, elist+i+1,
(count - (i+1)) * sizeof(struct odb_entry));
@@ -434,7 +427,7 @@ NTSTATUS odb_remove_pending(struct odb_lock *lck, void *private)
update create options on an open file
*/
NTSTATUS odb_set_create_options(struct odb_lock *lck,
- uint16_t fnum, uint32_t create_options)
+ void *file_handle, uint32_t create_options)
{
struct odb_context *odb = lck->odb;
TDB_DATA dbuf;
@@ -452,9 +445,8 @@ NTSTATUS odb_set_create_options(struct odb_lock *lck,
/* find the entry, and modify it */
for (i=0;i<count;i++) {
- if (fnum == elist[i].fnum &&
- odb->server == elist[i].server &&
- odb->tid == elist[i].tid) {
+ if (file_handle == elist[i].file_handle &&
+ odb->server == elist[i].server) {
elist[i].create_options = create_options;
break;
}
@@ -503,8 +495,7 @@ NTSTATUS odb_can_open(struct odb_context *odb, DATA_BLOB *key,
}
e.server = odb->server;
- e.tid = odb->tid;
- e.fnum = -1;
+ e.file_handle = NULL;
e.share_access = share_access;
e.create_options = create_options;
e.access_mask = access_mask;
diff --git a/source4/ntvfs/posix/pvfs_flush.c b/source4/ntvfs/posix/pvfs_flush.c
index 6195d254ff..66a0cc5edf 100644
--- a/source4/ntvfs/posix/pvfs_flush.c
+++ b/source4/ntvfs/posix/pvfs_flush.c
@@ -28,11 +28,11 @@
*/
static void pvfs_flush_file(struct pvfs_state *pvfs, struct pvfs_file *f)
{
- if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
return;
}
if (pvfs->flags & PVFS_FLAG_STRICT_SYNC) {
- fsync(f->fd);
+ fsync(f->handle->fd);
}
}
diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c
index c8fc6c2de3..a2691cb550 100644
--- a/source4/ntvfs/posix/pvfs_lock.c
+++ b/source4/ntvfs/posix/pvfs_lock.c
@@ -41,7 +41,7 @@ NTSTATUS pvfs_check_lock(struct pvfs_state *pvfs,
}
return brl_locktest(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
f->fnum,
smbpid,
offset, count, rw);
@@ -73,7 +73,7 @@ static void pvfs_lock_async_failed(struct pvfs_state *pvfs,
/* undo the locks we just did */
for (i=i-1;i>=0;i--) {
brl_unlock(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
locks[i].pid,
f->fnum,
locks[i].offset,
@@ -118,7 +118,7 @@ static void pvfs_pending_lock_continue(void *private, enum pvfs_wait_notice reas
DLIST_REMOVE(f->pending_list, pending);
status = brl_lock(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
req->smbpid,
f->fnum,
locks[pending->pending_lock].offset,
@@ -133,7 +133,8 @@ static void pvfs_pending_lock_continue(void *private, enum pvfs_wait_notice reas
don't need the pending lock any more */
if (NT_STATUS_IS_OK(status) || timed_out) {
NTSTATUS status2;
- status2 = brl_remove_pending(pvfs->brl_context, &f->locking_key, pending);
+ status2 = brl_remove_pending(pvfs->brl_context,
+ &f->handle->locking_key, pending);
if (!NT_STATUS_IS_OK(status2)) {
DEBUG(0,("pvfs_lock: failed to remove pending lock - %s\n", nt_errstr(status2)));
}
@@ -170,7 +171,7 @@ static void pvfs_pending_lock_continue(void *private, enum pvfs_wait_notice reas
}
status = brl_lock(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
req->smbpid,
f->fnum,
locks[i].offset,
@@ -214,7 +215,7 @@ void pvfs_lock_close(struct pvfs_state *pvfs, struct pvfs_file *f)
if (f->lock_count || f->pending_list) {
DEBUG(5,("pvfs_lock: removing %.0f locks on close\n",
(double)f->lock_count));
- brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum);
+ brl_close(f->pvfs->brl_context, &f->handle->locking_key, f->fnum);
f->lock_count = 0;
}
@@ -289,7 +290,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_HANDLE;
}
- if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
@@ -337,7 +338,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
for (i=0;i<lck->lockx.in.ulock_cnt;i++) {
status = brl_unlock(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
locks[i].pid,
f->fnum,
locks[i].offset,
@@ -356,7 +357,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
}
status = brl_lock(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
locks[i].pid,
f->fnum,
locks[i].offset,
@@ -379,7 +380,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
/* undo the locks we just did */
for (i=i-1;i>=0;i--) {
brl_unlock(pvfs->brl_context,
- &f->locking_key,
+ &f->handle->locking_key,
locks[i].pid,
f->fnum,
locks[i].offset,
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 1a25f57df1..5411f83e8d 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -47,6 +47,10 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs,
return NULL;
}
+ if (f->fnum != fnum) {
+ smb_panic("pvfs_find_fd: idtree_fnum corruption\n");
+ }
+
if (req->session != f->session) {
DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n",
fnum));
@@ -60,22 +64,31 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs,
/*
cleanup a open directory handle
*/
-static int pvfs_dir_fd_destructor(void *p)
+static int pvfs_dir_handle_destructor(void *p)
{
- struct pvfs_file *f = p;
- DLIST_REMOVE(f->pvfs->open_files, f);
- idr_remove(f->pvfs->idtree_fnum, f->fnum);
+ struct pvfs_file_handle *h = p;
- if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
- if (rmdir(f->name->full_name) != 0) {
+ if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+ if (rmdir(h->name->full_name) != 0) {
DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n",
- f->name->full_name, strerror(errno)));
+ h->name->full_name, strerror(errno)));
}
}
return 0;
}
+/*
+ cleanup a open directory fnum
+*/
+static int pvfs_dir_fnum_destructor(void *p)
+{
+ struct pvfs_file *f = p;
+ DLIST_REMOVE(f->pvfs->open_files, f);
+ idr_remove(f->pvfs->idtree_fnum, f->fnum);
+ return 0;
+}
+
/*
open a directory
@@ -124,34 +137,41 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
return NT_STATUS_NO_MEMORY;
}
+ f->handle = talloc_p(f, struct pvfs_file_handle);
+ if (f->handle == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX);
if (fnum == -1) {
return NT_STATUS_TOO_MANY_OPENED_FILES;
}
- f->fnum = fnum;
- f->fd = -1;
- f->name = talloc_steal(f, name);
- f->session = req->session;
- f->smbpid = req->smbpid;
- f->pvfs = pvfs;
+ f->fnum = fnum;
+ f->session = req->session;
+ f->smbpid = req->smbpid;
+ f->pvfs = pvfs;
f->pending_list = NULL;
- f->lock_count = 0;
- f->locking_key = data_blob(NULL, 0);
- f->create_options = io->generic.in.create_options;
- f->share_access = io->generic.in.share_access;
- f->seek_offset = 0;
- f->position = 0;
- f->mode = 0;
+ f->lock_count = 0;
+
+ f->handle->pvfs = pvfs;
+ f->handle->name = talloc_steal(f->handle, name);
+ f->handle->fd = -1;
+ f->handle->locking_key = data_blob(NULL, 0);
+ f->handle->create_options = io->generic.in.create_options;
+ f->handle->share_access = io->generic.in.share_access;
+ f->handle->seek_offset = 0;
+ f->handle->position = 0;
+ f->handle->mode = 0;
DLIST_ADD(pvfs->open_files, f);
/* TODO: should we check in the opendb? Do directory opens
follow the share_access rules? */
-
- /* setup a destructor to avoid leaks on abnormal termination */
- talloc_set_destructor(f, pvfs_dir_fd_destructor);
+ /* setup destructors to avoid leaks on abnormal termination */
+ talloc_set_destructor(f->handle, pvfs_dir_handle_destructor);
+ talloc_set_destructor(f, pvfs_dir_fnum_destructor);
if (!name->exists) {
uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY;
@@ -193,51 +213,61 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
return NT_STATUS_OK;
}
-
/*
- by using a destructor we make sure that abnormal cleanup will not
- leak file descriptors (assuming at least the top level pointer is freed, which
- will cascade down to here)
+ destroy a struct pvfs_file_handle
*/
-static int pvfs_fd_destructor(void *p)
+static int pvfs_handle_destructor(void *p)
{
- struct pvfs_file *f = p;
- struct odb_lock *lck;
- NTSTATUS status;
-
- DLIST_REMOVE(f->pvfs->open_files, f);
-
- pvfs_lock_close(f->pvfs, f);
+ struct pvfs_file_handle *h = p;
- if (f->fd != -1) {
- close(f->fd);
- f->fd = -1;
+ if (h->fd != -1) {
+ if (close(h->fd) != 0) {
+ DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n",
+ h->fd, h->name->full_name, strerror(errno)));
+ }
+ h->fd = -1;
}
- idr_remove(f->pvfs->idtree_fnum, f->fnum);
-
- if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
- if (unlink(f->name->full_name) != 0) {
+ if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+ if (unlink(h->name->full_name) != 0) {
DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",
- f->name->full_name, strerror(errno)));
+ h->name->full_name, strerror(errno)));
}
}
- lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key);
- if (lck == NULL) {
- DEBUG(0,("Unable to lock opendb for close\n"));
- return 0;
- }
+ if (h->have_opendb_entry) {
+ struct odb_lock *lck;
+ NTSTATUS status;
- if (f->have_opendb_entry) {
- status = odb_close_file(lck, f->fnum);
+ lck = odb_lock(h, h->pvfs->odb_context, &h->locking_key);
+ if (lck == NULL) {
+ DEBUG(0,("Unable to lock opendb for close\n"));
+ return 0;
+ }
+
+ status = odb_close_file(lck, h);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
- f->name->full_name, nt_errstr(status)));
+ h->name->full_name, nt_errstr(status)));
}
+
+ talloc_free(lck);
}
- talloc_free(lck);
+ return 0;
+}
+
+
+/*
+ destroy a struct pvfs_file
+*/
+static int pvfs_fnum_destructor(void *p)
+{
+ struct pvfs_file *f = p;
+
+ DLIST_REMOVE(f->pvfs->open_files, f);
+ pvfs_lock_close(f->pvfs, f);
+ idr_remove(f->pvfs->idtree_fnum, f->fnum);
return 0;
}
@@ -310,6 +340,11 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
return NT_STATUS_NO_MEMORY;
}
+ f->handle = talloc_p(f, struct pvfs_file_handle);
+ if (f->handle == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_NEW_FNUM, UINT16_MAX);
if (fnum == -1) {
return NT_STATUS_TOO_MANY_OPENED_FILES;
@@ -343,7 +378,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
/* form the lock context used for byte range locking and
opendb locking */
- status = pvfs_locking_key(name, f, &f->locking_key);
+ status = pvfs_locking_key(name, f->handle, &f->handle->locking_key);
if (!NT_STATUS_IS_OK(status)) {
idr_remove(pvfs->idtree_fnum, fnum);
close(fd);
@@ -351,7 +386,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
}
/* grab a lock on the open file record */
- lck = odb_lock(req, pvfs->odb_context, &f->locking_key);
+ lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key);
if (lck == NULL) {
DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
name->full_name));
@@ -362,7 +397,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- status = odb_open_file(lck, fnum, share_access, create_options, access_mask);
+ status = odb_open_file(lck, f->handle,
+ share_access, create_options, access_mask);
talloc_free(lck);
if (!NT_STATUS_IS_OK(status)) {
/* bad news, we must have hit a race */
@@ -372,26 +408,29 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
}
f->fnum = fnum;
- f->fd = fd;
- f->name = talloc_steal(f, name);
f->session = req->session;
f->smbpid = req->smbpid;
f->pvfs = pvfs;
f->pending_list = NULL;
f->lock_count = 0;
- f->create_options = io->generic.in.create_options;
- f->share_access = io->generic.in.share_access;
- f->access_mask = access_mask;
- f->seek_offset = 0;
- f->position = 0;
- f->mode = 0;
- f->have_opendb_entry = True;
+
+ f->handle->pvfs = pvfs;
+ f->handle->name = talloc_steal(f->handle, name);
+ f->handle->fd = fd;
+ f->handle->create_options = io->generic.in.create_options;
+ f->handle->share_access = io->generic.in.share_access;
+ f->handle->access_mask = access_mask;
+ f->handle->seek_offset = 0;
+ f->handle->position = 0;
+ f->handle->mode = 0;
+ f->handle->have_opendb_entry = True;
DLIST_ADD(pvfs->open_files, f);
/* setup a destructor to avoid file descriptor leaks on
abnormal termination */
- talloc_set_destructor(f, pvfs_fd_destructor);
+ talloc_set_destructor(f, pvfs_fnum_destructor);
+ talloc_set_destructor(f->handle, pvfs_handle_destructor);
io->generic.out.oplock_level = NO_OPLOCK;
io->generic.out.fnum = f->fnum;
@@ -518,7 +557,9 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
r->ntvfs = ntvfs;
r->req = req;
r->io = io;
- r->locking_key = data_blob_talloc(r, f->locking_key.data, f->locking_key.length);
+ r->locking_key = data_blob_talloc(r,
+ f->handle->locking_key.data,
+ f->handle->locking_key.length);
end_time = timeval_add(&req->request_time, 0, pvfs->sharing_violation_delay);
@@ -714,37 +755,44 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
return NT_STATUS_NO_MEMORY;
}
+ f->handle = talloc_p(f, struct pvfs_file_handle);
+ if (f->handle == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
/* allocate a fnum */
fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_FILE_FNUM, UINT16_MAX);
if (fnum == -1) {
return NT_STATUS_TOO_MANY_OPENED_FILES;
}
- f->fnum = fnum;
- f->fd = -1;
- f->name = talloc_steal(f, name);
- f->session = req->session;
- f->smbpid = req->smbpid;
- f->pvfs = pvfs;
+ f->fnum = fnum;
+ f->session = req->session;
+ f->smbpid = req->smbpid;
+ f->pvfs = pvfs;
f->pending_list = NULL;
- f->lock_count = 0;
- f->create_options = io->generic.in.create_options;
- f->share_access = io->generic.in.share_access;
- f->access_mask = access_mask;
- f->seek_offset = 0;
- f->position = 0;
- f->have_opendb_entry = False;
+ f->lock_count = 0;
+
+ f->handle->pvfs = pvfs;
+ f->handle->fd = -1;
+ f->handle->name = talloc_steal(f->handle, name);
+ f->handle->create_options = io->generic.in.create_options;
+ f->handle->share_access = io->generic.in.share_access;
+ f->handle->access_mask = access_mask;
+ f->handle->seek_offset = 0;
+ f->handle->position = 0;
+ f->handle->have_opendb_entry = False;
/* form the lock context used for byte range locking and
opendb locking */
- status = pvfs_locking_key(name, f, &f->locking_key);
+ status = pvfs_locking_key(name, f->handle, &f->handle->locking_key);
if (!NT_STATUS_IS_OK(status)) {
idr_remove(pvfs->idtree_fnum, f->fnum);
return status;
}
/* get a lock on this file before the actual open */
- lck = odb_lock(req, pvfs->odb_context, &f->locking_key);
+ lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key);
if (lck == NULL) {
DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
name->full_name));
@@ -758,11 +806,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
/* setup a destructor to avoid file descriptor leaks on
abnormal termination */
- talloc_set_destructor(f, pvfs_fd_destructor);
+ talloc_set_destructor(f, pvfs_fnum_destructor);
+ talloc_set_destructor(f->handle, pvfs_handle_destructor);
/* see if we are allowed to open at the same time as existing opens */
- status = odb_open_file(lck, f->fnum, share_access, create_options, access_mask);
+ status = odb_open_file(lck, f->handle,
+ share_access, create_options, access_mask);
/* on a sharing violation we need to retry when the file is closed by
the other user, or after 1 second */
@@ -776,19 +826,19 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
return status;
}
- f->have_opendb_entry = True;
+ f->handle->have_opendb_entry = True;
/* do the actual open */
- fd = open(f->name->full_name, flags);
+ fd = open(f->handle->name->full_name, flags);
if (fd == -1) {
talloc_free(lck);
return pvfs_map_errno(f->pvfs, errno);
}
- f->fd = fd;
+ f->handle->fd = fd;
/* re-resolve the open fd */
- status = pvfs_resolve_name_fd(f->pvfs, fd, f->name);
+ status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(lck);
return status;
@@ -816,13 +866,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
io->generic.out.oplock_level = NO_OPLOCK;
io->generic.out.fnum = f->fnum;
io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
- io->generic.out.create_time = f->name->dos.create_time;
- io->generic.out.access_time = f->name->dos.access_time;
- io->generic.out.write_time = f->name->dos.write_time;
- io->generic.out.change_time = f->name->dos.change_time;
- io->generic.out.attrib = f->name->dos.attrib;
- io->generic.out.alloc_size = f->name->dos.alloc_size;
- io->generic.out.size = f->name->st.st_size;
+ io->generic.out.create_time = name->dos.create_time;
+ io->generic.out.access_time = name->dos.access_time;
+ io->generic.out.write_time = name->dos.write_time;
+ io->generic.out.change_time = name->dos.change_time;
+ io->generic.out.attrib = name->dos.attrib;
+ io->generic.out.alloc_size = name->dos.alloc_size;
+ io->generic.out.size = name->st.st_size;
io->generic.out.file_type = FILE_TYPE_DISK;
io->generic.out.ipc_state = 0;
io->generic.out.is_directory = 0;
@@ -842,7 +892,6 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
{
struct pvfs_state *pvfs = ntvfs->private_data;
struct pvfs_file *f;
- NTSTATUS status;
struct utimbuf unix_times;
if (io->generic.level == RAW_CLOSE_SPLCLOSE) {
@@ -861,21 +910,12 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
if (!null_time(io->close.in.write_time)) {
unix_times.actime = 0;
unix_times.modtime = io->close.in.write_time;
- utime(f->name->full_name, &unix_times);
+ utime(f->handle->name->full_name, &unix_times);
}
- if (f->fd != -1 &&
- close(f->fd) == -1) {
- status = pvfs_map_errno(pvfs, errno);
- } else {
- status = NT_STATUS_OK;
- }
- f->fd = -1;
-
- /* the destructor takes care of the rest */
talloc_free(f);
- return status;
+ return NT_STATUS_OK;
}
@@ -929,23 +969,23 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs,
struct odb_lock *lck;
NTSTATUS status;
- if (f->create_options == create_options) {
+ if (f->handle->create_options == create_options) {
return NT_STATUS_OK;
}
- if ((f->name->dos.attrib & FILE_ATTRIBUTE_READONLY) &&
+ if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) &&
(create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
return NT_STATUS_CANNOT_DELETE;
}
- lck = odb_lock(req, pvfs->odb_context, &f->locking_key);
+ lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key);
if (lck == NULL) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- status = odb_set_create_options(lck, f->fnum, create_options);
+ status = odb_set_create_options(lck, f->handle, create_options);
if (NT_STATUS_IS_OK(status)) {
- f->create_options = create_options;
+ f->handle->create_options = create_options;
}
return status;
diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c
index 5847b1a2cc..fee3b19c9f 100644
--- a/source4/ntvfs/posix/pvfs_qfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_qfileinfo.c
@@ -242,27 +242,29 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
{
struct pvfs_state *pvfs = ntvfs->private_data;
struct pvfs_file *f;
+ struct pvfs_file_handle *h;
NTSTATUS status;
f = pvfs_find_fd(pvfs, req, info->generic.in.fnum);
if (!f) {
return NT_STATUS_INVALID_HANDLE;
}
+ h = f->handle;
/* update the file information */
- status = pvfs_resolve_name_fd(pvfs, f->fd, f->name);
+ status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = pvfs_map_fileinfo(pvfs, req, f->name, info, f->fd);
+ status = pvfs_map_fileinfo(pvfs, req, h->name, info, h->fd);
/* a qfileinfo can fill in a bit more info than a qpathinfo -
now modify the levels that need to be fixed up */
switch (info->generic.level) {
case RAW_FILEINFO_STANDARD_INFO:
case RAW_FILEINFO_STANDARD_INFORMATION:
- if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+ if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
info->standard_info.out.delete_pending = 1;
info->standard_info.out.nlink--;
}
@@ -270,22 +272,22 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
case RAW_FILEINFO_ALL_INFO:
case RAW_FILEINFO_ALL_INFORMATION:
- if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+ if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
info->all_info.out.delete_pending = 1;
info->all_info.out.nlink--;
}
break;
case RAW_FILEINFO_POSITION_INFORMATION:
- info->position_information.out.position = f->position;
+ info->position_information.out.position = h->position;
break;
case RAW_FILEINFO_ACCESS_INFORMATION:
- info->access_information.out.access_flags = f->access_mask;
+ info->access_information.out.access_flags = h->access_mask;
break;
case RAW_FILEINFO_MODE_INFORMATION:
- info->mode_information.out.mode = f->mode;
+ info->mode_information.out.mode = h->mode;
break;
default:
diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c
index f5df26f3d1..b14a1e601c 100644
--- a/source4/ntvfs/posix/pvfs_read.c
+++ b/source4/ntvfs/posix/pvfs_read.c
@@ -46,7 +46,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_HANDLE;
}
- if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
@@ -54,7 +54,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs,
if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
mask |= SA_RIGHT_FILE_EXECUTE;
}
- if (!(f->access_mask & mask)) {
+ if (!(f->handle->access_mask & mask)) {
return NT_STATUS_ACCESS_DENIED;
}
@@ -71,7 +71,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs,
return status;
}
- ret = pread(f->fd,
+ ret = pread(f->handle->fd,
rd->readx.out.data,
maxcnt,
rd->readx.in.offset);
@@ -79,7 +79,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs,
return pvfs_map_errno(pvfs, errno);
}
- f->position = f->seek_offset = rd->readx.in.offset + ret;
+ f->handle->position = f->handle->seek_offset = rd->readx.in.offset + ret;
rd->readx.out.nread = ret;
rd->readx.out.remaining = 0xFFFF;
diff --git a/source4/ntvfs/posix/pvfs_seek.c b/source4/ntvfs/posix/pvfs_seek.c
index c90db952fc..c4dd30bd85 100644
--- a/source4/ntvfs/posix/pvfs_seek.c
+++ b/source4/ntvfs/posix/pvfs_seek.c
@@ -31,31 +31,33 @@ NTSTATUS pvfs_seek(struct ntvfs_module_context *ntvfs,
{
struct pvfs_state *pvfs = ntvfs->private_data;
struct pvfs_file *f;
+ struct pvfs_file_handle *h;
NTSTATUS status;
f = pvfs_find_fd(pvfs, req, io->in.fnum);
if (!f) {
return NT_STATUS_INVALID_HANDLE;
}
+ h = f->handle;
status = NT_STATUS_OK;
switch (io->in.mode) {
case SEEK_MODE_START:
- f->seek_offset = io->in.offset;
+ h->seek_offset = io->in.offset;
break;
case SEEK_MODE_CURRENT:
- f->seek_offset += io->in.offset;
+ h->seek_offset += io->in.offset;
break;
case SEEK_MODE_END:
- status = pvfs_resolve_name_fd(pvfs, f->fd, f->name);
- f->seek_offset = f->name->st.st_size + io->in.offset;
+ status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
+ h->seek_offset = h->name->st.st_size + io->in.offset;
break;
}
- io->out.offset = f->seek_offset;
+ io->out.offset = h->seek_offset;
return status;
}
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index 15b7f168f2..cad51c751c 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -27,6 +27,47 @@
/*
+ rename_information level
+*/
+static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
+ struct smbsrv_request *req,
+ struct pvfs_filename *name,
+ struct smb_rename_information *r)
+{
+#if 0
+ NTSTATUS status;
+ struct pvfs_filename *name2;
+ char *base_dir, *p;
+
+ /* renames are only allowed within a directory */
+ if (strchr_m(r->new_name, '\\')) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ /* don't allow this for now */
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ /* work out the base directory that the source file is in */
+ base_dir = talloc_strdup(name, name->full_name);
+ p = strrchr(base_dir, '/');
+ *p = 0;
+
+ /* resolve the new name */
+ status = pvfs_resolve_partial(pvfs, req, base_dir, r->new_name, &name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (name2->exists && !r->overwrite) {
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+#endif
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+/*
add a single DOS EA
*/
static NTSTATUS pvfs_setfileinfo_ea_set(struct pvfs_state *pvfs,
@@ -90,6 +131,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
struct pvfs_state *pvfs = ntvfs->private_data;
struct utimbuf unix_times;
struct pvfs_file *f;
+ struct pvfs_file_handle *h;
uint32_t create_options;
struct pvfs_filename newstats;
NTSTATUS status;
@@ -99,8 +141,10 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_HANDLE;
}
+ h = f->handle;
+
/* update the file information */
- status = pvfs_resolve_name_fd(pvfs, f->fd, f->name);
+ status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -108,7 +152,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
/* we take a copy of the current file stats, then update
newstats in each of the elements below. At the end we
compare, and make any changes needed */
- newstats = *f->name;
+ newstats = *h->name;
switch (info->generic.level) {
case RAW_SFILEINFO_SETATTR:
@@ -134,7 +178,8 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
break;
case RAW_SFILEINFO_EA_SET:
- return pvfs_setfileinfo_ea_set(pvfs, f->name, f->fd, &info->ea_set.in.ea);
+ return pvfs_setfileinfo_ea_set(pvfs, h->name, h->fd,
+ &info->ea_set.in.ea);
case RAW_SFILEINFO_BASIC_INFO:
case RAW_SFILEINFO_BASIC_INFORMATION:
@@ -157,10 +202,10 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
case RAW_SFILEINFO_DISPOSITION_INFO:
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
- if (!(f->access_mask & STD_RIGHT_DELETE_ACCESS)) {
+ if (!(h->access_mask & STD_RIGHT_DELETE_ACCESS)) {
return NT_STATUS_ACCESS_DENIED;
}
- create_options = f->create_options;
+ create_options = h->create_options;
if (info->disposition_info.in.delete_on_close) {
create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
} else {
@@ -182,7 +227,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
break;
case RAW_SFILEINFO_POSITION_INFORMATION:
- f->position = info->position_information.in.position;
+ h->position = info->position_information.in.position;
break;
case RAW_SFILEINFO_MODE_INFORMATION:
@@ -193,23 +238,27 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
info->mode_information.in.mode != 6) {
return NT_STATUS_INVALID_PARAMETER;
}
- f->mode = info->mode_information.in.mode;
+ h->mode = info->mode_information.in.mode;
break;
+ case RAW_SFILEINFO_RENAME_INFORMATION:
+ return pvfs_setfileinfo_rename(pvfs, req, h->name,
+ &info->rename_information.in);
+
default:
return NT_STATUS_INVALID_LEVEL;
}
/* possibly change the file size */
- if (newstats.st.st_size != f->name->st.st_size) {
+ if (newstats.st.st_size != h->name->st.st_size) {
int ret;
- if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ if (h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
- if (f->access_mask & SA_RIGHT_FILE_WRITE_APPEND) {
- ret = ftruncate(f->fd, newstats.st.st_size);
+ if (h->access_mask & SA_RIGHT_FILE_WRITE_APPEND) {
+ ret = ftruncate(h->fd, newstats.st.st_size);
} else {
- ret = truncate(f->name->full_name, newstats.st.st_size);
+ ret = truncate(h->name->full_name, newstats.st.st_size);
}
if (ret == -1) {
return pvfs_map_errno(pvfs, errno);
@@ -218,33 +267,33 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
/* possibly change the file timestamps */
ZERO_STRUCT(unix_times);
- if (newstats.dos.access_time != f->name->dos.access_time) {
+ if (newstats.dos.access_time != h->name->dos.access_time) {
unix_times.actime = nt_time_to_unix(newstats.dos.access_time);
}
- if (newstats.dos.write_time != f->name->dos.write_time) {
+ if (newstats.dos.write_time != h->name->dos.write_time) {
unix_times.modtime = nt_time_to_unix(newstats.dos.write_time);
}
if (unix_times.actime != 0 || unix_times.modtime != 0) {
- if (utime(f->name->full_name, &unix_times) == -1) {
+ if (utime(h->name->full_name, &unix_times) == -1) {
return pvfs_map_errno(pvfs, errno);
}
}
/* possibly change the attribute */
- if (newstats.dos.attrib != f->name->dos.attrib) {
+ if (newstats.dos.attrib != h->name->dos.attrib) {
mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
- if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ if (h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
/* ignore on directories for now */
return NT_STATUS_OK;
}
- if (fchmod(f->fd, mode) == -1) {
+ if (fchmod(h->fd, mode) == -1) {
return pvfs_map_errno(pvfs, errno);
}
}
- *f->name = newstats;
+ *h->name = newstats;
- return pvfs_dosattrib_save(pvfs, f->name, f->fd);
+ return pvfs_dosattrib_save(pvfs, h->name, h->fd);
}
@@ -349,6 +398,10 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
}
return NT_STATUS_OK;
+ case RAW_SFILEINFO_RENAME_INFORMATION:
+ return pvfs_setfileinfo_rename(pvfs, req, name,
+ &info->rename_information.in);
+
case RAW_SFILEINFO_DISPOSITION_INFO:
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
case RAW_SFILEINFO_POSITION_INFORMATION:
diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c
index ccf3a775a8..7b38123971 100644
--- a/source4/ntvfs/posix/pvfs_write.c
+++ b/source4/ntvfs/posix/pvfs_write.c
@@ -44,11 +44,11 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_HANDLE;
}
- if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
+ if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
- if (!(f->access_mask & SA_RIGHT_FILE_WRITE_APPEND)) {
+ if (!(f->handle->access_mask & SA_RIGHT_FILE_WRITE_APPEND)) {
return NT_STATUS_ACCESS_VIOLATION;
}
@@ -60,7 +60,7 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs,
return status;
}
- ret = pwrite(f->fd,
+ ret = pwrite(f->handle->fd,
wr->writex.in.data,
wr->writex.in.count,
wr->writex.in.offset);
@@ -71,7 +71,7 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs,
return map_nt_error_from_unix(errno);
}
- f->seek_offset = wr->writex.in.offset + ret;
+ f->handle->seek_offset = wr->writex.in.offset + ret;
wr->writex.out.nwritten = ret;
wr->writex.out.remaining = 0; /* should fill this in? */
diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c
index da4296d062..39f6717cae 100644
--- a/source4/ntvfs/posix/vfs_posix.c
+++ b/source4/ntvfs/posix/vfs_posix.c
@@ -108,7 +108,6 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
pvfs->odb_context = odb_init(pvfs,
pvfs->tcon->smb_conn->connection->server_id,
- pvfs->tcon->service,
pvfs->tcon->smb_conn->connection->messaging_ctx);
if (pvfs->odb_context == NULL) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 91940e6355..3f74de4b63 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -84,12 +84,45 @@ struct pvfs_filename {
};
+/* open file handle state - encapsulates the posix fd
+
+ Note that this is separated from the pvfs_file structure in order
+ to cope with the openx DENY_DOS semantics where a 2nd DENY_DOS open
+ on the same connection gets the same low level filesystem handle,
+ rather than a new handle
+*/
+struct pvfs_file_handle {
+ int fd;
+
+ struct pvfs_filename *name;
+
+ /* a unique file key to be used for file locking */
+ DATA_BLOB locking_key;
+
+ uint32_t create_options;
+ uint32_t share_access;
+ uint32_t access_mask;
+
+ /* this is set by the mode_information level. What does it do? */
+ uint32_t mode;
+
+ /* yes, we need 2 independent positions ... */
+ uint64_t seek_offset;
+ uint64_t position;
+
+ BOOL have_opendb_entry;
+
+ /* we need this hook back to our parent for lock destruction */
+ struct pvfs_state *pvfs;
+};
+
/* open file state */
struct pvfs_file {
struct pvfs_file *next, *prev;
- int fd;
+ struct pvfs_file_handle *handle;
uint16_t fnum;
- struct pvfs_filename *name;
+
+ struct pvfs_state *pvfs;
/* we need to remember the session it was opened on,
as it is illegal to operate on someone elses fnum */
@@ -99,31 +132,12 @@ struct pvfs_file {
opened the file so SMBexit works */
uint16_t smbpid;
- /* a unique file key to be used for file locking */
- DATA_BLOB locking_key;
-
- /* we need this hook back to our parent for lock destruction */
- struct pvfs_state *pvfs;
-
/* a list of pending locks - used for locking cancel operations */
struct pvfs_pending_lock *pending_list;
/* a count of active locks - used to avoid calling brl_close on
file close */
uint64_t lock_count;
-
- uint32_t create_options;
- uint32_t share_access;
- uint32_t access_mask;
-
- /* this is set by the mode_information level. What does it do? */
- uint32_t mode;
-
- /* yes, we need 2 independent positions ... */
- uint64_t seek_offset;
- uint64_t position;
-
- BOOL have_opendb_entry;
};