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:
parent
ce51a06f02
commit
19fc6e8f51
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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? */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user