1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r3615: split out struct pvfs_file_handle from struct pvfs_file. This is in

preparation for adding code to pass the BASE-DENY1 and BASE-DENYDOS
tests, which require a shared filesystem handle for some specific
combinations of two DENY_DOS opens on the same connection.
(This used to be commit 6e4fdf01d1)
This commit is contained in:
Andrew Tridgell 2004-11-08 03:54:12 +00:00 committed by Gerald (Jerry) Carter
parent ce51a06f02
commit 19fc6e8f51
12 changed files with 313 additions and 211 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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,19 +64,28 @@ 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_handle *h = p;
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",
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);
if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
if (rmdir(f->name->full_name) != 0) {
DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n",
f->name->full_name, strerror(errno)));
}
}
return 0;
}
@ -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;
struct pvfs_file_handle *h = p;
DLIST_REMOVE(f->pvfs->open_files, f);
pvfs_lock_close(f->pvfs, f);
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;

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -26,6 +26,47 @@
#include "librpc/gen_ndr/ndr_xattr.h"
/*
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
*/
@ -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:

View File

@ -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? */

View File

@ -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;

View File

@ -84,34 +84,21 @@ struct pvfs_filename {
};
/* open file state */
struct pvfs_file {
struct pvfs_file *next, *prev;
/* 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;
uint16_t fnum;
struct pvfs_filename *name;
/* we need to remember the session it was opened on,
as it is illegal to operate on someone elses fnum */
struct smbsrv_session *session;
/* we need to remember the client pid that
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;
@ -124,6 +111,33 @@ struct pvfs_file {
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;
struct pvfs_file_handle *handle;
uint16_t fnum;
struct pvfs_state *pvfs;
/* we need to remember the session it was opened on,
as it is illegal to operate on someone elses fnum */
struct smbsrv_session *session;
/* we need to remember the client pid that
opened the file so SMBexit works */
uint16_t smbpid;
/* 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;
};