📄 pvfs_open.c
字号:
f->handle->have_opendb_entry = true; if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; } else if (oplock_granted != OPLOCK_NONE) { status = pvfs_setup_oplock(f, oplock_granted); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; } } stream_existed = name->stream_exists; /* if this was a stream create then create the stream as well */ if (!name->stream_exists) { status = pvfs_stream_create(pvfs, f->handle->name, fd); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; } if (stream_truncate) { status = pvfs_stream_truncate(pvfs, f->handle->name, fd, 0); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; } } } /* re-resolve the open fd */ status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; } if (f->handle->name->stream_id == 0 && (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE || io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) { /* for overwrite we need to replace file permissions */ uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; mode_t mode = pvfs_fileperms(pvfs, attrib); if (fchmod(fd, mode) == -1) { talloc_free(lck); return pvfs_map_errno(pvfs, errno); } name->dos.alloc_size = io->ntcreatex.in.alloc_size; name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; } } talloc_free(lck); status = ntvfs_handle_set_backend_data(h, ntvfs, f); NT_STATUS_NOT_OK_RETURN(status); /* mark the open as having completed fully, so delete on close can now be used */ f->handle->open_completed = true; io->generic.out.oplock_level = oplock_granted; io->generic.out.file.ntvfs = h; io->generic.out.create_action = stream_existed? create_action:NTCREATEX_ACTION_CREATED; 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; return NT_STATUS_OK;}/* close a file*/NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_close *io){ struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; struct utimbuf unix_times; if (io->generic.level == RAW_CLOSE_SPLCLOSE) { return NT_STATUS_DOS(ERRSRV, ERRerror); } if (io->generic.level != RAW_CLOSE_GENERIC) { return ntvfs_map_close(ntvfs, req, io); } f = pvfs_find_fd(pvfs, req, io->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } if (!null_time(io->generic.in.write_time)) { unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); } if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) { struct pvfs_filename *name; NTSTATUS status; struct pvfs_file_handle *h = f->handle; status = pvfs_resolve_name_handle(pvfs, h); if (!NT_STATUS_IS_OK(status)) { return status; } name = h->name; io->generic.out.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION; 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.alloc_size = name->dos.alloc_size; io->generic.out.size = name->st.st_size; io->generic.out.file_attr = name->dos.attrib; } else { ZERO_STRUCT(io->generic.out); } talloc_free(f); return NT_STATUS_OK;}/* logoff - close all file descriptors open by a vuid*/NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req){ struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; for (f=pvfs->files.list;f;f=next) { next = f->next; if (f->ntvfs->session_info == req->session_info) { talloc_free(f); } } return NT_STATUS_OK;}/* exit - close files for the current pid*/NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req){ struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; for (f=pvfs->files.list;f;f=next) { next = f->next; if (f->ntvfs->session_info == req->session_info && f->ntvfs->smbpid == req->smbpid) { talloc_free(f); } } return NT_STATUS_OK;}/* change the delete on close flag on an already open file*/NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_file *f, bool del_on_close){ struct odb_lock *lck; NTSTATUS status; if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && del_on_close) { return NT_STATUS_CANNOT_DELETE; } if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) && !pvfs_directory_empty(pvfs, f->handle->name)) { return NT_STATUS_DIRECTORY_NOT_EMPTY; } if (del_on_close) { f->handle->create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE; } else { f->handle->create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE; } lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); if (lck == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } status = odb_set_delete_on_close(lck, del_on_close); talloc_free(lck); return status;}/* determine if a file can be deleted, or if it is prevented by an already open file*/NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name, struct odb_lock **lckp){ NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; uint32_t share_access; uint32_t access_mask; bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_NO_MEMORY; } lck = odb_lock(req, pvfs->odb_context, &key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for can_delete\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; access_mask = SEC_STD_DELETE; delete_on_close = true; status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, NTCREATEX_DISP_OPEN, false); if (NT_STATUS_IS_OK(status)) { status = pvfs_access_check_simple(pvfs, req, name, access_mask); } /* * if it's a sharing violation or we got no oplock * only keep the lock if the caller requested access * to the lock */ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { if (lckp) { *lckp = lck; } else { talloc_free(lck); } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); if (lckp) { *lckp = NULL; } } else if (lckp) { *lckp = lck; } return status;}/* determine if a file can be renamed, or if it is prevented by an already open file*/NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name, struct odb_lock **lckp){ NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; uint32_t share_access; uint32_t access_mask; bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_NO_MEMORY; } lck = odb_lock(req, pvfs->odb_context, &key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for can_stat\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; access_mask = SEC_STD_DELETE; delete_on_close = false; status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, NTCREATEX_DISP_OPEN, false); /* * if it's a sharing violation or we got no oplock * only keep the lock if the caller requested access * to the lock */ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { if (lckp) { *lckp = lck; } else { talloc_free(lck); } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); if (lckp) { *lckp = NULL; } } else if (lckp) { *lckp = lck; } return status;}/* determine if the file size of a file can be changed, or if it is prevented by an already open file*/NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name, struct odb_lock **lckp){ NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; uint32_t share_access; uint32_t access_mask; bool break_to_none; bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_NO_MEMORY; } lck = odb_lock(req, pvfs->odb_context, &key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for can_stat\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; /* * I would have thought that we would need to pass * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too * * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions * to set the filesize. * * --metze */ access_mask = SEC_FILE_WRITE_ATTRIBUTE; delete_on_close = false; break_to_none = true; status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, NTCREATEX_DISP_OPEN, break_to_none); /* * if it's a sharing violation or we got no oplock * only keep the lock if the caller requested access * to the lock */ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { if (lckp) { *lckp = lck; } else { talloc_free(lck); } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); if (lckp) { *lckp = NULL; } } else if (lckp) { *lckp = lck; } return status;}/* determine if file meta data can be accessed, or if it is prevented by an already open file*/NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name){ NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; uint32_t share_access; uint32_t access_mask; bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_NO_MEMORY; } lck = odb_lock(req, pvfs->odb_context, &key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for can_stat\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; access_mask = SEC_FILE_READ_ATTRIBUTE; delete_on_close = false; status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, NTCREATEX_DISP_OPEN, false); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); } return status;}/* determine if delete on close is set on */bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h){ NTSTATUS status; bool del_on_close; status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, &del_on_close); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("WARNING: unable to determine delete on close status for open file\n")); return false; } return del_on_close;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -