summaryrefslogtreecommitdiffstats
path: root/source3/smbd/fd_handle.c
blob: eb7fa55e22a81b41c2c1730851412ef35757cd20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
   Unix SMB/CIFS implementation.
   fd_handle structure handling
   Copyright (C) Ralph Boehme 2020

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "includes.h"
#include "fd_handle.h"

struct fd_handle {
	size_t ref_count;
	int fd;
	uint64_t position_information;
	off_t pos;
	/*
	 * NT Create options, but we only look at
	 * NTCREATEX_FLAG_DENY_DOS and
	 * NTCREATEX_FLAG_DENY_FCB.
	 */
	uint32_t private_options;
	uint64_t gen_id;
};

static int fd_handle_destructor(struct fd_handle *fh)
{
	SMB_ASSERT((fh->fd == -1) || (fh->fd == AT_FDCWD));
	return 0;
}

struct fd_handle *fd_handle_create(TALLOC_CTX *mem_ctx)
{
	struct fd_handle *fh = NULL;

	fh = talloc_zero(mem_ctx, struct fd_handle);
	if (fh == NULL) {
		return NULL;
	}
	fh->fd = -1;

	talloc_set_destructor(fh, fd_handle_destructor);

	return fh;
}

size_t fh_get_refcount(struct fd_handle *fh)
{
	return fh->ref_count;
}

void fh_set_refcount(struct fd_handle *fh, size_t ref_count)
{
	fh->ref_count = ref_count;
}

uint64_t fh_get_position_information(struct fd_handle *fh)
{
	return fh->position_information;
}

void fh_set_position_information(struct fd_handle *fh, uint64_t posinfo)
{
	fh->position_information = posinfo;
}

off_t fh_get_pos(struct fd_handle *fh)
{
	return fh->pos;
}

void fh_set_pos(struct fd_handle *fh, off_t pos)
{
	fh->pos = pos;
}

uint32_t fh_get_private_options(struct fd_handle *fh)
{
	return fh->private_options;
}

void fh_set_private_options(struct fd_handle *fh, uint32_t private_options)
{
	fh->private_options = private_options;
}

uint64_t fh_get_gen_id(struct fd_handle *fh)
{
	return fh->gen_id;
}

void fh_set_gen_id(struct fd_handle *fh, uint64_t gen_id)
{
	fh->gen_id = gen_id;
}

/****************************************************************************
 Helper functions for working with fsp->fh->fd
****************************************************************************/

int fsp_get_io_fd(const struct files_struct *fsp)
{
	if (fsp->fsp_flags.is_pathref) {
		DBG_ERR("fsp [%s] is a path referencing fsp\n",
			fsp_str_dbg(fsp));
#ifdef DEVELOPER
		smb_panic("fsp is a pathref");
#endif
		return -1;
	}

	return fsp->fh->fd;
}

int fsp_get_pathref_fd(const struct files_struct *fsp)
{
	return fsp->fh->fd;
}

void fsp_set_fd(struct files_struct *fsp, int fd)
{
	/*
	 * Deliberately allow setting an fd if the existing fd is the
	 * same. This happens if a VFS module assigns the fd to
	 * fsp->fh->fd in its openat VFS function. The canonical place
	 * where the assignment is done is in fd_open(), but some VFS
	 * modules do it anyway.
	 */

	SMB_ASSERT(fsp->fh->fd == -1 ||
		   fsp->fh->fd == fd ||
		   fd == -1 ||
		   fd == AT_FDCWD);

	fsp->fh->fd = fd;
}