示例#1
0
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) );
		}
	}
}
示例#2
0
文件: oplock.c 项目: Distrotech/samba
/*
 * 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;
}
示例#3
0
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;
}
示例#4
0
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) );
		}
	}
}
示例#5
0
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;
}
示例#6
0
文件: oplock.c 项目: AIdrifter/samba
/*
 * 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;
}
示例#7
0
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;
}
示例#8
0
文件: posix.c 项目: eduardok/samba
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));
}
示例#9
0
文件: files.c 项目: hef/samba
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;
}
示例#10
0
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;
}
示例#11
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;
		}
	}
示例#12
0
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);
}
示例#13
0
文件: posix.c 项目: eduardok/samba
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)));
}
示例#14
0
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);
}
示例#15
0
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);
}
示例#16
0
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;
}
示例#17
0
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);
}
示例#18
0
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;
}
示例#19
0
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;
}
示例#20
0
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;
	}
}
示例#21
0
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;
}
示例#22
0
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;
}
示例#23
0
文件: oplock.c 项目: Distrotech/samba
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;
}
示例#24
0
文件: oplock.c 项目: AIdrifter/samba
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);
}
示例#25
0
文件: oplock.c 项目: AIdrifter/samba
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;
}
示例#26
0
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;
}
示例#27
0
文件: locking.c 项目: rchicoli/samba
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;
}
示例#28
0
文件: locking.c 项目: rchicoli/samba
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;
}
示例#29
0
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);
}
示例#30
0
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);
}