static void linux_release_kernel_oplock(struct kernel_oplocks *ctx, files_struct *fsp, int oplock_type) { if (DEBUGLVL(10)) { /* * Check and print out the current kernel * oplock state of this file. */ int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); dbgtext("linux_release_kernel_oplock: file %s, file_id = %s " "gen_id = %lu has kernel oplock state " "of %x.\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, state ); } /* * Remove the kernel oplock on this file. */ if ( SMB_VFS_LINUX_SETLEASE(fsp, F_UNLCK) == -1) { if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); dbgtext("%s, file_id = %s, gen_id = %lu. " "Error was %s\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) ); } } }
/* * Deal with a reply when a break-to-level II was sent. */ bool downgrade_oplock(files_struct *fsp) { bool ret; struct share_mode_lock *lck; DEBUG(10, ("downgrade_oplock called for %s\n", fsp_str_dbg(fsp))); lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp_str_dbg(fsp))); return False; } ret = downgrade_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " "for file %s, %s, file_id %s\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), file_id_string_tos(&fsp->file_id))); } downgrade_file_oplock(fsp); ret = update_num_read_oplocks(fsp, lck); if (!ret) { DEBUG(0, ("%s: update_num_read_oplocks failed for " "file %s, %s, %s\n", __func__, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), file_id_string_tos(&fsp->file_id))); } TALLOC_FREE(lck); return ret; }
static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx, files_struct *fsp, int oplock_type) { struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data, struct irix_oplocks_context); if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, ctx->write_fd) == -1) { if(errno != EAGAIN) { DEBUG(0,("irix_set_kernel_oplock: Unable to get " "kernel oplock on file %s, file_id %s " "gen_id = %ul. Error was %s\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) )); } else { DEBUG(5,("irix_set_kernel_oplock: Refused oplock on " "file %s, fd = %d, file_id = %s, " "gen_id = %ul. Another process had the file " "open.\n", fsp_str_dbg(fsp), fsp->fh->fd, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id )); } return False; } DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s " "gen_id = %ul\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id)); return True; }
static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx, files_struct *fsp, int oplock_type) { if (DEBUGLVL(10)) { /* * Check and print out the current kernel * oplock state of this file. */ int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); dbgtext("irix_release_kernel_oplock: file %s, file_id = %s" "gen_id = %ul, has kernel oplock state " "of %x.\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, state ); } /* * Remove the kernel oplock on this file. */ if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) { if( DEBUGLVL( 0 )) { dbgtext("irix_release_kernel_oplock: Error when " "removing kernel oplock on file " ); dbgtext("%s, file_id = %s gen_id = %ul. " "Error was %s\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) ); } } }
static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, files_struct *fsp, DATA_BLOB *pblob) { int ret; int saved_errno = 0; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp_str_dbg(fsp))); become_root(); if (fsp->fh->fd != -1) { ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME, pblob->data, pblob->length, 0); } else { ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name, XATTR_NTACL_NAME, pblob->data, pblob->length, 0); } if (ret) { saved_errno = errno; } unbecome_root(); if (ret) { DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s" "with error %s\n", fsp_str_dbg(fsp), strerror(saved_errno) )); errno = saved_errno; return map_nt_error_from_unix(saved_errno); } return NT_STATUS_OK; }
/* * Deal with a reply when a break-to-level II was sent. */ bool downgrade_oplock(files_struct *fsp) { bool ret; struct share_mode_lock *lck; struct byte_range_lock *brl; DEBUG(10, ("downgrade_oplock called for %s\n", fsp_str_dbg(fsp))); lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp_str_dbg(fsp))); return False; } ret = downgrade_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " "for file %s, %s, file_id %s\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), file_id_string_tos(&fsp->file_id))); } downgrade_file_oplock(fsp); brl = brl_get_locks(talloc_tos(), fsp); if (brl != NULL) { brl_set_have_read_oplocks(brl, true); TALLOC_FREE(brl); } TALLOC_FREE(lck); return ret; }
NTSTATUS can_set_delete_on_close(files_struct *fsp, uint32 dosmode) { /* * Only allow delete on close for writable files. */ if ((dosmode & FILE_ATTRIBUTE_READONLY) && !lp_delete_readonly(SNUM(fsp->conn))) { DEBUG(10,("can_set_delete_on_close: file %s delete on close " "flag set but file attribute is readonly.\n", fsp_str_dbg(fsp))); return NT_STATUS_CANNOT_DELETE; } /* * Only allow delete on close for writable shares. */ if (!CAN_WRITE(fsp->conn)) { DEBUG(10,("can_set_delete_on_close: file %s delete on " "close flag set but write access denied on share.\n", fsp_str_dbg(fsp))); return NT_STATUS_ACCESS_DENIED; } /* * Only allow delete on close for files/directories opened with delete * intent. */ if (!(fsp->access_mask & DELETE_ACCESS)) { DEBUG(10,("can_set_delete_on_close: file %s delete on " "close flag set but delete access denied.\n", fsp_str_dbg(fsp))); return NT_STATUS_ACCESS_DENIED; } /* Don't allow delete on close for non-empty directories. */ if (fsp->is_directory) { SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name)); /* Or the root of a share. */ if (ISDOT(fsp->fsp_name->base_name)) { DEBUG(10,("can_set_delete_on_close: can't set delete on " "close for the root of a share.\n")); return NT_STATUS_ACCESS_DENIED; } return can_delete_directory(fsp->conn, fsp->fsp_name->base_name); } return NT_STATUS_OK; }
void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) { struct lock_ref_count_key tmp; struct db_record *rec; int lock_ref_count = 0; NTSTATUS status; rec = posix_pending_close_db->fetch_locked( posix_pending_close_db, talloc_tos(), locking_ref_count_key_fsp(fsp, &tmp)); SMB_ASSERT((rec != NULL) && (rec->value.dptr != NULL) && (rec->value.dsize == sizeof(lock_ref_count))); memcpy(&lock_ref_count, rec->value.dptr, sizeof(lock_ref_count)); SMB_ASSERT(lock_ref_count > 0); lock_ref_count -= dcount; status = rec->store(rec, make_tdb_data((uint8 *)&lock_ref_count, sizeof(lock_ref_count)), 0); SMB_ASSERT(NT_STATUS_IS_OK(status)); TALLOC_FREE(rec); DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n", fsp_str_dbg(fsp), lock_ref_count)); }
files_struct *file_find_dif(struct smbd_server_connection *sconn, struct file_id id, unsigned long gen_id) { int count=0; files_struct *fsp; if (gen_id == 0) { return NULL; } for (fsp=sconn->files; fsp; fsp=fsp->next,count++) { /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ if (file_id_equal(&fsp->file_id, &id) && fsp->fh->gen_id == gen_id ) { if (count > 10) { DLIST_PROMOTE(sconn->files, fsp); } /* Paranoia check. */ if ((fsp->fh->fd == -1) && (fsp->oplock_type != NO_OPLOCK)) { DEBUG(0,("file_find_dif: file %s file_id = " "%s, gen = %u oplock_type = %u is a " "stat open with oplock type !\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), (unsigned int)fsp->fh->gen_id, (unsigned int)fsp->oplock_type )); smb_panic("file_find_dif"); } return fsp; } } return NULL; }
static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { struct smb_filename *smb_fname_base = NULL; int ret = -1; struct stream_io *io = (struct stream_io *) VFS_FETCH_FSP_EXTENSION(handle, fsp); if (io == NULL || fsp->base_fsp == NULL) { return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); } DBG_DEBUG("streams_xattr_fstat called for %s\n", fsp_str_dbg(io->fsp)); if (!streams_xattr_recheck(io)) { return -1; } /* Create an smb_filename with stream_name == NULL. */ smb_fname_base = synthetic_smb_fname(talloc_tos(), io->base, NULL, NULL, fsp->fsp_name->flags); if (smb_fname_base == NULL) { errno = ENOMEM; return -1; } if (smb_fname_base->flags & SMB_FILENAME_POSIX_PATH) { ret = SMB_VFS_LSTAT(handle->conn, smb_fname_base); } else { ret = SMB_VFS_STAT(handle->conn, smb_fname_base); } *sbuf = smb_fname_base->st; if (ret == -1) { TALLOC_FREE(smb_fname_base); return -1; } sbuf->st_ex_size = get_xattr_size(handle->conn, smb_fname_base, io->xattr_name); if (sbuf->st_ex_size == -1) { TALLOC_FREE(smb_fname_base); SET_STAT_INVALID(*sbuf); return -1; } DEBUG(10, ("sbuf->st_ex_size = %d\n", (int)sbuf->st_ex_size)); sbuf->st_ex_ino = stream_inode(sbuf, io->xattr_name); sbuf->st_ex_mode &= ~S_IFMT; sbuf->st_ex_mode &= ~S_IFDIR; sbuf->st_ex_mode |= S_IFREG; sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1; TALLOC_FREE(smb_fname_base); return 0; }
int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) { int ret; SMB_STRUCT_STAT st; SMB_OFF_T offset; size_t total; size_t num_to_write; ssize_t pwrite_ret; ret = SMB_VFS_FSTAT(fsp, &st); if (ret == -1) { return ret; } if (len <= st.st_ex_size) { return 0; } DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to " "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp), (double)st.st_ex_size, (double)len, (double)(len - st.st_ex_size))); contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE); flush_write_cache(fsp, SIZECHANGE_FLUSH); if (!sparse_buf) { sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); if (!sparse_buf) { errno = ENOMEM; ret = -1; goto out; } }
static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, files_struct *fsp, DATA_BLOB *pblob) { uint8_t id_buf[16]; struct file_id id; TDB_DATA data; struct db_context *db = acl_db; struct db_record *rec; NTSTATUS status; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp_str_dbg(fsp))); status = vfs_stat_fsp(fsp); if (!NT_STATUS_IS_OK(status)) { return status; } id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); rec = dbwrap_fetch_locked(db, talloc_tos(), make_tdb_data(id_buf, sizeof(id_buf))); if (rec == NULL) { DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } data.dptr = pblob->data; data.dsize = pblob->length; return dbwrap_record_store(rec, data, 0); }
static void add_fd_to_close_entry(files_struct *fsp) { struct db_record *rec; uint8_t *new_data; NTSTATUS status; rec = posix_pending_close_db->fetch_locked( posix_pending_close_db, talloc_tos(), fd_array_key_fsp(fsp)); SMB_ASSERT(rec != NULL); new_data = talloc_array( rec, uint8_t, rec->value.dsize + sizeof(fsp->fh->fd)); SMB_ASSERT(new_data != NULL); memcpy(new_data, rec->value.dptr, rec->value.dsize); memcpy(new_data + rec->value.dsize, &fsp->fh->fd, sizeof(fsp->fh->fd)); status = rec->store( rec, make_tdb_data(new_data, rec->value.dsize + sizeof(fsp->fh->fd)), 0); SMB_ASSERT(NT_STATUS_IS_OK(status)); TALLOC_FREE(rec); DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", fsp->fh->fd, fsp_str_dbg(fsp))); }
void trigger_write_time_update_immediate(struct files_struct *fsp) { struct smb_file_time ft; if (fsp->posix_open) { /* Don't use delayed writes on POSIX files. */ return; } if (fsp->write_time_forced) { /* * No point - "sticky" write times * in effect. */ return; } TALLOC_FREE(fsp->update_write_time_event); DEBUG(5, ("Update write time immediate on %s\n", fsp_str_dbg(fsp))); /* After an immediate update, reset the trigger. */ fsp->update_write_time_triggered = true; fsp->update_write_time_on_close = false; ZERO_STRUCT(ft); ft.mtime = timespec_current(); /* Update the time in the open file db. */ (void)set_write_time(fsp->file_id, ft.mtime); /* Now set on disk - takes care of notify. */ (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false); }
ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) { ssize_t ret=0,readret; /* you can't read from print files */ if (fsp->print_file) { errno = EBADF; return -1; } /* * Serve from write cache if we can. */ if(read_from_write_cache(fsp, data, pos, n)) { fsp->fh->pos = pos + n; fsp->fh->position_information = fsp->fh->pos; return n; } flush_write_cache(fsp, READ_FLUSH); fsp->fh->pos = pos; if (n > 0) { #ifdef DMF_FIX int numretries = 3; tryagain: readret = SMB_VFS_PREAD(fsp,data,n,pos); if (readret == -1) { if ((errno == EAGAIN) && numretries) { DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); (void)sleep(10); --numretries; goto tryagain; } return -1; } #else /* NO DMF fix. */ readret = SMB_VFS_PREAD(fsp,data,n,pos); if (readret == -1) { return -1; } #endif if (readret > 0) { ret += readret; } } DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret)); fsp->fh->pos += ret; fsp->fh->position_information = fsp->fh->pos; return(ret); }
NTSTATUS smb2_read_complete(struct tevent_req *req, ssize_t nread, int err) { struct smbd_smb2_read_state *state = tevent_req_data(req, struct smbd_smb2_read_state); files_struct *fsp = state->fsp; if (nread < 0) { NTSTATUS status = map_nt_error_from_unix(err); DEBUG( 3,( "smb2_read_complete: file %s nread = %d. " "Error = %s (NTSTATUS %s)\n", fsp_str_dbg(fsp), (int)nread, strerror(err), nt_errstr(status))); return status; } if (nread == 0 && state->in_length != 0) { DEBUG(5,("smb2_read_complete: read_file[%s] end of file\n", fsp_str_dbg(fsp))); return NT_STATUS_END_OF_FILE; } if (nread < state->in_minimum) { DEBUG(5,("smb2_read_complete: read_file[%s] read less %d than " "minimum requested %u. Returning end of file\n", fsp_str_dbg(fsp), (int)nread, (unsigned int)state->in_minimum)); return NT_STATUS_END_OF_FILE; } DEBUG(3,("smbd_smb2_read: fnum=[%d/%s] length=%lu offset=%lu read=%lu\n", fsp->fnum, fsp_str_dbg(fsp), (unsigned long)state->in_length, (unsigned long)state->in_offset, (unsigned long)nread)); state->out_data.length = nread; state->out_remaining = 0; return NT_STATUS_OK; }
static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, files_struct *fsp, struct security_descriptor *parent_desc, bool is_directory) { TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status = NT_STATUS_OK; struct security_descriptor *psd = NULL; size_t size; if (!sd_has_inheritable_components(parent_desc, is_directory)) { return NT_STATUS_OK; } /* Create an inherited descriptor from the parent. */ if (DEBUGLEVEL >= 10) { DEBUG(10,("inherit_new_acl: parent acl for %s is:\n", fsp_str_dbg(fsp) )); NDR_PRINT_DEBUG(security_descriptor, parent_desc); } status = se_create_child_secdesc(ctx, &psd, &size, parent_desc, &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX], &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX], is_directory); if (!NT_STATUS_IS_OK(status)) { return status; } if (DEBUGLEVEL >= 10) { DEBUG(10,("inherit_new_acl: child acl for %s is:\n", fsp_str_dbg(fsp) )); NDR_PRINT_DEBUG(security_descriptor, parent_desc); } return SMB_VFS_FSET_NT_ACL(fsp, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), psd); }
static NTSTATUS update_write_time_on_close(struct files_struct *fsp) { struct smb_file_time ft; NTSTATUS status; struct share_mode_lock *lck = NULL; ZERO_STRUCT(ft); if (!fsp->update_write_time_on_close) { return NT_STATUS_OK; } if (null_timespec(fsp->close_write_time)) { fsp->close_write_time = timespec_current(); } /* Ensure we have a valid stat struct for the source. */ status = vfs_stat_fsp(fsp); if (!NT_STATUS_IS_OK(status)) { return status; } if (!VALID_STAT(fsp->fsp_name->st)) { /* if it doesn't seem to be a real file */ return NT_STATUS_OK; } /* On close if we're changing the real file time we * must update it in the open file db too. */ (void)set_write_time(fsp->file_id, fsp->close_write_time); lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL); if (lck) { /* Close write times overwrite sticky write times so we must replace any sticky write time here. */ if (!null_timespec(lck->changed_write_time)) { (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time); } TALLOC_FREE(lck); } ft.mtime = fsp->close_write_time; /* We must use NULL for the fsp handle here, as smb_set_file_time() checks the fsp access_mask, which may not include FILE_WRITE_ATTRIBUTES. As this is a close based update, we are not directly changing the file attributes from a client call, but indirectly from a write. */ status = smb_set_file_time(fsp->conn, NULL, fsp->fsp_name, &ft, false); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("update_write_time_on_close: smb_set_file_time " "on file %s returned %s\n", fsp_str_dbg(fsp), nt_errstr(status))); return status; } return status; }
static bool linux_set_kernel_oplock(struct kernel_oplocks *ctx, files_struct *fsp, int oplock_type) { if ( SMB_VFS_LINUX_SETLEASE(fsp, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " "fd = %d, file_id = %s. (%s)\n", fsp_str_dbg(fsp), fsp->fh->fd, file_id_string_tos(&fsp->file_id), strerror(errno))); return False; } DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, " "file_id = %s gen_id = %lu\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id)); return True; }
void smbd_cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck, enum file_close_type close_type) { struct smbd_server_connection *sconn = fsp->conn->sconn; struct blocking_lock_record *blr, *blr_cancelled, *next = NULL; if (sconn->using_smb2) { cancel_pending_lock_requests_by_fid_smb2(fsp, br_lck, close_type); return; } for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) { unsigned char locktype = 0; next = blr->next; if (blr->fsp->fnum != fsp->fnum) { continue; } if (blr->req->cmd == SMBlockingX) { locktype = CVAL(blr->req->vwv+3, 0); } DEBUG(10, ("remove_pending_lock_requests_by_fid - removing " "request type %d for file %s, %s\n", blr->req->cmd, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp))); blr_cancelled = blocking_lock_cancel_smb1(fsp, blr->smblctx, blr->offset, blr->count, blr->lock_flav, locktype, NT_STATUS_RANGE_NOT_LOCKED); SMB_ASSERT(blr_cancelled == blr); brl_lock_cancel(br_lck, blr->smblctx, messaging_server_id(sconn->msg_ctx), blr->offset, blr->count, blr->lock_flav, blr); /* We're closing the file fsp here, so ensure * we don't have a dangling pointer. */ blr->fsp = NULL; } }
static int wcp_file_size_change(files_struct *fsp) { int ret; write_cache *wcp = fsp->wcp; wcp->file_size = wcp->offset + wcp->data_size; ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size); if (ret == -1) { DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f " "error %s\n", fsp_str_dbg(fsp), (double)wcp->file_size, strerror(errno))); } return ret; }
int aixjfs2_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl) { struct acl *acl_aixc; acl_type_t acl_type_info; int rc; DEBUG(10, ("aixjfs2_sys_acl_set_fd invoked for %s", fsp_str_dbg(fsp))); rc = aixjfs2_query_acl_support(fsp->fsp_name->base_name, ACL_AIXC, &acl_type_info); if (rc) { DEBUG(8, ("jfs2_set_nt_acl: AIXC support not found\n")); return -1; } acl_aixc = aixacl_smb_to_aixacl(SMB_ACL_TYPE_ACCESS, theacl); if (!acl_aixc) return -1; rc = aclx_fput( fsp->fh->fd, SET_ACL, /* set only the ACL, not mode bits */ acl_type_info, acl_aixc, acl_aixc->acl_len, 0 ); if (rc) { DEBUG(2, ("aclx_fput failed with %s for %s\n", strerror(errno), fsp_str_dbg(fsp))); return -1; } return 0; }
bool remove_oplock(files_struct *fsp) { bool ret; struct share_mode_lock *lck; DEBUG(10, ("remove_oplock called for %s\n", fsp_str_dbg(fsp))); /* Remove the oplock flag from the sharemode. */ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp_str_dbg(fsp))); return False; } ret = remove_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("remove_oplock: failed to remove share oplock for " "file %s, %s, %s\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), file_id_string_tos(&fsp->file_id))); } release_file_oplock(fsp); ret = update_num_read_oplocks(fsp, lck); if (!ret) { DEBUG(0, ("%s: update_num_read_oplocks failed for " "file %s, %s, %s\n", __func__, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), file_id_string_tos(&fsp->file_id))); } TALLOC_FREE(lck); return ret; }
static void oplock_timeout_handler(struct tevent_context *ctx, struct tevent_timer *te, struct timeval now, void *private_data) { files_struct *fsp = (files_struct *)private_data; SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT); /* Remove the timed event handler. */ TALLOC_FREE(fsp->oplock_timeout); DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp_str_dbg(fsp))); remove_oplock(fsp); }
static files_struct *initial_break_processing( struct smbd_server_connection *sconn, struct file_id id, unsigned long file_id) { files_struct *fsp = NULL; DEBUG(3, ("initial_break_processing: called for %s/%u\n" "Current oplocks_open (exclusive = %d, levelII = %d)\n", file_id_string_tos(&id), (int)file_id, sconn->oplocks.exclusive_open, sconn->oplocks.level_II_open)); /* * We need to search the file open table for the * entry containing this dev and inode, and ensure * we have an oplock on it. */ fsp = file_find_dif(sconn, id, file_id); if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ DEBUG(3, ("initial_break_processing: cannot find open file " "with file_id %s gen_id = %lu, allowing break to " "succeed.\n", file_id_string_tos(&id), file_id)); return NULL; } /* Ensure we have an oplock on the file */ /* * There is a potential race condition in that an oplock could * have been broken due to another udp request, and yet there are * still oplock break messages being sent in the udp message * queue for this file. So return true if we don't have an oplock, * as we may have just freed it. */ if(fsp->oplock_type == NO_OPLOCK) { DEBUG(3, ("initial_break_processing: file %s (file_id = %s " "gen_id = %lu) has no oplock. Allowing break to " "succeed regardless.\n", fsp_str_dbg(fsp), file_id_string_tos(&id), fsp->fh->gen_id)); return NULL; } return fsp; }
int print_spool_write(files_struct *fsp, const char *data, uint32_t size, SMB_OFF_T offset, uint32_t *written) { SMB_STRUCT_STAT st; ssize_t n; int ret; *written = 0; /* first of all stat file to find out if it is still there. * spoolss may have deleted it to signal someone has killed * the job through it's interface */ if (sys_fstat(fsp->fh->fd, &st, false) != 0) { ret = errno; DEBUG(3, ("printfile_offset: sys_fstat failed on %s (%s)\n", fsp_str_dbg(fsp), strerror(ret))); return ret; } /* check if the file is unlinked, this will signal spoolss has * killed it, just return an error and close the file */ if (st.st_ex_nlink == 0) { close(fsp->fh->fd); return EBADF; } /* When print files go beyond 4GB, the 32-bit offset sent in * old SMBwrite calls is relative to the current 4GB chunk * we're writing to. * Discovered by Sebastian Kloska <*****@*****.**>. */ if (offset < 0xffffffff00000000LL) { offset = (st.st_ex_size & 0xffffffff00000000LL) + offset; } n = write_data_at_offset(fsp->fh->fd, data, size, offset); if (n == -1) { ret = errno; print_spool_terminate(fsp->conn, fsp->print_file); } else { *written = n; ret = 0; } return ret; }
NTSTATUS do_lock_cancel(files_struct *fsp, uint64 smblctx, uint64_t count, uint64_t offset, enum brl_flavour lock_flav, struct blocking_lock_record *blr) { bool ok = False; struct byte_range_lock *br_lck = NULL; if (!fsp->can_lock) { return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(fsp->conn->params)) { return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for %s file %s\n", (double)offset, (double)count, fsp_fnum_dbg(fsp), fsp_str_dbg(fsp))); br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } ok = brl_lock_cancel(br_lck, smblctx, messaging_server_id(fsp->conn->sconn->msg_ctx), offset, count, lock_flav, blr); TALLOC_FREE(br_lck); if (!ok) { DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" )); return NT_STATUS_DOS(ERRDOS, ERRcancelviolation); } decrement_current_lock_count(fsp, lock_flav); return NT_STATUS_OK; }
NTSTATUS do_unlock(struct messaging_context *msg_ctx, files_struct *fsp, uint64_t smblctx, uint64_t count, uint64_t offset, enum brl_flavour lock_flav) { bool ok = False; struct byte_range_lock *br_lck = NULL; if (!fsp->can_lock) { return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE; } if (!lp_locking(fsp->conn->params)) { return NT_STATUS_OK; } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for %s file %s\n", (double)offset, (double)count, fsp_fnum_dbg(fsp), fsp_str_dbg(fsp))); br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { return NT_STATUS_NO_MEMORY; } ok = brl_unlock(msg_ctx, br_lck, smblctx, messaging_server_id(fsp->conn->sconn->msg_ctx), offset, count, lock_flav); TALLOC_FREE(br_lck); if (!ok) { DEBUG(10,("do_unlock: returning ERRlock.\n" )); return NT_STATUS_RANGE_NOT_LOCKED; } decrement_current_lock_count(fsp, lock_flav); return NT_STATUS_OK; }
void trigger_write_time_update(struct files_struct *fsp) { int delay; if (fsp->posix_open) { /* Don't use delayed writes on POSIX files. */ return; } if (fsp->write_time_forced) { /* No point - "sticky" write times * in effect. */ return; } /* We need to remember someone did a write * and update to current time on close. */ fsp->update_write_time_on_close = true; if (fsp->update_write_time_triggered) { /* * We only update the write time after 2 seconds * on the first normal write. After that * no other writes affect this until close. */ return; } fsp->update_write_time_triggered = true; delay = lp_parm_int(SNUM(fsp->conn), "smbd", "writetimeupdatedelay", WRITE_TIME_UPDATE_USEC_DELAY); DEBUG(5, ("Update write time %d usec later on %s\n", delay, fsp_str_dbg(fsp))); /* trigger the update 2 seconds later */ fsp->update_write_time_event = event_add_timed(smbd_event_context(), NULL, timeval_current_ofs(0, delay), update_write_time_handler, fsp); }
void update_write_time_handler(struct event_context *ctx, struct timed_event *te, struct timeval now, void *private_data) { files_struct *fsp = (files_struct *)private_data; DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp))); /* change the write time in the open file db. */ (void)set_write_time(fsp->file_id, timespec_current()); /* And notify. */ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name); /* Remove the timed event handler. */ TALLOC_FREE(fsp->update_write_time_event); }